diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2021-02-16 20:13:02 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2021-02-16 20:13:02 +0000 |
commit | b60736ec1405bb0a8dd40989f67ef4c93da068ab (patch) | |
tree | 5c43fbb7c9fc45f0f87e0e6795a86267dbd12f9d /clang/lib/Sema | |
parent | cfca06d7963fa0909f90483b42a6d7d194d01e08 (diff) | |
download | src-b60736ec1405bb0a8dd40989f67ef4c93da068ab.tar.gz src-b60736ec1405bb0a8dd40989f67ef4c93da068ab.zip |
Diffstat (limited to 'clang/lib/Sema')
43 files changed, 8271 insertions, 4308 deletions
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 3b7356893833..edd9742ed207 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -24,6 +24,7 @@ #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtVisitor.h" #include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" +#include "clang/Analysis/Analyses/CalledOnceCheck.h" #include "clang/Analysis/Analyses/Consumed.h" #include "clang/Analysis/Analyses/ReachableCode.h" #include "clang/Analysis/Analyses/ThreadSafety.h" @@ -36,6 +37,7 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallString.h" @@ -1623,6 +1625,82 @@ private: }); } }; + +class CalledOnceCheckReporter : public CalledOnceCheckHandler { +public: + CalledOnceCheckReporter(Sema &S) : S(S) {} + void handleDoubleCall(const ParmVarDecl *Parameter, const Expr *Call, + const Expr *PrevCall, bool IsCompletionHandler, + bool Poised) override { + auto DiagToReport = IsCompletionHandler + ? diag::warn_completion_handler_called_twice + : diag::warn_called_once_gets_called_twice; + S.Diag(Call->getBeginLoc(), DiagToReport) << Parameter; + S.Diag(PrevCall->getBeginLoc(), diag::note_called_once_gets_called_twice) + << Poised; + } + + void handleNeverCalled(const ParmVarDecl *Parameter, + bool IsCompletionHandler) override { + auto DiagToReport = IsCompletionHandler + ? diag::warn_completion_handler_never_called + : diag::warn_called_once_never_called; + S.Diag(Parameter->getBeginLoc(), DiagToReport) + << Parameter << /* Captured */ false; + } + + void handleNeverCalled(const ParmVarDecl *Parameter, const Stmt *Where, + NeverCalledReason Reason, bool IsCalledDirectly, + bool IsCompletionHandler) override { + auto DiagToReport = IsCompletionHandler + ? diag::warn_completion_handler_never_called_when + : diag::warn_called_once_never_called_when; + S.Diag(Where->getBeginLoc(), DiagToReport) + << Parameter << IsCalledDirectly << (unsigned)Reason; + } + + void handleCapturedNeverCalled(const ParmVarDecl *Parameter, + const Decl *Where, + bool IsCompletionHandler) override { + auto DiagToReport = IsCompletionHandler + ? diag::warn_completion_handler_never_called + : diag::warn_called_once_never_called; + S.Diag(Where->getBeginLoc(), DiagToReport) + << Parameter << /* Captured */ true; + } + +private: + Sema &S; +}; + +constexpr unsigned CalledOnceWarnings[] = { + diag::warn_called_once_never_called, + diag::warn_called_once_never_called_when, + diag::warn_called_once_gets_called_twice}; + +constexpr unsigned CompletionHandlerWarnings[]{ + diag::warn_completion_handler_never_called, + diag::warn_completion_handler_never_called_when, + diag::warn_completion_handler_called_twice}; + +bool shouldAnalyzeCalledOnceImpl(llvm::ArrayRef<unsigned> DiagIDs, + const DiagnosticsEngine &Diags, + SourceLocation At) { + return llvm::any_of(DiagIDs, [&Diags, At](unsigned DiagID) { + return !Diags.isIgnored(DiagID, At); + }); +} + +bool shouldAnalyzeCalledOnceConventions(const DiagnosticsEngine &Diags, + SourceLocation At) { + return shouldAnalyzeCalledOnceImpl(CompletionHandlerWarnings, Diags, At); +} + +bool shouldAnalyzeCalledOnceParameters(const DiagnosticsEngine &Diags, + SourceLocation At) { + return shouldAnalyzeCalledOnceImpl(CalledOnceWarnings, Diags, At) || + shouldAnalyzeCalledOnceConventions(Diags, At); +} } // anonymous namespace namespace clang { @@ -1849,8 +1927,8 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler { << *PossibleMatch); if (Verbose && POK == POK_VarAccess) { PartialDiagnosticAt VNote(D->getLocation(), - S.PDiag(diag::note_guarded_by_declared_here) - << D->getNameAsString()); + S.PDiag(diag::note_guarded_by_declared_here) + << D->getDeclName()); Warnings.emplace_back(std::move(Warning), getNotes(Note, VNote)); } else Warnings.emplace_back(std::move(Warning), getNotes(Note)); @@ -1892,6 +1970,13 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler { Warnings.emplace_back(std::move(Warning), getNotes()); } + void handleNegativeNotHeld(const NamedDecl *D, Name LockName, + SourceLocation Loc) override { + PartialDiagnosticAt Warning( + Loc, S.PDiag(diag::warn_fun_requires_negative_cap) << D << LockName); + Warnings.emplace_back(std::move(Warning), getNotes()); + } + void handleFunExcludesLock(StringRef Kind, Name FunName, Name LockName, SourceLocation Loc) override { PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_fun_excludes_mutex) @@ -2089,7 +2174,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, if (cast<DeclContext>(D)->isDependentContext()) return; - if (Diags.hasUncompilableErrorOccurred()) { + if (S.hasUncompilableErrorOccurred()) { // Flush out any possibly unreachable diagnostics. flushDiagnostics(S, fscope); return; @@ -2257,6 +2342,17 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, } } + // Check for violations of "called once" parameter properties. + if (S.getLangOpts().ObjC && + shouldAnalyzeCalledOnceParameters(Diags, D->getBeginLoc())) { + if (AC.getCFG()) { + CalledOnceCheckReporter Reporter(S); + checkCalledOnceParameters( + AC, Reporter, + shouldAnalyzeCalledOnceConventions(Diags, D->getBeginLoc())); + } + } + bool FallThroughDiagFull = !Diags.isIgnored(diag::warn_unannotated_fallthrough, D->getBeginLoc()); bool FallThroughDiagPerFunction = !Diags.isIgnored( diff --git a/clang/lib/Sema/CodeCompleteConsumer.cpp b/clang/lib/Sema/CodeCompleteConsumer.cpp index f1ad8aeaacbb..678a09ba1003 100644 --- a/clang/lib/Sema/CodeCompleteConsumer.cpp +++ b/clang/lib/Sema/CodeCompleteConsumer.cpp @@ -356,8 +356,7 @@ const char *CodeCompletionAllocator::CopyString(const Twine &String) { } StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) { - const NamedDecl *ND = dyn_cast<NamedDecl>(DC); - if (!ND) + if (!isa<NamedDecl>(DC)) return {}; // Check whether we've already cached the parent name. @@ -470,8 +469,7 @@ void CodeCompletionBuilder::addParentContext(const DeclContext *DC) { if (DC->isFunctionOrMethod()) return; - const NamedDecl *ND = dyn_cast<NamedDecl>(DC); - if (!ND) + if (!isa<NamedDecl>(DC)) return; ParentName = getCodeCompletionTUInfo().getParentName(DC); diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index f4c30c90ad27..da42db3e8f7b 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -181,6 +181,8 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, SourceLocation LocalRangeEnd, Declarator &TheDeclarator, TypeResult TrailingReturnType, + SourceLocation + TrailingReturnTypeLoc, DeclSpec *MethodQualifiers) { assert(!(MethodQualifiers && MethodQualifiers->getTypeQualifiers() & DeclSpec::TQ_atomic) && "function cannot have _Atomic qualifier"); @@ -189,27 +191,29 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, I.Kind = Function; I.Loc = LocalRangeBegin; I.EndLoc = LocalRangeEnd; + new (&I.Fun) FunctionTypeInfo; I.Fun.hasPrototype = hasProto; I.Fun.isVariadic = EllipsisLoc.isValid(); I.Fun.isAmbiguous = isAmbiguous; - I.Fun.LParenLoc = LParenLoc.getRawEncoding(); - I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding(); - I.Fun.RParenLoc = RParenLoc.getRawEncoding(); + I.Fun.LParenLoc = LParenLoc; + I.Fun.EllipsisLoc = EllipsisLoc; + I.Fun.RParenLoc = RParenLoc; I.Fun.DeleteParams = false; I.Fun.NumParams = NumParams; I.Fun.Params = nullptr; I.Fun.RefQualifierIsLValueRef = RefQualifierIsLvalueRef; - I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding(); - I.Fun.MutableLoc = MutableLoc.getRawEncoding(); + I.Fun.RefQualifierLoc = RefQualifierLoc; + I.Fun.MutableLoc = MutableLoc; I.Fun.ExceptionSpecType = ESpecType; - I.Fun.ExceptionSpecLocBeg = ESpecRange.getBegin().getRawEncoding(); - I.Fun.ExceptionSpecLocEnd = ESpecRange.getEnd().getRawEncoding(); + I.Fun.ExceptionSpecLocBeg = ESpecRange.getBegin(); + I.Fun.ExceptionSpecLocEnd = ESpecRange.getEnd(); I.Fun.NumExceptionsOrDecls = 0; I.Fun.Exceptions = nullptr; I.Fun.NoexceptExpr = nullptr; I.Fun.HasTrailingReturnType = TrailingReturnType.isUsable() || TrailingReturnType.isInvalid(); I.Fun.TrailingReturnType = TrailingReturnType.get(); + I.Fun.TrailingReturnTypeLoc = TrailingReturnTypeLoc; I.Fun.MethodQualifiers = nullptr; I.Fun.QualAttrFactory = nullptr; @@ -405,7 +409,7 @@ bool Declarator::isDeclarationOfFunction() const { } bool Declarator::isStaticMember() { - assert(getContext() == DeclaratorContext::MemberContext); + assert(getContext() == DeclaratorContext::Member); return getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static || (getName().Kind == UnqualifiedIdKind::IK_OperatorFunctionId && CXXMethodDecl::isStaticOverloadedOperator( @@ -499,12 +503,16 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TSCS S) { llvm_unreachable("Unknown typespec!"); } -const char *DeclSpec::getSpecifierName(TSW W) { +const char *DeclSpec::getSpecifierName(TypeSpecifierWidth W) { switch (W) { - case TSW_unspecified: return "unspecified"; - case TSW_short: return "short"; - case TSW_long: return "long"; - case TSW_longlong: return "long long"; + case TypeSpecifierWidth::Unspecified: + return "unspecified"; + case TypeSpecifierWidth::Short: + return "short"; + case TypeSpecifierWidth::Long: + return "long"; + case TypeSpecifierWidth::LongLong: + return "long long"; } llvm_unreachable("Unknown typespec!"); } @@ -518,12 +526,14 @@ const char *DeclSpec::getSpecifierName(TSC C) { llvm_unreachable("Unknown typespec!"); } - -const char *DeclSpec::getSpecifierName(TSS S) { +const char *DeclSpec::getSpecifierName(TypeSpecifierSign S) { switch (S) { - case TSS_unspecified: return "unspecified"; - case TSS_signed: return "signed"; - case TSS_unsigned: return "unsigned"; + case TypeSpecifierSign::Unspecified: + return "unspecified"; + case TypeSpecifierSign::Signed: + return "signed"; + case TypeSpecifierSign::Unsigned: + return "unsigned"; } llvm_unreachable("Unknown typespec!"); } @@ -579,10 +589,14 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T, const char *DeclSpec::getSpecifierName(ConstexprSpecKind C) { switch (C) { - case CSK_unspecified: return "unspecified"; - case CSK_constexpr: return "constexpr"; - case CSK_consteval: return "consteval"; - case CSK_constinit: return "constinit"; + case ConstexprSpecKind::Unspecified: + return "unspecified"; + case ConstexprSpecKind::Constexpr: + return "constexpr"; + case ConstexprSpecKind::Consteval: + return "consteval"; + case ConstexprSpecKind::Constinit: + return "constinit"; } llvm_unreachable("Unknown ConstexprSpecKind"); } @@ -675,18 +689,18 @@ bool DeclSpec::SetStorageClassSpecThread(TSCS TSC, SourceLocation Loc, /// These methods set the specified attribute of the DeclSpec, but return true /// and ignore the request if invalid (e.g. "extern" then "auto" is /// specified). -bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc, - const char *&PrevSpec, - unsigned &DiagID, +bool DeclSpec::SetTypeSpecWidth(TypeSpecifierWidth W, SourceLocation Loc, + const char *&PrevSpec, unsigned &DiagID, const PrintingPolicy &Policy) { // Overwrite TSWRange.Begin only if TypeSpecWidth was unspecified, so that // for 'long long' we will keep the source location of the first 'long'. - if (TypeSpecWidth == TSW_unspecified) + if (getTypeSpecWidth() == TypeSpecifierWidth::Unspecified) TSWRange.setBegin(Loc); // Allow turning long -> long long. - else if (W != TSW_longlong || TypeSpecWidth != TSW_long) - return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID); - TypeSpecWidth = W; + else if (W != TypeSpecifierWidth::LongLong || + getTypeSpecWidth() != TypeSpecifierWidth::Long) + return BadSpecifier(W, getTypeSpecWidth(), PrevSpec, DiagID); + TypeSpecWidth = static_cast<unsigned>(W); // Remember location of the last 'long' TSWRange.setEnd(Loc); return false; @@ -702,12 +716,11 @@ bool DeclSpec::SetTypeSpecComplex(TSC C, SourceLocation Loc, return false; } -bool DeclSpec::SetTypeSpecSign(TSS S, SourceLocation Loc, - const char *&PrevSpec, - unsigned &DiagID) { - if (TypeSpecSign != TSS_unspecified) - return BadSpecifier(S, (TSS)TypeSpecSign, PrevSpec, DiagID); - TypeSpecSign = S; +bool DeclSpec::SetTypeSpecSign(TypeSpecifierSign S, SourceLocation Loc, + const char *&PrevSpec, unsigned &DiagID) { + if (getTypeSpecSign() != TypeSpecifierSign::Unspecified) + return BadSpecifier(S, getTypeSpecSign(), PrevSpec, DiagID); + TypeSpecSign = static_cast<unsigned>(S); TSSLoc = Loc; return false; } @@ -870,7 +883,7 @@ bool DeclSpec::SetTypePipe(bool isPipe, SourceLocation Loc, } if (isPipe) { - TypeSpecPipe = TSP_pipe; + TypeSpecPipe = static_cast<unsigned>(TypeSpecifiersPipe::Pipe); } return false; } @@ -1014,9 +1027,6 @@ bool DeclSpec::setFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, ExplicitSpecifier ExplicitSpec, SourceLocation CloseParenLoc) { - assert((ExplicitSpec.getKind() == ExplicitSpecKind::ResolvedTrue || - ExplicitSpec.getExpr()) && - "invalid ExplicitSpecifier"); // 'explicit explicit' is ok, but warn as this is likely not what the user // intended. if (hasExplicitSpecifier()) { @@ -1080,17 +1090,17 @@ bool DeclSpec::setModulePrivateSpec(SourceLocation Loc, const char *&PrevSpec, bool DeclSpec::SetConstexprSpec(ConstexprSpecKind ConstexprKind, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID) { - if (getConstexprSpecifier() != CSK_unspecified) + if (getConstexprSpecifier() != ConstexprSpecKind::Unspecified) return BadSpecifier(ConstexprKind, getConstexprSpecifier(), PrevSpec, DiagID); - ConstexprSpecifier = ConstexprKind; + ConstexprSpecifier = static_cast<unsigned>(ConstexprKind); ConstexprLoc = Loc; return false; } void DeclSpec::SaveWrittenBuiltinSpecs() { - writtenBS.Sign = getTypeSpecSign(); - writtenBS.Width = getTypeSpecWidth(); + writtenBS.Sign = static_cast<int>(getTypeSpecSign()); + writtenBS.Width = static_cast<int>(getTypeSpecWidth()); writtenBS.Type = getTypeSpecType(); // Search the list of attributes for the presence of a mode attribute. writtenBS.ModeAttr = getAttributes().hasAttribute(ParsedAttr::AT_Mode); @@ -1111,9 +1121,9 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { // If decltype(auto) is used, no other type specifiers are permitted. if (TypeSpecType == TST_decltype_auto && - (TypeSpecWidth != TSW_unspecified || + (getTypeSpecWidth() != TypeSpecifierWidth::Unspecified || TypeSpecComplex != TSC_unspecified || - TypeSpecSign != TSS_unspecified || + getTypeSpecSign() != TypeSpecifierSign::Unspecified || TypeAltiVecVector || TypeAltiVecPixel || TypeAltiVecBool || TypeQualifiers)) { const unsigned NumLocs = 9; @@ -1132,9 +1142,9 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { Hints[I] = FixItHint::CreateRemoval(ExtraLocs[I]); } } - TypeSpecWidth = TSW_unspecified; + TypeSpecWidth = static_cast<unsigned>(TypeSpecifierWidth::Unspecified); TypeSpecComplex = TSC_unspecified; - TypeSpecSign = TSS_unspecified; + TypeSpecSign = static_cast<unsigned>(TypeSpecifierSign::Unspecified); TypeAltiVecVector = TypeAltiVecPixel = TypeAltiVecBool = false; TypeQualifiers = 0; S.Diag(TSTLoc, diag::err_decltype_auto_cannot_be_combined) @@ -1146,9 +1156,9 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { if (TypeAltiVecVector) { if (TypeAltiVecBool) { // Sign specifiers are not allowed with vector bool. (PIM 2.1) - if (TypeSpecSign != TSS_unspecified) { + if (getTypeSpecSign() != TypeSpecifierSign::Unspecified) { S.Diag(TSSLoc, diag::err_invalid_vector_bool_decl_spec) - << getSpecifierName((TSS)TypeSpecSign); + << getSpecifierName(getTypeSpecSign()); } // Only char/int are valid with vector bool prior to Power10. // Power10 adds instructions that produce vector bool data @@ -1166,13 +1176,14 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { S.Diag(TSTLoc, diag::err_invalid_vector_bool_int128_decl_spec); // Only 'short' and 'long long' are valid with vector bool. (PIM 2.1) - if ((TypeSpecWidth != TSW_unspecified) && (TypeSpecWidth != TSW_short) && - (TypeSpecWidth != TSW_longlong)) + if ((getTypeSpecWidth() != TypeSpecifierWidth::Unspecified) && + (getTypeSpecWidth() != TypeSpecifierWidth::Short) && + (getTypeSpecWidth() != TypeSpecifierWidth::LongLong)) S.Diag(TSWRange.getBegin(), diag::err_invalid_vector_bool_decl_spec) - << getSpecifierName((TSW)TypeSpecWidth); + << getSpecifierName(getTypeSpecWidth()); // vector bool long long requires VSX support or ZVector. - if ((TypeSpecWidth == TSW_longlong) && + if ((getTypeSpecWidth() == TypeSpecifierWidth::LongLong) && (!S.Context.getTargetInfo().hasFeature("vsx")) && (!S.Context.getTargetInfo().hasFeature("power8-vector")) && !S.getLangOpts().ZVector) @@ -1180,12 +1191,14 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { // Elements of vector bool are interpreted as unsigned. (PIM 2.1) if ((TypeSpecType == TST_char) || (TypeSpecType == TST_int) || - (TypeSpecType == TST_int128) || (TypeSpecWidth != TSW_unspecified)) - TypeSpecSign = TSS_unsigned; + (TypeSpecType == TST_int128) || + (getTypeSpecWidth() != TypeSpecifierWidth::Unspecified)) + TypeSpecSign = static_cast<unsigned>(TypeSpecifierSign::Unsigned); } else if (TypeSpecType == TST_double) { // vector long double and vector long long double are never allowed. // vector double is OK for Power7 and later, and ZVector. - if (TypeSpecWidth == TSW_long || TypeSpecWidth == TSW_longlong) + if (getTypeSpecWidth() == TypeSpecifierWidth::Long || + getTypeSpecWidth() == TypeSpecifierWidth::LongLong) S.Diag(TSWRange.getBegin(), diag::err_invalid_vector_long_double_decl_spec); else if (!S.Context.getTargetInfo().hasFeature("vsx") && @@ -1197,9 +1210,15 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { if (S.getLangOpts().ZVector && !S.Context.getTargetInfo().hasFeature("arch12")) S.Diag(TSTLoc, diag::err_invalid_vector_float_decl_spec); - } else if (TypeSpecWidth == TSW_long) { + } else if (getTypeSpecWidth() == TypeSpecifierWidth::Long) { // vector long is unsupported for ZVector and deprecated for AltiVec. - if (S.getLangOpts().ZVector) + // It has also been historically deprecated on AIX (as an alias for + // "vector int" in both 32-bit and 64-bit modes). It was then made + // unsupported in the Clang-based XL compiler since the deprecated type + // has a number of conflicting semantics and continuing to support it + // is a disservice to users. + if (S.getLangOpts().ZVector || + S.Context.getTargetInfo().getTriple().isOSAIX()) S.Diag(TSWRange.getBegin(), diag::err_invalid_vector_long_decl_spec); else S.Diag(TSWRange.getBegin(), @@ -1210,8 +1229,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { if (TypeAltiVecPixel) { //TODO: perform validation TypeSpecType = TST_int; - TypeSpecSign = TSS_unsigned; - TypeSpecWidth = TSW_short; + TypeSpecSign = static_cast<unsigned>(TypeSpecifierSign::Unsigned); + TypeSpecWidth = static_cast<unsigned>(TypeSpecifierWidth::Short); TypeSpecOwned = false; } } @@ -1220,7 +1239,7 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { TypeSpecType == TST_accum || TypeSpecType == TST_fract; // signed/unsigned are only valid with int/char/wchar_t/_Accum. - if (TypeSpecSign != TSS_unspecified) { + if (getTypeSpecSign() != TypeSpecifierSign::Unspecified) { if (TypeSpecType == TST_unspecified) TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int. else if (TypeSpecType != TST_int && TypeSpecType != TST_int128 && @@ -1229,19 +1248,21 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { S.Diag(TSSLoc, diag::err_invalid_sign_spec) << getSpecifierName((TST)TypeSpecType, Policy); // signed double -> double. - TypeSpecSign = TSS_unspecified; + TypeSpecSign = static_cast<unsigned>(TypeSpecifierSign::Unspecified); } } // Validate the width of the type. - switch (TypeSpecWidth) { - case TSW_unspecified: break; - case TSW_short: // short int - case TSW_longlong: // long long int + switch (getTypeSpecWidth()) { + case TypeSpecifierWidth::Unspecified: + break; + case TypeSpecifierWidth::Short: // short int + case TypeSpecifierWidth::LongLong: // long long int if (TypeSpecType == TST_unspecified) TypeSpecType = TST_int; // short -> short int, long long -> long long int. else if (!(TypeSpecType == TST_int || - (IsFixedPointType && TypeSpecWidth != TSW_longlong))) { + (IsFixedPointType && + getTypeSpecWidth() != TypeSpecifierWidth::LongLong))) { S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec) << (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy); TypeSpecType = TST_int; @@ -1249,7 +1270,7 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { TypeSpecOwned = false; } break; - case TSW_long: // long double, long int + case TypeSpecifierWidth::Long: // long double, long int if (TypeSpecType == TST_unspecified) TypeSpecType = TST_int; // long -> long int. else if (TypeSpecType != TST_int && TypeSpecType != TST_double && @@ -1279,6 +1300,7 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { S.Diag(TSTLoc, diag::ext_integer_complex); } else if (TypeSpecType != TST_float && TypeSpecType != TST_double && TypeSpecType != TST_float128) { + // FIXME: _Float16, __fp16? S.Diag(TSCLoc, diag::err_invalid_complex_spec) << getSpecifierName((TST)TypeSpecType, Policy); TypeSpecComplex = TSC_unspecified; @@ -1337,11 +1359,11 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { else if (TypeSpecType == TST_char16 || TypeSpecType == TST_char32) S.Diag(TSTLoc, diag::warn_cxx98_compat_unicode_type) << (TypeSpecType == TST_char16 ? "char16_t" : "char32_t"); - if (getConstexprSpecifier() == CSK_constexpr) + if (getConstexprSpecifier() == ConstexprSpecKind::Constexpr) S.Diag(ConstexprLoc, diag::warn_cxx98_compat_constexpr); - else if (getConstexprSpecifier() == CSK_consteval) + else if (getConstexprSpecifier() == ConstexprSpecKind::Consteval) S.Diag(ConstexprLoc, diag::warn_cxx20_compat_consteval); - else if (getConstexprSpecifier() == CSK_constinit) + else if (getConstexprSpecifier() == ConstexprSpecKind::Constinit) S.Diag(ConstexprLoc, diag::warn_cxx20_compat_constinit); // C++ [class.friend]p6: // No storage-class-specifier shall appear in the decl-specifier-seq @@ -1422,9 +1444,10 @@ void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc, Kind = UnqualifiedIdKind::IK_OperatorFunctionId; StartLocation = OperatorLoc; EndLocation = OperatorLoc; + new (&OperatorFunctionId) struct OFI; OperatorFunctionId.Operator = Op; for (unsigned I = 0; I != 3; ++I) { - OperatorFunctionId.SymbolLocations[I] = SymbolLocations[I].getRawEncoding(); + OperatorFunctionId.SymbolLocations[I] = SymbolLocations[I]; if (SymbolLocations[I].isValid()) EndLocation = SymbolLocations[I]; diff --git a/clang/lib/Sema/JumpDiagnostics.cpp b/clang/lib/Sema/JumpDiagnostics.cpp index b34243edea35..d33b14a79dc1 100644 --- a/clang/lib/Sema/JumpDiagnostics.cpp +++ b/clang/lib/Sema/JumpDiagnostics.cpp @@ -17,6 +17,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtOpenMP.h" #include "llvm/ADT/BitVector.h" using namespace clang; @@ -580,6 +581,17 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, break; default: + if (auto *ED = dyn_cast<OMPExecutableDirective>(S)) { + if (!ED->isStandaloneDirective()) { + unsigned NewParentScope = Scopes.size(); + Scopes.emplace_back(ParentScope, + diag::note_omp_protected_structured_block, + diag::note_omp_exits_structured_block, + ED->getStructuredBlock()->getBeginLoc()); + BuildScopeInformation(ED->getStructuredBlock(), NewParentScope); + return; + } + } break; } @@ -904,6 +916,11 @@ void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc, S.Diag(From->getBeginLoc(), diag::warn_jump_out_of_seh_finally); break; } + if (Scopes[I].InDiag == diag::note_omp_protected_structured_block) { + S.Diag(From->getBeginLoc(), diag::err_goto_into_protected_scope); + S.Diag(To->getBeginLoc(), diag::note_omp_exits_structured_block); + break; + } } } diff --git a/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/clang/lib/Sema/MultiplexExternalSemaSource.cpp index 80333e63127e..252008cda15d 100644 --- a/clang/lib/Sema/MultiplexExternalSemaSource.cpp +++ b/clang/lib/Sema/MultiplexExternalSemaSource.cpp @@ -172,13 +172,6 @@ Module *MultiplexExternalSemaSource::getModule(unsigned ID) { return nullptr; } -bool MultiplexExternalSemaSource::DeclIsFromPCHWithObjectFile(const Decl *D) { - for (auto *S : Sources) - if (S->DeclIsFromPCHWithObjectFile(D)) - return true; - return false; -} - bool MultiplexExternalSemaSource::layoutRecordType(const RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, diff --git a/clang/lib/Sema/ScopeInfo.cpp b/clang/lib/Sema/ScopeInfo.cpp index b2a26af9b4a5..4857346018ae 100644 --- a/clang/lib/Sema/ScopeInfo.cpp +++ b/clang/lib/Sema/ScopeInfo.cpp @@ -29,6 +29,7 @@ void FunctionScopeInfo::Clear() { HasDroppedStmt = false; HasOMPDeclareReductionCombiner = false; HasFallthroughStmt = false; + UsesFPIntrin = false; HasPotentialAvailabilityViolations = false; ObjCShouldCallSuper = false; ObjCIsDesignatedInit = false; diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 2f2b52106f3d..55cb3aee6194 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -42,7 +42,7 @@ #include "clang/Sema/TemplateInstCallback.h" #include "clang/Sema/TypoCorrection.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/TimeProfiler.h" using namespace clang; @@ -120,8 +120,9 @@ public: } IncludeStack.push_back(IncludeLoc); - S->DiagnoseNonDefaultPragmaPack( - Sema::PragmaPackDiagnoseKind::NonDefaultStateAtInclude, IncludeLoc); + S->DiagnoseNonDefaultPragmaAlignPack( + Sema::PragmaAlignPackDiagnoseKind::NonDefaultStateAtInclude, + IncludeLoc); } break; } @@ -130,8 +131,8 @@ public: if (llvm::timeTraceProfilerEnabled()) llvm::timeTraceProfilerEnd(); - S->DiagnoseNonDefaultPragmaPack( - Sema::PragmaPackDiagnoseKind::ChangedStateAtExit, + S->DiagnoseNonDefaultPragmaAlignPack( + Sema::PragmaAlignPackDiagnoseKind::ChangedStateAtExit, IncludeStack.pop_back_val()); } break; @@ -157,10 +158,12 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, OriginalLexicalContext(nullptr), MSStructPragmaOn(false), MSPointerToMemberRepresentationMethod( LangOpts.getMSPointerToMemberRepresentationMethod()), - VtorDispStack(LangOpts.getVtorDispMode()), PackStack(0), + VtorDispStack(LangOpts.getVtorDispMode()), + AlignPackStack(AlignPackInfo(getLangOpts().XLPragmaPack)), DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr), - CodeSegStack(nullptr), FpPragmaStack(0xffffffff), CurInitSeg(nullptr), - VisContext(nullptr), PragmaAttributeCurrentTargetDecl(nullptr), + CodeSegStack(nullptr), FpPragmaStack(FPOptionsOverride()), + CurInitSeg(nullptr), VisContext(nullptr), + PragmaAttributeCurrentTargetDecl(nullptr), IsBuildingRecoveryCallExpr(false), Cleanup{}, LateTemplateParser(nullptr), LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp), StdExperimentalNamespaceCache(nullptr), StdInitializerList(nullptr), @@ -235,7 +238,9 @@ void Sema::Initialize() { return; // Initialize predefined 128-bit integer types, if needed. - if (Context.getTargetInfo().hasInt128Type()) { + if (Context.getTargetInfo().hasInt128Type() || + (Context.getAuxTargetInfo() && + Context.getAuxTargetInfo()->hasInt128Type())) { // If either of the 128-bit integer types are unavailable to name lookup, // define them now. DeclarationName Int128 = &Context.Idents.get("__int128_t"); @@ -292,7 +297,7 @@ void Sema::Initialize() { // core features. if (getLangOpts().OpenCL) { getOpenCLOptions().addSupport( - Context.getTargetInfo().getSupportedOpenCLOpts()); + Context.getTargetInfo().getSupportedOpenCLOpts(), getLangOpts()); getOpenCLOptions().enableSupportedCore(getLangOpts()); addImplicitTypedef("sampler_t", Context.OCLSamplerTy); addImplicitTypedef("event_t", Context.OCLEventTy); @@ -368,6 +373,18 @@ void Sema::Initialize() { #include "clang/Basic/AArch64SVEACLETypes.def" } + if (Context.getTargetInfo().getTriple().isPPC64() && + Context.getTargetInfo().hasFeature("paired-vector-memops")) { + if (Context.getTargetInfo().hasFeature("mma")) { +#define PPC_VECTOR_MMA_TYPE(Name, Id, Size) \ + addImplicitTypedef(#Name, Context.Id##Ty); +#include "clang/Basic/PPCTypes.def" + } +#define PPC_VECTOR_VSX_TYPE(Name, Id, Size) \ + addImplicitTypedef(#Name, Context.Id##Ty); +#include "clang/Basic/PPCTypes.def" + } + if (Context.getTargetInfo().hasBuiltinMSVaList()) { DeclarationName MSVaList = &Context.Idents.get("__builtin_ms_va_list"); if (IdResolver.begin(MSVaList) == IdResolver.end()) @@ -380,6 +397,9 @@ void Sema::Initialize() { } Sema::~Sema() { + assert(InstantiatingSpecializations.empty() && + "failed to clean up an InstantiatingTemplate?"); + if (VisContext) FreeVisContext(); // Kill all the active scopes. @@ -493,7 +513,8 @@ void Sema::diagnoseNullableToNonnullConversion(QualType DstType, QualType SrcType, SourceLocation Loc) { Optional<NullabilityKind> ExprNullability = SrcType->getNullability(Context); - if (!ExprNullability || *ExprNullability != NullabilityKind::Nullable) + if (!ExprNullability || (*ExprNullability != NullabilityKind::Nullable && + *ExprNullability != NullabilityKind::NullableResult)) return; Optional<NullabilityKind> TypeNullability = DstType->getNullability(Context); @@ -539,8 +560,10 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, if (VK == VK_RValue && !E->isRValue()) { switch (Kind) { default: - llvm_unreachable("can't implicitly cast lvalue to rvalue with this cast " - "kind"); + llvm_unreachable(("can't implicitly cast lvalue to rvalue with this cast " + "kind: " + + std::string(CastExpr::getCastKindName(Kind))) + .c_str()); case CK_Dependent: case CK_LValueToRValue: case CK_ArrayToPointerDecay: @@ -583,7 +606,8 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, } } - return ImplicitCastExpr::Create(Context, Ty, Kind, E, BasePath, VK); + return ImplicitCastExpr::Create(Context, Ty, Kind, E, BasePath, VK, + CurFPFeatureOverrides()); } /// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding @@ -1016,7 +1040,7 @@ void Sema::ActOnEndOfTranslationUnit() { } } - DiagnoseUnterminatedPragmaPack(); + DiagnoseUnterminatedPragmaAlignPack(); DiagnoseUnterminatedPragmaAttribute(); // All delayed member exception specs should be checked or we end up accepting @@ -1195,7 +1219,7 @@ void Sema::ActOnEndOfTranslationUnit() { if (DiagD->isReferenced()) { if (isa<CXXMethodDecl>(DiagD)) Diag(DiagD->getLocation(), diag::warn_unneeded_member_function) - << DiagD->getDeclName(); + << DiagD; else { if (FD->getStorageClass() == SC_Static && !FD->isInlineSpecified() && @@ -1203,20 +1227,20 @@ void Sema::ActOnEndOfTranslationUnit() { SourceMgr.getExpansionLoc(FD->getLocation()))) Diag(DiagD->getLocation(), diag::warn_unneeded_static_internal_decl) - << DiagD->getDeclName(); + << DiagD; else Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl) - << /*function*/0 << DiagD->getDeclName(); + << /*function*/ 0 << DiagD; } } else { if (FD->getDescribedFunctionTemplate()) Diag(DiagD->getLocation(), diag::warn_unused_template) - << /*function*/0 << DiagD->getDeclName(); + << /*function*/ 0 << DiagD; else - Diag(DiagD->getLocation(), - isa<CXXMethodDecl>(DiagD) ? diag::warn_unused_member_function + Diag(DiagD->getLocation(), isa<CXXMethodDecl>(DiagD) + ? diag::warn_unused_member_function : diag::warn_unused_function) - << DiagD->getDeclName(); + << DiagD; } } else { const VarDecl *DiagD = cast<VarDecl>(*I)->getDefinition(); @@ -1224,20 +1248,19 @@ void Sema::ActOnEndOfTranslationUnit() { DiagD = cast<VarDecl>(*I); if (DiagD->isReferenced()) { Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl) - << /*variable*/1 << DiagD->getDeclName(); + << /*variable*/ 1 << DiagD; } else if (DiagD->getType().isConstQualified()) { const SourceManager &SM = SourceMgr; if (SM.getMainFileID() != SM.getFileID(DiagD->getLocation()) || !PP.getLangOpts().IsHeaderFile) Diag(DiagD->getLocation(), diag::warn_unused_const_variable) - << DiagD->getDeclName(); + << DiagD; } else { if (DiagD->getDescribedVarTemplate()) Diag(DiagD->getLocation(), diag::warn_unused_template) - << /*variable*/1 << DiagD->getDeclName(); + << /*variable*/ 1 << DiagD; else - Diag(DiagD->getLocation(), diag::warn_unused_variable) - << DiagD->getDeclName(); + Diag(DiagD->getLocation(), diag::warn_unused_variable) << DiagD; } } } @@ -1433,11 +1456,24 @@ void Sema::EmitCurrentDiagnostic(unsigned DiagID) { } Sema::SemaDiagnosticBuilder -Sema::Diag(SourceLocation Loc, const PartialDiagnostic& PD) { - SemaDiagnosticBuilder Builder(Diag(Loc, PD.getDiagID())); - PD.Emit(Builder); +Sema::Diag(SourceLocation Loc, const PartialDiagnostic &PD, bool DeferHint) { + return Diag(Loc, PD.getDiagID(), DeferHint) << PD; +} - return Builder; +bool Sema::hasUncompilableErrorOccurred() const { + if (getDiagnostics().hasUncompilableErrorOccurred()) + return true; + auto *FD = dyn_cast<FunctionDecl>(CurContext); + if (!FD) + return false; + auto Loc = DeviceDeferredDiags.find(FD); + if (Loc == DeviceDeferredDiags.end()) + return false; + for (auto PDAt : Loc->second) { + if (DiagnosticIDs::isDefaultMappingAsError(PDAt.second.getDiagID())) + return true; + } + return false; } // Print notes showing how we can reach FD starting from an a priori @@ -1490,7 +1526,7 @@ public: typedef UsedDeclVisitor<DeferredDiagnosticsEmitter> Inherited; // Whether the function is already in the current use-path. - llvm::SmallSet<CanonicalDeclPtr<Decl>, 4> InUsePath; + llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> InUsePath; // The current use-path. llvm::SmallVector<CanonicalDeclPtr<FunctionDecl>, 4> UsePath; @@ -1499,7 +1535,7 @@ public: // case not in OpenMP device context. Done[1] is for the case in OpenMP // device context. We need two sets because diagnostics emission may be // different depending on whether it is in OpenMP device context. - llvm::SmallSet<CanonicalDeclPtr<Decl>, 4> DoneMap[2]; + llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> DoneMap[2]; // Emission state of the root node of the current use graph. bool ShouldEmitRootNode; @@ -1549,7 +1585,8 @@ public: S.shouldIgnoreInHostDeviceCheck(FD) || InUsePath.count(FD)) return; // Finalize analysis of OpenMP-specific constructs. - if (Caller && S.LangOpts.OpenMP && UsePath.size() == 1) + if (Caller && S.LangOpts.OpenMP && UsePath.size() == 1 && + (ShouldEmitRootNode || InOMPDeviceContext)) S.finalizeOpenMPDelayedAnalysis(Caller, FD, Loc); if (Caller) S.DeviceKnownEmittedFns[FD] = {Caller, Loc}; @@ -1649,9 +1686,9 @@ void Sema::emitDeferredDiags() { // until we discover that the function is known-emitted, at which point we take // it out of this map and emit the diagnostic. -Sema::DeviceDiagBuilder::DeviceDiagBuilder(Kind K, SourceLocation Loc, - unsigned DiagID, FunctionDecl *Fn, - Sema &S) +Sema::SemaDiagnosticBuilder::SemaDiagnosticBuilder(Kind K, SourceLocation Loc, + unsigned DiagID, + FunctionDecl *Fn, Sema &S) : S(S), Loc(Loc), DiagID(DiagID), Fn(Fn), ShowCallStack(K == K_ImmediateWithCallStack || K == K_Deferred) { switch (K) { @@ -1659,7 +1696,8 @@ Sema::DeviceDiagBuilder::DeviceDiagBuilder(Kind K, SourceLocation Loc, break; case K_Immediate: case K_ImmediateWithCallStack: - ImmediateDiag.emplace(S.Diag(Loc, DiagID)); + ImmediateDiag.emplace( + ImmediateDiagBuilder(S.Diags.Report(Loc, DiagID), S, DiagID)); break; case K_Deferred: assert(Fn && "Must have a function to attach the deferred diag to."); @@ -1670,7 +1708,7 @@ Sema::DeviceDiagBuilder::DeviceDiagBuilder(Kind K, SourceLocation Loc, } } -Sema::DeviceDiagBuilder::DeviceDiagBuilder(DeviceDiagBuilder &&D) +Sema::SemaDiagnosticBuilder::SemaDiagnosticBuilder(SemaDiagnosticBuilder &&D) : S(D.S), Loc(D.Loc), DiagID(D.DiagID), Fn(D.Fn), ShowCallStack(D.ShowCallStack), ImmediateDiag(D.ImmediateDiag), PartialDiagId(D.PartialDiagId) { @@ -1680,7 +1718,7 @@ Sema::DeviceDiagBuilder::DeviceDiagBuilder(DeviceDiagBuilder &&D) D.PartialDiagId.reset(); } -Sema::DeviceDiagBuilder::~DeviceDiagBuilder() { +Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() { if (ImmediateDiag) { // Emit our diagnostic and, if it was a warning or error, output a callstack // if Fn isn't a priori known-emitted. @@ -1695,7 +1733,8 @@ Sema::DeviceDiagBuilder::~DeviceDiagBuilder() { } } -Sema::DeviceDiagBuilder Sema::targetDiag(SourceLocation Loc, unsigned DiagID) { +Sema::SemaDiagnosticBuilder Sema::targetDiag(SourceLocation Loc, + unsigned DiagID) { if (LangOpts.OpenMP) return LangOpts.OpenMPIsDevice ? diagIfOpenMPDeviceCode(Loc, DiagID) : diagIfOpenMPHostCode(Loc, DiagID); @@ -1706,8 +1745,32 @@ Sema::DeviceDiagBuilder Sema::targetDiag(SourceLocation Loc, unsigned DiagID) { if (getLangOpts().SYCLIsDevice) return SYCLDiagIfDeviceCode(Loc, DiagID); - return DeviceDiagBuilder(DeviceDiagBuilder::K_Immediate, Loc, DiagID, - getCurFunctionDecl(), *this); + return SemaDiagnosticBuilder(SemaDiagnosticBuilder::K_Immediate, Loc, DiagID, + getCurFunctionDecl(), *this); +} + +Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, unsigned DiagID, + bool DeferHint) { + bool IsError = Diags.getDiagnosticIDs()->isDefaultMappingAsError(DiagID); + bool ShouldDefer = getLangOpts().CUDA && LangOpts.GPUDeferDiag && + DiagnosticIDs::isDeferrable(DiagID) && + (DeferHint || !IsError); + auto SetIsLastErrorImmediate = [&](bool Flag) { + if (IsError) + IsLastErrorImmediate = Flag; + }; + if (!ShouldDefer) { + SetIsLastErrorImmediate(true); + return SemaDiagnosticBuilder(SemaDiagnosticBuilder::K_Immediate, Loc, + DiagID, getCurFunctionDecl(), *this); + } + + SemaDiagnosticBuilder DB = + getLangOpts().CUDAIsDevice + ? CUDADiagIfDeviceCode(Loc, DiagID) + : CUDADiagIfHostCode(Loc, DiagID); + SetIsLastErrorImmediate(DB.isImmediate()); + return DB; } void Sema::checkDeviceDecl(const ValueDecl *D, SourceLocation Loc) { @@ -1732,6 +1795,15 @@ void Sema::checkDeviceDecl(const ValueDecl *D, SourceLocation Loc) { if (Ty->isDependentType()) return; + if (Ty->isExtIntType()) { + if (!Context.getTargetInfo().hasExtIntType()) { + targetDiag(Loc, diag::err_device_unsupported_type) + << D << false /*show bit size*/ << 0 /*bitsize*/ + << Ty << Context.getTargetInfo().getTriple().str(); + } + return; + } + if ((Ty->isFloat16Type() && !Context.getTargetInfo().hasFloat16Type()) || ((Ty->isFloat128Type() || (Ty->isRealFloatingType() && Context.getTypeSize(Ty) == 128)) && @@ -1739,7 +1811,8 @@ void Sema::checkDeviceDecl(const ValueDecl *D, SourceLocation Loc) { (Ty->isIntegerType() && Context.getTypeSize(Ty) == 128 && !Context.getTargetInfo().hasInt128Type())) { targetDiag(Loc, diag::err_device_unsupported_type) - << D << static_cast<unsigned>(Context.getTypeSize(Ty)) << Ty + << D << true /*show bit size*/ + << static_cast<unsigned>(Context.getTypeSize(Ty)) << Ty << Context.getTargetInfo().getTriple().str(); targetDiag(D->getLocation(), diag::note_defined_here) << D; } @@ -1768,7 +1841,7 @@ bool Sema::findMacroSpelling(SourceLocation &locref, StringRef name) { loc = getSourceManager().getExpansionLoc(loc); // If that's written with the name, stop here. - SmallVector<char, 16> buffer; + SmallString<16> buffer; if (getPreprocessor().getSpelling(loc, buffer) == name) { locref = loc; return true; diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index bd15b81cbed0..be30445d143c 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -1476,7 +1476,8 @@ void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *D) { } else if (FunctionDecl *FN = dyn_cast<FunctionDecl>(D)) { DC = FN; } else if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) { - DC = cast<DeclContext>(TD->getTemplatedDecl()); + if (isa<DeclContext>(TD->getTemplatedDecl())) + DC = cast<DeclContext>(TD->getTemplatedDecl()); } EffectiveContext EC(DC); diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index b354e810974c..6e441a0ded0d 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -48,28 +48,38 @@ Sema::PragmaStackSentinelRAII::~PragmaStackSentinelRAII() { } void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) { - // If there is no pack value, we don't need any attributes. - if (!PackStack.CurrentValue) + AlignPackInfo InfoVal = AlignPackStack.CurrentValue; + AlignPackInfo::Mode M = InfoVal.getAlignMode(); + bool IsPackSet = InfoVal.IsPackSet(); + bool IsXLPragma = getLangOpts().XLPragmaPack; + + // If we are not under mac68k/natural alignment mode and also there is no pack + // value, we don't need any attributes. + if (!IsPackSet && M != AlignPackInfo::Mac68k && M != AlignPackInfo::Natural) return; - // Otherwise, check to see if we need a max field alignment attribute. - if (unsigned Alignment = PackStack.CurrentValue) { - if (Alignment == Sema::kMac68kAlignmentSentinel) - RD->addAttr(AlignMac68kAttr::CreateImplicit(Context)); - else - RD->addAttr(MaxFieldAlignmentAttr::CreateImplicit(Context, - Alignment * 8)); + if (M == AlignPackInfo::Mac68k && (IsXLPragma || InfoVal.IsAlignAttr())) { + RD->addAttr(AlignMac68kAttr::CreateImplicit(Context)); + } else if (IsPackSet) { + // Check to see if we need a max field alignment attribute. + RD->addAttr(MaxFieldAlignmentAttr::CreateImplicit( + Context, InfoVal.getPackNumber() * 8)); } - if (PackIncludeStack.empty()) + + if (IsXLPragma && M == AlignPackInfo::Natural) + RD->addAttr(AlignNaturalAttr::CreateImplicit(Context)); + + if (AlignPackIncludeStack.empty()) return; - // The #pragma pack affected a record in an included file, so Clang should - // warn when that pragma was written in a file that included the included - // file. - for (auto &PackedInclude : llvm::reverse(PackIncludeStack)) { - if (PackedInclude.CurrentPragmaLocation != PackStack.CurrentPragmaLocation) + // The #pragma align/pack affected a record in an included file, so Clang + // should warn when that pragma was written in a file that included the + // included file. + for (auto &AlignPackedInclude : llvm::reverse(AlignPackIncludeStack)) { + if (AlignPackedInclude.CurrentPragmaLocation != + AlignPackStack.CurrentPragmaLocation) break; - if (PackedInclude.HasNonDefaultValue) - PackedInclude.ShouldWarnOnInclude = true; + if (AlignPackedInclude.HasNonDefaultValue) + AlignPackedInclude.ShouldWarnOnInclude = true; } } @@ -205,23 +215,27 @@ void Sema::inferGslOwnerPointerAttribute(CXXRecordDecl *Record) { void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, SourceLocation PragmaLoc) { PragmaMsStackAction Action = Sema::PSK_Reset; - unsigned Alignment = 0; + AlignPackInfo::Mode ModeVal = AlignPackInfo::Native; + switch (Kind) { - // For all targets we support native and natural are the same. + // For most of the platforms we support, native and natural are the same. + // With XL, native is the same as power, natural means something else. // // FIXME: This is not true on Darwin/PPC. case POAK_Native: case POAK_Power: + Action = Sema::PSK_Push_Set; + break; case POAK_Natural: Action = Sema::PSK_Push_Set; - Alignment = 0; + ModeVal = AlignPackInfo::Natural; break; // Note that '#pragma options align=packed' is not equivalent to attribute // packed, it has a different precedence relative to attribute aligned. case POAK_Packed: Action = Sema::PSK_Push_Set; - Alignment = 1; + ModeVal = AlignPackInfo::Packed; break; case POAK_Mac68k: @@ -231,15 +245,15 @@ void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, return; } Action = Sema::PSK_Push_Set; - Alignment = Sema::kMac68kAlignmentSentinel; + ModeVal = AlignPackInfo::Mac68k; break; - case POAK_Reset: // Reset just pops the top of the stack, or resets the current alignment to // default. Action = Sema::PSK_Pop; - if (PackStack.Stack.empty()) { - if (PackStack.CurrentValue) { + if (AlignPackStack.Stack.empty()) { + if (AlignPackStack.CurrentValue.getAlignMode() != AlignPackInfo::Native || + AlignPackStack.CurrentValue.IsPackAttr()) { Action = Sema::PSK_Reset; } else { Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed) @@ -250,7 +264,9 @@ void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, break; } - PackStack.Act(PragmaLoc, Action, StringRef(), Alignment); + AlignPackInfo Info(ModeVal, getLangOpts().XLPragmaPack); + + AlignPackStack.Act(PragmaLoc, Action, StringRef(), Info); } void Sema::ActOnPragmaClangSection(SourceLocation PragmaLoc, PragmaClangSectionAction Action, @@ -295,98 +311,129 @@ void Sema::ActOnPragmaClangSection(SourceLocation PragmaLoc, PragmaClangSectionA void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action, StringRef SlotLabel, Expr *alignment) { + bool IsXLPragma = getLangOpts().XLPragmaPack; + // XL pragma pack does not support identifier syntax. + if (IsXLPragma && !SlotLabel.empty()) { + Diag(PragmaLoc, diag::err_pragma_pack_identifer_not_supported); + return; + } + + const AlignPackInfo CurVal = AlignPackStack.CurrentValue; Expr *Alignment = static_cast<Expr *>(alignment); // If specified then alignment must be a "small" power of two. unsigned AlignmentVal = 0; + AlignPackInfo::Mode ModeVal = CurVal.getAlignMode(); + if (Alignment) { - llvm::APSInt Val; + Optional<llvm::APSInt> Val; + Val = Alignment->getIntegerConstantExpr(Context); // pack(0) is like pack(), which just works out since that is what // we use 0 for in PackAttr. - if (Alignment->isTypeDependent() || - Alignment->isValueDependent() || - !Alignment->isIntegerConstantExpr(Val, Context) || - !(Val == 0 || Val.isPowerOf2()) || - Val.getZExtValue() > 16) { + if (Alignment->isTypeDependent() || Alignment->isValueDependent() || !Val || + !(*Val == 0 || Val->isPowerOf2()) || Val->getZExtValue() > 16) { Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment); return; // Ignore } - AlignmentVal = (unsigned) Val.getZExtValue(); + if (IsXLPragma && *Val == 0) { + // pack(0) does not work out with XL. + Diag(PragmaLoc, diag::err_pragma_pack_invalid_alignment); + return; // Ignore + } + + AlignmentVal = (unsigned)Val->getZExtValue(); } + if (Action == Sema::PSK_Show) { // Show the current alignment, making sure to show the right value // for the default. // FIXME: This should come from the target. - AlignmentVal = PackStack.CurrentValue; - if (AlignmentVal == 0) - AlignmentVal = 8; - if (AlignmentVal == Sema::kMac68kAlignmentSentinel) + AlignmentVal = CurVal.IsPackSet() ? CurVal.getPackNumber() : 8; + if (ModeVal == AlignPackInfo::Mac68k && + (IsXLPragma || CurVal.IsAlignAttr())) Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k"; else Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal; } + // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack: // "#pragma pack(pop, identifier, n) is undefined" if (Action & Sema::PSK_Pop) { if (Alignment && !SlotLabel.empty()) Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifier_and_alignment); - if (PackStack.Stack.empty()) + if (AlignPackStack.Stack.empty()) { + assert(CurVal.getAlignMode() == AlignPackInfo::Native && + "Empty pack stack can only be at Native alignment mode."); Diag(PragmaLoc, diag::warn_pragma_pop_failed) << "pack" << "stack empty"; + } } - PackStack.Act(PragmaLoc, Action, SlotLabel, AlignmentVal); + AlignPackInfo Info(ModeVal, AlignmentVal, IsXLPragma); + + AlignPackStack.Act(PragmaLoc, Action, SlotLabel, Info); } -void Sema::DiagnoseNonDefaultPragmaPack(PragmaPackDiagnoseKind Kind, - SourceLocation IncludeLoc) { - if (Kind == PragmaPackDiagnoseKind::NonDefaultStateAtInclude) { - SourceLocation PrevLocation = PackStack.CurrentPragmaLocation; +void Sema::DiagnoseNonDefaultPragmaAlignPack(PragmaAlignPackDiagnoseKind Kind, + SourceLocation IncludeLoc) { + if (Kind == PragmaAlignPackDiagnoseKind::NonDefaultStateAtInclude) { + SourceLocation PrevLocation = AlignPackStack.CurrentPragmaLocation; // Warn about non-default alignment at #includes (without redundant // warnings for the same directive in nested includes). // The warning is delayed until the end of the file to avoid warnings // for files that don't have any records that are affected by the modified // alignment. bool HasNonDefaultValue = - PackStack.hasValue() && - (PackIncludeStack.empty() || - PackIncludeStack.back().CurrentPragmaLocation != PrevLocation); - PackIncludeStack.push_back( - {PackStack.CurrentValue, - PackStack.hasValue() ? PrevLocation : SourceLocation(), + AlignPackStack.hasValue() && + (AlignPackIncludeStack.empty() || + AlignPackIncludeStack.back().CurrentPragmaLocation != PrevLocation); + AlignPackIncludeStack.push_back( + {AlignPackStack.CurrentValue, + AlignPackStack.hasValue() ? PrevLocation : SourceLocation(), HasNonDefaultValue, /*ShouldWarnOnInclude*/ false}); return; } - assert(Kind == PragmaPackDiagnoseKind::ChangedStateAtExit && "invalid kind"); - PackIncludeState PrevPackState = PackIncludeStack.pop_back_val(); - if (PrevPackState.ShouldWarnOnInclude) { + assert(Kind == PragmaAlignPackDiagnoseKind::ChangedStateAtExit && + "invalid kind"); + AlignPackIncludeState PrevAlignPackState = + AlignPackIncludeStack.pop_back_val(); + // FIXME: AlignPackStack may contain both #pragma align and #pragma pack + // information, diagnostics below might not be accurate if we have mixed + // pragmas. + if (PrevAlignPackState.ShouldWarnOnInclude) { // Emit the delayed non-default alignment at #include warning. Diag(IncludeLoc, diag::warn_pragma_pack_non_default_at_include); - Diag(PrevPackState.CurrentPragmaLocation, diag::note_pragma_pack_here); + Diag(PrevAlignPackState.CurrentPragmaLocation, diag::note_pragma_pack_here); } // Warn about modified alignment after #includes. - if (PrevPackState.CurrentValue != PackStack.CurrentValue) { + if (PrevAlignPackState.CurrentValue != AlignPackStack.CurrentValue) { Diag(IncludeLoc, diag::warn_pragma_pack_modified_after_include); - Diag(PackStack.CurrentPragmaLocation, diag::note_pragma_pack_here); + Diag(AlignPackStack.CurrentPragmaLocation, diag::note_pragma_pack_here); } } -void Sema::DiagnoseUnterminatedPragmaPack() { - if (PackStack.Stack.empty()) +void Sema::DiagnoseUnterminatedPragmaAlignPack() { + if (AlignPackStack.Stack.empty()) return; bool IsInnermost = true; - for (const auto &StackSlot : llvm::reverse(PackStack.Stack)) { + + // FIXME: AlignPackStack may contain both #pragma align and #pragma pack + // information, diagnostics below might not be accurate if we have mixed + // pragmas. + for (const auto &StackSlot : llvm::reverse(AlignPackStack.Stack)) { Diag(StackSlot.PragmaPushLocation, diag::warn_pragma_pack_no_pop_eof); // The user might have already reset the alignment, so suggest replacing // the reset with a pop. - if (IsInnermost && PackStack.CurrentValue == PackStack.DefaultValue) { - DiagnosticBuilder DB = Diag(PackStack.CurrentPragmaLocation, - diag::note_pragma_pack_pop_instead_reset); - SourceLocation FixItLoc = Lexer::findLocationAfterToken( - PackStack.CurrentPragmaLocation, tok::l_paren, SourceMgr, LangOpts, - /*SkipTrailing=*/false); + if (IsInnermost && + AlignPackStack.CurrentValue == AlignPackStack.DefaultValue) { + auto DB = Diag(AlignPackStack.CurrentPragmaLocation, + diag::note_pragma_pack_pop_instead_reset); + SourceLocation FixItLoc = + Lexer::findLocationAfterToken(AlignPackStack.CurrentPragmaLocation, + tok::l_paren, SourceMgr, LangOpts, + /*SkipTrailing=*/false); if (FixItLoc.isValid()) DB << FixItHint::CreateInsertion(FixItLoc, "pop"); } @@ -417,10 +464,7 @@ void Sema::ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name, void Sema::ActOnPragmaFloatControl(SourceLocation Loc, PragmaMsStackAction Action, PragmaFloatControlKind Value) { - unsigned NewValue = FpPragmaStack.hasValue() - ? FpPragmaStack.CurrentValue - : CurFPFeatureOverrides().getAsOpaqueInt(); - FPOptionsOverride NewFPFeatures(NewValue); + FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); if ((Action == PSK_Push_Set || Action == PSK_Push || Action == PSK_Pop) && !(CurContext->isTranslationUnit()) && !CurContext->isNamespace()) { // Push and pop can only occur at file or namespace scope. @@ -432,8 +476,7 @@ void Sema::ActOnPragmaFloatControl(SourceLocation Loc, llvm_unreachable("invalid pragma float_control kind"); case PFC_Precise: NewFPFeatures.setFPPreciseEnabled(true); - NewValue = NewFPFeatures.getAsOpaqueInt(); - FpPragmaStack.Act(Loc, Action, StringRef(), NewValue); + FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures); break; case PFC_NoPrecise: if (CurFPFeatures.getFPExceptionMode() == LangOptions::FPE_Strict) @@ -442,25 +485,21 @@ void Sema::ActOnPragmaFloatControl(SourceLocation Loc, Diag(Loc, diag::err_pragma_fc_noprecise_requires_nofenv); else NewFPFeatures.setFPPreciseEnabled(false); - NewValue = NewFPFeatures.getAsOpaqueInt(); - FpPragmaStack.Act(Loc, Action, StringRef(), NewValue); + FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures); break; case PFC_Except: if (!isPreciseFPEnabled()) Diag(Loc, diag::err_pragma_fc_except_requires_precise); else NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Strict); - NewValue = NewFPFeatures.getAsOpaqueInt(); - FpPragmaStack.Act(Loc, Action, StringRef(), NewValue); + FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures); break; case PFC_NoExcept: NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Ignore); - NewValue = NewFPFeatures.getAsOpaqueInt(); - FpPragmaStack.Act(Loc, Action, StringRef(), NewValue); + FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures); break; case PFC_Push: - FpPragmaStack.Act(Loc, Sema::PSK_Push_Set, StringRef(), - NewFPFeatures.getAsOpaqueInt()); + FpPragmaStack.Act(Loc, Sema::PSK_Push_Set, StringRef(), NewFPFeatures); break; case PFC_Pop: if (FpPragmaStack.Stack.empty()) { @@ -468,14 +507,11 @@ void Sema::ActOnPragmaFloatControl(SourceLocation Loc, << "stack empty"; return; } - FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures.getAsOpaqueInt()); - NewValue = FpPragmaStack.CurrentValue; + FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures); + NewFPFeatures = FpPragmaStack.CurrentValue; break; } - FPOptionsOverride NewOverrides; - if (NewValue != FpPragmaStack.DefaultValue) - NewOverrides.getFromOpaqueInt(NewValue); - CurFPFeatures = NewOverrides.applyOverrides(getLangOpts()); + CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); } void Sema::ActOnPragmaMSPointersToMembers( @@ -494,9 +530,70 @@ void Sema::ActOnPragmaMSVtorDisp(PragmaMsStackAction Action, VtorDispStack.Act(PragmaLoc, Action, StringRef(), Mode); } -bool Sema::UnifySection(StringRef SectionName, - int SectionFlags, - DeclaratorDecl *Decl) { +template <> +void Sema::PragmaStack<Sema::AlignPackInfo>::Act(SourceLocation PragmaLocation, + PragmaMsStackAction Action, + llvm::StringRef StackSlotLabel, + AlignPackInfo Value) { + if (Action == PSK_Reset) { + CurrentValue = DefaultValue; + CurrentPragmaLocation = PragmaLocation; + return; + } + if (Action & PSK_Push) + Stack.emplace_back(Slot(StackSlotLabel, CurrentValue, CurrentPragmaLocation, + PragmaLocation)); + else if (Action & PSK_Pop) { + if (!StackSlotLabel.empty()) { + // If we've got a label, try to find it and jump there. + auto I = llvm::find_if(llvm::reverse(Stack), [&](const Slot &x) { + return x.StackSlotLabel == StackSlotLabel; + }); + // We found the label, so pop from there. + if (I != Stack.rend()) { + CurrentValue = I->Value; + CurrentPragmaLocation = I->PragmaLocation; + Stack.erase(std::prev(I.base()), Stack.end()); + } + } else if (Value.IsXLStack() && Value.IsAlignAttr() && + CurrentValue.IsPackAttr()) { + // XL '#pragma align(reset)' would pop the stack until + // a current in effect pragma align is popped. + auto I = llvm::find_if(llvm::reverse(Stack), [&](const Slot &x) { + return x.Value.IsAlignAttr(); + }); + // If we found pragma align so pop from there. + if (I != Stack.rend()) { + Stack.erase(std::prev(I.base()), Stack.end()); + if (Stack.empty()) { + CurrentValue = DefaultValue; + CurrentPragmaLocation = PragmaLocation; + } else { + CurrentValue = Stack.back().Value; + CurrentPragmaLocation = Stack.back().PragmaLocation; + Stack.pop_back(); + } + } + } else if (!Stack.empty()) { + // xl '#pragma align' sets the baseline, and `#pragma pack` cannot pop + // over the baseline. + if (Value.IsXLStack() && Value.IsPackAttr() && CurrentValue.IsAlignAttr()) + return; + + // We don't have a label, just pop the last entry. + CurrentValue = Stack.back().Value; + CurrentPragmaLocation = Stack.back().PragmaLocation; + Stack.pop_back(); + } + } + if (Action & PSK_Set) { + CurrentValue = Value; + CurrentPragmaLocation = PragmaLocation; + } +} + +bool Sema::UnifySection(StringRef SectionName, int SectionFlags, + NamedDecl *Decl) { SourceLocation PragmaLocation; if (auto A = Decl->getAttr<SectionAttr>()) if (A->isImplicit()) @@ -968,10 +1065,7 @@ void Sema::ActOnPragmaVisibility(const IdentifierInfo* VisType, void Sema::ActOnPragmaFPContract(SourceLocation Loc, LangOptions::FPModeKind FPC) { - unsigned NewValue = FpPragmaStack.hasValue() - ? FpPragmaStack.CurrentValue - : CurFPFeatureOverrides().getAsOpaqueInt(); - FPOptionsOverride NewFPFeatures(NewValue); + FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); switch (FPC) { case LangOptions::FPM_On: NewFPFeatures.setAllowFPContractWithinStatement(); @@ -982,54 +1076,45 @@ void Sema::ActOnPragmaFPContract(SourceLocation Loc, case LangOptions::FPM_Off: NewFPFeatures.setDisallowFPContract(); break; + case LangOptions::FPM_FastHonorPragmas: + llvm_unreachable("Should not happen"); } + FpPragmaStack.Act(Loc, Sema::PSK_Set, StringRef(), NewFPFeatures); CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); - FpPragmaStack.Act(Loc, Sema::PSK_Set, StringRef(), - NewFPFeatures.getAsOpaqueInt()); } void Sema::ActOnPragmaFPReassociate(SourceLocation Loc, bool IsEnabled) { - unsigned NewValue = FpPragmaStack.hasValue() - ? FpPragmaStack.CurrentValue - : CurFPFeatureOverrides().getAsOpaqueInt(); - FPOptionsOverride NewFPFeatures(NewValue); + FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); NewFPFeatures.setAllowFPReassociateOverride(IsEnabled); - NewValue = NewFPFeatures.getAsOpaqueInt(); - FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewValue); - FPOptionsOverride NewOverrides(NewValue); - CurFPFeatures = NewOverrides.applyOverrides(getLangOpts()); + FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); + CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); } void Sema::setRoundingMode(SourceLocation Loc, llvm::RoundingMode FPR) { - unsigned NewValue = FpPragmaStack.hasValue() - ? FpPragmaStack.CurrentValue - : CurFPFeatureOverrides().getAsOpaqueInt(); - FPOptionsOverride NewFPFeatures(NewValue); + // C2x: 7.6.2p3 If the FE_DYNAMIC mode is specified and FENV_ACCESS is "off", + // the translator may assume that the default rounding mode is in effect. + if (FPR == llvm::RoundingMode::Dynamic && + !CurFPFeatures.getAllowFEnvAccess() && + CurFPFeatures.getFPExceptionMode() == LangOptions::FPE_Ignore) + FPR = llvm::RoundingMode::NearestTiesToEven; + + FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); NewFPFeatures.setRoundingModeOverride(FPR); - NewValue = NewFPFeatures.getAsOpaqueInt(); - FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewValue); - FPOptionsOverride NewOverrides(NewValue); - CurFPFeatures = NewOverrides.applyOverrides(getLangOpts()); + FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); + CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); } void Sema::setExceptionMode(SourceLocation Loc, LangOptions::FPExceptionModeKind FPE) { - unsigned NewValue = FpPragmaStack.hasValue() - ? FpPragmaStack.CurrentValue - : CurFPFeatureOverrides().getAsOpaqueInt(); - FPOptionsOverride NewFPFeatures(NewValue); + FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); NewFPFeatures.setFPExceptionModeOverride(FPE); - NewValue = NewFPFeatures.getAsOpaqueInt(); - FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewValue); - FPOptionsOverride NewOverrides(NewValue); - CurFPFeatures = NewOverrides.applyOverrides(getLangOpts()); + FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); + CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); } void Sema::ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled) { - unsigned NewValue = FpPragmaStack.hasValue() - ? FpPragmaStack.CurrentValue - : CurFPFeatureOverrides().getAsOpaqueInt(); - FPOptionsOverride NewFPFeatures(NewValue); + FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); + auto LO = getLangOpts(); if (IsEnabled) { // Verify Microsoft restriction: // You can't enable fenv_access unless precise semantics are enabled. @@ -1038,12 +1123,20 @@ void Sema::ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled) { if (!isPreciseFPEnabled()) Diag(Loc, diag::err_pragma_fenv_requires_precise); NewFPFeatures.setAllowFEnvAccessOverride(true); - } else + // Enabling FENV access sets the RoundingMode to Dynamic. + // and ExceptionBehavior to Strict + NewFPFeatures.setRoundingModeOverride(llvm::RoundingMode::Dynamic); + NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Strict); + } else { NewFPFeatures.setAllowFEnvAccessOverride(false); - NewValue = NewFPFeatures.getAsOpaqueInt(); - FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewValue); - FPOptionsOverride NewOverrides(NewValue); - CurFPFeatures = NewOverrides.applyOverrides(getLangOpts()); + } + FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); + CurFPFeatures = NewFPFeatures.applyOverrides(LO); +} + +void Sema::ActOnPragmaFPExceptions(SourceLocation Loc, + LangOptions::FPExceptionModeKind FPE) { + setExceptionMode(Loc, FPE); } void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr, diff --git a/clang/lib/Sema/SemaCUDA.cpp b/clang/lib/Sema/SemaCUDA.cpp index 283a04683a32..ee91eb4c5deb 100644 --- a/clang/lib/Sema/SemaCUDA.cpp +++ b/clang/lib/Sema/SemaCUDA.cpp @@ -123,7 +123,8 @@ Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D, return CFT_Device; } else if (hasAttr<CUDAHostAttr>(D, IgnoreImplicitHDAttr)) { return CFT_Host; - } else if (D->isImplicit() && !IgnoreImplicitHDAttr) { + } else if ((D->isImplicit() || !D->isUserProvided()) && + !IgnoreImplicitHDAttr) { // Some implicit declarations (like intrinsic functions) are not marked. // Set the most lenient target on them for maximal flexibility. return CFT_HostDevice; @@ -519,7 +520,6 @@ void Sema::checkAllowedCUDAInitializer(VarDecl *VD) { VD->hasAttr<CUDASharedAttr>()) { if (LangOpts.GPUAllowDeviceInit) return; - assert(!VD->isStaticLocal() || VD->hasAttr<CUDASharedAttr>()); bool AllowedInit = false; if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(Init)) AllowedInit = @@ -639,58 +639,63 @@ void Sema::MaybeAddCUDAConstantAttr(VarDecl *VD) { } } -Sema::DeviceDiagBuilder Sema::CUDADiagIfDeviceCode(SourceLocation Loc, - unsigned DiagID) { +Sema::SemaDiagnosticBuilder Sema::CUDADiagIfDeviceCode(SourceLocation Loc, + unsigned DiagID) { assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); - DeviceDiagBuilder::Kind DiagKind = [this] { + SemaDiagnosticBuilder::Kind DiagKind = [&] { + if (!isa<FunctionDecl>(CurContext)) + return SemaDiagnosticBuilder::K_Nop; switch (CurrentCUDATarget()) { case CFT_Global: case CFT_Device: - return DeviceDiagBuilder::K_Immediate; + return SemaDiagnosticBuilder::K_Immediate; case CFT_HostDevice: // An HD function counts as host code if we're compiling for host, and // device code if we're compiling for device. Defer any errors in device // mode until the function is known-emitted. - if (getLangOpts().CUDAIsDevice) { - return (getEmissionStatus(cast<FunctionDecl>(CurContext)) == - FunctionEmissionStatus::Emitted) - ? DeviceDiagBuilder::K_ImmediateWithCallStack - : DeviceDiagBuilder::K_Deferred; - } - return DeviceDiagBuilder::K_Nop; - + if (!getLangOpts().CUDAIsDevice) + return SemaDiagnosticBuilder::K_Nop; + if (IsLastErrorImmediate && Diags.getDiagnosticIDs()->isBuiltinNote(DiagID)) + return SemaDiagnosticBuilder::K_Immediate; + return (getEmissionStatus(cast<FunctionDecl>(CurContext)) == + FunctionEmissionStatus::Emitted) + ? SemaDiagnosticBuilder::K_ImmediateWithCallStack + : SemaDiagnosticBuilder::K_Deferred; default: - return DeviceDiagBuilder::K_Nop; + return SemaDiagnosticBuilder::K_Nop; } }(); - return DeviceDiagBuilder(DiagKind, Loc, DiagID, - dyn_cast<FunctionDecl>(CurContext), *this); + return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, + dyn_cast<FunctionDecl>(CurContext), *this); } -Sema::DeviceDiagBuilder Sema::CUDADiagIfHostCode(SourceLocation Loc, - unsigned DiagID) { +Sema::SemaDiagnosticBuilder Sema::CUDADiagIfHostCode(SourceLocation Loc, + unsigned DiagID) { assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); - DeviceDiagBuilder::Kind DiagKind = [this] { + SemaDiagnosticBuilder::Kind DiagKind = [&] { + if (!isa<FunctionDecl>(CurContext)) + return SemaDiagnosticBuilder::K_Nop; switch (CurrentCUDATarget()) { case CFT_Host: - return DeviceDiagBuilder::K_Immediate; + return SemaDiagnosticBuilder::K_Immediate; case CFT_HostDevice: // An HD function counts as host code if we're compiling for host, and // device code if we're compiling for device. Defer any errors in device // mode until the function is known-emitted. if (getLangOpts().CUDAIsDevice) - return DeviceDiagBuilder::K_Nop; - + return SemaDiagnosticBuilder::K_Nop; + if (IsLastErrorImmediate && Diags.getDiagnosticIDs()->isBuiltinNote(DiagID)) + return SemaDiagnosticBuilder::K_Immediate; return (getEmissionStatus(cast<FunctionDecl>(CurContext)) == FunctionEmissionStatus::Emitted) - ? DeviceDiagBuilder::K_ImmediateWithCallStack - : DeviceDiagBuilder::K_Deferred; + ? SemaDiagnosticBuilder::K_ImmediateWithCallStack + : SemaDiagnosticBuilder::K_Deferred; default: - return DeviceDiagBuilder::K_Nop; + return SemaDiagnosticBuilder::K_Nop; } }(); - return DeviceDiagBuilder(DiagKind, Loc, DiagID, - dyn_cast<FunctionDecl>(CurContext), *this); + return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, + dyn_cast<FunctionDecl>(CurContext), *this); } bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) { @@ -711,24 +716,24 @@ bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) { // Otherwise, mark the call in our call graph so we can traverse it later. bool CallerKnownEmitted = getEmissionStatus(Caller) == FunctionEmissionStatus::Emitted; - DeviceDiagBuilder::Kind DiagKind = [this, Caller, Callee, - CallerKnownEmitted] { + SemaDiagnosticBuilder::Kind DiagKind = [this, Caller, Callee, + CallerKnownEmitted] { switch (IdentifyCUDAPreference(Caller, Callee)) { case CFP_Never: - return DeviceDiagBuilder::K_Immediate; case CFP_WrongSide: - assert(Caller && "WrongSide calls require a non-null caller"); + assert(Caller && "Never/wrongSide calls require a non-null caller"); // If we know the caller will be emitted, we know this wrong-side call // will be emitted, so it's an immediate error. Otherwise, defer the // error until we know the caller is emitted. - return CallerKnownEmitted ? DeviceDiagBuilder::K_ImmediateWithCallStack - : DeviceDiagBuilder::K_Deferred; + return CallerKnownEmitted + ? SemaDiagnosticBuilder::K_ImmediateWithCallStack + : SemaDiagnosticBuilder::K_Deferred; default: - return DeviceDiagBuilder::K_Nop; + return SemaDiagnosticBuilder::K_Nop; } }(); - if (DiagKind == DeviceDiagBuilder::K_Nop) + if (DiagKind == SemaDiagnosticBuilder::K_Nop) return true; // Avoid emitting this error twice for the same location. Using a hashtable @@ -738,13 +743,15 @@ bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) { if (!LocsWithCUDACallDiags.insert({Caller, Loc}).second) return true; - DeviceDiagBuilder(DiagKind, Loc, diag::err_ref_bad_target, Caller, *this) - << IdentifyCUDATarget(Callee) << Callee << IdentifyCUDATarget(Caller); - DeviceDiagBuilder(DiagKind, Callee->getLocation(), diag::note_previous_decl, - Caller, *this) - << Callee; - return DiagKind != DeviceDiagBuilder::K_Immediate && - DiagKind != DeviceDiagBuilder::K_ImmediateWithCallStack; + SemaDiagnosticBuilder(DiagKind, Loc, diag::err_ref_bad_target, Caller, *this) + << IdentifyCUDATarget(Callee) << /*function*/ 0 << Callee + << IdentifyCUDATarget(Caller); + if (!Callee->getBuiltinID()) + SemaDiagnosticBuilder(DiagKind, Callee->getLocation(), + diag::note_previous_decl, Caller, *this) + << Callee; + return DiagKind != SemaDiagnosticBuilder::K_Immediate && + DiagKind != SemaDiagnosticBuilder::K_ImmediateWithCallStack; } // Check the wrong-sided reference capture of lambda for CUDA/HIP. @@ -781,14 +788,14 @@ void Sema::CUDACheckLambdaCapture(CXXMethodDecl *Callee, bool ShouldCheck = CalleeIsDevice && CallerIsHost; if (!ShouldCheck || !Capture.isReferenceCapture()) return; - auto DiagKind = DeviceDiagBuilder::K_Deferred; + auto DiagKind = SemaDiagnosticBuilder::K_Deferred; if (Capture.isVariableCapture()) { - DeviceDiagBuilder(DiagKind, Capture.getLocation(), - diag::err_capture_bad_target, Callee, *this) + SemaDiagnosticBuilder(DiagKind, Capture.getLocation(), + diag::err_capture_bad_target, Callee, *this) << Capture.getVariable(); } else if (Capture.isThisCapture()) { - DeviceDiagBuilder(DiagKind, Capture.getLocation(), - diag::err_capture_bad_target_this_ptr, Callee, *this); + SemaDiagnosticBuilder(DiagKind, Capture.getLocation(), + diag::err_capture_bad_target_this_ptr, Callee, *this); } return; } diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index 2efe26052c78..671820afd485 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -105,10 +105,10 @@ namespace { // If this is an unbridged cast, wrap the result in an implicit // cast that yields the unbridged-cast placeholder type. if (IsARCUnbridgedCast) { - castExpr = ImplicitCastExpr::Create(Self.Context, - Self.Context.ARCUnbridgedCastTy, - CK_Dependent, castExpr, nullptr, - castExpr->getValueKind()); + castExpr = ImplicitCastExpr::Create( + Self.Context, Self.Context.ARCUnbridgedCastTy, CK_Dependent, + castExpr, nullptr, castExpr->getValueKind(), + Self.CurFPFeatureOverrides()); } updatePartOfExplicitCastFlags(castExpr); return castExpr; @@ -361,11 +361,10 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, DiscardMisalignedMemberAddress(DestType.getTypePtr(), E); } - return Op.complete(CXXStaticCastExpr::Create(Context, Op.ResultType, - Op.ValueKind, Op.Kind, Op.SrcExpr.get(), - &Op.BasePath, DestTInfo, - OpLoc, Parens.getEnd(), - AngleBrackets)); + return Op.complete(CXXStaticCastExpr::Create( + Context, Op.ResultType, Op.ValueKind, Op.Kind, Op.SrcExpr.get(), + &Op.BasePath, DestTInfo, CurFPFeatureOverrides(), OpLoc, + Parens.getEnd(), AngleBrackets)); } } } @@ -510,12 +509,10 @@ static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType, if (RecFrom && RecTo) { auto DeclFrom = RecFrom->getAsCXXRecordDecl(); if (!DeclFrom->isCompleteDefinition()) - S.Diag(DeclFrom->getLocation(), diag::note_type_incomplete) - << DeclFrom->getDeclName(); + S.Diag(DeclFrom->getLocation(), diag::note_type_incomplete) << DeclFrom; auto DeclTo = RecTo->getAsCXXRecordDecl(); if (!DeclTo->isCompleteDefinition()) - S.Diag(DeclTo->getLocation(), diag::note_type_incomplete) - << DeclTo->getDeclName(); + S.Diag(DeclTo->getLocation(), diag::note_type_incomplete) << DeclTo; } } } @@ -892,6 +889,18 @@ void CastOperation::CheckDynamicCast() { return; } + // Warns when dynamic_cast is used with RTTI data disabled. + if (!Self.getLangOpts().RTTIData) { + bool MicrosoftABI = + Self.getASTContext().getTargetInfo().getCXXABI().isMicrosoft(); + bool isClangCL = Self.getDiagnostics().getDiagnosticOptions().getFormat() == + DiagnosticOptions::MSVC; + if (MicrosoftABI || !DestPointee->isVoidType()) + Self.Diag(OpRange.getBegin(), + diag::warn_no_dynamic_cast_with_rtti_disabled) + << isClangCL; + } + // Done. Everything else is run-time checks. Kind = CK_Dynamic; } @@ -1245,7 +1254,13 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, return TC_Failed; } if (SrcType->isIntegralOrEnumerationType()) { - Kind = CK_IntegralCast; + // [expr.static.cast]p10 If the enumeration type has a fixed underlying + // type, the value is first converted to that type by integral conversion + const EnumType *Enum = DestType->getAs<EnumType>(); + Kind = Enum->getDecl()->isFixed() && + Enum->getDecl()->getIntegerType()->isBooleanType() + ? CK_IntegralToBoolean + : CK_IntegralCast; return TC_Success; } else if (SrcType->isRealFloatingType()) { Kind = CK_FloatingToIntegral; @@ -2204,6 +2219,12 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, bool destIsVector = DestType->isVectorType(); bool srcIsVector = SrcType->isVectorType(); if (srcIsVector || destIsVector) { + // Allow bitcasting between SVE VLATs and VLSTs, and vice-versa. + if (Self.isValidSveBitcast(SrcType, DestType)) { + Kind = CK_BitCast; + return TC_Success; + } + // The non-vector type, if any, must have integral type. This is // the same rule that C vector casts use; note, however, that enum // types are not integral in C++. @@ -2659,6 +2680,8 @@ static void DiagnoseBadFunctionCast(Sema &Self, const ExprResult &SrcExpr, return; if (SrcType->isComplexIntegerType() && DestType->isComplexIntegerType()) return; + if (SrcType->isFixedPointType() && DestType->isFixedPointType()) + return; Self.Diag(SrcExpr.get()->getExprLoc(), diag::warn_bad_function_cast) @@ -2690,6 +2713,17 @@ void CastOperation::CheckCStyleCast() { return; } + // If the type is dependent, we won't do any other semantic analysis now. + if (Self.getASTContext().isDependenceAllowed() && + (DestType->isDependentType() || SrcExpr.get()->isTypeDependent() || + SrcExpr.get()->isValueDependent())) { + assert((DestType->containsErrors() || SrcExpr.get()->containsErrors() || + SrcExpr.get()->containsErrors()) && + "should only occur in error-recovery path."); + assert(Kind == CK_Dependent); + return; + } + // Overloads are allowed with C extensions, so we need to support them. if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { DeclAccessPair DAP; @@ -2724,6 +2758,13 @@ void CastOperation::CheckCStyleCast() { return; } + // Allow bitcasting between compatible SVE vector types. + if ((SrcType->isVectorType() || DestType->isVectorType()) && + Self.isValidSveBitcast(SrcType, DestType)) { + Kind = CK_BitCast; + return; + } + if (!DestType->isScalarType() && !DestType->isVectorType()) { const RecordType *DestRecordTy = DestType->getAs<RecordType>(); @@ -3027,9 +3068,9 @@ ExprResult Sema::BuildCStyleCastExpr(SourceLocation LPLoc, // -Wcast-qual DiagnoseCastQual(Op.Self, Op.SrcExpr, Op.DestType); - return Op.complete(CStyleCastExpr::Create(Context, Op.ResultType, - Op.ValueKind, Op.Kind, Op.SrcExpr.get(), - &Op.BasePath, CastTypeInfo, LPLoc, RPLoc)); + return Op.complete(CStyleCastExpr::Create( + Context, Op.ResultType, Op.ValueKind, Op.Kind, Op.SrcExpr.get(), + &Op.BasePath, CurFPFeatureOverrides(), CastTypeInfo, LPLoc, RPLoc)); } ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo, @@ -3052,7 +3093,7 @@ ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo, if (auto *ConstructExpr = dyn_cast<CXXConstructExpr>(SubExpr)) ConstructExpr->setParenOrBraceRange(SourceRange(LPLoc, RPLoc)); - return Op.complete(CXXFunctionalCastExpr::Create(Context, Op.ResultType, - Op.ValueKind, CastTypeInfo, Op.Kind, - Op.SrcExpr.get(), &Op.BasePath, LPLoc, RPLoc)); + return Op.complete(CXXFunctionalCastExpr::Create( + Context, Op.ResultType, Op.ValueKind, CastTypeInfo, Op.Kind, + Op.SrcExpr.get(), &Op.BasePath, CurFPFeatureOverrides(), LPLoc, RPLoc)); } diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 509d88e25000..2d3d36f4adad 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -75,6 +75,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSet.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/AtomicOrdering.h" @@ -1274,11 +1275,8 @@ static bool SemaBuiltinPipePackets(Sema &S, CallExpr *Call) { // \return True if a semantic error has been found, false otherwise. static bool SemaOpenCLBuiltinToAddr(Sema &S, unsigned BuiltinID, CallExpr *Call) { - if (Call->getNumArgs() != 1) { - S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_to_addr_arg_num) - << Call->getDirectCallee() << Call->getSourceRange(); + if (checkArgCount(S, Call, 1)) return true; - } auto RT = Call->getArg(0)->getType(); if (!RT->isPointerType() || RT->getPointeeType() @@ -1425,6 +1423,7 @@ bool Sema::CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, case llvm::Triple::x86_64: return CheckX86BuiltinFunctionCall(TI, BuiltinID, TheCall); case llvm::Triple::ppc: + case llvm::Triple::ppcle: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: return CheckPPCBuiltinFunctionCall(TI, BuiltinID, TheCall); @@ -1573,15 +1572,14 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, if (SemaBuiltinSetjmp(TheCall)) return ExprError(); break; - case Builtin::BI_setjmp: - case Builtin::BI_setjmpex: - if (checkArgCount(*this, TheCall, 1)) - return true; - break; case Builtin::BI__builtin_classify_type: if (checkArgCount(*this, TheCall, 1)) return true; TheCall->setType(Context.IntTy); break; + case Builtin::BI__builtin_complex: + if (SemaBuiltinComplex(TheCall)) + return ExprError(); + break; case Builtin::BI__builtin_constant_p: { if (checkArgCount(*this, TheCall, 1)) return true; ExprResult Arg = DefaultFunctionArrayLvalueConversion(TheCall->getArg(0)); @@ -1818,8 +1816,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, SmallVector<PartialDiagnosticAt, 8> Notes; Expr::EvalResult Eval; Eval.Diag = &Notes; - if ((!ProbArg->EvaluateAsConstantExpr(Eval, Expr::EvaluateForCodeGen, - Context)) || + if ((!ProbArg->EvaluateAsConstantExpr(Eval, Context)) || !Eval.Val.isFloat()) { Diag(ProbArg->getBeginLoc(), diag::err_probability_not_constant_float) << ProbArg->getSourceRange(); @@ -1946,7 +1943,8 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, // -Wframe-address warning if non-zero passed to builtin // return/frame address. Expr::EvalResult Result; - if (TheCall->getArg(0)->EvaluateAsInt(Result, getASTContext()) && + if (!TheCall->getArg(0)->isValueDependent() && + TheCall->getArg(0)->EvaluateAsInt(Result, getASTContext()) && Result.Val.getInt() != 0) Diag(TheCall->getBeginLoc(), diag::warn_frame_address) << ((BuiltinID == Builtin::BI__builtin_return_address) @@ -2284,10 +2282,7 @@ bool Sema::CheckARMCoprocessorImmediate(const TargetInfo &TI, if (CoprocArg->isTypeDependent() || CoprocArg->isValueDependent()) return false; - llvm::APSInt CoprocNoAP; - bool IsICE = CoprocArg->isIntegerConstantExpr(CoprocNoAP, Context); - (void)IsICE; - assert(IsICE && "Coprocossor immediate is not a constant expression"); + llvm::APSInt CoprocNoAP = *CoprocArg->getIntegerConstantExpr(Context); int64_t CoprocNo = CoprocNoAP.getExtValue(); assert(CoprocNo >= 0 && "Coprocessor immediate must be non-negative"); @@ -2559,54 +2554,164 @@ bool Sema::CheckAArch64BuiltinFunctionCall(const TargetInfo &TI, return SemaBuiltinConstantArgRange(TheCall, i, l, u + l); } -bool Sema::CheckBPFBuiltinFunctionCall(unsigned BuiltinID, - CallExpr *TheCall) { - assert((BuiltinID == BPF::BI__builtin_preserve_field_info || - BuiltinID == BPF::BI__builtin_btf_type_id) && - "unexpected ARM builtin"); +static bool isValidBPFPreserveFieldInfoArg(Expr *Arg) { + if (Arg->getType()->getAsPlaceholderType()) + return false; - if (checkArgCount(*this, TheCall, 2)) + // The first argument needs to be a record field access. + // If it is an array element access, we delay decision + // to BPF backend to check whether the access is a + // field access or not. + return (Arg->IgnoreParens()->getObjectKind() == OK_BitField || + dyn_cast<MemberExpr>(Arg->IgnoreParens()) || + dyn_cast<ArraySubscriptExpr>(Arg->IgnoreParens())); +} + +static bool isEltOfVectorTy(ASTContext &Context, CallExpr *Call, Sema &S, + QualType VectorTy, QualType EltTy) { + QualType VectorEltTy = VectorTy->castAs<VectorType>()->getElementType(); + if (!Context.hasSameType(VectorEltTy, EltTy)) { + S.Diag(Call->getBeginLoc(), diag::err_typecheck_call_different_arg_types) + << Call->getSourceRange() << VectorEltTy << EltTy; + return false; + } + return true; +} + +static bool isValidBPFPreserveTypeInfoArg(Expr *Arg) { + QualType ArgType = Arg->getType(); + if (ArgType->getAsPlaceholderType()) + return false; + + // for TYPE_EXISTENCE/TYPE_SIZEOF reloc type + // format: + // 1. __builtin_preserve_type_info(*(<type> *)0, flag); + // 2. <type> var; + // __builtin_preserve_type_info(var, flag); + if (!dyn_cast<DeclRefExpr>(Arg->IgnoreParens()) && + !dyn_cast<UnaryOperator>(Arg->IgnoreParens())) + return false; + + // Typedef type. + if (ArgType->getAs<TypedefType>()) return true; - Expr *Arg; - if (BuiltinID == BPF::BI__builtin_btf_type_id) { - // The second argument needs to be a constant int - llvm::APSInt Value; - Arg = TheCall->getArg(1); - if (!Arg->isIntegerConstantExpr(Value, Context)) { - Diag(Arg->getBeginLoc(), diag::err_btf_type_id_not_const) - << 2 << Arg->getSourceRange(); + // Record type or Enum type. + const Type *Ty = ArgType->getUnqualifiedDesugaredType(); + if (const auto *RT = Ty->getAs<RecordType>()) { + if (!RT->getDecl()->getDeclName().isEmpty()) return true; - } + } else if (const auto *ET = Ty->getAs<EnumType>()) { + if (!ET->getDecl()->getDeclName().isEmpty()) + return true; + } - TheCall->setType(Context.UnsignedIntTy); + return false; +} + +static bool isValidBPFPreserveEnumValueArg(Expr *Arg) { + QualType ArgType = Arg->getType(); + if (ArgType->getAsPlaceholderType()) + return false; + + // for ENUM_VALUE_EXISTENCE/ENUM_VALUE reloc type + // format: + // __builtin_preserve_enum_value(*(<enum_type> *)<enum_value>, + // flag); + const auto *UO = dyn_cast<UnaryOperator>(Arg->IgnoreParens()); + if (!UO) + return false; + + const auto *CE = dyn_cast<CStyleCastExpr>(UO->getSubExpr()); + if (!CE || CE->getCastKind() != CK_IntegralToPointer) + return false; + + // The integer must be from an EnumConstantDecl. + const auto *DR = dyn_cast<DeclRefExpr>(CE->getSubExpr()); + if (!DR) + return false; + + const EnumConstantDecl *Enumerator = + dyn_cast<EnumConstantDecl>(DR->getDecl()); + if (!Enumerator) + return false; + + // The type must be EnumType. + const Type *Ty = ArgType->getUnqualifiedDesugaredType(); + const auto *ET = Ty->getAs<EnumType>(); + if (!ET) return false; + + // The enum value must be supported. + for (auto *EDI : ET->getDecl()->enumerators()) { + if (EDI == Enumerator) + return true; } - // The first argument needs to be a record field access. - // If it is an array element access, we delay decision - // to BPF backend to check whether the access is a - // field access or not. - Arg = TheCall->getArg(0); - if (Arg->getType()->getAsPlaceholderType() || - (Arg->IgnoreParens()->getObjectKind() != OK_BitField && - !dyn_cast<MemberExpr>(Arg->IgnoreParens()) && - !dyn_cast<ArraySubscriptExpr>(Arg->IgnoreParens()))) { - Diag(Arg->getBeginLoc(), diag::err_preserve_field_info_not_field) - << 1 << Arg->getSourceRange(); + return false; +} + +bool Sema::CheckBPFBuiltinFunctionCall(unsigned BuiltinID, + CallExpr *TheCall) { + assert((BuiltinID == BPF::BI__builtin_preserve_field_info || + BuiltinID == BPF::BI__builtin_btf_type_id || + BuiltinID == BPF::BI__builtin_preserve_type_info || + BuiltinID == BPF::BI__builtin_preserve_enum_value) && + "unexpected BPF builtin"); + + if (checkArgCount(*this, TheCall, 2)) return true; - } // The second argument needs to be a constant int - Arg = TheCall->getArg(1); - llvm::APSInt Value; - if (!Arg->isIntegerConstantExpr(Value, Context)) { - Diag(Arg->getBeginLoc(), diag::err_preserve_field_info_not_const) - << 2 << Arg->getSourceRange(); + Expr *Arg = TheCall->getArg(1); + Optional<llvm::APSInt> Value = Arg->getIntegerConstantExpr(Context); + diag::kind kind; + if (!Value) { + if (BuiltinID == BPF::BI__builtin_preserve_field_info) + kind = diag::err_preserve_field_info_not_const; + else if (BuiltinID == BPF::BI__builtin_btf_type_id) + kind = diag::err_btf_type_id_not_const; + else if (BuiltinID == BPF::BI__builtin_preserve_type_info) + kind = diag::err_preserve_type_info_not_const; + else + kind = diag::err_preserve_enum_value_not_const; + Diag(Arg->getBeginLoc(), kind) << 2 << Arg->getSourceRange(); return true; } - TheCall->setType(Context.UnsignedIntTy); + // The first argument + Arg = TheCall->getArg(0); + bool InvalidArg = false; + bool ReturnUnsignedInt = true; + if (BuiltinID == BPF::BI__builtin_preserve_field_info) { + if (!isValidBPFPreserveFieldInfoArg(Arg)) { + InvalidArg = true; + kind = diag::err_preserve_field_info_not_field; + } + } else if (BuiltinID == BPF::BI__builtin_preserve_type_info) { + if (!isValidBPFPreserveTypeInfoArg(Arg)) { + InvalidArg = true; + kind = diag::err_preserve_type_info_invalid; + } + } else if (BuiltinID == BPF::BI__builtin_preserve_enum_value) { + if (!isValidBPFPreserveEnumValueArg(Arg)) { + InvalidArg = true; + kind = diag::err_preserve_enum_value_invalid; + } + ReturnUnsignedInt = false; + } else if (BuiltinID == BPF::BI__builtin_btf_type_id) { + ReturnUnsignedInt = false; + } + + if (InvalidArg) { + Diag(Arg->getBeginLoc(), kind) << 1 << Arg->getSourceRange(); + return true; + } + + if (ReturnUnsignedInt) + TheCall->setType(Context.UnsignedIntTy); + else + TheCall->setType(Context.UnsignedLongTy); return false; } @@ -3067,6 +3172,62 @@ bool Sema::CheckMipsBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall) { SemaBuiltinConstantArgMultiple(TheCall, i, m); } +/// DecodePPCMMATypeFromStr - This decodes one PPC MMA type descriptor from Str, +/// advancing the pointer over the consumed characters. The decoded type is +/// returned. If the decoded type represents a constant integer with a +/// constraint on its value then Mask is set to that value. The type descriptors +/// used in Str are specific to PPC MMA builtins and are documented in the file +/// defining the PPC builtins. +static QualType DecodePPCMMATypeFromStr(ASTContext &Context, const char *&Str, + unsigned &Mask) { + bool RequireICE = false; + ASTContext::GetBuiltinTypeError Error = ASTContext::GE_None; + switch (*Str++) { + case 'V': + return Context.getVectorType(Context.UnsignedCharTy, 16, + VectorType::VectorKind::AltiVecVector); + case 'i': { + char *End; + unsigned size = strtoul(Str, &End, 10); + assert(End != Str && "Missing constant parameter constraint"); + Str = End; + Mask = size; + return Context.IntTy; + } + case 'W': { + char *End; + unsigned size = strtoul(Str, &End, 10); + assert(End != Str && "Missing PowerPC MMA type size"); + Str = End; + QualType Type; + switch (size) { + #define PPC_VECTOR_TYPE(typeName, Id, size) \ + case size: Type = Context.Id##Ty; break; + #include "clang/Basic/PPCTypes.def" + default: llvm_unreachable("Invalid PowerPC MMA vector type"); + } + bool CheckVectorArgs = false; + while (!CheckVectorArgs) { + switch (*Str++) { + case '*': + Type = Context.getPointerType(Type); + break; + case 'C': + Type = Type.withConst(); + break; + default: + CheckVectorArgs = true; + --Str; + break; + } + } + return Type; + } + default: + return Context.DecodeTypeStr(--Str, Context, Error, RequireICE, true); + } +} + bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall) { unsigned i = 0, l = 0, u = 0; @@ -3127,6 +3288,14 @@ bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, return SemaVSXCheck(TheCall); case PPC::BI__builtin_altivec_vgnb: return SemaBuiltinConstantArgRange(TheCall, 1, 2, 7); + case PPC::BI__builtin_altivec_vec_replace_elt: + case PPC::BI__builtin_altivec_vec_replace_unaligned: { + QualType VecTy = TheCall->getArg(0)->getType(); + QualType EltTy = TheCall->getArg(1)->getType(); + unsigned Width = Context.getIntWidth(EltTy); + return SemaBuiltinConstantArgRange(TheCall, 2, 0, Width == 32 ? 12 : 8) || + !isEltOfVectorTy(Context, TheCall, *this, VecTy, EltTy); + } case PPC::BI__builtin_vsx_xxeval: return SemaBuiltinConstantArgRange(TheCall, 3, 0, 255); case PPC::BI__builtin_altivec_vsldbi: @@ -3135,10 +3304,31 @@ bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, return SemaBuiltinConstantArgRange(TheCall, 2, 0, 7); case PPC::BI__builtin_vsx_xxpermx: return SemaBuiltinConstantArgRange(TheCall, 3, 0, 7); +#define CUSTOM_BUILTIN(Name, Types, Acc) \ + case PPC::BI__builtin_##Name: \ + return SemaBuiltinPPCMMACall(TheCall, Types); +#include "clang/Basic/BuiltinsPPC.def" } return SemaBuiltinConstantArgRange(TheCall, i, l, u); } +// Check if the given type is a non-pointer PPC MMA type. This function is used +// in Sema to prevent invalid uses of restricted PPC MMA types. +bool Sema::CheckPPCMMAType(QualType Type, SourceLocation TypeLoc) { + if (Type->isPointerType() || Type->isArrayType()) + return false; + + QualType CoreType = Type.getCanonicalType().getUnqualifiedType(); +#define PPC_VECTOR_TYPE(Name, Id, Size) || CoreType == Context.Id##Ty + if (false +#include "clang/Basic/PPCTypes.def" + ) { + Diag(TypeLoc, diag::err_ppc_invalid_use_mma_type); + return true; + } + return false; +} + bool Sema::CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { // position of memory order and scope arguments in the builtin @@ -3186,8 +3376,7 @@ bool Sema::CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID, ArgExpr = Arg.get(); Expr::EvalResult ArgResult1; // Check that sync scope is a constant literal - if (!ArgExpr->EvaluateAsConstantExpr(ArgResult1, Expr::EvaluateForCodeGen, - Context)) + if (!ArgExpr->EvaluateAsConstantExpr(ArgResult1, Context)) return Diag(ArgExpr->getExprLoc(), diag::err_expr_not_string_literal) << ArgExpr->getType(); @@ -3198,11 +3387,10 @@ bool Sema::CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { if (BuiltinID == SystemZ::BI__builtin_tabort) { Expr *Arg = TheCall->getArg(0); - llvm::APSInt AbortCode(32); - if (Arg->isIntegerConstantExpr(AbortCode, Context) && - AbortCode.getSExtValue() >= 0 && AbortCode.getSExtValue() < 256) - return Diag(Arg->getBeginLoc(), diag::err_systemz_invalid_tabort_code) - << Arg->getSourceRange(); + if (Optional<llvm::APSInt> AbortCode = Arg->getIntegerConstantExpr(Context)) + if (AbortCode->getSExtValue() >= 0 && AbortCode->getSExtValue() < 256) + return Diag(Arg->getBeginLoc(), diag::err_systemz_invalid_tabort_code) + << Arg->getSourceRange(); } // For intrinsics which take an immediate value as part of the instruction, @@ -3611,7 +3799,7 @@ bool Sema::CheckX86BuiltinGatherScatterScale(unsigned BuiltinID, enum { TileRegLow = 0, TileRegHigh = 7 }; bool Sema::CheckX86BuiltinTileArgumentsRange(CallExpr *TheCall, - ArrayRef<int> ArgNums) { + ArrayRef<int> ArgNums) { for (int ArgNum : ArgNums) { if (SemaBuiltinConstantArgRange(TheCall, ArgNum, TileRegLow, TileRegHigh)) return true; @@ -3619,19 +3807,20 @@ bool Sema::CheckX86BuiltinTileArgumentsRange(CallExpr *TheCall, return false; } -bool Sema::CheckX86BuiltinTileArgumentsRange(CallExpr *TheCall, int ArgNum) { - return SemaBuiltinConstantArgRange(TheCall, ArgNum, TileRegLow, TileRegHigh); -} - bool Sema::CheckX86BuiltinTileDuplicate(CallExpr *TheCall, ArrayRef<int> ArgNums) { // Because the max number of tile register is TileRegHigh + 1, so here we use // each bit to represent the usage of them in bitset. std::bitset<TileRegHigh + 1> ArgValues; for (int ArgNum : ArgNums) { - llvm::APSInt Arg; - SemaBuiltinConstantArg(TheCall, ArgNum, Arg); - int ArgExtValue = Arg.getExtValue(); + Expr *Arg = TheCall->getArg(ArgNum); + if (Arg->isTypeDependent() || Arg->isValueDependent()) + continue; + + llvm::APSInt Result; + if (SemaBuiltinConstantArg(TheCall, ArgNum, Result)) + return true; + int ArgExtValue = Result.getExtValue(); assert((ArgExtValue >= TileRegLow || ArgExtValue <= TileRegHigh) && "Incorrect tile register num."); if (ArgValues.test(ArgExtValue)) @@ -4382,6 +4571,8 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, if (!FnInfo) return false; + CheckTCBEnforcement(TheCall, FDecl); + CheckAbsoluteValueFunction(TheCall, FDecl); CheckMaxUnsignedZero(TheCall, FDecl); @@ -4389,16 +4580,24 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, DiagnoseCStringFormatDirectiveInCFAPI(*this, FDecl, Args, NumArgs); unsigned CMId = FDecl->getMemoryFunctionKind(); - if (CMId == 0) - return false; // Handle memory setting and copying functions. - if (CMId == Builtin::BIstrlcpy || CMId == Builtin::BIstrlcat) + switch (CMId) { + case 0: + return false; + case Builtin::BIstrlcpy: // fallthrough + case Builtin::BIstrlcat: CheckStrlcpycatArguments(TheCall, FnInfo); - else if (CMId == Builtin::BIstrncat) + break; + case Builtin::BIstrncat: CheckStrncatArguments(TheCall, FnInfo); - else + break; + case Builtin::BIfree: + CheckFreeArguments(TheCall); + break; + default: CheckMemaccessArguments(TheCall, CMId, FnInfo); + } return false; } @@ -4923,21 +5122,21 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, } if (SubExprs.size() >= 2 && Form != Init) { - llvm::APSInt Result(32); - if (SubExprs[1]->isIntegerConstantExpr(Result, Context) && - !isValidOrderingForOp(Result.getSExtValue(), Op)) - Diag(SubExprs[1]->getBeginLoc(), - diag::warn_atomic_op_has_invalid_memory_order) - << SubExprs[1]->getSourceRange(); + if (Optional<llvm::APSInt> Result = + SubExprs[1]->getIntegerConstantExpr(Context)) + if (!isValidOrderingForOp(Result->getSExtValue(), Op)) + Diag(SubExprs[1]->getBeginLoc(), + diag::warn_atomic_op_has_invalid_memory_order) + << SubExprs[1]->getSourceRange(); } if (auto ScopeModel = AtomicExpr::getScopeModel(Op)) { auto *Scope = Args[Args.size() - 1]; - llvm::APSInt Result(32); - if (Scope->isIntegerConstantExpr(Result, Context) && - !ScopeModel->isValid(Result.getZExtValue())) { - Diag(Scope->getBeginLoc(), diag::err_atomic_op_has_invalid_synch_scope) - << Scope->getSourceRange(); + if (Optional<llvm::APSInt> Result = + Scope->getIntegerConstantExpr(Context)) { + if (!ScopeModel->isValid(Result->getZExtValue())) + Diag(Scope->getBeginLoc(), diag::err_atomic_op_has_invalid_synch_scope) + << Scope->getSourceRange(); } SubExprs.push_back(Scope); } @@ -4956,6 +5155,11 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, ? 0 : 1); + if (ValType->isExtIntType()) { + Diag(Ptr->getExprLoc(), diag::err_atomic_builtin_ext_int_prohibit); + return ExprError(); + } + return AE; } @@ -5574,21 +5778,8 @@ bool Sema::SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall) { if (checkVAStartABI(*this, BuiltinID, Fn)) return true; - if (TheCall->getNumArgs() > 2) { - Diag(TheCall->getArg(2)->getBeginLoc(), - diag::err_typecheck_call_too_many_args) - << 0 /*function call*/ << 2 << TheCall->getNumArgs() - << Fn->getSourceRange() - << SourceRange(TheCall->getArg(2)->getBeginLoc(), - (*(TheCall->arg_end() - 1))->getEndLoc()); + if (checkArgCount(*this, TheCall, 2)) return true; - } - - if (TheCall->getNumArgs() < 2) { - return Diag(TheCall->getEndLoc(), - diag::err_typecheck_call_too_few_args_at_least) - << 0 /*function call*/ << 2 << TheCall->getNumArgs(); - } // Type-check the first argument normally. if (checkBuiltinArgument(*this, TheCall, 0)) @@ -5698,15 +5889,8 @@ bool Sema::SemaBuiltinVAStartARMMicrosoft(CallExpr *Call) { /// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isgreater and /// friends. This is declared to take (...), so we have to check everything. bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) { - if (TheCall->getNumArgs() < 2) - return Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args) - << 0 << 2 << TheCall->getNumArgs() /*function call*/; - if (TheCall->getNumArgs() > 2) - return Diag(TheCall->getArg(2)->getBeginLoc(), - diag::err_typecheck_call_too_many_args) - << 0 /*function call*/ << 2 << TheCall->getNumArgs() - << SourceRange(TheCall->getArg(2)->getBeginLoc(), - (*(TheCall->arg_end() - 1))->getEndLoc()); + if (checkArgCount(*this, TheCall, 2)) + return true; ExprResult OrigArg0 = TheCall->getArg(0); ExprResult OrigArg1 = TheCall->getArg(1); @@ -5744,15 +5928,8 @@ bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) { /// to check everything. We expect the last argument to be a floating point /// value. bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) { - if (TheCall->getNumArgs() < NumArgs) - return Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args) - << 0 << NumArgs << TheCall->getNumArgs() /*function call*/; - if (TheCall->getNumArgs() > NumArgs) - return Diag(TheCall->getArg(NumArgs)->getBeginLoc(), - diag::err_typecheck_call_too_many_args) - << 0 /*function call*/ << NumArgs << TheCall->getNumArgs() - << SourceRange(TheCall->getArg(NumArgs)->getBeginLoc(), - (*(TheCall->arg_end() - 1))->getEndLoc()); + if (checkArgCount(*this, TheCall, NumArgs)) + return true; // __builtin_fpclassify is the only case where NumArgs != 1, so we can count // on all preceding parameters just being int. Try all of those. @@ -5792,6 +5969,61 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) { return false; } +/// Perform semantic analysis for a call to __builtin_complex. +bool Sema::SemaBuiltinComplex(CallExpr *TheCall) { + if (checkArgCount(*this, TheCall, 2)) + return true; + + bool Dependent = false; + for (unsigned I = 0; I != 2; ++I) { + Expr *Arg = TheCall->getArg(I); + QualType T = Arg->getType(); + if (T->isDependentType()) { + Dependent = true; + continue; + } + + // Despite supporting _Complex int, GCC requires a real floating point type + // for the operands of __builtin_complex. + if (!T->isRealFloatingType()) { + return Diag(Arg->getBeginLoc(), diag::err_typecheck_call_requires_real_fp) + << Arg->getType() << Arg->getSourceRange(); + } + + ExprResult Converted = DefaultLvalueConversion(Arg); + if (Converted.isInvalid()) + return true; + TheCall->setArg(I, Converted.get()); + } + + if (Dependent) { + TheCall->setType(Context.DependentTy); + return false; + } + + Expr *Real = TheCall->getArg(0); + Expr *Imag = TheCall->getArg(1); + if (!Context.hasSameType(Real->getType(), Imag->getType())) { + return Diag(Real->getBeginLoc(), + diag::err_typecheck_call_different_arg_types) + << Real->getType() << Imag->getType() + << Real->getSourceRange() << Imag->getSourceRange(); + } + + // We don't allow _Complex _Float16 nor _Complex __fp16 as type specifiers; + // don't allow this builtin to form those types either. + // FIXME: Should we allow these types? + if (Real->getType()->isFloat16Type()) + return Diag(TheCall->getBeginLoc(), diag::err_invalid_complex_spec) + << "_Float16"; + if (Real->getType()->isHalfType()) + return Diag(TheCall->getBeginLoc(), diag::err_invalid_complex_spec) + << "half"; + + TheCall->setType(Context.getComplexType(Real->getType())); + return false; +} + // Customized Sema Checking for VSX builtins that have the following signature: // vector [...] builtinName(vector [...], vector [...], const int); // Which takes the same type of vectors (any legal vector type) for the first @@ -5801,21 +6033,11 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) { // vector short vec_xxsldwi(vector short, vector short, int); bool Sema::SemaBuiltinVSX(CallExpr *TheCall) { unsigned ExpectedNumArgs = 3; - if (TheCall->getNumArgs() < ExpectedNumArgs) - return Diag(TheCall->getEndLoc(), - diag::err_typecheck_call_too_few_args_at_least) - << 0 /*function call*/ << ExpectedNumArgs << TheCall->getNumArgs() - << TheCall->getSourceRange(); - - if (TheCall->getNumArgs() > ExpectedNumArgs) - return Diag(TheCall->getEndLoc(), - diag::err_typecheck_call_too_many_args_at_most) - << 0 /*function call*/ << ExpectedNumArgs << TheCall->getNumArgs() - << TheCall->getSourceRange(); + if (checkArgCount(*this, TheCall, ExpectedNumArgs)) + return true; // Check the third argument is a compile time constant - llvm::APSInt Value; - if(!TheCall->getArg(2)->isIntegerConstantExpr(Value, Context)) + if (!TheCall->getArg(2)->isIntegerConstantExpr(Context)) return Diag(TheCall->getBeginLoc(), diag::err_vsx_builtin_nonconstant_argument) << 3 /* argument index */ << TheCall->getDirectCallee() @@ -5910,17 +6132,18 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { TheCall->getArg(i)->isValueDependent()) continue; - llvm::APSInt Result(32); - if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context)) + Optional<llvm::APSInt> Result; + if (!(Result = TheCall->getArg(i)->getIntegerConstantExpr(Context))) return ExprError(Diag(TheCall->getBeginLoc(), diag::err_shufflevector_nonconstant_argument) << TheCall->getArg(i)->getSourceRange()); // Allow -1 which will be translated to undef in the IR. - if (Result.isSigned() && Result.isAllOnesValue()) + if (Result->isSigned() && Result->isAllOnesValue()) continue; - if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2) + if (Result->getActiveBits() > 64 || + Result->getZExtValue() >= numElements * 2) return ExprError(Diag(TheCall->getBeginLoc(), diag::err_shufflevector_argument_too_large) << TheCall->getArg(i)->getSourceRange()); @@ -6167,10 +6390,11 @@ bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum, if (Arg->isTypeDependent() || Arg->isValueDependent()) return false; - if (!Arg->isIntegerConstantExpr(Result, Context)) + Optional<llvm::APSInt> R; + if (!(R = Arg->getIntegerConstantExpr(Context))) return Diag(TheCall->getBeginLoc(), diag::err_constant_integer_arg_type) << FDecl->getDeclName() << Arg->getSourceRange(); - + Result = *R; return false; } @@ -6588,6 +6812,64 @@ bool Sema::SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, return false; } +/// SemaBuiltinPPCMMACall - Check the call to a PPC MMA builtin for validity. +/// Emit an error and return true on failure; return false on success. +/// TypeStr is a string containing the type descriptor of the value returned by +/// the builtin and the descriptors of the expected type of the arguments. +bool Sema::SemaBuiltinPPCMMACall(CallExpr *TheCall, const char *TypeStr) { + + assert((TypeStr[0] != '\0') && + "Invalid types in PPC MMA builtin declaration"); + + unsigned Mask = 0; + unsigned ArgNum = 0; + + // The first type in TypeStr is the type of the value returned by the + // builtin. So we first read that type and change the type of TheCall. + QualType type = DecodePPCMMATypeFromStr(Context, TypeStr, Mask); + TheCall->setType(type); + + while (*TypeStr != '\0') { + Mask = 0; + QualType ExpectedType = DecodePPCMMATypeFromStr(Context, TypeStr, Mask); + if (ArgNum >= TheCall->getNumArgs()) { + ArgNum++; + break; + } + + Expr *Arg = TheCall->getArg(ArgNum); + QualType ArgType = Arg->getType(); + + if ((ExpectedType->isVoidPointerType() && !ArgType->isPointerType()) || + (!ExpectedType->isVoidPointerType() && + ArgType.getCanonicalType() != ExpectedType)) + return Diag(Arg->getBeginLoc(), diag::err_typecheck_convert_incompatible) + << ArgType << ExpectedType << 1 << 0 << 0; + + // If the value of the Mask is not 0, we have a constraint in the size of + // the integer argument so here we ensure the argument is a constant that + // is in the valid range. + if (Mask != 0 && + SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, Mask, true)) + return true; + + ArgNum++; + } + + // In case we exited early from the previous loop, there are other types to + // read from TypeStr. So we need to read them all to ensure we have the right + // number of arguments in TheCall and if it is not the case, to display a + // better error message. + while (*TypeStr != '\0') { + (void) DecodePPCMMATypeFromStr(Context, TypeStr, Mask); + ArgNum++; + } + if (checkArgCount(*this, TheCall, ArgNum)) + return true; + + return false; +} + /// SemaBuiltinLongjmp - Handle __builtin_longjmp(void *env[5], int val). /// This checks that the target supports __builtin_longjmp and /// that val is a constant 1. @@ -9966,6 +10248,68 @@ void Sema::CheckStrncatArguments(const CallExpr *CE, << FixItHint::CreateReplacement(SR, OS.str()); } +namespace { +void CheckFreeArgumentsOnLvalue(Sema &S, const std::string &CalleeName, + const UnaryOperator *UnaryExpr, + const VarDecl *Var) { + StorageClass Class = Var->getStorageClass(); + if (Class == StorageClass::SC_Extern || + Class == StorageClass::SC_PrivateExtern || + Var->getType()->isReferenceType()) + return; + + S.Diag(UnaryExpr->getBeginLoc(), diag::warn_free_nonheap_object) + << CalleeName << Var; +} + +void CheckFreeArgumentsOnLvalue(Sema &S, const std::string &CalleeName, + const UnaryOperator *UnaryExpr, const Decl *D) { + if (const auto *Field = dyn_cast<FieldDecl>(D)) + S.Diag(UnaryExpr->getBeginLoc(), diag::warn_free_nonheap_object) + << CalleeName << Field; +} + +void CheckFreeArgumentsAddressof(Sema &S, const std::string &CalleeName, + const UnaryOperator *UnaryExpr) { + if (UnaryExpr->getOpcode() != UnaryOperator::Opcode::UO_AddrOf) + return; + + if (const auto *Lvalue = dyn_cast<DeclRefExpr>(UnaryExpr->getSubExpr())) + if (const auto *Var = dyn_cast<VarDecl>(Lvalue->getDecl())) + return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr, Var); + + if (const auto *Lvalue = dyn_cast<MemberExpr>(UnaryExpr->getSubExpr())) + return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr, + Lvalue->getMemberDecl()); +} + +void CheckFreeArgumentsStackArray(Sema &S, const std::string &CalleeName, + const DeclRefExpr *Lvalue) { + if (!Lvalue->getType()->isArrayType()) + return; + + const auto *Var = dyn_cast<VarDecl>(Lvalue->getDecl()); + if (Var == nullptr) + return; + + S.Diag(Lvalue->getBeginLoc(), diag::warn_free_nonheap_object) + << CalleeName << Var; +} +} // namespace + +/// Alerts the user that they are attempting to free a non-malloc'd object. +void Sema::CheckFreeArguments(const CallExpr *E) { + const Expr *Arg = E->getArg(0)->IgnoreParenCasts(); + const std::string CalleeName = + dyn_cast<FunctionDecl>(E->getCalleeDecl())->getQualifiedNameAsString(); + + if (const auto *UnaryExpr = dyn_cast<UnaryOperator>(Arg)) + return CheckFreeArgumentsAddressof(*this, CalleeName, UnaryExpr); + + if (const auto *Lvalue = dyn_cast<DeclRefExpr>(Arg)) + return CheckFreeArgumentsStackArray(*this, CalleeName, Lvalue); +} + void Sema::CheckReturnValExpr(Expr *RetValExp, QualType lhsType, SourceLocation ReturnLoc, @@ -9995,6 +10339,11 @@ Sema::CheckReturnValExpr(Expr *RetValExp, QualType lhsType, << FD << getLangOpts().CPlusPlus11; } } + + // PPC MMA non-pointer types are not allowed as return type. Checking the type + // here prevent the user from using a PPC MMA type as trailing return type. + if (Context.getTargetInfo().getTriple().isPPC64()) + CheckPPCMMAType(RetValExp->getType(), ReturnLoc); } //===--- CHECK: Floating-Point comparisons (-Wfloat-equal) ---------------===// @@ -10048,15 +10397,23 @@ namespace { /// Structure recording the 'active' range of an integer-valued /// expression. struct IntRange { - /// The number of bits active in the int. + /// The number of bits active in the int. Note that this includes exactly one + /// sign bit if !NonNegative. unsigned Width; - /// True if the int is known not to have negative values. + /// True if the int is known not to have negative values. If so, all leading + /// bits before Width are known zero, otherwise they are known to be the + /// same as the MSB within Width. bool NonNegative; IntRange(unsigned Width, bool NonNegative) : Width(Width), NonNegative(NonNegative) {} + /// Number of bits excluding the sign bit. + unsigned valueBits() const { + return NonNegative ? Width : Width - 1; + } + /// Returns the range of the bool type. static IntRange forBoolType() { return IntRange(1, true); @@ -10140,14 +10497,63 @@ struct IntRange { /// Returns the supremum of two ranges: i.e. their conservative merge. static IntRange join(IntRange L, IntRange R) { - return IntRange(std::max(L.Width, R.Width), + bool Unsigned = L.NonNegative && R.NonNegative; + return IntRange(std::max(L.valueBits(), R.valueBits()) + !Unsigned, L.NonNegative && R.NonNegative); } - /// Returns the infinum of two ranges: i.e. their aggressive merge. - static IntRange meet(IntRange L, IntRange R) { - return IntRange(std::min(L.Width, R.Width), - L.NonNegative || R.NonNegative); + /// Return the range of a bitwise-AND of the two ranges. + static IntRange bit_and(IntRange L, IntRange R) { + unsigned Bits = std::max(L.Width, R.Width); + bool NonNegative = false; + if (L.NonNegative) { + Bits = std::min(Bits, L.Width); + NonNegative = true; + } + if (R.NonNegative) { + Bits = std::min(Bits, R.Width); + NonNegative = true; + } + return IntRange(Bits, NonNegative); + } + + /// Return the range of a sum of the two ranges. + static IntRange sum(IntRange L, IntRange R) { + bool Unsigned = L.NonNegative && R.NonNegative; + return IntRange(std::max(L.valueBits(), R.valueBits()) + 1 + !Unsigned, + Unsigned); + } + + /// Return the range of a difference of the two ranges. + static IntRange difference(IntRange L, IntRange R) { + // We need a 1-bit-wider range if: + // 1) LHS can be negative: least value can be reduced. + // 2) RHS can be negative: greatest value can be increased. + bool CanWiden = !L.NonNegative || !R.NonNegative; + bool Unsigned = L.NonNegative && R.Width == 0; + return IntRange(std::max(L.valueBits(), R.valueBits()) + CanWiden + + !Unsigned, + Unsigned); + } + + /// Return the range of a product of the two ranges. + static IntRange product(IntRange L, IntRange R) { + // If both LHS and RHS can be negative, we can form + // -2^L * -2^R = 2^(L + R) + // which requires L + R + 1 value bits to represent. + bool CanWiden = !L.NonNegative && !R.NonNegative; + bool Unsigned = L.NonNegative && R.NonNegative; + return IntRange(L.valueBits() + R.valueBits() + CanWiden + !Unsigned, + Unsigned); + } + + /// Return the range of a remainder operation between the two ranges. + static IntRange rem(IntRange L, IntRange R) { + // The result of a remainder can't be larger than the result of + // either side. The sign of the result is the sign of the LHS. + bool Unsigned = L.NonNegative; + return IntRange(std::min(L.valueBits(), R.valueBits()) + !Unsigned, + Unsigned); } }; @@ -10205,9 +10611,13 @@ static QualType GetExprType(const Expr *E) { /// Pseudo-evaluate the given integer expression, estimating the /// range of values it might take. /// -/// \param MaxWidth - the width to which the value will be truncated +/// \param MaxWidth The width to which the value will be truncated. +/// \param Approximate If \c true, return a likely range for the result: in +/// particular, assume that aritmetic on narrower types doesn't leave +/// those types. If \c false, return a range including all possible +/// result values. static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth, - bool InConstantContext) { + bool InConstantContext, bool Approximate) { E = E->IgnoreParens(); // Try a full evaluation first. @@ -10220,7 +10630,8 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth, // being of the new, wider type. if (const auto *CE = dyn_cast<ImplicitCastExpr>(E)) { if (CE->getCastKind() == CK_NoOp || CE->getCastKind() == CK_LValueToRValue) - return GetExprRange(C, CE->getSubExpr(), MaxWidth, InConstantContext); + return GetExprRange(C, CE->getSubExpr(), MaxWidth, InConstantContext, + Approximate); IntRange OutputTypeRange = IntRange::forValueOfType(C, GetExprType(CE)); @@ -10233,7 +10644,7 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth, IntRange SubRange = GetExprRange(C, CE->getSubExpr(), std::min(MaxWidth, OutputTypeRange.Width), - InConstantContext); + InConstantContext, Approximate); // Bail out if the subexpr's range is as wide as the cast type. if (SubRange.Width >= OutputTypeRange.Width) @@ -10251,17 +10662,25 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth, if (CO->getCond()->EvaluateAsBooleanCondition(CondResult, C)) return GetExprRange(C, CondResult ? CO->getTrueExpr() : CO->getFalseExpr(), - MaxWidth, InConstantContext); + MaxWidth, InConstantContext, Approximate); // Otherwise, conservatively merge. - IntRange L = - GetExprRange(C, CO->getTrueExpr(), MaxWidth, InConstantContext); - IntRange R = - GetExprRange(C, CO->getFalseExpr(), MaxWidth, InConstantContext); + // GetExprRange requires an integer expression, but a throw expression + // results in a void type. + Expr *E = CO->getTrueExpr(); + IntRange L = E->getType()->isVoidType() + ? IntRange{0, true} + : GetExprRange(C, E, MaxWidth, InConstantContext, Approximate); + E = CO->getFalseExpr(); + IntRange R = E->getType()->isVoidType() + ? IntRange{0, true} + : GetExprRange(C, E, MaxWidth, InConstantContext, Approximate); return IntRange::join(L, R); } if (const auto *BO = dyn_cast<BinaryOperator>(E)) { + IntRange (*Combine)(IntRange, IntRange) = IntRange::join; + switch (BO->getOpcode()) { case BO_Cmp: llvm_unreachable("builtin <=> should have class type"); @@ -10293,7 +10712,8 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth, // been coerced to the LHS type. case BO_Assign: // TODO: bitfields? - return GetExprRange(C, BO->getRHS(), MaxWidth, InConstantContext); + return GetExprRange(C, BO->getRHS(), MaxWidth, InConstantContext, + Approximate); // Operations with opaque sources are black-listed. case BO_PtrMemD: @@ -10303,9 +10723,8 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth, // Bitwise-and uses the *infinum* of the two source ranges. case BO_And: case BO_AndAssign: - return IntRange::meet( - GetExprRange(C, BO->getLHS(), MaxWidth, InConstantContext), - GetExprRange(C, BO->getRHS(), MaxWidth, InConstantContext)); + Combine = IntRange::bit_and; + break; // Left shift gets black-listed based on a judgement call. case BO_Shl: @@ -10326,18 +10745,20 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth, // Right shift by a constant can narrow its left argument. case BO_Shr: case BO_ShrAssign: { - IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth, InConstantContext); + IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth, InConstantContext, + Approximate); // If the shift amount is a positive constant, drop the width by // that much. - llvm::APSInt shift; - if (BO->getRHS()->isIntegerConstantExpr(shift, C) && - shift.isNonNegative()) { - unsigned zext = shift.getZExtValue(); - if (zext >= L.Width) - L.Width = (L.NonNegative ? 0 : 1); - else - L.Width -= zext; + if (Optional<llvm::APSInt> shift = + BO->getRHS()->getIntegerConstantExpr(C)) { + if (shift->isNonNegative()) { + unsigned zext = shift->getZExtValue(); + if (zext >= L.Width) + L.Width = (L.NonNegative ? 0 : 1); + else + L.Width -= zext; + } } return L; @@ -10345,12 +10766,24 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth, // Comma acts as its right operand. case BO_Comma: - return GetExprRange(C, BO->getRHS(), MaxWidth, InConstantContext); + return GetExprRange(C, BO->getRHS(), MaxWidth, InConstantContext, + Approximate); + + case BO_Add: + if (!Approximate) + Combine = IntRange::sum; + break; - // Black-list pointer subtractions. case BO_Sub: if (BO->getLHS()->getType()->isPointerType()) return IntRange::forValueOfType(C, GetExprType(E)); + if (!Approximate) + Combine = IntRange::difference; + break; + + case BO_Mul: + if (!Approximate) + Combine = IntRange::product; break; // The width of a division result is mostly determined by the size @@ -10358,12 +10791,13 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth, case BO_Div: { // Don't 'pre-truncate' the operands. unsigned opWidth = C.getIntWidth(GetExprType(E)); - IntRange L = GetExprRange(C, BO->getLHS(), opWidth, InConstantContext); + IntRange L = GetExprRange(C, BO->getLHS(), opWidth, InConstantContext, + Approximate); // If the divisor is constant, use that. - llvm::APSInt divisor; - if (BO->getRHS()->isIntegerConstantExpr(divisor, C)) { - unsigned log2 = divisor.logBase2(); // floor(log_2(divisor)) + if (Optional<llvm::APSInt> divisor = + BO->getRHS()->getIntegerConstantExpr(C)) { + unsigned log2 = divisor->logBase2(); // floor(log_2(divisor)) if (log2 >= L.Width) L.Width = (L.NonNegative ? 0 : 1); else @@ -10372,36 +10806,35 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth, } // Otherwise, just use the LHS's width. - IntRange R = GetExprRange(C, BO->getRHS(), opWidth, InConstantContext); + // FIXME: This is wrong if the LHS could be its minimal value and the RHS + // could be -1. + IntRange R = GetExprRange(C, BO->getRHS(), opWidth, InConstantContext, + Approximate); return IntRange(L.Width, L.NonNegative && R.NonNegative); } - // The result of a remainder can't be larger than the result of - // either side. - case BO_Rem: { - // Don't 'pre-truncate' the operands. - unsigned opWidth = C.getIntWidth(GetExprType(E)); - IntRange L = GetExprRange(C, BO->getLHS(), opWidth, InConstantContext); - IntRange R = GetExprRange(C, BO->getRHS(), opWidth, InConstantContext); - - IntRange meet = IntRange::meet(L, R); - meet.Width = std::min(meet.Width, MaxWidth); - return meet; - } + case BO_Rem: + Combine = IntRange::rem; + break; // The default behavior is okay for these. - case BO_Mul: - case BO_Add: case BO_Xor: case BO_Or: break; } - // The default case is to treat the operation as if it were closed - // on the narrowest type that encompasses both operands. - IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth, InConstantContext); - IntRange R = GetExprRange(C, BO->getRHS(), MaxWidth, InConstantContext); - return IntRange::join(L, R); + // Combine the two ranges, but limit the result to the type in which we + // performed the computation. + QualType T = GetExprType(E); + unsigned opWidth = C.getIntWidth(T); + IntRange L = + GetExprRange(C, BO->getLHS(), opWidth, InConstantContext, Approximate); + IntRange R = + GetExprRange(C, BO->getRHS(), opWidth, InConstantContext, Approximate); + IntRange C = Combine(L, R); + C.NonNegative |= T->isUnsignedIntegerOrEnumerationType(); + C.Width = std::min(C.Width, MaxWidth); + return C; } if (const auto *UO = dyn_cast<UnaryOperator>(E)) { @@ -10416,12 +10849,14 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth, return IntRange::forValueOfType(C, GetExprType(E)); default: - return GetExprRange(C, UO->getSubExpr(), MaxWidth, InConstantContext); + return GetExprRange(C, UO->getSubExpr(), MaxWidth, InConstantContext, + Approximate); } } if (const auto *OVE = dyn_cast<OpaqueValueExpr>(E)) - return GetExprRange(C, OVE->getSourceExpr(), MaxWidth, InConstantContext); + return GetExprRange(C, OVE->getSourceExpr(), MaxWidth, InConstantContext, + Approximate); if (const auto *BitField = E->getSourceBitField()) return IntRange(BitField->getBitWidthValue(C), @@ -10431,8 +10866,9 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth, } static IntRange GetExprRange(ASTContext &C, const Expr *E, - bool InConstantContext) { - return GetExprRange(C, E, C.getIntWidth(GetExprType(E)), InConstantContext); + bool InConstantContext, bool Approximate) { + return GetExprRange(C, E, C.getIntWidth(GetExprType(E)), InConstantContext, + Approximate); } /// Checks whether the given value, which currently has the given @@ -10677,15 +11113,16 @@ static bool CheckTautologicalComparison(Sema &S, BinaryOperator *E, S.Context.hasSameUnqualifiedType(Constant->getType(), Other->getType())) return false; - // TODO: Investigate using GetExprRange() to get tighter bounds - // on the bit ranges. + IntRange OtherValueRange = GetExprRange( + S.Context, Other, S.isConstantEvaluated(), /*Approximate*/ false); + QualType OtherT = Other->getType(); if (const auto *AT = OtherT->getAs<AtomicType>()) OtherT = AT->getValueType(); - IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT); + IntRange OtherTypeRange = IntRange::forValueOfType(S.Context, OtherT); // Special case for ObjC BOOL on targets where its a typedef for a signed char - // (Namely, macOS). + // (Namely, macOS). FIXME: IntRange::forValueOfType should do this. bool IsObjCSignedCharBool = S.getLangOpts().ObjC && S.NSAPIObj->isObjCBOOLType(OtherT) && OtherT->isSpecificBuiltinType(BuiltinType::SChar); @@ -10695,17 +11132,37 @@ static bool CheckTautologicalComparison(Sema &S, BinaryOperator *E, bool OtherIsBooleanDespiteType = !OtherT->isBooleanType() && Other->isKnownToHaveBooleanValue(); if (OtherIsBooleanDespiteType || IsObjCSignedCharBool) - OtherRange = IntRange::forBoolType(); + OtherTypeRange = OtherValueRange = IntRange::forBoolType(); - // Determine the promoted range of the other type and see if a comparison of - // the constant against that range is tautological. - PromotedRange OtherPromotedRange(OtherRange, Value.getBitWidth(), - Value.isUnsigned()); - auto Cmp = OtherPromotedRange.compare(Value); + // Check if all values in the range of possible values of this expression + // lead to the same comparison outcome. + PromotedRange OtherPromotedValueRange(OtherValueRange, Value.getBitWidth(), + Value.isUnsigned()); + auto Cmp = OtherPromotedValueRange.compare(Value); auto Result = PromotedRange::constantValue(E->getOpcode(), Cmp, RhsConstant); if (!Result) return false; + // Also consider the range determined by the type alone. This allows us to + // classify the warning under the proper diagnostic group. + bool TautologicalTypeCompare = false; + { + PromotedRange OtherPromotedTypeRange(OtherTypeRange, Value.getBitWidth(), + Value.isUnsigned()); + auto TypeCmp = OtherPromotedTypeRange.compare(Value); + if (auto TypeResult = PromotedRange::constantValue(E->getOpcode(), TypeCmp, + RhsConstant)) { + TautologicalTypeCompare = true; + Cmp = TypeCmp; + Result = TypeResult; + } + } + + // Don't warn if the non-constant operand actually always evaluates to the + // same value. + if (!TautologicalTypeCompare && OtherValueRange.Width == 0) + return false; + // Suppress the diagnostic for an in-range comparison if the constant comes // from a macro or enumerator. We don't want to diagnose // @@ -10716,6 +11173,12 @@ static bool CheckTautologicalComparison(Sema &S, BinaryOperator *E, if (InRange && IsEnumConstOrFromMacro(S, Constant)) return false; + // A comparison of an unsigned bit-field against 0 is really a type problem, + // even though at the type level the bit-field might promote to 'signed int'. + if (Other->refersToBitField() && InRange && Value == 0 && + Other->getType()->isUnsignedIntegerOrEnumerationType()) + TautologicalTypeCompare = true; + // If this is a comparison to an enum constant, include that // constant in the diagnostic. const EnumConstantDecl *ED = nullptr; @@ -10734,6 +11197,14 @@ static bool CheckTautologicalComparison(Sema &S, BinaryOperator *E, OS << Value; } + if (!TautologicalTypeCompare) { + S.Diag(E->getOperatorLoc(), diag::warn_tautological_compare_value_range) + << RhsConstant << OtherValueRange.Width << OtherValueRange.NonNegative + << E->getOpcodeStr() << OS.str() << *Result + << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); + return true; + } + if (IsObjCSignedCharBool) { S.DiagRuntimeBehavior(E->getOperatorLoc(), E, S.PDiag(diag::warn_tautological_compare_objc_bool) @@ -10795,23 +11266,20 @@ static void AnalyzeComparison(Sema &S, BinaryOperator *E) { Expr *RHS = E->getRHS(); if (T->isIntegralType(S.Context)) { - llvm::APSInt RHSValue; - llvm::APSInt LHSValue; - - bool IsRHSIntegralLiteral = RHS->isIntegerConstantExpr(RHSValue, S.Context); - bool IsLHSIntegralLiteral = LHS->isIntegerConstantExpr(LHSValue, S.Context); + Optional<llvm::APSInt> RHSValue = RHS->getIntegerConstantExpr(S.Context); + Optional<llvm::APSInt> LHSValue = LHS->getIntegerConstantExpr(S.Context); // We don't care about expressions whose result is a constant. - if (IsRHSIntegralLiteral && IsLHSIntegralLiteral) + if (RHSValue && LHSValue) return AnalyzeImpConvsInComparison(S, E); // We only care about expressions where just one side is literal - if (IsRHSIntegralLiteral ^ IsLHSIntegralLiteral) { + if ((bool)RHSValue ^ (bool)LHSValue) { // Is the constant on the RHS or LHS? - const bool RhsConstant = IsRHSIntegralLiteral; + const bool RhsConstant = (bool)RHSValue; Expr *Const = RhsConstant ? RHS : LHS; Expr *Other = RhsConstant ? LHS : RHS; - const llvm::APSInt &Value = RhsConstant ? RHSValue : LHSValue; + const llvm::APSInt &Value = RhsConstant ? *RHSValue : *LHSValue; // Check whether an integer constant comparison results in a value // of 'true' or 'false'. @@ -10856,8 +11324,8 @@ static void AnalyzeComparison(Sema &S, BinaryOperator *E) { } // Otherwise, calculate the effective range of the signed operand. - IntRange signedRange = - GetExprRange(S.Context, signedOperand, S.isConstantEvaluated()); + IntRange signedRange = GetExprRange( + S.Context, signedOperand, S.isConstantEvaluated(), /*Approximate*/ true); // Go ahead and analyze implicit conversions in the operands. Note // that we skip the implicit conversions on both sides. @@ -10875,7 +11343,8 @@ static void AnalyzeComparison(Sema &S, BinaryOperator *E) { if (E->isEqualityOp()) { unsigned comparisonWidth = S.Context.getIntWidth(T); IntRange unsignedRange = - GetExprRange(S.Context, unsignedOperand, S.isConstantEvaluated()); + GetExprRange(S.Context, unsignedOperand, S.isConstantEvaluated(), + /*Approximate*/ true); // We should never be unable to prove that the unsigned operand is // non-negative. @@ -10915,7 +11384,7 @@ static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, BitfieldEnumDecl->getNumPositiveBits() > 0 && BitfieldEnumDecl->getNumNegativeBits() == 0) { S.Diag(InitLoc, diag::warn_no_underlying_type_specified_for_enum_bitfield) - << BitfieldEnumDecl->getNameAsString(); + << BitfieldEnumDecl; } } @@ -11695,9 +12164,9 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, Expr::EvalResult Result; if (E->EvaluateAsFixedPoint(Result, S.Context, Expr::SE_AllowSideEffects, S.isConstantEvaluated())) { - APFixedPoint Value = Result.Val.getFixedPoint(); - APFixedPoint MaxVal = S.Context.getFixedPointMax(T); - APFixedPoint MinVal = S.Context.getFixedPointMin(T); + llvm::APFixedPoint Value = Result.Val.getFixedPoint(); + llvm::APFixedPoint MaxVal = S.Context.getFixedPointMax(T); + llvm::APFixedPoint MinVal = S.Context.getFixedPointMin(T); if (Value > MaxVal || Value < MinVal) { S.DiagRuntimeBehavior(E->getExprLoc(), E, S.PDiag(diag::warn_impcast_fixed_point_range) @@ -11712,7 +12181,7 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, if (!S.isConstantEvaluated() && E->EvaluateAsFixedPoint(Result, S.Context, Expr::SE_AllowSideEffects)) { - APFixedPoint FXResult = Result.Val.getFixedPoint(); + llvm::APFixedPoint FXResult = Result.Val.getFixedPoint(); bool Overflowed; llvm::APSInt IntResult = FXResult.convertToInt( @@ -11737,7 +12206,7 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, llvm::APSInt Value = Result.Val.getInt(); bool Overflowed; - APFixedPoint IntResult = APFixedPoint::getFromIntValue( + llvm::APFixedPoint IntResult = llvm::APFixedPoint::getFromIntValue( Value, S.Context.getFixedPointSemantics(T), &Overflowed); if (Overflowed) { @@ -11758,7 +12227,8 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, if (SourceBT && TargetBT && SourceBT->isIntegerType() && TargetBT->isFloatingType() && !IsListInit) { // Determine the number of precision bits in the source integer type. - IntRange SourceRange = GetExprRange(S.Context, E, S.isConstantEvaluated()); + IntRange SourceRange = GetExprRange(S.Context, E, S.isConstantEvaluated(), + /*Approximate*/ true); unsigned int SourcePrecision = SourceRange.Width; // Determine the number of precision bits in the @@ -11769,8 +12239,8 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, if (SourcePrecision > 0 && TargetPrecision > 0 && SourcePrecision > TargetPrecision) { - llvm::APSInt SourceInt; - if (E->isIntegerConstantExpr(SourceInt, S.Context)) { + if (Optional<llvm::APSInt> SourceInt = + E->getIntegerConstantExpr(S.Context)) { // If the source integer is a constant, convert it to the target // floating point type. Issue a warning if the value changes // during the whole conversion. @@ -11778,11 +12248,11 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, S.Context.getFloatTypeSemantics(QualType(TargetBT, 0))); llvm::APFloat::opStatus ConversionStatus = TargetFloatValue.convertFromAPInt( - SourceInt, SourceBT->isSignedInteger(), + *SourceInt, SourceBT->isSignedInteger(), llvm::APFloat::rmNearestTiesToEven); if (ConversionStatus != llvm::APFloat::opOK) { - std::string PrettySourceValue = SourceInt.toString(10); + std::string PrettySourceValue = SourceInt->toString(10); SmallString<32> PrettyTargetValue; TargetFloatValue.toString(PrettyTargetValue, TargetPrecision); @@ -11823,10 +12293,13 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, << E->getType()); } - IntRange SourceRange = GetExprRange(S.Context, E, S.isConstantEvaluated()); + IntRange SourceTypeRange = + IntRange::forTargetOfCanonicalType(S.Context, Source); + IntRange LikelySourceRange = + GetExprRange(S.Context, E, S.isConstantEvaluated(), /*Approximate*/ true); IntRange TargetRange = IntRange::forTargetOfCanonicalType(S.Context, Target); - if (SourceRange.Width > TargetRange.Width) { + if (LikelySourceRange.Width > TargetRange.Width) { // If the source is a constant, use a default-on diagnostic. // TODO: this should happen for bitfield stores, too. Expr::EvalResult Result; @@ -11845,7 +12318,7 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, E->getExprLoc(), E, S.PDiag(diag::warn_impcast_integer_precision_constant) << PrettySourceValue << PrettyTargetValue << E->getType() << T - << E->getSourceRange() << clang::SourceRange(CC)); + << E->getSourceRange() << SourceRange(CC)); return; } @@ -11859,7 +12332,7 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_precision); } - if (TargetRange.Width > SourceRange.Width) { + if (TargetRange.Width > SourceTypeRange.Width) { if (auto *UO = dyn_cast<UnaryOperator>(E)) if (UO->getOpcode() == UO_Minus) if (Source->isUnsignedIntegerType()) { @@ -11872,8 +12345,9 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, } } - if (TargetRange.Width == SourceRange.Width && !TargetRange.NonNegative && - SourceRange.NonNegative && Source->isSignedIntegerType()) { + if (TargetRange.Width == LikelySourceRange.Width && + !TargetRange.NonNegative && LikelySourceRange.NonNegative && + Source->isSignedIntegerType()) { // Warn when doing a signed to signed conversion, warn if the positive // source value is exactly the width of the target type, which will // cause a negative value to be stored. @@ -11890,7 +12364,7 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, E->getExprLoc(), E, S.PDiag(diag::warn_impcast_integer_precision_constant) << PrettySourceValue << PrettyTargetValue << E->getType() << T - << E->getSourceRange() << clang::SourceRange(CC)); + << E->getSourceRange() << SourceRange(CC)); return; } } @@ -11898,9 +12372,9 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, // Fall through for non-constants to give a sign conversion warning. } - if ((TargetRange.NonNegative && !SourceRange.NonNegative) || - (!TargetRange.NonNegative && SourceRange.NonNegative && - SourceRange.Width == TargetRange.Width)) { + if ((TargetRange.NonNegative && !LikelySourceRange.NonNegative) || + (!TargetRange.NonNegative && LikelySourceRange.NonNegative && + LikelySourceRange.Width == TargetRange.Width)) { if (S.SourceMgr.isInSystemMacro(CC)) return; @@ -13505,10 +13979,9 @@ getAlignmentAndOffsetFromBinAddOrSub(const Expr *PtrE, const Expr *IntE, if (!P) return llvm::None; - llvm::APSInt IdxRes; CharUnits EltSize = Ctx.getTypeSizeInChars(PointeeType); - if (IntE->isIntegerConstantExpr(IdxRes, Ctx)) { - CharUnits Offset = EltSize * IdxRes.getExtValue(); + if (Optional<llvm::APSInt> IdxRes = IntE->getIntegerConstantExpr(Ctx)) { + CharUnits Offset = EltSize * IdxRes->getExtValue(); if (IsSub) Offset = -Offset; return std::make_pair(P->first, P->second + Offset); @@ -13911,8 +14384,7 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, if (ND) DiagRuntimeBehavior(ND->getBeginLoc(), BaseExpr, - PDiag(diag::note_array_declared_here) - << ND->getDeclName()); + PDiag(diag::note_array_declared_here) << ND); } void Sema::CheckArrayAccess(const Expr *expr) { @@ -14133,9 +14605,10 @@ namespace { return; if (Expr *RHS = BinOp->getRHS()) { RHS = RHS->IgnoreParenCasts(); - llvm::APSInt Value; + Optional<llvm::APSInt> Value; VarWillBeReased = - (RHS && RHS->isIntegerConstantExpr(Value, Context) && Value == 0); + (RHS && (Value = RHS->getIntegerConstantExpr(Context)) && + *Value == 0); } } } @@ -15362,14 +15835,15 @@ ExprResult Sema::SemaBuiltinMatrixTranspose(CallExpr *TheCall, // Get and verify the matrix dimensions. static llvm::Optional<unsigned> getAndVerifyMatrixDimension(Expr *Expr, StringRef Name, Sema &S) { - llvm::APSInt Value(64); SourceLocation ErrorPos; - if (!Expr->isIntegerConstantExpr(Value, S.Context, &ErrorPos)) { + Optional<llvm::APSInt> Value = + Expr->getIntegerConstantExpr(S.Context, &ErrorPos); + if (!Value) { S.Diag(Expr->getBeginLoc(), diag::err_builtin_matrix_scalar_unsigned_arg) << Name; return {}; } - uint64_t Dim = Value.getZExtValue(); + uint64_t Dim = Value->getZExtValue(); if (!ConstantMatrixType::isDimensionValid(Dim)) { S.Diag(Expr->getBeginLoc(), diag::err_builtin_matrix_invalid_dimension) << Name << ConstantMatrixType::getMaxElementsPerDimension(); @@ -15473,13 +15947,15 @@ ExprResult Sema::SemaBuiltinMatrixColumnMajorLoad(CallExpr *TheCall, StrideExpr = StrideConv.get(); TheCall->setArg(3, StrideExpr); - llvm::APSInt Value(64); - if (MaybeRows && StrideExpr->isIntegerConstantExpr(Value, Context)) { - uint64_t Stride = Value.getZExtValue(); - if (Stride < *MaybeRows) { - Diag(StrideExpr->getBeginLoc(), - diag::err_builtin_matrix_stride_too_small); - ArgError = true; + if (MaybeRows) { + if (Optional<llvm::APSInt> Value = + StrideExpr->getIntegerConstantExpr(Context)) { + uint64_t Stride = Value->getZExtValue(); + if (Stride < *MaybeRows) { + Diag(StrideExpr->getBeginLoc(), + diag::err_builtin_matrix_stride_too_small); + ArgError = true; + } } } @@ -15570,13 +16046,15 @@ ExprResult Sema::SemaBuiltinMatrixColumnMajorStore(CallExpr *TheCall, } // Check stride argument. - llvm::APSInt Value(64); - if (MatrixTy && StrideExpr->isIntegerConstantExpr(Value, Context)) { - uint64_t Stride = Value.getZExtValue(); - if (Stride < MatrixTy->getNumRows()) { - Diag(StrideExpr->getBeginLoc(), - diag::err_builtin_matrix_stride_too_small); - ArgError = true; + if (MatrixTy) { + if (Optional<llvm::APSInt> Value = + StrideExpr->getIntegerConstantExpr(Context)) { + uint64_t Stride = Value->getZExtValue(); + if (Stride < MatrixTy->getNumRows()) { + Diag(StrideExpr->getBeginLoc(), + diag::err_builtin_matrix_stride_too_small); + ArgError = true; + } } } @@ -15585,3 +16063,38 @@ ExprResult Sema::SemaBuiltinMatrixColumnMajorStore(CallExpr *TheCall, return CallResult; } + +/// \brief Enforce the bounds of a TCB +/// CheckTCBEnforcement - Enforces that every function in a named TCB only +/// directly calls other functions in the same TCB as marked by the enforce_tcb +/// and enforce_tcb_leaf attributes. +void Sema::CheckTCBEnforcement(const CallExpr *TheCall, + const FunctionDecl *Callee) { + const FunctionDecl *Caller = getCurFunctionDecl(); + + // Calls to builtins are not enforced. + if (!Caller || !Caller->hasAttr<EnforceTCBAttr>() || + Callee->getBuiltinID() != 0) + return; + + // Search through the enforce_tcb and enforce_tcb_leaf attributes to find + // all TCBs the callee is a part of. + llvm::StringSet<> CalleeTCBs; + for_each(Callee->specific_attrs<EnforceTCBAttr>(), + [&](const auto *A) { CalleeTCBs.insert(A->getTCBName()); }); + for_each(Callee->specific_attrs<EnforceTCBLeafAttr>(), + [&](const auto *A) { CalleeTCBs.insert(A->getTCBName()); }); + + // Go through the TCBs the caller is a part of and emit warnings if Caller + // is in a TCB that the Callee is not. + for_each( + Caller->specific_attrs<EnforceTCBAttr>(), + [&](const auto *A) { + StringRef CallerTCB = A->getTCBName(); + if (CalleeTCBs.count(CallerTCB) == 0) { + this->Diag(TheCall->getExprLoc(), + diag::warn_tcb_enforcement_violation) << Callee + << CallerTCB; + } + }); +} diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 0a8a27068ebf..c2785fd60fc2 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -2294,6 +2294,29 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S, Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); Builder.AddChunk(CodeCompletionString::CK_RightBrace); Results.AddResult(Result(Builder.TakeString())); + + if (SemaRef.getLangOpts().CPlusPlus11 || SemaRef.getLangOpts().ObjC) { + // for ( range_declaration (:|in) range_expression ) { statements } + Builder.AddTypedTextChunk("for"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("range-declaration"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + if (SemaRef.getLangOpts().ObjC) + Builder.AddTextChunk("in"); + else + Builder.AddChunk(CodeCompletionString::CK_Colon); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("range-expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Results.AddResult(Result(Builder.TakeString())); + } } if (S->getContinueParent()) { @@ -2700,6 +2723,10 @@ static std::string formatObjCParamQualifiers(unsigned ObjCQuals, case NullabilityKind::Unspecified: Result += "null_unspecified "; break; + + case NullabilityKind::NullableResult: + llvm_unreachable("Not supported as a context-sensitive keyword!"); + break; } } } @@ -3502,9 +3529,11 @@ CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl( Result.AddTypedTextChunk(""); } unsigned Idx = 0; + // The extra Idx < Sel.getNumArgs() check is needed due to legacy C-style + // method parameters. for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(), PEnd = Method->param_end(); - P != PEnd; (void)++P, ++Idx) { + P != PEnd && Idx < Sel.getNumArgs(); (void)++P, ++Idx) { if (Idx > 0) { std::string Keyword; if (Idx > StartParameter) @@ -4256,7 +4285,7 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier && DS.getTypeSpecType() == DeclSpec::TST_typename && DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified && - DS.getTypeSpecSign() == DeclSpec::TSS_unspecified && + DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified && !DS.isTypeAltiVecVector() && S && (S->getFlags() & Scope::DeclScope) != 0 && (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope | @@ -5395,8 +5424,8 @@ void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D, AddTypeQualifierResults(DS, Results, LangOpts); if (LangOpts.CPlusPlus11) { Results.AddResult("noexcept"); - if (D.getContext() == DeclaratorContext::MemberContext && - !D.isCtorOrDtor() && !D.isStaticMember()) { + if (D.getContext() == DeclaratorContext::Member && !D.isCtorOrDtor() && + !D.isStaticMember()) { if (!VS || !VS->isFinalSpecified()) Results.AddResult("final"); if (!VS || !VS->isOverrideSpecified()) @@ -5500,7 +5529,7 @@ typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate; static void mergeCandidatesWithResults( Sema &SemaRef, SmallVectorImpl<ResultCandidate> &Results, - OverloadCandidateSet &CandidateSet, SourceLocation Loc) { + OverloadCandidateSet &CandidateSet, SourceLocation Loc, size_t ArgSize) { // Sort the overload candidate set by placing the best overloads first. llvm::stable_sort(CandidateSet, [&](const OverloadCandidate &X, const OverloadCandidate &Y) { @@ -5510,8 +5539,19 @@ static void mergeCandidatesWithResults( // Add the remaining viable overload candidates as code-completion results. for (OverloadCandidate &Candidate : CandidateSet) { - if (Candidate.Function && Candidate.Function->isDeleted()) - continue; + if (Candidate.Function) { + if (Candidate.Function->isDeleted()) + continue; + if (!Candidate.Function->isVariadic() && + Candidate.Function->getNumParams() <= ArgSize && + // Having zero args is annoying, normally we don't surface a function + // with 2 params, if you already have 2 params, because you are + // inserting the 3rd now. But with zero, it helps the user to figure + // out there are no overloads that take any arguments. Hence we are + // keeping the overload. + ArgSize > 0) + continue; + } if (Candidate.Viable) Results.push_back(ResultCandidate(Candidate.Function)); } @@ -5562,22 +5602,25 @@ QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn, // FIXME: Provide support for variadic template functions. // Ignore type-dependent call expressions entirely. - if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) || - Expr::hasAnyTypeDependentArguments(Args)) { + if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args)) return QualType(); - } + // In presence of dependent args we surface all possible signatures using the + // non-dependent args in the prefix. Afterwards we do a post filtering to make + // sure provided candidates satisfy parameter count restrictions. + auto ArgsWithoutDependentTypes = + Args.take_while([](Expr *Arg) { return !Arg->isTypeDependent(); }); + + SmallVector<ResultCandidate, 8> Results; + Expr *NakedFn = Fn->IgnoreParenCasts(); // Build an overload candidate set based on the functions we find. SourceLocation Loc = Fn->getExprLoc(); OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); - SmallVector<ResultCandidate, 8> Results; - - Expr *NakedFn = Fn->IgnoreParenCasts(); - if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn)) - AddOverloadedCallCandidates(ULE, Args, CandidateSet, + if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn)) { + AddOverloadedCallCandidates(ULE, ArgsWithoutDependentTypes, CandidateSet, /*PartialOverloading=*/true); - else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) { + } else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) { TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr; if (UME->hasExplicitTemplateArgs()) { UME->copyTemplateArgumentsInto(TemplateArgsBuffer); @@ -5587,7 +5630,8 @@ QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn, // Add the base as first argument (use a nullptr if the base is implicit). SmallVector<Expr *, 12> ArgExprs( 1, UME->isImplicitAccess() ? nullptr : UME->getBase()); - ArgExprs.append(Args.begin(), Args.end()); + ArgExprs.append(ArgsWithoutDependentTypes.begin(), + ArgsWithoutDependentTypes.end()); UnresolvedSet<8> Decls; Decls.append(UME->decls_begin(), UME->decls_end()); const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase(); @@ -5606,7 +5650,7 @@ QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn, Results.push_back(ResultCandidate(FD)); else AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()), - Args, CandidateSet, + ArgsWithoutDependentTypes, CandidateSet, /*SuppressUserConversions=*/false, /*PartialOverloading=*/true); @@ -5621,7 +5665,8 @@ QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn, LookupQualifiedName(R, DC); R.suppressDiagnostics(); SmallVector<Expr *, 12> ArgExprs(1, NakedFn); - ArgExprs.append(Args.begin(), Args.end()); + ArgExprs.append(ArgsWithoutDependentTypes.begin(), + ArgsWithoutDependentTypes.end()); AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet, /*ExplicitArgs=*/nullptr, /*SuppressUserConversions=*/false, @@ -5635,7 +5680,8 @@ QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn, T = T->getPointeeType(); if (auto FP = T->getAs<FunctionProtoType>()) { - if (!TooManyArguments(FP->getNumParams(), Args.size(), + if (!TooManyArguments(FP->getNumParams(), + ArgsWithoutDependentTypes.size(), /*PartialOverloading=*/true) || FP->isVariadic()) Results.push_back(ResultCandidate(FP)); @@ -5644,7 +5690,7 @@ QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn, Results.push_back(ResultCandidate(FT)); } } - mergeCandidatesWithResults(*this, Results, CandidateSet, Loc); + mergeCandidatesWithResults(*this, Results, CandidateSet, Loc, Args.size()); QualType ParamType = ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc); return !CandidateSet.empty() ? ParamType : QualType(); @@ -5685,7 +5731,7 @@ QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type, } SmallVector<ResultCandidate, 8> Results; - mergeCandidatesWithResults(*this, Results, CandidateSet, Loc); + mergeCandidatesWithResults(*this, Results, CandidateSet, Loc, Args.size()); return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc); } diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index ddd95faebe99..1ff7b1cdd515 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -1053,25 +1053,20 @@ ReturnTypeRequirement(TemplateParameterList *TPL) : auto *Constraint = cast_or_null<ConceptSpecializationExpr>( TC->getImmediatelyDeclaredConstraint()); - bool Dependent = false; - if (Constraint->getTemplateArgsAsWritten()) { - for (auto &ArgLoc : - Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1)) { - if (ArgLoc.getArgument().isDependent()) { - Dependent = true; - break; - } - } - } + bool Dependent = + Constraint->getTemplateArgsAsWritten() && + TemplateSpecializationType::anyInstantiationDependentTemplateArguments( + Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1)); TypeConstraintInfo.setInt(Dependent ? 1 : 0); } concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) : - Requirement(RK_Type, T->getType()->isDependentType(), + Requirement(RK_Type, T->getType()->isInstantiationDependentType(), T->getType()->containsUnexpandedParameterPack(), // We reach this ctor with either dependent types (in which // IsSatisfied doesn't matter) or with non-dependent type in // which the existence of the type indicates satisfaction. - /*IsSatisfied=*/true - ), Value(T), - Status(T->getType()->isDependentType() ? SS_Dependent : SS_Satisfied) {} + /*IsSatisfied=*/true), + Value(T), + Status(T->getType()->isInstantiationDependentType() ? SS_Dependent + : SS_Satisfied) {} diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index 992cccac6405..7a48bfa429e9 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -398,39 +398,54 @@ static Expr *maybeTailCall(Sema &S, QualType RetType, Expr *E, diag::warn_coroutine_handle_address_invalid_return_type) << JustAddress->getType(); + // Clean up temporary objects so that they don't live across suspension points + // unnecessarily. We choose to clean up before the call to + // __builtin_coro_resume so that the cleanup code are not inserted in-between + // the resume call and return instruction, which would interfere with the + // musttail call contract. + JustAddress = S.MaybeCreateExprWithCleanups(JustAddress); return buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_resume, JustAddress); } /// Build calls to await_ready, await_suspend, and await_resume for a co_await /// expression. +/// The generated AST tries to clean up temporary objects as early as +/// possible so that they don't live across suspension points if possible. +/// Having temporary objects living across suspension points unnecessarily can +/// lead to large frame size, and also lead to memory corruptions if the +/// coroutine frame is destroyed after coming back from suspension. This is done +/// by wrapping both the await_ready call and the await_suspend call with +/// ExprWithCleanups. In the end of this function, we also need to explicitly +/// set cleanup state so that the CoawaitExpr is also wrapped with an +/// ExprWithCleanups to clean up the awaiter associated with the co_await +/// expression. static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise, SourceLocation Loc, Expr *E) { OpaqueValueExpr *Operand = new (S.Context) OpaqueValueExpr(Loc, E->getType(), VK_LValue, E->getObjectKind(), E); - // Assume invalid until we see otherwise. - ReadySuspendResumeResult Calls = {{}, Operand, /*IsInvalid=*/true}; - - ExprResult CoroHandleRes = buildCoroutineHandle(S, CoroPromise->getType(), Loc); - if (CoroHandleRes.isInvalid()) - return Calls; - Expr *CoroHandle = CoroHandleRes.get(); + // Assume valid until we see otherwise. + // Further operations are responsible for setting IsInalid to true. + ReadySuspendResumeResult Calls = {{}, Operand, /*IsInvalid=*/false}; - const StringRef Funcs[] = {"await_ready", "await_suspend", "await_resume"}; - MultiExprArg Args[] = {None, CoroHandle, None}; - for (size_t I = 0, N = llvm::array_lengthof(Funcs); I != N; ++I) { - ExprResult Result = buildMemberCall(S, Operand, Loc, Funcs[I], Args[I]); - if (Result.isInvalid()) - return Calls; - Calls.Results[I] = Result.get(); - } + using ACT = ReadySuspendResumeResult::AwaitCallType; - // Assume the calls are valid; all further checking should make them invalid. - Calls.IsInvalid = false; + auto BuildSubExpr = [&](ACT CallType, StringRef Func, + MultiExprArg Arg) -> Expr * { + ExprResult Result = buildMemberCall(S, Operand, Loc, Func, Arg); + if (Result.isInvalid()) { + Calls.IsInvalid = true; + return nullptr; + } + Calls.Results[CallType] = Result.get(); + return Result.get(); + }; - using ACT = ReadySuspendResumeResult::AwaitCallType; - CallExpr *AwaitReady = cast<CallExpr>(Calls.Results[ACT::ACT_Ready]); + CallExpr *AwaitReady = + cast_or_null<CallExpr>(BuildSubExpr(ACT::ACT_Ready, "await_ready", None)); + if (!AwaitReady) + return Calls; if (!AwaitReady->getType()->isDependentType()) { // [expr.await]p3 [...] // — await-ready is the expression e.await_ready(), contextually converted @@ -442,18 +457,36 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise, S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required) << AwaitReady->getDirectCallee() << E->getSourceRange(); Calls.IsInvalid = true; - } - Calls.Results[ACT::ACT_Ready] = Conv.get(); + } else + Calls.Results[ACT::ACT_Ready] = S.MaybeCreateExprWithCleanups(Conv.get()); + } + + ExprResult CoroHandleRes = + buildCoroutineHandle(S, CoroPromise->getType(), Loc); + if (CoroHandleRes.isInvalid()) { + Calls.IsInvalid = true; + return Calls; } - CallExpr *AwaitSuspend = cast<CallExpr>(Calls.Results[ACT::ACT_Suspend]); + Expr *CoroHandle = CoroHandleRes.get(); + CallExpr *AwaitSuspend = cast_or_null<CallExpr>( + BuildSubExpr(ACT::ACT_Suspend, "await_suspend", CoroHandle)); + if (!AwaitSuspend) + return Calls; if (!AwaitSuspend->getType()->isDependentType()) { // [expr.await]p3 [...] // - await-suspend is the expression e.await_suspend(h), which shall be - // a prvalue of type void or bool. + // a prvalue of type void, bool, or std::coroutine_handle<Z> for some + // type Z. QualType RetType = AwaitSuspend->getCallReturnType(S.Context); // Experimental support for coroutine_handle returning await_suspend. - if (Expr *TailCallSuspend = maybeTailCall(S, RetType, AwaitSuspend, Loc)) + if (Expr *TailCallSuspend = + maybeTailCall(S, RetType, AwaitSuspend, Loc)) + // Note that we don't wrap the expression with ExprWithCleanups here + // because that might interfere with tailcall contract (e.g. inserting + // clean up instructions in-between tailcall and return). Instead + // ExprWithCleanups is wrapped within maybeTailCall() prior to the resume + // call. Calls.Results[ACT::ACT_Suspend] = TailCallSuspend; else { // non-class prvalues always have cv-unqualified types @@ -465,10 +498,17 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise, S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required) << AwaitSuspend->getDirectCallee(); Calls.IsInvalid = true; - } + } else + Calls.Results[ACT::ACT_Suspend] = + S.MaybeCreateExprWithCleanups(AwaitSuspend); } } + BuildSubExpr(ACT::ACT_Resume, "await_resume", None); + + // Make sure the awaiter object gets a chance to be cleaned up. + S.Cleanup.setExprNeedsCleanups(true); + return Calls; } @@ -504,6 +544,7 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) { auto *VD = VarDecl::Create(Context, FD, FD->getLocation(), FD->getLocation(), &PP.getIdentifierTable().get("__promise"), T, Context.getTrivialTypeSourceInfo(T, Loc), SC_None); + VD->setImplicit(); CheckVariableDeclarationType(VD); if (VD->isInvalidDecl()) return nullptr; @@ -865,8 +906,8 @@ ExprResult Sema::BuildResolvedCoawaitExpr(SourceLocation Loc, Expr *E, SourceLocation CallLoc = E->getExprLoc(); // Build the await_ready, await_suspend, await_resume calls. - ReadySuspendResumeResult RSS = - buildCoawaitCalls(*this, Coroutine->CoroutinePromise, CallLoc, E); + ReadySuspendResumeResult RSS = buildCoawaitCalls( + *this, Coroutine->CoroutinePromise, CallLoc, E); if (RSS.IsInvalid) return ExprError(); @@ -920,8 +961,8 @@ ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) { E = CreateMaterializeTemporaryExpr(E->getType(), E, true); // Build the await_ready, await_suspend, await_resume calls. - ReadySuspendResumeResult RSS = - buildCoawaitCalls(*this, Coroutine->CoroutinePromise, Loc, E); + ReadySuspendResumeResult RSS = buildCoawaitCalls( + *this, Coroutine->CoroutinePromise, Loc, E); if (RSS.IsInvalid) return ExprError(); @@ -1537,6 +1578,7 @@ bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() { S.Context, &FD, FD.getLocation(), FD.getLocation(), &S.PP.getIdentifierTable().get("__coro_gro"), GroType, S.Context.getTrivialTypeSourceInfo(GroType, Loc), SC_None); + GroDecl->setImplicit(); S.CheckVariableDeclarationType(GroDecl); if (GroDecl->isInvalidDecl()) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 3e2b61ae8cdf..3ee0c43097d7 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -255,7 +255,7 @@ static ParsedType recoverFromTypeInKnownDependentBase(Sema &S, // We found some types in dependent base classes. Recover as if the user // wrote 'typename MyClass::II' instead of 'II'. We'll fully resolve the // lookup during template instantiation. - S.Diag(NameLoc, diag::ext_found_via_dependent_bases_lookup) << &II; + S.Diag(NameLoc, diag::ext_found_in_dependent_base) << &II; ASTContext &Context = S.Context; auto *NNS = NestedNameSpecifier::Create(Context, nullptr, false, @@ -436,9 +436,7 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, Res != ResEnd; ++Res) { if (isa<TypeDecl>(*Res) || isa<ObjCInterfaceDecl>(*Res) || (AllowDeducedTemplate && getAsTypeTemplateDecl(*Res))) { - if (!IIDecl || - (*Res)->getLocation().getRawEncoding() < - IIDecl->getLocation().getRawEncoding()) + if (!IIDecl || (*Res)->getLocation() < IIDecl->getLocation()) IIDecl = *Res; } } @@ -1184,23 +1182,20 @@ Corrected: return ParsedType::make(T); } - // FIXME: This is context-dependent. We need to defer building the member - // expression until the classification is consumed. - if (FirstDecl->isCXXClassMember()) - return NameClassification::ContextIndependentExpr( - BuildPossibleImplicitMemberExpr(SS, SourceLocation(), Result, nullptr, - S)); - // If we already know which single declaration is referenced, just annotate - // that declaration directly. + // that declaration directly. Defer resolving even non-overloaded class + // member accesses, as we need to defer certain access checks until we know + // the context. bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren)); - if (Result.isSingleResult() && !ADL) + if (Result.isSingleResult() && !ADL && !FirstDecl->isCXXClassMember()) return NameClassification::NonType(Result.getRepresentativeDecl()); - // Build an UnresolvedLookupExpr. Note that this doesn't depend on the - // context in which we performed classification, so it's safe to do now. - return NameClassification::ContextIndependentExpr( - BuildDeclarationNameExpr(SS, Result, ADL)); + // Otherwise, this is an overload set that we will need to resolve later. + Result.suppressDiagnostics(); + return NameClassification::OverloadSet(UnresolvedLookupExpr::Create( + Context, Result.getNamingClass(), SS.getWithLocInContext(Context), + Result.getLookupNameInfo(), ADL, Result.isOverloadedResult(), + Result.begin(), Result.end())); } ExprResult @@ -1240,6 +1235,30 @@ ExprResult Sema::ActOnNameClassifiedAsNonType(Scope *S, const CXXScopeSpec &SS, return BuildDeclarationNameExpr(SS, Result, ADL); } +ExprResult Sema::ActOnNameClassifiedAsOverloadSet(Scope *S, Expr *E) { + // For an implicit class member access, transform the result into a member + // access expression if necessary. + auto *ULE = cast<UnresolvedLookupExpr>(E); + if ((*ULE->decls_begin())->isCXXClassMember()) { + CXXScopeSpec SS; + SS.Adopt(ULE->getQualifierLoc()); + + // Reconstruct the lookup result. + LookupResult Result(*this, ULE->getName(), ULE->getNameLoc(), + LookupOrdinaryName); + Result.setNamingClass(ULE->getNamingClass()); + for (auto I = ULE->decls_begin(), E = ULE->decls_end(); I != E; ++I) + Result.addDecl(*I, I.getAccess()); + Result.resolveKind(); + return BuildPossibleImplicitMemberExpr(SS, SourceLocation(), Result, + nullptr, S); + } + + // Otherwise, this is already in the form we needed, and no further checks + // are necessary. + return ULE; +} + Sema::TemplateNameKindForDiagnostics Sema::getTemplateNameKindForDiagnostics(TemplateName Name) { auto *TD = Name.getAsTemplateDecl(); @@ -1457,10 +1476,7 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { // Out-of-line definitions shouldn't be pushed into scope in C++, unless they // are function-local declarations. - if (getLangOpts().CPlusPlus && D->isOutOfLine() && - !D->getDeclContext()->getRedeclContext()->Equals( - D->getLexicalDeclContext()->getRedeclContext()) && - !D->getLexicalDeclContext()->isFunctionOrMethod()) + if (getLangOpts().CPlusPlus && D->isOutOfLine() && !S->getFnParent()) return; // Template instantiations should also not be pushed into scope. @@ -1742,25 +1758,20 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { if (D->isInvalidDecl()) return false; - bool Referenced = false; if (auto *DD = dyn_cast<DecompositionDecl>(D)) { // For a decomposition declaration, warn if none of the bindings are // referenced, instead of if the variable itself is referenced (which // it is, by the bindings' expressions). - for (auto *BD : DD->bindings()) { - if (BD->isReferenced()) { - Referenced = true; - break; - } - } + for (auto *BD : DD->bindings()) + if (BD->isReferenced()) + return false; } else if (!D->getDeclName()) { return false; } else if (D->isReferenced() || D->isUsed()) { - Referenced = true; + return false; } - if (Referenced || D->hasAttr<UnusedAttr>() || - D->hasAttr<ObjCPreciseLifetimeAttr>()) + if (D->hasAttr<UnusedAttr>() || D->hasAttr<ObjCPreciseLifetimeAttr>()) return false; if (isa<LabelDecl>(D)) @@ -1905,7 +1916,7 @@ static void CheckPoppedLabel(LabelDecl *L, Sema &S) { else Diagnose = L->getStmt() == nullptr; if (Diagnose) - S.Diag(L->getLocation(), diag::err_undeclared_label_use) <<L->getDeclName(); + S.Diag(L->getLocation(), diag::err_undeclared_label_use) << L; } void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { @@ -2019,24 +2030,6 @@ Scope *Sema::getNonFieldDeclScope(Scope *S) { return S; } -/// Looks up the declaration of "struct objc_super" and -/// saves it for later use in building builtin declaration of -/// objc_msgSendSuper and objc_msgSendSuper_stret. If no such -/// pre-existing declaration exists no action takes place. -static void LookupPredefedObjCSuperType(Sema &ThisSema, Scope *S, - IdentifierInfo *II) { - if (!II->isStr("objc_msgSendSuper")) - return; - ASTContext &Context = ThisSema.Context; - - LookupResult Result(ThisSema, &Context.Idents.get("objc_super"), - SourceLocation(), Sema::LookupTagName); - ThisSema.LookupName(Result, S); - if (Result.getResultKind() == LookupResult::Found) - if (const TagDecl *TD = Result.getAsSingle<TagDecl>()) - Context.setObjCSuperType(Context.getTagDeclType(TD)); -} - static StringRef getHeaderName(Builtin::Context &BuiltinInfo, unsigned ID, ASTContext::GetBuiltinTypeError Error) { switch (Error) { @@ -2054,6 +2047,42 @@ static StringRef getHeaderName(Builtin::Context &BuiltinInfo, unsigned ID, llvm_unreachable("unhandled error kind"); } +FunctionDecl *Sema::CreateBuiltin(IdentifierInfo *II, QualType Type, + unsigned ID, SourceLocation Loc) { + DeclContext *Parent = Context.getTranslationUnitDecl(); + + if (getLangOpts().CPlusPlus) { + LinkageSpecDecl *CLinkageDecl = LinkageSpecDecl::Create( + Context, Parent, Loc, Loc, LinkageSpecDecl::lang_c, false); + CLinkageDecl->setImplicit(); + Parent->addDecl(CLinkageDecl); + Parent = CLinkageDecl; + } + + FunctionDecl *New = FunctionDecl::Create(Context, Parent, Loc, Loc, II, Type, + /*TInfo=*/nullptr, SC_Extern, false, + Type->isFunctionProtoType()); + New->setImplicit(); + New->addAttr(BuiltinAttr::CreateImplicit(Context, ID)); + + // Create Decl objects for each parameter, adding them to the + // FunctionDecl. + if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(Type)) { + SmallVector<ParmVarDecl *, 16> Params; + for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { + ParmVarDecl *parm = ParmVarDecl::Create( + Context, New, SourceLocation(), SourceLocation(), nullptr, + FT->getParamType(i), /*TInfo=*/nullptr, SC_None, nullptr); + parm->setScopeInfo(0, i); + Params.push_back(parm); + } + New->setParams(Params); + } + + AddKnownFunctionAttributes(New); + return New; +} + /// LazilyCreateBuiltin - The specified Builtin-ID was first used at /// file scope. lazily create a decl for it. ForRedeclaration is true /// if we're creating this built-in in anticipation of redeclaring the @@ -2061,7 +2090,7 @@ static StringRef getHeaderName(Builtin::Context &BuiltinInfo, unsigned ID, NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, Scope *S, bool ForRedeclaration, SourceLocation Loc) { - LookupPredefedObjCSuperType(*this, S, II); + LookupNecessaryTypesForBuiltin(S, ID); ASTContext::GetBuiltinTypeError Error; QualType R = Context.GetBuiltinType(ID, Error); @@ -2071,7 +2100,8 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, // If we have a builtin without an associated type we should not emit a // warning when we were not able to find a type for it. - if (Error == ASTContext::GE_Missing_type) + if (Error == ASTContext::GE_Missing_type || + Context.BuiltinInfo.allowTypeMismatch(ID)) return nullptr; // If we could not find a type for setjmp it is because the jmp_buf type was @@ -2095,50 +2125,15 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, Context.BuiltinInfo.isHeaderDependentFunction(ID))) { Diag(Loc, diag::ext_implicit_lib_function_decl) << Context.BuiltinInfo.getName(ID) << R; - if (Context.BuiltinInfo.getHeaderName(ID) && - !Diags.isIgnored(diag::ext_implicit_lib_function_decl, Loc)) + if (const char *Header = Context.BuiltinInfo.getHeaderName(ID)) Diag(Loc, diag::note_include_header_or_declare) - << Context.BuiltinInfo.getHeaderName(ID) - << Context.BuiltinInfo.getName(ID); + << Header << Context.BuiltinInfo.getName(ID); } if (R.isNull()) return nullptr; - DeclContext *Parent = Context.getTranslationUnitDecl(); - if (getLangOpts().CPlusPlus) { - LinkageSpecDecl *CLinkageDecl = - LinkageSpecDecl::Create(Context, Parent, Loc, Loc, - LinkageSpecDecl::lang_c, false); - CLinkageDecl->setImplicit(); - Parent->addDecl(CLinkageDecl); - Parent = CLinkageDecl; - } - - FunctionDecl *New = FunctionDecl::Create(Context, - Parent, - Loc, Loc, II, R, /*TInfo=*/nullptr, - SC_Extern, - false, - R->isFunctionProtoType()); - New->setImplicit(); - - // Create Decl objects for each parameter, adding them to the - // FunctionDecl. - if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(R)) { - SmallVector<ParmVarDecl*, 16> Params; - for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { - ParmVarDecl *parm = - ParmVarDecl::Create(Context, New, SourceLocation(), SourceLocation(), - nullptr, FT->getParamType(i), /*TInfo=*/nullptr, - SC_None, nullptr); - parm->setScopeInfo(0, i); - Params.push_back(parm); - } - New->setParams(Params); - } - - AddKnownFunctionAttributes(New); + FunctionDecl *New = CreateBuiltin(II, R, ID, Loc); RegisterLocallyScopedExternCDecl(New, S); // TUScope is the translation-unit scope to insert this function into. @@ -2146,7 +2141,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, // relate Scopes to DeclContexts, and probably eliminate CurContext // entirely, but we're not there yet. DeclContext *SavedContext = CurContext; - CurContext = Parent; + CurContext = New->getDeclContext(); PushOnScopeChains(New, TUScope); CurContext = SavedContext; return New; @@ -2591,6 +2586,8 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, return false; } else if (const auto *MA = dyn_cast<MinSizeAttr>(Attr)) NewAttr = S.mergeMinSizeAttr(D, *MA); + else if (const auto *SNA = dyn_cast<SwiftNameAttr>(Attr)) + NewAttr = S.mergeSwiftNameAttr(D, *SNA, SNA->getName()); else if (const auto *OA = dyn_cast<OptimizeNoneAttr>(Attr)) NewAttr = S.mergeOptimizeNoneAttr(D, *OA); else if (const auto *InternalLinkageA = dyn_cast<InternalLinkageAttr>(Attr)) @@ -2615,6 +2612,10 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, NewAttr = S.mergeImportModuleAttr(D, *IMA); else if (const auto *INA = dyn_cast<WebAssemblyImportNameAttr>(Attr)) NewAttr = S.mergeImportNameAttr(D, *INA); + else if (const auto *TCBA = dyn_cast<EnforceTCBAttr>(Attr)) + NewAttr = S.mergeEnforceTCBAttr(D, *TCBA); + else if (const auto *TCBLA = dyn_cast<EnforceTCBLeafAttr>(Attr)) + NewAttr = S.mergeEnforceTCBLeafAttr(D, *TCBLA); else if (Attr->shouldInheritEvenIfAlreadyPresent() || !DeclHasAttr(D, Attr)) NewAttr = cast<InheritableAttr>(Attr->clone(S.Context)); @@ -2638,8 +2639,11 @@ static const NamedDecl *getDefinition(const Decl *D) { return Def; return VD->getActingDefinition(); } - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) - return FD->getDefinition(); + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + const FunctionDecl *Def = nullptr; + if (FD->isDefined(Def, true)) + return Def; + } return nullptr; } @@ -3234,6 +3238,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, } } + // If the old declaration was found in an inline namespace and the new + // declaration was qualified, update the DeclContext to match. + adjustDeclContextForDeclaratorDecl(New, Old); + // If the old declaration is invalid, just give up here. if (Old->isInvalidDecl()) return true; @@ -3348,7 +3356,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, // there but not here. NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC()); RequiresAdjustment = true; - } else if (New->getBuiltinID()) { + } else if (Old->getBuiltinID()) { + // Builtin attribute isn't propagated to the new one yet at this point, + // so we check if the old one is a builtin. + // Calling Conventions on a Builtin aren't really useful and setting a // default calling convention and cdecl'ing some builtin redeclarations is // common, so warn and ignore the calling convention on the redeclaration. @@ -3781,18 +3792,6 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, Diag(New->getLocation(), diag::warn_redecl_library_builtin) << New; Diag(OldLocation, diag::note_previous_builtin_declaration) << Old << Old->getType(); - - // If this is a global redeclaration, just forget hereafter - // about the "builtin-ness" of the function. - // - // Doing this for local extern declarations is problematic. If - // the builtin declaration remains visible, a second invalid - // local declaration will produce a hard error; if it doesn't - // remain visible, a single bogus local redeclaration (which is - // actually only a warning) could break all the downstream code. - if (!New->getLexicalDeclContext()->isFunctionOrMethod()) - New->getIdentifier()->revertBuiltin(); - return false; } @@ -4057,6 +4056,10 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { return New->setInvalidDecl(); } + // If the old declaration was found in an inline namespace and the new + // declaration was qualified, update the DeclContext to match. + adjustDeclContextForDeclaratorDecl(New, Old); + // Ensure the template parameters are compatible. if (NewTemplate && !TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(), @@ -4241,7 +4244,6 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { New->setPreviousDecl(Old); if (NewTemplate) NewTemplate->setPreviousDecl(OldTemplate); - adjustDeclContextForDeclaratorDecl(New, Old); // Inherit access appropriately. New->setAccess(Old->getAccess()); @@ -4606,10 +4608,10 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, if (Tag) Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_tag) << GetDiagnosticTypeSpecifierID(DS.getTypeSpecType()) - << DS.getConstexprSpecifier(); + << static_cast<int>(DS.getConstexprSpecifier()); else Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_wrong_decl_kind) - << DS.getConstexprSpecifier(); + << static_cast<int>(DS.getConstexprSpecifier()); // Don't emit warnings after this error. return TagD; } @@ -4745,7 +4747,10 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, if (!DeclaresAnything) { // In C, we allow this as a (popular) extension / bug. Don't bother // producing further diagnostics for redundant qualifiers after this. - Diag(DS.getBeginLoc(), diag::ext_no_declarators) << DS.getSourceRange(); + Diag(DS.getBeginLoc(), (IsExplicitInstantiation || !TemplateParams.empty()) + ? diag::err_no_declarators + : diag::ext_no_declarators) + << DS.getSourceRange(); return TagD; } @@ -5164,7 +5169,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, Diag(DS.getBeginLoc(), diag::ext_no_declarators) << DS.getSourceRange(); // Mock up a declarator. - Declarator Dc(DS, DeclaratorContext::MemberContext); + Declarator Dc(DS, DeclaratorContext::Member); TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S); assert(TInfo && "couldn't build declarator info for anonymous struct/union"); @@ -5261,7 +5266,7 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS, assert(Record && "expected a record!"); // Mock up a declarator. - Declarator Dc(DS, DeclaratorContext::TypeNameContext); + Declarator Dc(DS, DeclaratorContext::TypeName); TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S); assert(TInfo && "couldn't build declarator info for anonymous struct"); @@ -5346,8 +5351,8 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { case UnqualifiedIdKind::IK_OperatorFunctionId: NameInfo.setName(Context.DeclarationNames.getCXXOperatorName( Name.OperatorFunctionId.Operator)); - NameInfo.getInfo().CXXOperatorName.BeginOpNameLoc - = Name.OperatorFunctionId.SymbolLocations[0]; + NameInfo.getInfo().CXXOperatorName.BeginOpNameLoc = + Name.OperatorFunctionId.SymbolLocations[0].getRawEncoding(); NameInfo.getInfo().CXXOperatorName.EndOpNameLoc = Name.EndLocation.getRawEncoding(); return NameInfo; @@ -5495,7 +5500,7 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D, // Grab the type from the parser. TypeSourceInfo *TSI = nullptr; QualType T = S.GetTypeFromParser(DS.getRepAsType(), &TSI); - if (T.isNull() || !T->isDependentType()) break; + if (T.isNull() || !T->isInstantiationDependentType()) break; // Make sure there's a type source info. This isn't really much // of a waste; most dependent types should have type source info @@ -5547,7 +5552,7 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D, } Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) { - D.setFunctionDefinitionKind(FDK_Declaration); + D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration); Decl *Dcl = HandleDeclarator(S, D, MultiTemplateParamsArg()); if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer() && @@ -5936,9 +5941,14 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T, const VariableArrayType* VLATy = dyn_cast<VariableArrayType>(T); if (!VLATy) return QualType(); - // FIXME: We should probably handle this case - if (VLATy->getElementType()->isVariablyModifiedType()) - return QualType(); + + QualType ElemTy = VLATy->getElementType(); + if (ElemTy->isVariablyModifiedType()) { + ElemTy = TryToFixInvalidVariablyModifiedType(ElemTy, Context, + SizeIsNegative, Oversized); + if (ElemTy.isNull()) + return QualType(); + } Expr::EvalResult Result; if (!VLATy->getSizeExpr() || @@ -5954,16 +5964,19 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T, } // Check whether the array is too large to be addressed. - unsigned ActiveSizeBits - = ConstantArrayType::getNumAddressingBits(Context, VLATy->getElementType(), - Res); + unsigned ActiveSizeBits = + (!ElemTy->isDependentType() && !ElemTy->isVariablyModifiedType() && + !ElemTy->isIncompleteType() && !ElemTy->isUndeducedType()) + ? ConstantArrayType::getNumAddressingBits(Context, ElemTy, Res) + : Res.getActiveBits(); if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) { Oversized = Res; return QualType(); } - return Context.getConstantArrayType( - VLATy->getElementType(), Res, VLATy->getSizeExpr(), ArrayType::Normal, 0); + QualType FoldedArrayType = Context.getConstantArrayType( + ElemTy, Res, VLATy->getSizeExpr(), ArrayType::Normal, 0); + return Qs.apply(Context, FoldedArrayType); } static void @@ -5989,7 +6002,13 @@ FixInvalidVariablyModifiedTypeLoc(TypeLoc SrcTL, TypeLoc DstTL) { ArrayTypeLoc DstATL = DstTL.castAs<ArrayTypeLoc>(); TypeLoc SrcElemTL = SrcATL.getElementLoc(); TypeLoc DstElemTL = DstATL.getElementLoc(); - DstElemTL.initializeFullCopy(SrcElemTL); + if (VariableArrayTypeLoc SrcElemATL = + SrcElemTL.getAs<VariableArrayTypeLoc>()) { + ConstantArrayTypeLoc DstElemATL = DstElemTL.castAs<ConstantArrayTypeLoc>(); + FixInvalidVariablyModifiedTypeLoc(SrcElemATL, DstElemATL); + } else { + DstElemTL.initializeFullCopy(SrcElemTL); + } DstATL.setLBracketLoc(SrcATL.getLBracketLoc()); DstATL.setSizeExpr(SrcATL.getSizeExpr()); DstATL.setRBracketLoc(SrcATL.getRBracketLoc()); @@ -6014,6 +6033,31 @@ TryToFixInvalidVariablyModifiedTypeSourceInfo(TypeSourceInfo *TInfo, return FixedTInfo; } +/// Attempt to fold a variable-sized type to a constant-sized type, returning +/// true if we were successful. +static bool tryToFixVariablyModifiedVarType(Sema &S, TypeSourceInfo *&TInfo, + QualType &T, SourceLocation Loc, + unsigned FailedFoldDiagID) { + bool SizeIsNegative; + llvm::APSInt Oversized; + TypeSourceInfo *FixedTInfo = TryToFixInvalidVariablyModifiedTypeSourceInfo( + TInfo, S.Context, SizeIsNegative, Oversized); + if (FixedTInfo) { + S.Diag(Loc, diag::ext_vla_folded_to_constant); + TInfo = FixedTInfo; + T = FixedTInfo->getType(); + return true; + } + + if (SizeIsNegative) + S.Diag(Loc, diag::err_typecheck_negative_array_size); + else if (Oversized.getBoolValue()) + S.Diag(Loc, diag::err_array_too_large) << Oversized.toString(10); + else if (FailedFoldDiagID) + S.Diag(Loc, FailedFoldDiagID); + return false; +} + /// Register the given locally-scoped extern "C" declaration so /// that it can be found later for redeclarations. We include any extern "C" /// declaration that is not visible in the translation unit here, not just @@ -6073,7 +6117,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, << getLangOpts().CPlusPlus17; if (D.getDeclSpec().hasConstexprSpecifier()) Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr) - << 1 << D.getDeclSpec().getConstexprSpecifier(); + << 1 << static_cast<int>(D.getDeclSpec().getConstexprSpecifier()); if (D.getName().Kind != UnqualifiedIdKind::IK_Identifier) { if (D.getName().Kind == UnqualifiedIdKind::IK_DeductionGuideName) @@ -6119,7 +6163,7 @@ Sema::CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *NewTD) { SizeIsNegative, Oversized); if (FixedTInfo) { - Diag(NewTD->getLocation(), diag::warn_illegal_constant_array_size); + Diag(NewTD->getLocation(), diag::ext_vla_folded_to_constant); NewTD->setTypeSourceInfo(FixedTInfo); } else { if (SizeIsNegative) @@ -6501,7 +6545,7 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, // special MSVC extension: in the last case, the declaration is treated as if // it were marked dllexport. bool IsInline = false, IsStaticDataMember = false, IsQualifiedFriend = false; - bool IsMicrosoft = S.Context.getTargetInfo().getCXXABI().isMicrosoft(); + bool IsMicrosoftABI = S.Context.getTargetInfo().shouldDLLImportComdatSymbols(); if (const auto *VD = dyn_cast<VarDecl>(NewDecl)) { // Ignore static data because out-of-line definitions are diagnosed // separately. @@ -6515,9 +6559,9 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, } if (OldImportAttr && !HasNewAttr && - (!IsInline || (IsMicrosoft && IsTemplate)) && !IsStaticDataMember && + (!IsInline || (IsMicrosoftABI && IsTemplate)) && !IsStaticDataMember && !NewDecl->isLocalExternDecl() && !IsQualifiedFriend) { - if (IsMicrosoft && IsDefinition) { + if (IsMicrosoftABI && IsDefinition) { S.Diag(NewDecl->getLocation(), diag::warn_redeclaration_without_import_attribute) << NewDecl; @@ -6534,7 +6578,7 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, OldDecl->dropAttr<DLLImportAttr>(); NewDecl->dropAttr<DLLImportAttr>(); } - } else if (IsInline && OldImportAttr && !IsMicrosoft) { + } else if (IsInline && OldImportAttr && !IsMicrosoftABI) { // In MinGW, seeing a function declared inline drops the dllimport // attribute. OldDecl->dropAttr<DLLImportAttr>(); @@ -6713,14 +6757,16 @@ static bool diagnoseOpenCLTypes(Scope *S, Sema &Se, Declarator &D, } // OpenCL v1.0 s6.8.a.3: Pointers to functions are not allowed. - QualType NR = R; - while (NR->isPointerType()) { - if (NR->isFunctionPointerType()) { - Se.Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer); - D.setInvalidType(); - return false; + if (!Se.getOpenCLOptions().isEnabled("__cl_clang_function_pointers")) { + QualType NR = R; + while (NR->isPointerType() || NR->isMemberFunctionPointerType()) { + if (NR->isFunctionPointerType() || NR->isMemberFunctionPointerType()) { + Se.Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer); + D.setInvalidType(); + return false; + } + NR = NR->getPointeeType(); } - NR = NR->getPointeeType(); } if (!Se.getOpenCLOptions().isEnabled("cl_khr_fp16")) { @@ -6852,6 +6898,12 @@ NamedDecl *Sema::ActOnVariableDeclarator( } } + // If this variable has a variable-modified type and an initializer, try to + // fold to a constant-sized type. This is otherwise invalid. + if (D.hasInitializer() && R->isVariablyModifiedType()) + tryToFixVariablyModifiedVarType(*this, TInfo, R, D.getIdentifierLoc(), + /*DiagID=*/0); + bool IsMemberSpecialization = false; bool IsVariableTemplateSpecialization = false; bool IsPartialSpecialization = false; @@ -6970,19 +7022,18 @@ NamedDecl *Sema::ActOnVariableDeclarator( TemplateParams->getRAngleLoc()); TemplateParams = nullptr; } else { + // Check that we can declare a template here. + if (CheckTemplateDeclScope(S, TemplateParams)) + return nullptr; + if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) { // This is an explicit specialization or a partial specialization. - // FIXME: Check that we can declare a specialization here. IsVariableTemplateSpecialization = true; IsPartialSpecialization = TemplateParams->size() > 0; } else { // if (TemplateParams->size() > 0) // This is a template declaration. IsVariableTemplate = true; - // Check that we can declare a template here. - if (CheckTemplateDeclScope(S, TemplateParams)) - return nullptr; - // Only C++1y supports variable templates (N3651). Diag(D.getIdentifierLoc(), getLangOpts().CPlusPlus14 @@ -6991,6 +7042,10 @@ NamedDecl *Sema::ActOnVariableDeclarator( } } } else { + // Check that we can declare a member specialization here. + if (!TemplateParamLists.empty() && IsMemberSpecialization && + CheckTemplateDeclScope(S, TemplateParamLists.back())) + return nullptr; assert((Invalid || D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) && "should have a 'template<>' for this decl"); @@ -7110,16 +7165,16 @@ NamedDecl *Sema::ActOnVariableDeclarator( } switch (D.getDeclSpec().getConstexprSpecifier()) { - case CSK_unspecified: + case ConstexprSpecKind::Unspecified: break; - case CSK_consteval: + case ConstexprSpecKind::Consteval: Diag(D.getDeclSpec().getConstexprSpecLoc(), - diag::err_constexpr_wrong_decl_kind) - << D.getDeclSpec().getConstexprSpecifier(); + diag::err_constexpr_wrong_decl_kind) + << static_cast<int>(D.getDeclSpec().getConstexprSpecifier()); LLVM_FALLTHROUGH; - case CSK_constexpr: + case ConstexprSpecKind::Constexpr: NewVD->setConstexpr(true); MaybeAddCUDAConstantAttr(NewVD); // C++1z [dcl.spec.constexpr]p1: @@ -7131,7 +7186,7 @@ NamedDecl *Sema::ActOnVariableDeclarator( NewVD->setImplicitlyInline(); break; - case CSK_constinit: + case ConstexprSpecKind::Constinit: if (!NewVD->hasGlobalStorage()) Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_constinit_local_variable); @@ -7173,9 +7228,10 @@ NamedDecl *Sema::ActOnVariableDeclarator( << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc()); else if (NewVD->hasLocalStorage()) Diag(NewVD->getLocation(), diag::err_module_private_local) - << 0 << NewVD->getDeclName() - << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc()) - << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc()); + << 0 << NewVD + << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc()) + << FixItHint::CreateRemoval( + D.getDeclSpec().getModulePrivateSpecLoc()); else { NewVD->setModulePrivate(); if (NewTemplate) @@ -7982,7 +8038,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { return; } - Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size); + Diag(NewVD->getLocation(), diag::ext_vla_folded_to_constant); NewVD->setType(FixedT); NewVD->setTypeSourceInfo(FixedTInfo); } @@ -8022,6 +8078,14 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { NewVD->setInvalidDecl(); return; } + + // PPC MMA non-pointer types are not allowed as non-local variable types. + if (Context.getTargetInfo().getTriple().isPPC64() && + !NewVD->isLocalVarDecl() && + CheckPPCMMAType(T, NewVD->getLocation())) { + NewVD->setInvalidDecl(); + return; + } } /// Perform semantic checking on a newly-created variable @@ -8056,73 +8120,54 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous) { return false; } -namespace { -struct FindOverriddenMethod { - Sema *S; - CXXMethodDecl *Method; - - /// Member lookup function that determines whether a given C++ - /// method overrides a method in a base class, to be used with - /// CXXRecordDecl::lookupInBases(). - bool operator()(const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { - RecordDecl *BaseRecord = - Specifier->getType()->castAs<RecordType>()->getDecl(); +/// AddOverriddenMethods - See if a method overrides any in the base classes, +/// and if so, check that it's a valid override and remember it. +bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { + llvm::SmallPtrSet<const CXXMethodDecl*, 4> Overridden; - DeclarationName Name = Method->getDeclName(); + // Look for methods in base classes that this method might override. + CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/false, + /*DetectVirtual=*/false); + auto VisitBase = [&] (const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { + CXXRecordDecl *BaseRecord = Specifier->getType()->getAsCXXRecordDecl(); + DeclarationName Name = MD->getDeclName(); - // FIXME: Do we care about other names here too? if (Name.getNameKind() == DeclarationName::CXXDestructorName) { // We really want to find the base class destructor here. - QualType T = S->Context.getTypeDeclType(BaseRecord); - CanQualType CT = S->Context.getCanonicalType(T); - - Name = S->Context.DeclarationNames.getCXXDestructorName(CT); - } - - for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty(); - Path.Decls = Path.Decls.slice(1)) { - NamedDecl *D = Path.Decls.front(); - if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { - if (MD->isVirtual() && - !S->IsOverload( - Method, MD, /*UseMemberUsingDeclRules=*/false, - /*ConsiderCudaAttrs=*/true, - // C++2a [class.virtual]p2 does not consider requires clauses - // when overriding. - /*ConsiderRequiresClauses=*/false)) - return true; + QualType T = Context.getTypeDeclType(BaseRecord); + CanQualType CT = Context.getCanonicalType(T); + Name = Context.DeclarationNames.getCXXDestructorName(CT); + } + + for (NamedDecl *BaseND : BaseRecord->lookup(Name)) { + CXXMethodDecl *BaseMD = + dyn_cast<CXXMethodDecl>(BaseND->getCanonicalDecl()); + if (!BaseMD || !BaseMD->isVirtual() || + IsOverload(MD, BaseMD, /*UseMemberUsingDeclRules=*/false, + /*ConsiderCudaAttrs=*/true, + // C++2a [class.virtual]p2 does not consider requires + // clauses when overriding. + /*ConsiderRequiresClauses=*/false)) + continue; + + if (Overridden.insert(BaseMD).second) { + MD->addOverriddenMethod(BaseMD); + CheckOverridingFunctionReturnType(MD, BaseMD); + CheckOverridingFunctionAttributes(MD, BaseMD); + CheckOverridingFunctionExceptionSpec(MD, BaseMD); + CheckIfOverriddenFunctionIsMarkedFinal(MD, BaseMD); } + + // A method can only override one function from each base class. We + // don't track indirectly overridden methods from bases of bases. + return true; } return false; - } -}; -} // end anonymous namespace - -/// AddOverriddenMethods - See if a method overrides any in the base classes, -/// and if so, check that it's a valid override and remember it. -bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { - // Look for methods in base classes that this method might override. - CXXBasePaths Paths; - FindOverriddenMethod FOM; - FOM.Method = MD; - FOM.S = this; - bool AddedAny = false; - if (DC->lookupInBases(FOM, Paths)) { - for (auto *I : Paths.found_decls()) { - if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(I)) { - MD->addOverriddenMethod(OldMD->getCanonicalDecl()); - if (!CheckOverridingFunctionReturnType(MD, OldMD) && - !CheckOverridingFunctionAttributes(MD, OldMD) && - !CheckOverridingFunctionExceptionSpec(MD, OldMD) && - !CheckIfOverriddenFunctionIsMarkedFinal(MD, OldMD)) { - AddedAny = true; - } - } - } - } + }; - return AddedAny; + DC->lookupInBases(VisitBase, Paths); + return !Overridden.empty(); } namespace { @@ -8401,7 +8446,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, NewFD = FunctionDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), NameInfo, R, TInfo, SC, isInline, HasPrototype, - CSK_unspecified, + ConstexprSpecKind::Unspecified, /*TrailingRequiresClause=*/nullptr); if (D.isInvalidType()) NewFD->setInvalidDecl(); @@ -8412,11 +8457,11 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, ExplicitSpecifier ExplicitSpecifier = D.getDeclSpec().getExplicitSpecifier(); ConstexprSpecKind ConstexprKind = D.getDeclSpec().getConstexprSpecifier(); - if (ConstexprKind == CSK_constinit) { + if (ConstexprKind == ConstexprSpecKind::Constinit) { SemaRef.Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_constexpr_wrong_decl_kind) - << ConstexprKind; - ConstexprKind = CSK_unspecified; + << static_cast<int>(ConstexprKind); + ConstexprKind = ConstexprSpecKind::Unspecified; D.getMutableDeclSpec().ClearConstexprSpec(); } Expr *TrailingRequiresClause = D.getTrailingRequiresClause(); @@ -8570,12 +8615,21 @@ static bool isOpenCLSizeDependentType(ASTContext &C, QualType Ty) { static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) { if (PT->isPointerType()) { QualType PointeeType = PT->getPointeeType(); - if (PointeeType->isPointerType()) - return PtrPtrKernelParam; if (PointeeType.getAddressSpace() == LangAS::opencl_generic || PointeeType.getAddressSpace() == LangAS::opencl_private || PointeeType.getAddressSpace() == LangAS::Default) return InvalidAddrSpacePtrKernelParam; + + if (PointeeType->isPointerType()) { + // This is a pointer to pointer parameter. + // Recursively check inner type. + OpenCLParamType ParamKind = getOpenCLKernelParameterType(S, PointeeType); + if (ParamKind == InvalidAddrSpacePtrKernelParam || + ParamKind == InvalidKernelParam) + return ParamKind; + + return PtrPtrKernelParam; + } return PtrKernelParam; } @@ -8628,11 +8682,17 @@ static void checkIsValidOpenCLKernelParameter( switch (getOpenCLKernelParameterType(S, PT)) { case PtrPtrKernelParam: - // OpenCL v1.2 s6.9.a: - // A kernel function argument cannot be declared as a - // pointer to a pointer type. - S.Diag(Param->getLocation(), diag::err_opencl_ptrptr_kernel_param); - D.setInvalidType(); + // OpenCL v3.0 s6.11.a: + // A kernel function argument cannot be declared as a pointer to a pointer + // type. [...] This restriction only applies to OpenCL C 1.2 or below. + if (S.getLangOpts().OpenCLVersion < 120 && + !S.getLangOpts().OpenCLCPlusPlus) { + S.Diag(Param->getLocation(), diag::err_opencl_ptrptr_kernel_param); + D.setInvalidType(); + return; + } + + ValidTypes.insert(PT.getTypePtr()); return; case InvalidAddrSpacePtrKernelParam: @@ -8916,13 +8976,13 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, TemplateParamLists, isFriend, isMemberSpecialization, Invalid); if (TemplateParams) { + // Check that we can declare a template here. + if (CheckTemplateDeclScope(S, TemplateParams)) + NewFD->setInvalidDecl(); + if (TemplateParams->size() > 0) { // This is a function template - // Check that we can declare a template here. - if (CheckTemplateDeclScope(S, TemplateParams)) - NewFD->setInvalidDecl(); - // A destructor cannot be a template. if (Name.getNameKind() == DeclarationName::CXXDestructorName) { Diag(NewFD->getLocation(), diag::err_destructor_template); @@ -8981,6 +9041,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } } } else { + // Check that we can declare a template here. + if (!TemplateParamLists.empty() && isMemberSpecialization && + CheckTemplateDeclScope(S, TemplateParamLists.back())) + NewFD->setInvalidDecl(); + // All template param lists were matched against the scope specifier: // this is NOT (an explicit specialization of) a template. if (TemplateParamLists.size() > 0) @@ -9075,8 +9140,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } } - if (ConstexprSpecKind ConstexprKind = - D.getDeclSpec().getConstexprSpecifier()) { + ConstexprSpecKind ConstexprKind = D.getDeclSpec().getConstexprSpecifier(); + if (ConstexprKind != ConstexprSpecKind::Unspecified) { // C++11 [dcl.constexpr]p2: constexpr functions and constexpr constructors // are implicitly inline. NewFD->setImplicitlyInline(); @@ -9085,15 +9150,18 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // be either constructors or to return a literal type. Therefore, // destructors cannot be declared constexpr. if (isa<CXXDestructorDecl>(NewFD) && - (!getLangOpts().CPlusPlus20 || ConstexprKind == CSK_consteval)) { + (!getLangOpts().CPlusPlus20 || + ConstexprKind == ConstexprSpecKind::Consteval)) { Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_constexpr_dtor) - << ConstexprKind; - NewFD->setConstexprKind(getLangOpts().CPlusPlus20 ? CSK_unspecified : CSK_constexpr); + << static_cast<int>(ConstexprKind); + NewFD->setConstexprKind(getLangOpts().CPlusPlus20 + ? ConstexprSpecKind::Unspecified + : ConstexprSpecKind::Constexpr); } // C++20 [dcl.constexpr]p2: An allocation function, or a // deallocation function shall not be declared with the consteval // specifier. - if (ConstexprKind == CSK_consteval && + if (ConstexprKind == ConstexprSpecKind::Consteval && (NewFD->getOverloadedOperator() == OO_New || NewFD->getOverloadedOperator() == OO_Array_New || NewFD->getOverloadedOperator() == OO_Delete || @@ -9101,7 +9169,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_consteval_decl_kind) << NewFD; - NewFD->setConstexprKind(CSK_constexpr); + NewFD->setConstexprKind(ConstexprSpecKind::Constexpr); } } @@ -9132,17 +9200,17 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // If a function is defined as defaulted or deleted, mark it as such now. // We'll do the relevant checks on defaulted / deleted functions later. switch (D.getFunctionDefinitionKind()) { - case FDK_Declaration: - case FDK_Definition: - break; + case FunctionDefinitionKind::Declaration: + case FunctionDefinitionKind::Definition: + break; - case FDK_Defaulted: - NewFD->setDefaulted(); - break; + case FunctionDefinitionKind::Defaulted: + NewFD->setDefaulted(); + break; - case FDK_Deleted: - NewFD->setDeletedAsWritten(); - break; + case FunctionDefinitionKind::Deleted: + NewFD->setDeletedAsWritten(); + break; } if (isa<CXXMethodDecl>(NewFD) && DC == CurContext && @@ -9459,12 +9527,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // that either the specialized function type or the specialized // template is dependent, and therefore matching will fail. In // this case, don't check the specialization yet. - bool InstantiationDependent = false; if (isFunctionTemplateSpecialization && isFriend && (NewFD->getType()->isDependentType() || DC->isDependentContext() || - TemplateSpecializationType::anyDependentTemplateArguments( - TemplateArgs, - InstantiationDependent))) { + TemplateSpecializationType::anyInstantiationDependentTemplateArguments( + TemplateArgs.arguments()))) { assert(HasExplicitTemplateArgs && "friend function specialization without template args"); if (CheckDependentFunctionTemplateSpecialization(NewFD, TemplateArgs, @@ -9636,6 +9702,36 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } } + // If this is the first declaration of a library builtin function, add + // attributes as appropriate. + if (!D.isRedeclaration() && + NewFD->getDeclContext()->getRedeclContext()->isFileContext()) { + if (IdentifierInfo *II = Previous.getLookupName().getAsIdentifierInfo()) { + if (unsigned BuiltinID = II->getBuiltinID()) { + if (NewFD->getLanguageLinkage() == CLanguageLinkage) { + // Validate the type matches unless this builtin is specified as + // matching regardless of its declared type. + if (Context.BuiltinInfo.allowTypeMismatch(BuiltinID)) { + NewFD->addAttr(BuiltinAttr::CreateImplicit(Context, BuiltinID)); + } else { + ASTContext::GetBuiltinTypeError Error; + LookupNecessaryTypesForBuiltin(S, BuiltinID); + QualType BuiltinType = Context.GetBuiltinType(BuiltinID, Error); + + if (!Error && !BuiltinType.isNull() && + Context.hasSameFunctionTypeIgnoringExceptionSpec( + NewFD->getType(), BuiltinType)) + NewFD->addAttr(BuiltinAttr::CreateImplicit(Context, BuiltinID)); + } + } else if (BuiltinID == Builtin::BI__GetExceptionInfo && + Context.getTargetInfo().getCXXABI().isMicrosoft()) { + // FIXME: We should consider this a builtin only in the std namespace. + NewFD->addAttr(BuiltinAttr::CreateImplicit(Context, BuiltinID)); + } + } + } + } + ProcessPragmaWeak(S, NewFD); checkAttributesAfterMerging(*this, *NewFD); @@ -9813,17 +9909,17 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // because Sema::ActOnStartOfFunctionDef has not been called yet. if (const auto *NBA = NewFD->getAttr<NoBuiltinAttr>()) switch (D.getFunctionDefinitionKind()) { - case FDK_Defaulted: - case FDK_Deleted: + case FunctionDefinitionKind::Defaulted: + case FunctionDefinitionKind::Deleted: Diag(NBA->getLocation(), diag::err_attribute_no_builtin_on_defaulted_deleted_function) << NBA->getSpelling(); break; - case FDK_Declaration: + case FunctionDefinitionKind::Declaration: Diag(NBA->getLocation(), diag::err_attribute_no_builtin_on_non_definition) << NBA->getSpelling(); break; - case FDK_Definition: + case FunctionDefinitionKind::Definition: break; } @@ -9996,31 +10092,50 @@ static bool CheckMultiVersionValue(Sema &S, const FunctionDecl *FD) { // multiversion functions. static bool AttrCompatibleWithMultiVersion(attr::Kind Kind, MultiVersionKind MVType) { + // Note: this list/diagnosis must match the list in + // checkMultiversionAttributesAllSame. switch (Kind) { default: return false; case attr::Used: return MVType == MultiVersionKind::Target; + case attr::NonNull: + case attr::NoThrow: + return true; } } -static bool HasNonMultiVersionAttributes(const FunctionDecl *FD, - MultiVersionKind MVType) { +static bool checkNonMultiVersionCompatAttributes(Sema &S, + const FunctionDecl *FD, + const FunctionDecl *CausedFD, + MultiVersionKind MVType) { + bool IsCPUSpecificCPUDispatchMVType = + MVType == MultiVersionKind::CPUDispatch || + MVType == MultiVersionKind::CPUSpecific; + const auto Diagnose = [FD, CausedFD, IsCPUSpecificCPUDispatchMVType]( + Sema &S, const Attr *A) { + S.Diag(FD->getLocation(), diag::err_multiversion_disallowed_other_attr) + << IsCPUSpecificCPUDispatchMVType << A; + if (CausedFD) + S.Diag(CausedFD->getLocation(), diag::note_multiversioning_caused_here); + return true; + }; + for (const Attr *A : FD->attrs()) { switch (A->getKind()) { case attr::CPUDispatch: case attr::CPUSpecific: if (MVType != MultiVersionKind::CPUDispatch && MVType != MultiVersionKind::CPUSpecific) - return true; + return Diagnose(S, A); break; case attr::Target: if (MVType != MultiVersionKind::Target) - return true; + return Diagnose(S, A); break; default: if (!AttrCompatibleWithMultiVersion(A->getKind(), MVType)) - return true; + return Diagnose(S, A); break; } } @@ -10154,18 +10269,12 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD, MVType == MultiVersionKind::CPUDispatch || MVType == MultiVersionKind::CPUSpecific; - // For now, disallow all other attributes. These should be opt-in, but - // an analysis of all of them is a future FIXME. - if (CausesMV && OldFD && HasNonMultiVersionAttributes(OldFD, MVType)) { - S.Diag(OldFD->getLocation(), diag::err_multiversion_no_other_attrs) - << IsCPUSpecificCPUDispatchMVType; - S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here); + if (CausesMV && OldFD && + checkNonMultiVersionCompatAttributes(S, OldFD, NewFD, MVType)) return true; - } - if (HasNonMultiVersionAttributes(NewFD, MVType)) - return S.Diag(NewFD->getLocation(), diag::err_multiversion_no_other_attrs) - << IsCPUSpecificCPUDispatchMVType; + if (checkNonMultiVersionCompatAttributes(S, NewFD, nullptr, MVType)) + return true; // Only allow transition to MultiVersion if it hasn't been used. if (OldFD && CausesMV && OldFD->isUsed(false)) @@ -10618,6 +10727,12 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, MergeTypeWithPrevious, Previous)) return Redeclaration; + // PPC MMA non-pointer types are not allowed as function return types. + if (Context.getTargetInfo().getTriple().isPPC64() && + CheckPPCMMAType(NewFD->getReturnType(), NewFD->getLocation())) { + NewFD->setInvalidDecl(); + } + // C++11 [dcl.constexpr]p8: // A constexpr specifier for a non-static member function that is not // a constructor declares that member function to be const. @@ -10680,7 +10795,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, NewTemplateDecl->mergePrevDecl(OldTemplateDecl); NewFD->setPreviousDeclaration(OldFD); - adjustDeclContextForDeclaratorDecl(NewFD, OldFD); if (NewFD->isCXXClassMember()) { NewFD->setAccess(OldTemplateDecl->getAccess()); NewTemplateDecl->setAccess(OldTemplateDecl->getAccess()); @@ -10707,7 +10821,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, auto *OldFD = cast<FunctionDecl>(OldDecl); // This needs to happen first so that 'inline' propagates. NewFD->setPreviousDeclaration(OldFD); - adjustDeclContextForDeclaratorDecl(NewFD, OldFD); if (NewFD->isCXXClassMember()) NewFD->setAccess(OldFD->getAccess()); } @@ -10737,6 +10850,9 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, } } + if (LangOpts.OpenMP) + ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(NewFD); + // Semantic checking for this function declaration (in isolation). if (getLangOpts().CPlusPlus) { @@ -10815,7 +10931,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // declaration against the expected type for the builtin. if (unsigned BuiltinID = NewFD->getBuiltinID()) { ASTContext::GetBuiltinTypeError Error; - LookupPredefedObjCSuperType(*this, S, NewFD->getIdentifier()); + LookupNecessaryTypesForBuiltin(S, BuiltinID); QualType T = Context.GetBuiltinType(BuiltinID, Error); // If the type of the builtin differs only in its exception // specification, that's OK. @@ -10911,7 +11027,7 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) { Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_main) << FD->isConsteval() << FixItHint::CreateRemoval(DS.getConstexprSpecLoc()); - FD->setConstexprKind(CSK_unspecified); + FD->setConstexprKind(ConstexprSpecKind::Unspecified); } if (getLangOpts().OpenCL) { @@ -11067,8 +11183,14 @@ bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) { // except that the aforementioned are allowed in unevaluated // expressions. Everything else falls under the // "may accept other forms of constant expressions" exception. - // (We never end up here for C++, so the constant expression - // rules there don't matter.) + // + // Regular C++ code will not end up here (exceptions: language extensions, + // OpenCL C++ etc), so the constant expression rules there don't matter. + if (Init->isValueDependent()) { + assert(Init->containsErrors() && + "Dependent code should only occur in error-recovery path."); + return true; + } const Expr *Culprit; if (Init->isConstantInitializer(Context, false, &Culprit)) return false; @@ -12033,7 +12155,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { // Try to correct any TypoExprs in the initialization arguments. for (size_t Idx = 0; Idx < Args.size(); ++Idx) { ExprResult Res = CorrectDelayedTyposInExpr( - Args[Idx], VDecl, /*RecoverUncorrectedTypos=*/false, + Args[Idx], VDecl, /*RecoverUncorrectedTypos=*/true, [this, Entity, Kind](Expr *E) { InitializationSequence Init(*this, Entity, Kind, MultiExprArg(E)); return Init.Failed() ? ExprError() : E; @@ -12402,7 +12524,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { !Context.getTargetInfo().getCXXABI().isMicrosoft()) { Diag(Var->getLocation(), diag::err_constexpr_static_mem_var_requires_init) - << Var->getDeclName(); + << Var; Var->setInvalidDecl(); return; } @@ -12424,6 +12546,17 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { } if (!Var->isInvalidDecl() && RealDecl->hasAttr<LoaderUninitializedAttr>()) { + if (Var->getStorageClass() == SC_Extern) { + Diag(Var->getLocation(), diag::err_loader_uninitialized_extern_decl) + << Var; + Var->setInvalidDecl(); + return; + } + if (RequireCompleteType(Var->getLocation(), Var->getType(), + diag::err_typecheck_decl_incomplete_type)) { + Var->setInvalidDecl(); + return; + } if (CXXRecordDecl *RD = Var->getType()->getAsCXXRecordDecl()) { if (!RD->hasTrivialDefaultConstructor()) { Diag(Var->getLocation(), diag::err_loader_uninitialized_trivial_ctor); @@ -12431,12 +12564,6 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { return; } } - if (Var->getStorageClass() == SC_Extern) { - Diag(Var->getLocation(), diag::err_loader_uninitialized_extern_decl) - << Var; - Var->setInvalidDecl(); - return; - } } VarDecl::DefinitionKind DefKind = Var->isThisDeclarationADefinition(); @@ -12535,8 +12662,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { // definitions with reference type. if (Type->isReferenceType()) { Diag(Var->getLocation(), diag::err_reference_var_requires_init) - << Var->getDeclName() - << SourceRange(Var->getLocation(), Var->getLocation()); + << Var << SourceRange(Var->getLocation(), Var->getLocation()); Var->setInvalidDecl(); return; } @@ -12667,9 +12793,21 @@ void Sema::ActOnCXXForRangeDecl(Decl *D) { Error = 4; break; } + + // for-range-declaration cannot be given a storage class specifier con't. + switch (VD->getTSCSpec()) { + case TSCS_thread_local: + Error = 6; + break; + case TSCS___thread: + case TSCS__Thread_local: + case TSCS_unspecified: + break; + } + if (Error != -1) { Diag(VD->getOuterLocStart(), diag::err_for_range_storage_class) - << VD->getDeclName() << Error; + << VD << Error; D->setInvalidDecl(); } } @@ -12691,7 +12829,7 @@ Sema::ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc, DS.SetTypeSpecType(DeclSpec::TST_auto, IdentLoc, PrevSpec, DiagID, getPrintingPolicy()); - Declarator D(DS, DeclaratorContext::ForContext); + Declarator D(DS, DeclaratorContext::ForInit); D.SetIdentifier(Ident, IdentLoc); D.takeAttributes(Attrs, AttrEnd); @@ -12835,20 +12973,64 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { AttributeCommonInfo::AS_Pragma)); } + if (!var->getType()->isStructureType() && var->hasInit() && + isa<InitListExpr>(var->getInit())) { + const auto *ILE = cast<InitListExpr>(var->getInit()); + unsigned NumInits = ILE->getNumInits(); + if (NumInits > 2) + for (unsigned I = 0; I < NumInits; ++I) { + const auto *Init = ILE->getInit(I); + if (!Init) + break; + const auto *SL = dyn_cast<StringLiteral>(Init->IgnoreImpCasts()); + if (!SL) + break; + + unsigned NumConcat = SL->getNumConcatenated(); + // Diagnose missing comma in string array initialization. + // Do not warn when all the elements in the initializer are concatenated + // together. Do not warn for macros too. + if (NumConcat == 2 && !SL->getBeginLoc().isMacroID()) { + bool OnlyOneMissingComma = true; + for (unsigned J = I + 1; J < NumInits; ++J) { + const auto *Init = ILE->getInit(J); + if (!Init) + break; + const auto *SLJ = dyn_cast<StringLiteral>(Init->IgnoreImpCasts()); + if (!SLJ || SLJ->getNumConcatenated() > 1) { + OnlyOneMissingComma = false; + break; + } + } + + if (OnlyOneMissingComma) { + SmallVector<FixItHint, 1> Hints; + for (unsigned i = 0; i < NumConcat - 1; ++i) + Hints.push_back(FixItHint::CreateInsertion( + PP.getLocForEndOfToken(SL->getStrTokenLoc(i)), ",")); + + Diag(SL->getStrTokenLoc(1), + diag::warn_concatenated_literal_array_init) + << Hints; + Diag(SL->getBeginLoc(), + diag::note_concatenated_string_literal_silence); + } + // In any case, stop now. + break; + } + } + } + // All the following checks are C++ only. if (!getLangOpts().CPlusPlus) { - // If this variable must be emitted, add it as an initializer for the - // current module. - if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty()) - Context.addModuleInitializer(ModuleScopes.back().Module, var); - return; + // If this variable must be emitted, add it as an initializer for the + // current module. + if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty()) + Context.addModuleInitializer(ModuleScopes.back().Module, var); + return; } - if (auto *DD = dyn_cast<DecompositionDecl>(var)) - CheckCompleteDecompositionDeclaration(DD); - QualType type = var->getType(); - if (type->isDependentType()) return; if (var->hasAttr<BlocksAttr>()) getCurFunction()->addByrefBlockVar(var); @@ -12857,79 +13039,93 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { bool IsGlobal = GlobalStorage && !var->isStaticLocal(); QualType baseType = Context.getBaseElementType(type); - if (Init && !Init->isValueDependent()) { - if (var->isConstexpr()) { - SmallVector<PartialDiagnosticAt, 8> Notes; - if (!var->evaluateValue(Notes) || !var->isInitICE()) { - SourceLocation DiagLoc = var->getLocation(); - // If the note doesn't add any useful information other than a source - // location, fold it into the primary diagnostic. - if (Notes.size() == 1 && Notes[0].second.getDiagID() == - diag::note_invalid_subexpr_in_const_expr) { - DiagLoc = Notes[0].first; - Notes.clear(); - } - Diag(DiagLoc, diag::err_constexpr_var_requires_const_init) - << var << Init->getSourceRange(); - for (unsigned I = 0, N = Notes.size(); I != N; ++I) - Diag(Notes[I].first, Notes[I].second); + // Check whether the initializer is sufficiently constant. + if (!type->isDependentType() && Init && !Init->isValueDependent() && + (GlobalStorage || var->isConstexpr() || + var->mightBeUsableInConstantExpressions(Context))) { + // If this variable might have a constant initializer or might be usable in + // constant expressions, check whether or not it actually is now. We can't + // do this lazily, because the result might depend on things that change + // later, such as which constexpr functions happen to be defined. + SmallVector<PartialDiagnosticAt, 8> Notes; + bool HasConstInit; + if (!getLangOpts().CPlusPlus11) { + // Prior to C++11, in contexts where a constant initializer is required, + // the set of valid constant initializers is described by syntactic rules + // in [expr.const]p2-6. + // FIXME: Stricter checking for these rules would be useful for constinit / + // -Wglobal-constructors. + HasConstInit = checkConstInit(); + + // Compute and cache the constant value, and remember that we have a + // constant initializer. + if (HasConstInit) { + (void)var->checkForConstantInitialization(Notes); + Notes.clear(); + } else if (CacheCulprit) { + Notes.emplace_back(CacheCulprit->getExprLoc(), + PDiag(diag::note_invalid_subexpr_in_const_expr)); + Notes.back().second << CacheCulprit->getSourceRange(); } - } else if (var->mightBeUsableInConstantExpressions(Context)) { - // Check whether the initializer of a const variable of integral or - // enumeration type is an ICE now, since we can't tell whether it was - // initialized by a constant expression if we check later. - var->checkInitIsICE(); - } - - // Don't emit further diagnostics about constexpr globals since they - // were just diagnosed. - if (!var->isConstexpr() && GlobalStorage && var->hasAttr<ConstInitAttr>()) { - // FIXME: Need strict checking in C++03 here. - bool DiagErr = getLangOpts().CPlusPlus11 - ? !var->checkInitIsICE() : !checkConstInit(); - if (DiagErr) { - auto *Attr = var->getAttr<ConstInitAttr>(); - Diag(var->getLocation(), diag::err_require_constant_init_failed) - << Init->getSourceRange(); - Diag(Attr->getLocation(), - diag::note_declared_required_constant_init_here) - << Attr->getRange() << Attr->isConstinit(); - if (getLangOpts().CPlusPlus11) { - APValue Value; - SmallVector<PartialDiagnosticAt, 8> Notes; - Init->EvaluateAsInitializer(Value, getASTContext(), var, Notes); - for (auto &it : Notes) - Diag(it.first, it.second); - } else { - Diag(CacheCulprit->getExprLoc(), - diag::note_invalid_subexpr_in_const_expr) - << CacheCulprit->getSourceRange(); - } + } else { + // Evaluate the initializer to see if it's a constant initializer. + HasConstInit = var->checkForConstantInitialization(Notes); + } + + if (HasConstInit) { + // FIXME: Consider replacing the initializer with a ConstantExpr. + } else if (var->isConstexpr()) { + SourceLocation DiagLoc = var->getLocation(); + // If the note doesn't add any useful information other than a source + // location, fold it into the primary diagnostic. + if (Notes.size() == 1 && Notes[0].second.getDiagID() == + diag::note_invalid_subexpr_in_const_expr) { + DiagLoc = Notes[0].first; + Notes.clear(); } - } - else if (!var->isConstexpr() && IsGlobal && - !getDiagnostics().isIgnored(diag::warn_global_constructor, - var->getLocation())) { + Diag(DiagLoc, diag::err_constexpr_var_requires_const_init) + << var << Init->getSourceRange(); + for (unsigned I = 0, N = Notes.size(); I != N; ++I) + Diag(Notes[I].first, Notes[I].second); + } else if (GlobalStorage && var->hasAttr<ConstInitAttr>()) { + auto *Attr = var->getAttr<ConstInitAttr>(); + Diag(var->getLocation(), diag::err_require_constant_init_failed) + << Init->getSourceRange(); + Diag(Attr->getLocation(), diag::note_declared_required_constant_init_here) + << Attr->getRange() << Attr->isConstinit(); + for (auto &it : Notes) + Diag(it.first, it.second); + } else if (IsGlobal && + !getDiagnostics().isIgnored(diag::warn_global_constructor, + var->getLocation())) { // Warn about globals which don't have a constant initializer. Don't // warn about globals with a non-trivial destructor because we already // warned about them. CXXRecordDecl *RD = baseType->getAsCXXRecordDecl(); if (!(RD && !RD->hasTrivialDestructor())) { + // checkConstInit() here permits trivial default initialization even in + // C++11 onwards, where such an initializer is not a constant initializer + // but nonetheless doesn't require a global constructor. if (!checkConstInit()) Diag(var->getLocation(), diag::warn_global_constructor) - << Init->getSourceRange(); + << Init->getSourceRange(); } } } // Require the destructor. - if (const RecordType *recordType = baseType->getAs<RecordType>()) - FinalizeVarWithDestructor(var, recordType); + if (!type->isDependentType()) + if (const RecordType *recordType = baseType->getAs<RecordType>()) + FinalizeVarWithDestructor(var, recordType); // If this variable must be emitted, add it as an initializer for the current // module. if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty()) Context.addModuleInitializer(ModuleScopes.back().Module, var); + + // Build the bindings if this is a structured binding declaration. + if (auto *DD = dyn_cast<DecompositionDecl>(var)) + CheckCompleteDecompositionDeclaration(DD); } /// Determines if a variable's alignment is dependent. @@ -13041,32 +13237,9 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) { } } - if (VD->isStaticLocal()) { + if (VD->isStaticLocal()) CheckStaticLocalForDllExport(VD); - if (dyn_cast_or_null<FunctionDecl>(VD->getParentFunctionOrMethod())) { - // CUDA 8.0 E.3.9.4: Within the body of a __device__ or __global__ - // function, only __shared__ variables or variables without any device - // memory qualifiers may be declared with static storage class. - // Note: It is unclear how a function-scope non-const static variable - // without device memory qualifier is implemented, therefore only static - // const variable without device memory qualifier is allowed. - [&]() { - if (!getLangOpts().CUDA) - return; - if (VD->hasAttr<CUDASharedAttr>()) - return; - if (VD->getType().isConstQualified() && - !(VD->hasAttr<CUDADeviceAttr>() || VD->hasAttr<CUDAConstantAttr>())) - return; - if (CUDADiagIfDeviceCode(VD->getLocation(), - diag::err_device_static_local_var) - << CurrentCUDATarget()) - VD->setInvalidDecl(); - }(); - } - } - // Perform check for initializers of device-side global variables. // CUDA allows empty constructors as initializers (see E.2.3.1, CUDA // 7.5). We must also apply the same checks to all __shared__ @@ -13144,20 +13317,20 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) { if (!MagicValueExpr) { continue; } - llvm::APSInt MagicValueInt; - if (!MagicValueExpr->isIntegerConstantExpr(MagicValueInt, Context)) { + Optional<llvm::APSInt> MagicValueInt; + if (!(MagicValueInt = MagicValueExpr->getIntegerConstantExpr(Context))) { Diag(I->getRange().getBegin(), diag::err_type_tag_for_datatype_not_ice) << LangOpts.CPlusPlus << MagicValueExpr->getSourceRange(); continue; } - if (MagicValueInt.getActiveBits() > 64) { + if (MagicValueInt->getActiveBits() > 64) { Diag(I->getRange().getBegin(), diag::err_type_tag_for_datatype_too_large) << LangOpts.CPlusPlus << MagicValueExpr->getSourceRange(); continue; } - uint64_t MagicValue = MagicValueInt.getZExtValue(); + uint64_t MagicValue = MagicValueInt->getZExtValue(); RegisterTypeTagForDatatype(I->getArgumentKind(), MagicValue, I->getMatchingCType(), @@ -13392,7 +13565,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { << getLangOpts().CPlusPlus17; if (DS.hasConstexprSpecifier()) Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr) - << 0 << D.getDeclSpec().getConstexprSpecifier(); + << 0 << static_cast<int>(D.getDeclSpec().getConstexprSpecifier()); DiagnoseFunctionSpecifiers(DS); @@ -13450,9 +13623,8 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { if (D.getDeclSpec().isModulePrivateSpecified()) Diag(New->getLocation(), diag::err_module_private_local) - << 1 << New->getDeclName() - << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc()) - << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc()); + << 1 << New << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc()) + << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc()); if (New->hasAttr<BlocksAttr>()) { Diag(New->getLocation(), diag::err_block_on_nonlocal); @@ -13504,8 +13676,7 @@ void Sema::DiagnoseSizeOfParametersAndReturnValue( if (!ReturnTy->isDependentType() && ReturnTy.isPODType(Context)) { unsigned Size = Context.getTypeSizeInChars(ReturnTy).getQuantity(); if (Size > LangOpts.NumLargeByValueCopy) - Diag(D->getLocation(), diag::warn_return_value_size) - << D->getDeclName() << Size; + Diag(D->getLocation(), diag::warn_return_value_size) << D << Size; } // Warn if any parameter is pass-by-value and larger than the specified @@ -13517,7 +13688,7 @@ void Sema::DiagnoseSizeOfParametersAndReturnValue( unsigned Size = Context.getTypeSizeInChars(T).getQuantity(); if (Size > LangOpts.NumLargeByValueCopy) Diag(Parameter->getLocation(), diag::warn_parameter_size) - << Parameter->getDeclName() << Size; + << Parameter << Size; } } @@ -13601,6 +13772,12 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc, New->setInvalidDecl(); } + // PPC MMA non-pointer types are not allowed as function argument types. + if (Context.getTargetInfo().getTriple().isPPC64() && + CheckPPCMMAType(New->getOriginalType(), New->getLocation())) { + New->setInvalidDecl(); + } + return New; } @@ -13632,7 +13809,7 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, // Use the identifier location for the type source range. DS.SetRangeStart(FTI.Params[i].IdentLoc); DS.SetRangeEnd(FTI.Params[i].IdentLoc); - Declarator ParamD(DS, DeclaratorContext::KNRTypeListContext); + Declarator ParamD(DS, DeclaratorContext::KNRTypeList); ParamD.SetIdentifier(FTI.Params[i].Ident, FTI.Params[i].IdentLoc); FTI.Params[i].Param = ActOnParamDeclarator(S, ParamD); } @@ -13655,19 +13832,17 @@ Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D, // variant` annotation which specifies the mangled definition as a // specialization function under the OpenMP context defined as part of the // `omp begin declare variant`. - FunctionDecl *BaseFD = nullptr; - if (LangOpts.OpenMP && isInOpenMPDeclareVariantScope() && - TemplateParameterLists.empty()) - BaseFD = ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope( - ParentScope, D); + SmallVector<FunctionDecl *, 4> Bases; + if (LangOpts.OpenMP && isInOpenMPDeclareVariantScope()) + ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope( + ParentScope, D, TemplateParameterLists, Bases); - D.setFunctionDefinitionKind(FDK_Definition); + D.setFunctionDefinitionKind(FunctionDefinitionKind::Definition); Decl *DP = HandleDeclarator(ParentScope, D, TemplateParameterLists); Decl *Dcl = ActOnStartOfFunctionDef(FnBodyScope, DP, SkipBody); - if (BaseFD) - ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope( - cast<FunctionDecl>(Dcl), BaseFD); + if (!Bases.empty()) + ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(Dcl, Bases); return Dcl; } @@ -13736,69 +13911,23 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD, const FunctionDecl *EffectiveDefinition, SkipBodyInfo *SkipBody) { const FunctionDecl *Definition = EffectiveDefinition; - if (!Definition && !FD->isDefined(Definition) && !FD->isCXXClassMember()) { - // If this is a friend function defined in a class template, it does not - // have a body until it is used, nevertheless it is a definition, see - // [temp.inst]p2: - // - // ... for the purpose of determining whether an instantiated redeclaration - // is valid according to [basic.def.odr] and [class.mem], a declaration that - // corresponds to a definition in the template is considered to be a - // definition. - // - // The following code must produce redefinition error: - // - // template<typename T> struct C20 { friend void func_20() {} }; - // C20<int> c20i; - // void func_20() {} - // - for (auto I : FD->redecls()) { - if (I != FD && !I->isInvalidDecl() && - I->getFriendObjectKind() != Decl::FOK_None) { - if (FunctionDecl *Original = I->getInstantiatedFromMemberFunction()) { - if (FunctionDecl *OrigFD = FD->getInstantiatedFromMemberFunction()) { - // A merged copy of the same function, instantiated as a member of - // the same class, is OK. - if (declaresSameEntity(OrigFD, Original) && - declaresSameEntity(cast<Decl>(I->getLexicalDeclContext()), - cast<Decl>(FD->getLexicalDeclContext()))) - continue; - } + if (!Definition && + !FD->isDefined(Definition, /*CheckForPendingFriendDefinition*/ true)) + return; - if (Original->isThisDeclarationADefinition()) { - Definition = I; - break; - } - } + if (Definition->getFriendObjectKind() != Decl::FOK_None) { + if (FunctionDecl *OrigDef = Definition->getInstantiatedFromMemberFunction()) { + if (FunctionDecl *OrigFD = FD->getInstantiatedFromMemberFunction()) { + // A merged copy of the same function, instantiated as a member of + // the same class, is OK. + if (declaresSameEntity(OrigFD, OrigDef) && + declaresSameEntity(cast<Decl>(Definition->getLexicalDeclContext()), + cast<Decl>(FD->getLexicalDeclContext()))) + return; } } } - if (!Definition) - // Similar to friend functions a friend function template may be a - // definition and do not have a body if it is instantiated in a class - // template. - if (FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate()) { - for (auto I : FTD->redecls()) { - auto D = cast<FunctionTemplateDecl>(I); - if (D != FTD) { - assert(!D->isThisDeclarationADefinition() && - "More than one definition in redeclaration chain"); - if (D->getFriendObjectKind() != Decl::FOK_None) - if (FunctionTemplateDecl *FT = - D->getInstantiatedFromMemberTemplate()) { - if (FT->isThisDeclarationADefinition()) { - Definition = D->getTemplatedDecl(); - break; - } - } - } - } - } - - if (!Definition) - return; - if (canRedefineFunction(Definition, getLangOpts())) return; @@ -13825,9 +13954,9 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD, if (getLangOpts().GNUMode && Definition->isInlineSpecified() && Definition->getStorageClass() == SC_Extern) Diag(FD->getLocation(), diag::err_redefinition_extern_inline) - << FD->getDeclName() << getLangOpts().CPlusPlus; + << FD << getLangOpts().CPlusPlus; else - Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName(); + Diag(FD->getLocation(), diag::err_redefinition) << FD; Diag(Definition->getLocation(), diag::note_previous_definition); FD->setInvalidDecl(); @@ -13916,9 +14045,20 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, FD->setInvalidDecl(); } - // See if this is a redefinition. If 'will have body' is already set, then - // these checks were already performed when it was set. - if (!FD->willHaveBody() && !FD->isLateTemplateParsed()) { + if (auto *Ctor = dyn_cast<CXXConstructorDecl>(FD)) { + if (Ctor->getTemplateSpecializationKind() == TSK_ExplicitSpecialization && + Ctor->isDefaultConstructor() && + Context.getTargetInfo().getCXXABI().isMicrosoft()) { + // If this is an MS ABI dllexport default constructor, instantiate any + // default arguments. + InstantiateDefaultCtorDefaultArgs(Ctor); + } + } + + // See if this is a redefinition. If 'will have body' (or similar) is already + // set, then these checks were already performed when it was set. + if (!FD->willHaveBody() && !FD->isLateTemplateParsed() && + !FD->isThisDeclarationInstantiatedFromAFriendDefinition()) { CheckForFunctionRedefinition(FD, nullptr, SkipBody); // If we're skipping the body, we're done. Don't enter the scope. @@ -14158,12 +14298,16 @@ static void diagnoseImplicitlyRetainedSelf(Sema &S) { Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, bool IsInstantiation) { + FunctionScopeInfo *FSI = getCurFunction(); FunctionDecl *FD = dcl ? dcl->getAsFunction() : nullptr; + if (FSI->UsesFPIntrin && !FD->hasAttr<StrictFPAttr>()) + FD->addAttr(StrictFPAttr::CreateImplicit(Context)); + sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy(); sema::AnalysisBasedWarnings::Policy *ActivePolicy = nullptr; - if (getLangOpts().Coroutines && getCurFunction()->isCoroutine()) + if (getLangOpts().Coroutines && FSI->isCoroutine()) CheckCompletedCoroutineBody(FD, Body); // Do not call PopExpressionEvaluationContext() if it is a lambda because one @@ -14240,7 +14384,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, // to deduce an implicit return type. if (FD->getReturnType()->isRecordType() && (!getLangOpts().CPlusPlus || !FD->isDependentContext())) - computeNRVO(Body, getCurFunction()); + computeNRVO(Body, FSI); } // GNU warning -Wmissing-prototypes: @@ -14364,14 +14508,14 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, MD->getReturnType(), MD); if (Body) - computeNRVO(Body, getCurFunction()); + computeNRVO(Body, FSI); } - if (getCurFunction()->ObjCShouldCallSuper) { + if (FSI->ObjCShouldCallSuper) { Diag(MD->getEndLoc(), diag::warn_objc_missing_super_call) << MD->getSelector().getAsString(); - getCurFunction()->ObjCShouldCallSuper = false; + FSI->ObjCShouldCallSuper = false; } - if (getCurFunction()->ObjCWarnForNoDesignatedInitChain) { + if (FSI->ObjCWarnForNoDesignatedInitChain) { const ObjCMethodDecl *InitMethod = nullptr; bool isDesignated = MD->isDesignatedInitializerForTheInterface(&InitMethod); @@ -14396,14 +14540,14 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, Diag(InitMethod->getLocation(), diag::note_objc_designated_init_marked_here); } - getCurFunction()->ObjCWarnForNoDesignatedInitChain = false; + FSI->ObjCWarnForNoDesignatedInitChain = false; } - if (getCurFunction()->ObjCWarnForNoInitDelegation) { + if (FSI->ObjCWarnForNoInitDelegation) { // Don't issue this warning for unavaialable inits. if (!MD->isUnavailable()) Diag(MD->getLocation(), diag::warn_objc_secondary_init_missing_init_call); - getCurFunction()->ObjCWarnForNoInitDelegation = false; + FSI->ObjCWarnForNoInitDelegation = false; } diagnoseImplicitlyRetainedSelf(*this); @@ -14414,10 +14558,10 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, return nullptr; } - if (Body && getCurFunction()->HasPotentialAvailabilityViolations) + if (Body && FSI->HasPotentialAvailabilityViolations) DiagnoseUnguardedAvailabilityViolations(dcl); - assert(!getCurFunction()->ObjCShouldCallSuper && + assert(!FSI->ObjCShouldCallSuper && "This should only be set for ObjC methods, which should have been " "handled in the block above."); @@ -14430,7 +14574,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, DiagnoseReturnInConstructorExceptionHandler(cast<CXXTryStmt>(Body)); // Verify that gotos and switch cases don't jump into scopes illegally. - if (getCurFunction()->NeedsScopeChecking() && + if (FSI->NeedsScopeChecking() && !PP.isCodeCompletionEnabled()) DiagnoseInvalidJumps(Body); @@ -14445,11 +14589,11 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, // If any errors have occurred, clear out any temporaries that may have // been leftover. This ensures that these temporaries won't be picked up for // deletion in some later function. - if (getDiagnostics().hasUncompilableErrorOccurred() || + if (hasUncompilableErrorOccurred() || getDiagnostics().getSuppressAllDiagnostics()) { DiscardCleanupsInEvaluationContext(); } - if (!getDiagnostics().hasUncompilableErrorOccurred() && + if (!hasUncompilableErrorOccurred() && !isa<FunctionTemplateDecl>(dcl)) { // Since the body is valid, issue any analysis-based warnings that are // enabled. @@ -14501,11 +14645,11 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, // If any errors have occurred, clear out any temporaries that may have // been leftover. This ensures that these temporaries won't be picked up for // deletion in some later function. - if (getDiagnostics().hasUncompilableErrorOccurred()) { + if (hasUncompilableErrorOccurred()) { DiscardCleanupsInEvaluationContext(); } - if (LangOpts.OpenMP || LangOpts.CUDA || LangOpts.SYCLIsDevice) { + if (FD && (LangOpts.OpenMP || LangOpts.CUDA || LangOpts.SYCLIsDevice)) { auto ES = getEmissionStatus(FD); if (ES == Sema::FunctionEmissionStatus::Emitted || ES == Sema::FunctionEmissionStatus::Unknown) @@ -14612,7 +14756,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, (void)Error; // Silence warning. assert(!Error && "Error setting up implicit decl!"); SourceLocation NoLoc; - Declarator D(DS, DeclaratorContext::BlockContext); + Declarator D(DS, DeclaratorContext::Block); D.AddTypeInfo(DeclaratorChunk::getFunction(/*HasProto=*/false, /*IsAmbiguous=*/false, /*LParenLoc=*/NoLoc, @@ -14882,9 +15026,10 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, if (D.getDeclSpec().isModulePrivateSpecified()) { if (CurContext->isFunctionOrMethod()) Diag(NewTD->getLocation(), diag::err_module_private_local) - << 2 << NewTD->getDeclName() - << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc()) - << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc()); + << 2 << NewTD + << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc()) + << FixItHint::CreateRemoval( + D.getDeclSpec().getModulePrivateSpecLoc()); else NewTD->setModulePrivate(); } @@ -15272,6 +15417,10 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, isMemberSpecialization = true; } } + + if (!TemplateParameterLists.empty() && isMemberSpecialization && + CheckTemplateDeclScope(S, TemplateParameterLists.back())) + return nullptr; } // Figure out the underlying type if this a enum declaration. We need to do @@ -15592,6 +15741,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // type declared by an elaborated-type-specifier. In C that is not correct // and we should instead merge compatible types found by lookup. if (getLangOpts().CPlusPlus) { + // FIXME: This can perform qualified lookups into function contexts, + // which are meaningless. Previous.setRedeclarationKind(forRedeclarationInCurContext()); LookupQualifiedName(Previous, SearchDC); } else { @@ -16309,7 +16460,7 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc, return BitWidth; llvm::APSInt Value; - ExprResult ICE = VerifyIntegerConstantExpression(BitWidth, &Value); + ExprResult ICE = VerifyIntegerConstantExpression(BitWidth, &Value, AllowFold); if (ICE.isInvalid()) return ICE; BitWidth = ICE.get(); @@ -16329,6 +16480,13 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc, << Value.toString(10); } + // The size of the bit-field must not exceed our maximum permitted object + // size. + if (Value.getActiveBits() > ConstantArrayType::getMaxSizeBits(Context)) { + return Diag(FieldLoc, diag::err_bitfield_too_wide) + << !FieldName << FieldName << Value.toString(10); + } + if (!FieldTy->isDependentType()) { uint64_t TypeStorageSize = Context.getTypeSize(FieldTy); uint64_t TypeWidth = Context.getIntWidth(FieldTy); @@ -16346,25 +16504,21 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc, CStdConstraintViolation ? TypeWidth : TypeStorageSize; if (FieldName) return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_width) - << FieldName << (unsigned)Value.getZExtValue() + << FieldName << Value.toString(10) << !CStdConstraintViolation << DiagWidth; return Diag(FieldLoc, diag::err_anon_bitfield_width_exceeds_type_width) - << (unsigned)Value.getZExtValue() << !CStdConstraintViolation + << Value.toString(10) << !CStdConstraintViolation << DiagWidth; } // Warn on types where the user might conceivably expect to get all // specified bits as value bits: that's all integral types other than // 'bool'. - if (BitfieldIsOverwide && !FieldTy->isBooleanType()) { - if (FieldName) - Diag(FieldLoc, diag::warn_bitfield_width_exceeds_type_width) - << FieldName << (unsigned)Value.getZExtValue() - << (unsigned)TypeWidth; - else - Diag(FieldLoc, diag::warn_anon_bitfield_width_exceeds_type_width) - << (unsigned)Value.getZExtValue() << (unsigned)TypeWidth; + if (BitfieldIsOverwide && !FieldTy->isBooleanType() && FieldName) { + Diag(FieldLoc, diag::warn_bitfield_width_exceeds_type_width) + << FieldName << Value.toString(10) + << (unsigned)TypeWidth; } } @@ -16558,27 +16712,9 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, // C99 6.7.2.1p8: A member of a structure or union may have any type other // than a variably modified type. if (!InvalidDecl && T->isVariablyModifiedType()) { - bool SizeIsNegative; - llvm::APSInt Oversized; - - TypeSourceInfo *FixedTInfo = - TryToFixInvalidVariablyModifiedTypeSourceInfo(TInfo, Context, - SizeIsNegative, - Oversized); - if (FixedTInfo) { - Diag(Loc, diag::warn_illegal_constant_array_size); - TInfo = FixedTInfo; - T = FixedTInfo->getType(); - } else { - if (SizeIsNegative) - Diag(Loc, diag::err_typecheck_negative_array_size); - else if (Oversized.getBoolValue()) - Diag(Loc, diag::err_array_too_large) - << Oversized.toString(10); - else - Diag(Loc, diag::err_typecheck_field_variable_size); + if (!tryToFixVariablyModifiedVarType( + *this, TInfo, T, Loc, diag::err_typecheck_field_variable_size)) InvalidDecl = true; - } } // Fields can not have abstract class types @@ -16599,14 +16735,6 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, BitWidth = nullptr; ZeroWidth = false; } - - // Only data members can have in-class initializers. - if (BitWidth && !II && InitStyle) { - Diag(Loc, diag::err_anon_bitfield_init); - InvalidDecl = true; - BitWidth = nullptr; - ZeroWidth = false; - } } // Check that 'mutable' is consistent with the type of the declaration. @@ -16694,6 +16822,11 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, if (T.isObjCGCWeak()) Diag(Loc, diag::warn_attribute_weak_on_field); + // PPC MMA non-pointer types are not allowed as field types. + if (Context.getTargetInfo().getTriple().isPPC64() && + CheckPPCMMAType(T, NewFD->getLocation())) + NewFD->setInvalidDecl(); + NewFD->setAccess(AS); return NewFD; } @@ -16807,8 +16940,9 @@ Decl *Sema::ActOnIvar(Scope *S, // C99 6.7.2.1p8: A member of a structure or union may have any type other // than a variably modified type. else if (T->isVariablyModifiedType()) { - Diag(Loc, diag::err_typecheck_ivar_variable_size); - D.setInvalidType(); + if (!tryToFixVariablyModifiedVarType( + *this, TInfo, T, Loc, diag::err_typecheck_ivar_variable_size)) + D.setInvalidType(); } // Get the visibility (access control) for this ivar. @@ -17271,7 +17405,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, CXXRecordDecl *CXXRecord = cast<CXXRecordDecl>(Record); CheckForZeroSize = CXXRecord->getLexicalDeclContext()->isExternCContext() && - !CXXRecord->isDependentType() && + !CXXRecord->isDependentType() && !inTemplateInstantiation() && CXXRecord->isCLike(); } if (CheckForZeroSize) { @@ -17435,6 +17569,8 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, if (Enum->isDependentType() || Val->isTypeDependent()) EltTy = Context.DependentTy; else { + // FIXME: We don't allow folding in C++11 mode for an enum with a fixed + // underlying type, but do allow it in all other contexts. if (getLangOpts().CPlusPlus11 && Enum->isFixed()) { // C++11 [dcl.enum]p5: If the underlying type is fixed, [...] the // constant-expression in the enumerator-definition shall be a converted @@ -17448,8 +17584,9 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, else Val = Converted.get(); } else if (!Val->isValueDependent() && - !(Val = VerifyIntegerConstantExpression(Val, - &EnumVal).get())) { + !(Val = + VerifyIntegerConstantExpression(Val, &EnumVal, AllowFold) + .get())) { // C99 6.7.2.2p2: Make sure we have an integer constant expression. } else { if (Enum->isComplete()) { @@ -18070,11 +18207,9 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, // Adjust the Expr initializer and type. if (ECD->getInitExpr() && !Context.hasSameType(NewTy, ECD->getInitExpr()->getType())) - ECD->setInitExpr(ImplicitCastExpr::Create(Context, NewTy, - CK_IntegralCast, - ECD->getInitExpr(), - /*base paths*/ nullptr, - VK_RValue)); + ECD->setInitExpr(ImplicitCastExpr::Create( + Context, NewTy, CK_IntegralCast, ECD->getInitExpr(), + /*base paths*/ nullptr, VK_RValue, FPOptionsOverride())); if (getLangOpts().CPlusPlus) // C++ [dcl.enum]p4: Following the closing brace of an // enum-specifier, each enumerator has the type of its diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 1a0594512a60..30d08b3d4ac0 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -21,7 +21,9 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/Mangle.h" #include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/Type.h" #include "clang/Basic/CharInfo.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetBuiltins.h" #include "clang/Basic/TargetInfo.h" @@ -30,12 +32,16 @@ #include "clang/Sema/DelayedDiagnostic.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/ParsedAttr.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/IR/Assumptions.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" using namespace clang; using namespace sema; @@ -240,9 +246,9 @@ template <typename AttrInfo> static bool checkUInt32Argument(Sema &S, const AttrInfo &AI, const Expr *Expr, uint32_t &Val, unsigned Idx = UINT_MAX, bool StrictlyUnsigned = false) { - llvm::APSInt I(32); + Optional<llvm::APSInt> I = llvm::APSInt(32); if (Expr->isTypeDependent() || Expr->isValueDependent() || - !Expr->isIntegerConstantExpr(I, S.Context)) { + !(I = Expr->getIntegerConstantExpr(S.Context))) { if (Idx != UINT_MAX) S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type) << &AI << Idx << AANT_ArgumentIntegerConstant @@ -253,19 +259,19 @@ static bool checkUInt32Argument(Sema &S, const AttrInfo &AI, const Expr *Expr, return false; } - if (!I.isIntN(32)) { + if (!I->isIntN(32)) { S.Diag(Expr->getExprLoc(), diag::err_ice_too_large) - << I.toString(10, false) << 32 << /* Unsigned */ 1; + << I->toString(10, false) << 32 << /* Unsigned */ 1; return false; } - if (StrictlyUnsigned && I.isSigned() && I.isNegative()) { + if (StrictlyUnsigned && I->isSigned() && I->isNegative()) { S.Diag(getAttrLoc(AI), diag::err_attribute_requires_positive_integer) << &AI << /*non-negative*/ 1; return false; } - Val = (uint32_t)I.getZExtValue(); + Val = (uint32_t)I->getZExtValue(); return true; } @@ -332,16 +338,16 @@ static bool checkFunctionOrMethodParameterIndex( unsigned NumParams = (HP ? getFunctionOrMethodNumParams(D) : 0) + HasImplicitThisParam; - llvm::APSInt IdxInt; + Optional<llvm::APSInt> IdxInt; if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() || - !IdxExpr->isIntegerConstantExpr(IdxInt, S.Context)) { + !(IdxInt = IdxExpr->getIntegerConstantExpr(S.Context))) { S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type) << &AI << AttrArgNum << AANT_ArgumentIntegerConstant << IdxExpr->getSourceRange(); return false; } - unsigned IdxSource = IdxInt.getLimitedValue(UINT_MAX); + unsigned IdxSource = IdxInt->getLimitedValue(UINT_MAX); if (IdxSource < 1 || (!IV && IdxSource > NumParams)) { S.Diag(getAttrLoc(AI), diag::err_attribute_argument_out_of_bounds) << &AI << AttrArgNum << IdxExpr->getSourceRange(); @@ -1376,6 +1382,43 @@ static void handlePackedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL; } +static void handlePreferredName(Sema &S, Decl *D, const ParsedAttr &AL) { + auto *RD = cast<CXXRecordDecl>(D); + ClassTemplateDecl *CTD = RD->getDescribedClassTemplate(); + assert(CTD && "attribute does not appertain to this declaration"); + + ParsedType PT = AL.getTypeArg(); + TypeSourceInfo *TSI = nullptr; + QualType T = S.GetTypeFromParser(PT, &TSI); + if (!TSI) + TSI = S.Context.getTrivialTypeSourceInfo(T, AL.getLoc()); + + if (!T.hasQualifiers() && T->isTypedefNameType()) { + // Find the template name, if this type names a template specialization. + const TemplateDecl *Template = nullptr; + if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>( + T->getAsCXXRecordDecl())) { + Template = CTSD->getSpecializedTemplate(); + } else if (const auto *TST = T->getAs<TemplateSpecializationType>()) { + while (TST && TST->isTypeAlias()) + TST = TST->getAliasedType()->getAs<TemplateSpecializationType>(); + if (TST) + Template = TST->getTemplateName().getAsTemplateDecl(); + } + + if (Template && declaresSameEntity(Template, CTD)) { + D->addAttr(::new (S.Context) PreferredNameAttr(S.Context, AL, TSI)); + return; + } + } + + S.Diag(AL.getLoc(), diag::err_attribute_preferred_name_arg_invalid) + << T << CTD; + if (const auto *TT = T->getAs<TypedefType>()) + S.Diag(TT->getDecl()->getLocation(), diag::note_entity_declared_at) + << TT->getDecl(); +} + static bool checkIBOutletCommon(Sema &S, Decl *D, const ParsedAttr &AL) { // The IBOutlet/IBOutletCollection attributes only apply to instance // variables or properties of Objective-C classes. The outlet must also @@ -1605,8 +1648,8 @@ void Sema::AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E, } if (!E->isValueDependent()) { - llvm::APSInt I(64); - if (!E->isIntegerConstantExpr(I, Context)) { + Optional<llvm::APSInt> I = llvm::APSInt(64); + if (!(I = E->getIntegerConstantExpr(Context))) { if (OE) Diag(AttrLoc, diag::err_attribute_argument_n_type) << &TmpAttr << 1 << AANT_ArgumentIntegerConstant @@ -1618,27 +1661,22 @@ void Sema::AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E, return; } - if (!I.isPowerOf2()) { + if (!I->isPowerOf2()) { Diag(AttrLoc, diag::err_alignment_not_power_of_two) << E->getSourceRange(); return; } - if (I > Sema::MaximumAlignment) + if (*I > Sema::MaximumAlignment) Diag(CI.getLoc(), diag::warn_assume_aligned_too_great) << CI.getRange() << Sema::MaximumAlignment; } - if (OE) { - if (!OE->isValueDependent()) { - llvm::APSInt I(64); - if (!OE->isIntegerConstantExpr(I, Context)) { - Diag(AttrLoc, diag::err_attribute_argument_n_type) - << &TmpAttr << 2 << AANT_ArgumentIntegerConstant - << OE->getSourceRange(); - return; - } - } + if (OE && !OE->isValueDependent() && !OE->isIntegerConstantExpr(Context)) { + Diag(AttrLoc, diag::err_attribute_argument_n_type) + << &TmpAttr << 2 << AANT_ArgumentIntegerConstant + << OE->getSourceRange(); + return; } D->addAttr(::new (Context) AssumeAlignedAttr(Context, CI, E, OE)); @@ -1676,6 +1714,42 @@ void Sema::AddAllocAlignAttr(Decl *D, const AttributeCommonInfo &CI, D->addAttr(::new (Context) AllocAlignAttr(Context, CI, Idx)); } +/// Check if \p AssumptionStr is a known assumption and warn if not. +static void checkAssumptionAttr(Sema &S, SourceLocation Loc, + StringRef AssumptionStr) { + if (llvm::KnownAssumptionStrings.count(AssumptionStr)) + return; + + unsigned BestEditDistance = 3; + StringRef Suggestion; + for (const auto &KnownAssumptionIt : llvm::KnownAssumptionStrings) { + unsigned EditDistance = + AssumptionStr.edit_distance(KnownAssumptionIt.getKey()); + if (EditDistance < BestEditDistance) { + Suggestion = KnownAssumptionIt.getKey(); + BestEditDistance = EditDistance; + } + } + + if (!Suggestion.empty()) + S.Diag(Loc, diag::warn_assume_attribute_string_unknown_suggested) + << AssumptionStr << Suggestion; + else + S.Diag(Loc, diag::warn_assume_attribute_string_unknown) << AssumptionStr; +} + +static void handleAssumumptionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + // Handle the case where the attribute has a text message. + StringRef Str; + SourceLocation AttrStrLoc; + if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc)) + return; + + checkAssumptionAttr(S, AttrStrLoc, Str); + + D->addAttr(::new (S.Context) AssumptionAttr(S.Context, AL, Str)); +} + /// Normalize the attribute, __foo__ becomes foo. /// Returns true if normalization was applied. static bool normalizeName(StringRef &AttrName) { @@ -2056,7 +2130,8 @@ bool Sema::CheckAttrNoArgs(const ParsedAttr &Attrs) { bool Sema::CheckAttrTarget(const ParsedAttr &AL) { // Check whether the attribute is valid on the current target. if (!AL.existsInTarget(Context.getTargetInfo())) { - Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) << AL; + Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) + << AL << AL.getRange(); AL.setInvalid(); return true; } @@ -2618,6 +2693,11 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const ParsedAttr &AL, D->addAttr(newAttr); } +static void handleObjCNonRuntimeProtocolAttr(Sema &S, Decl *D, + const ParsedAttr &AL) { + handleSimpleAttribute<ObjCNonRuntimeProtocolAttr>(S, D, AL); +} + static void handleObjCDirectAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // objc_direct cannot be set on methods declared in the context of a protocol if (isa<ObjCProtocolDecl>(D->getDeclContext())) { @@ -2729,36 +2809,36 @@ static void handleSentinelAttr(Sema &S, Decl *D, const ParsedAttr &AL) { unsigned sentinel = (unsigned)SentinelAttr::DefaultSentinel; if (AL.getNumArgs() > 0) { Expr *E = AL.getArgAsExpr(0); - llvm::APSInt Idx(32); + Optional<llvm::APSInt> Idx = llvm::APSInt(32); if (E->isTypeDependent() || E->isValueDependent() || - !E->isIntegerConstantExpr(Idx, S.Context)) { + !(Idx = E->getIntegerConstantExpr(S.Context))) { S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) << AL << 1 << AANT_ArgumentIntegerConstant << E->getSourceRange(); return; } - if (Idx.isSigned() && Idx.isNegative()) { + if (Idx->isSigned() && Idx->isNegative()) { S.Diag(AL.getLoc(), diag::err_attribute_sentinel_less_than_zero) << E->getSourceRange(); return; } - sentinel = Idx.getZExtValue(); + sentinel = Idx->getZExtValue(); } unsigned nullPos = (unsigned)SentinelAttr::DefaultNullPos; if (AL.getNumArgs() > 1) { Expr *E = AL.getArgAsExpr(1); - llvm::APSInt Idx(32); + Optional<llvm::APSInt> Idx = llvm::APSInt(32); if (E->isTypeDependent() || E->isValueDependent() || - !E->isIntegerConstantExpr(Idx, S.Context)) { + !(Idx = E->getIntegerConstantExpr(S.Context))) { S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) << AL << 2 << AANT_ArgumentIntegerConstant << E->getSourceRange(); return; } - nullPos = Idx.getZExtValue(); + nullPos = Idx->getZExtValue(); - if ((Idx.isSigned() && Idx.isNegative()) || nullPos > 1) { + if ((Idx->isSigned() && Idx->isNegative()) || nullPos > 1) { // FIXME: This error message could be improved, it would be nice // to say what the bounds actually are. S.Diag(AL.getLoc(), diag::err_attribute_sentinel_not_zero_or_one) @@ -3001,8 +3081,14 @@ static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } SectionAttr *NewAttr = S.mergeSectionAttr(D, AL, Str); - if (NewAttr) + if (NewAttr) { D->addAttr(NewAttr); + if (isa<FunctionDecl, FunctionTemplateDecl, ObjCMethodDecl, + ObjCPropertyDecl>(D)) + S.UnifySection(NewAttr->getName(), + ASTContext::PSF_Execute | ASTContext::PSF_Read, + cast<NamedDecl>(D)); + } } // This is used for `__declspec(code_seg("segname"))` on a decl. @@ -3063,23 +3149,36 @@ static void handleCodeSegAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // Check for things we'd like to warn about. Multiversioning issues are // handled later in the process, once we know how many exist. bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) { - enum FirstParam { Unsupported, Duplicate }; - enum SecondParam { None, Architecture }; - for (auto Str : {"tune=", "fpmath="}) - if (AttrStr.find(Str) != StringRef::npos) - return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) - << Unsupported << None << Str; + enum FirstParam { Unsupported, Duplicate, Unknown }; + enum SecondParam { None, Architecture, Tune }; + if (AttrStr.find("fpmath=") != StringRef::npos) + return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) + << Unsupported << None << "fpmath="; + + // Diagnose use of tune if target doesn't support it. + if (!Context.getTargetInfo().supportsTargetAttributeTune() && + AttrStr.find("tune=") != StringRef::npos) + return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) + << Unsupported << None << "tune="; ParsedTargetAttr ParsedAttrs = TargetAttr::parse(AttrStr); if (!ParsedAttrs.Architecture.empty() && !Context.getTargetInfo().isValidCPUName(ParsedAttrs.Architecture)) return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) - << Unsupported << Architecture << ParsedAttrs.Architecture; + << Unknown << Architecture << ParsedAttrs.Architecture; + + if (!ParsedAttrs.Tune.empty() && + !Context.getTargetInfo().isValidCPUName(ParsedAttrs.Tune)) + return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) + << Unknown << Tune << ParsedAttrs.Tune; if (ParsedAttrs.DuplicateArchitecture) return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) << Duplicate << None << "arch="; + if (ParsedAttrs.DuplicateTune) + return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) + << Duplicate << None << "tune="; for (const auto &Feature : ParsedAttrs.Features) { auto CurFeature = StringRef(Feature).drop_front(); // remove + or -. @@ -3301,7 +3400,11 @@ static void handleInitPriorityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { return; } - if (prioritynum < 101 || prioritynum > 65535) { + // Only perform the priority check if the attribute is outside of a system + // header. Values <= 100 are reserved for the implementation, and libc++ + // benefits from being able to specify values in that range. + if ((prioritynum < 101 || prioritynum > 65535) && + !S.getSourceManager().isInSystemHeader(AL.getLoc())) { S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_range) << E->getSourceRange() << AL << 101 << 65535; AL.setInvalid(); @@ -3590,6 +3693,26 @@ static void handleCallbackAttr(Sema &S, Decl *D, const ParsedAttr &AL) { S.Context, AL, EncodingIndices.data(), EncodingIndices.size())); } +static bool isFunctionLike(const Type &T) { + // Check for explicit function types. + // 'called_once' is only supported in Objective-C and it has + // function pointers and block pointers. + return T.isFunctionPointerType() || T.isBlockPointerType(); +} + +/// Handle 'called_once' attribute. +static void handleCalledOnceAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + // 'called_once' only applies to parameters representing functions. + QualType T = cast<ParmVarDecl>(D)->getType(); + + if (!isFunctionLike(*T)) { + S.Diag(AL.getLoc(), diag::err_called_once_attribute_wrong_type); + return; + } + + D->addAttr(::new (S.Context) CalledOnceAttr(S.Context, AL)); +} + static void handleTransparentUnionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // Try to find the underlying union declaration. RecordDecl *RD = nullptr; @@ -3645,15 +3768,15 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { S.Context.getTypeAlign(FieldType) > FirstAlign) { // Warn if we drop the attribute. bool isSize = S.Context.getTypeSize(FieldType) != FirstSize; - unsigned FieldBits = isSize? S.Context.getTypeSize(FieldType) - : S.Context.getTypeAlign(FieldType); + unsigned FieldBits = isSize ? S.Context.getTypeSize(FieldType) + : S.Context.getTypeAlign(FieldType); S.Diag(Field->getLocation(), - diag::warn_transparent_union_attribute_field_size_align) - << isSize << Field->getDeclName() << FieldBits; - unsigned FirstBits = isSize? FirstSize : FirstAlign; + diag::warn_transparent_union_attribute_field_size_align) + << isSize << *Field << FieldBits; + unsigned FirstBits = isSize ? FirstSize : FirstAlign; S.Diag(FirstField->getLocation(), diag::note_transparent_union_first_field_size_align) - << isSize << FirstBits; + << isSize << FirstBits; return; } } @@ -3661,20 +3784,68 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { RD->addAttr(::new (S.Context) TransparentUnionAttr(S.Context, AL)); } +void Sema::AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI, + StringRef Str, MutableArrayRef<Expr *> Args) { + auto *Attr = AnnotateAttr::Create(Context, Str, Args.data(), Args.size(), CI); + llvm::SmallVector<PartialDiagnosticAt, 8> Notes; + for (unsigned Idx = 0; Idx < Attr->args_size(); Idx++) { + Expr *&E = Attr->args_begin()[Idx]; + assert(E && "error are handled before"); + if (E->isValueDependent() || E->isTypeDependent()) + continue; + + if (E->getType()->isArrayType()) + E = ImpCastExprToType(E, Context.getPointerType(E->getType()), + clang::CK_ArrayToPointerDecay) + .get(); + if (E->getType()->isFunctionType()) + E = ImplicitCastExpr::Create(Context, + Context.getPointerType(E->getType()), + clang::CK_FunctionToPointerDecay, E, nullptr, + VK_RValue, FPOptionsOverride()); + if (E->isLValue()) + E = ImplicitCastExpr::Create(Context, E->getType().getNonReferenceType(), + clang::CK_LValueToRValue, E, nullptr, + VK_RValue, FPOptionsOverride()); + + Expr::EvalResult Eval; + Notes.clear(); + Eval.Diag = &Notes; + + bool Result = + E->EvaluateAsConstantExpr(Eval, Context); + + /// Result means the expression can be folded to a constant. + /// Note.empty() means the expression is a valid constant expression in the + /// current language mode. + if (!Result || !Notes.empty()) { + Diag(E->getBeginLoc(), diag::err_attribute_argument_n_type) + << CI << (Idx + 1) << AANT_ArgumentConstantExpr; + for (auto &Note : Notes) + Diag(Note.first, Note.second); + return; + } + assert(Eval.Val.hasValue()); + E = ConstantExpr::Create(Context, E, Eval.Val); + } + D->addAttr(Attr); +} + static void handleAnnotateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - // Make sure that there is a string literal as the annotation's single + // Make sure that there is a string literal as the annotation's first // argument. StringRef Str; if (!S.checkStringLiteralArgumentAttr(AL, 0, Str)) return; - // Don't duplicate annotations that are already set. - for (const auto *I : D->specific_attrs<AnnotateAttr>()) { - if (I->getAnnotation() == Str) - return; + llvm::SmallVector<Expr *, 4> Args; + Args.reserve(AL.getNumArgs() - 1); + for (unsigned Idx = 1; Idx < AL.getNumArgs(); Idx++) { + assert(!AL.isArgIdent(Idx)); + Args.push_back(AL.getArgAsExpr(Idx)); } - D->addAttr(::new (S.Context) AnnotateAttr(S.Context, AL, Str)); + S.AddAnnotationAttr(D, AL, Str, Args); } static void handleAlignValueAttr(Sema &S, Decl *D, const ParsedAttr &AL) { @@ -3702,10 +3873,8 @@ void Sema::AddAlignValueAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E) { if (!E->isValueDependent()) { llvm::APSInt Alignment; - ExprResult ICE - = VerifyIntegerConstantExpression(E, &Alignment, - diag::err_align_value_attribute_argument_not_int, - /*AllowFold*/ false); + ExprResult ICE = VerifyIntegerConstantExpression( + E, &Alignment, diag::err_align_value_attribute_argument_not_int); if (ICE.isInvalid()) return; @@ -3811,10 +3980,8 @@ void Sema::AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E, // FIXME: Cache the number on the AL object? llvm::APSInt Alignment; - ExprResult ICE - = VerifyIntegerConstantExpression(E, &Alignment, - diag::err_aligned_attribute_argument_not_int, - /*AllowFold*/ false); + ExprResult ICE = VerifyIntegerConstantExpression( + E, &Alignment, diag::err_aligned_attribute_argument_not_int); if (ICE.isInvalid()) return; @@ -4265,6 +4432,20 @@ NoSpeculativeLoadHardeningAttr *Sema::mergeNoSpeculativeLoadHardeningAttr( return ::new (Context) NoSpeculativeLoadHardeningAttr(Context, AL); } +SwiftNameAttr *Sema::mergeSwiftNameAttr(Decl *D, const SwiftNameAttr &SNA, + StringRef Name) { + if (const auto *PrevSNA = D->getAttr<SwiftNameAttr>()) { + if (PrevSNA->getName() != Name && !PrevSNA->isImplicit()) { + Diag(PrevSNA->getLocation(), diag::err_attributes_are_not_compatible) + << PrevSNA << &SNA; + Diag(SNA.getLoc(), diag::note_conflicting_attribute); + } + + D->dropAttr<SwiftNameAttr>(); + } + return ::new (Context) SwiftNameAttr(Context, SNA, Name); +} + OptimizeNoneAttr *Sema::mergeOptimizeNoneAttr(Decl *D, const AttributeCommonInfo &CI) { if (AlwaysInlineAttr *Inline = D->getAttr<AlwaysInlineAttr>()) { @@ -4312,18 +4493,20 @@ static void handleOptimizeNoneAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } static void handleConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (checkAttrMutualExclusion<CUDASharedAttr>(S, D, AL)) + if (checkAttrMutualExclusion<CUDASharedAttr>(S, D, AL) || + checkAttrMutualExclusion<HIPManagedAttr>(S, D, AL)) return; const auto *VD = cast<VarDecl>(D); - if (!VD->hasGlobalStorage()) { - S.Diag(AL.getLoc(), diag::err_cuda_nonglobal_constant); + if (VD->hasLocalStorage()) { + S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev); return; } D->addAttr(::new (S.Context) CUDAConstantAttr(S.Context, AL)); } static void handleSharedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, AL)) + if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, AL) || + checkAttrMutualExclusion<HIPManagedAttr>(S, D, AL)) return; const auto *VD = cast<VarDecl>(D); // extern __shared__ is only allowed on arrays with no length (e.g. @@ -4377,6 +4560,44 @@ static void handleGlobalAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(NoDebugAttr::CreateImplicit(S.Context)); } +static void handleDeviceAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + if (checkAttrMutualExclusion<CUDAGlobalAttr>(S, D, AL)) { + return; + } + + if (const auto *VD = dyn_cast<VarDecl>(D)) { + if (VD->hasLocalStorage()) { + S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev); + return; + } + } + + if (auto *A = D->getAttr<CUDADeviceAttr>()) { + if (!A->isImplicit()) + return; + D->dropAttr<CUDADeviceAttr>(); + } + D->addAttr(::new (S.Context) CUDADeviceAttr(S.Context, AL)); +} + +static void handleManagedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, AL) || + checkAttrMutualExclusion<CUDASharedAttr>(S, D, AL)) { + return; + } + + if (const auto *VD = dyn_cast<VarDecl>(D)) { + if (VD->hasLocalStorage()) { + S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev); + return; + } + } + if (!D->hasAttr<HIPManagedAttr>()) + D->addAttr(::new (S.Context) HIPManagedAttr(S.Context, AL)); + if (!D->hasAttr<CUDADeviceAttr>()) + D->addAttr(CUDADeviceAttr::CreateImplicit(S.Context)); +} + static void handleGNUInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) { const auto *Fn = cast<FunctionDecl>(D); if (!Fn->isInlineSpecified()) { @@ -4833,19 +5054,19 @@ static Expr *makeLaunchBoundsArgExpr(Sema &S, Expr *E, if (E->isValueDependent()) return E; - llvm::APSInt I(64); - if (!E->isIntegerConstantExpr(I, S.Context)) { + Optional<llvm::APSInt> I = llvm::APSInt(64); + if (!(I = E->getIntegerConstantExpr(S.Context))) { S.Diag(E->getExprLoc(), diag::err_attribute_argument_n_type) << &AL << Idx << AANT_ArgumentIntegerConstant << E->getSourceRange(); return nullptr; } // Make sure we can fit it in 32 bits. - if (!I.isIntN(32)) { - S.Diag(E->getExprLoc(), diag::err_ice_too_large) << I.toString(10, false) - << 32 << /* Unsigned */ 1; + if (!I->isIntN(32)) { + S.Diag(E->getExprLoc(), diag::err_ice_too_large) + << I->toString(10, false) << 32 << /* Unsigned */ 1; return nullptr; } - if (I < 0) + if (*I < 0) S.Diag(E->getExprLoc(), diag::warn_attribute_argument_n_negative) << &AL << Idx << E->getSourceRange(); @@ -5327,6 +5548,31 @@ static void handleObjCRequiresSuperAttr(Sema &S, Decl *D, D->addAttr(::new (S.Context) ObjCRequiresSuperAttr(S.Context, Attrs)); } +static void handleNSErrorDomain(Sema &S, Decl *D, const ParsedAttr &AL) { + auto *E = AL.getArgAsExpr(0); + auto Loc = E ? E->getBeginLoc() : AL.getLoc(); + + auto *DRE = dyn_cast<DeclRefExpr>(AL.getArgAsExpr(0)); + if (!DRE) { + S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0; + return; + } + + auto *VD = dyn_cast<VarDecl>(DRE->getDecl()); + if (!VD) { + S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 1 << DRE->getDecl(); + return; + } + + if (!isNSStringType(VD->getType(), S.Context) && + !isCFStringType(VD->getType(), S.Context)) { + S.Diag(Loc, diag::err_nserrordomain_wrong_type) << VD; + return; + } + + D->addAttr(::new (S.Context) NSErrorDomainAttr(S.Context, AL, VD)); +} + static void handleObjCBridgeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr; @@ -5488,6 +5734,515 @@ static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D, D->addAttr(::new (S.Context) ObjCPreciseLifetimeAttr(S.Context, AL)); } +static void handleSwiftAttrAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + // Make sure that there is a string literal as the annotation's single + // argument. + StringRef Str; + if (!S.checkStringLiteralArgumentAttr(AL, 0, Str)) + return; + + D->addAttr(::new (S.Context) SwiftAttrAttr(S.Context, AL, Str)); +} + +static void handleSwiftBridge(Sema &S, Decl *D, const ParsedAttr &AL) { + // Make sure that there is a string literal as the annotation's single + // argument. + StringRef BT; + if (!S.checkStringLiteralArgumentAttr(AL, 0, BT)) + return; + + // Don't duplicate annotations that are already set. + if (D->hasAttr<SwiftBridgeAttr>()) { + S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; + return; + } + + D->addAttr(::new (S.Context) SwiftBridgeAttr(S.Context, AL, BT)); +} + +static bool isErrorParameter(Sema &S, QualType QT) { + const auto *PT = QT->getAs<PointerType>(); + if (!PT) + return false; + + QualType Pointee = PT->getPointeeType(); + + // Check for NSError**. + if (const auto *OPT = Pointee->getAs<ObjCObjectPointerType>()) + if (const auto *ID = OPT->getInterfaceDecl()) + if (ID->getIdentifier() == S.getNSErrorIdent()) + return true; + + // Check for CFError**. + if (const auto *PT = Pointee->getAs<PointerType>()) + if (const auto *RT = PT->getPointeeType()->getAs<RecordType>()) + if (S.isCFError(RT->getDecl())) + return true; + + return false; +} + +static void handleSwiftError(Sema &S, Decl *D, const ParsedAttr &AL) { + auto hasErrorParameter = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool { + for (unsigned I = 0, E = getFunctionOrMethodNumParams(D); I != E; ++I) { + if (isErrorParameter(S, getFunctionOrMethodParamType(D, I))) + return true; + } + + S.Diag(AL.getLoc(), diag::err_attr_swift_error_no_error_parameter) + << AL << isa<ObjCMethodDecl>(D); + return false; + }; + + auto hasPointerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool { + // - C, ObjC, and block pointers are definitely okay. + // - References are definitely not okay. + // - nullptr_t is weird, but acceptable. + QualType RT = getFunctionOrMethodResultType(D); + if (RT->hasPointerRepresentation() && !RT->isReferenceType()) + return true; + + S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type) + << AL << AL.getArgAsIdent(0)->Ident->getName() << isa<ObjCMethodDecl>(D) + << /*pointer*/ 1; + return false; + }; + + auto hasIntegerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool { + QualType RT = getFunctionOrMethodResultType(D); + if (RT->isIntegralType(S.Context)) + return true; + + S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type) + << AL << AL.getArgAsIdent(0)->Ident->getName() << isa<ObjCMethodDecl>(D) + << /*integral*/ 0; + return false; + }; + + if (D->isInvalidDecl()) + return; + + IdentifierLoc *Loc = AL.getArgAsIdent(0); + SwiftErrorAttr::ConventionKind Convention; + if (!SwiftErrorAttr::ConvertStrToConventionKind(Loc->Ident->getName(), + Convention)) { + S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) + << AL << Loc->Ident; + return; + } + + switch (Convention) { + case SwiftErrorAttr::None: + // No additional validation required. + break; + + case SwiftErrorAttr::NonNullError: + if (!hasErrorParameter(S, D, AL)) + return; + break; + + case SwiftErrorAttr::NullResult: + if (!hasErrorParameter(S, D, AL) || !hasPointerResult(S, D, AL)) + return; + break; + + case SwiftErrorAttr::NonZeroResult: + case SwiftErrorAttr::ZeroResult: + if (!hasErrorParameter(S, D, AL) || !hasIntegerResult(S, D, AL)) + return; + break; + } + + D->addAttr(::new (S.Context) SwiftErrorAttr(S.Context, AL, Convention)); +} + +// For a function, this will validate a compound Swift name, e.g. +// <code>init(foo:bar:baz:)</code> or <code>controllerForName(_:)</code>, and +// the function will output the number of parameter names, and whether this is a +// single-arg initializer. +// +// For a type, enum constant, property, or variable declaration, this will +// validate either a simple identifier, or a qualified +// <code>context.identifier</code> name. +static bool +validateSwiftFunctionName(Sema &S, const ParsedAttr &AL, SourceLocation Loc, + StringRef Name, unsigned &SwiftParamCount, + bool &IsSingleParamInit) { + SwiftParamCount = 0; + IsSingleParamInit = false; + + // Check whether this will be mapped to a getter or setter of a property. + bool IsGetter = false, IsSetter = false; + if (Name.startswith("getter:")) { + IsGetter = true; + Name = Name.substr(7); + } else if (Name.startswith("setter:")) { + IsSetter = true; + Name = Name.substr(7); + } + + if (Name.back() != ')') { + S.Diag(Loc, diag::warn_attr_swift_name_function) << AL; + return false; + } + + bool IsMember = false; + StringRef ContextName, BaseName, Parameters; + + std::tie(BaseName, Parameters) = Name.split('('); + + // Split at the first '.', if it exists, which separates the context name + // from the base name. + std::tie(ContextName, BaseName) = BaseName.split('.'); + if (BaseName.empty()) { + BaseName = ContextName; + ContextName = StringRef(); + } else if (ContextName.empty() || !isValidIdentifier(ContextName)) { + S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) + << AL << /*context*/ 1; + return false; + } else { + IsMember = true; + } + + if (!isValidIdentifier(BaseName) || BaseName == "_") { + S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) + << AL << /*basename*/ 0; + return false; + } + + bool IsSubscript = BaseName == "subscript"; + // A subscript accessor must be a getter or setter. + if (IsSubscript && !IsGetter && !IsSetter) { + S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter) + << AL << /* getter or setter */ 0; + return false; + } + + if (Parameters.empty()) { + S.Diag(Loc, diag::warn_attr_swift_name_missing_parameters) << AL; + return false; + } + + assert(Parameters.back() == ')' && "expected ')'"); + Parameters = Parameters.drop_back(); // ')' + + if (Parameters.empty()) { + // Setters and subscripts must have at least one parameter. + if (IsSubscript) { + S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter) + << AL << /* have at least one parameter */1; + return false; + } + + if (IsSetter) { + S.Diag(Loc, diag::warn_attr_swift_name_setter_parameters) << AL; + return false; + } + + return true; + } + + if (Parameters.back() != ':') { + S.Diag(Loc, diag::warn_attr_swift_name_function) << AL; + return false; + } + + StringRef CurrentParam; + llvm::Optional<unsigned> SelfLocation; + unsigned NewValueCount = 0; + llvm::Optional<unsigned> NewValueLocation; + do { + std::tie(CurrentParam, Parameters) = Parameters.split(':'); + + if (!isValidIdentifier(CurrentParam)) { + S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) + << AL << /*parameter*/2; + return false; + } + + if (IsMember && CurrentParam == "self") { + // "self" indicates the "self" argument for a member. + + // More than one "self"? + if (SelfLocation) { + S.Diag(Loc, diag::warn_attr_swift_name_multiple_selfs) << AL; + return false; + } + + // The "self" location is the current parameter. + SelfLocation = SwiftParamCount; + } else if (CurrentParam == "newValue") { + // "newValue" indicates the "newValue" argument for a setter. + + // There should only be one 'newValue', but it's only significant for + // subscript accessors, so don't error right away. + ++NewValueCount; + + NewValueLocation = SwiftParamCount; + } + + ++SwiftParamCount; + } while (!Parameters.empty()); + + // Only instance subscripts are currently supported. + if (IsSubscript && !SelfLocation) { + S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter) + << AL << /*have a 'self:' parameter*/2; + return false; + } + + IsSingleParamInit = + SwiftParamCount == 1 && BaseName == "init" && CurrentParam != "_"; + + // Check the number of parameters for a getter/setter. + if (IsGetter || IsSetter) { + // Setters have one parameter for the new value. + unsigned NumExpectedParams = IsGetter ? 0 : 1; + unsigned ParamDiag = + IsGetter ? diag::warn_attr_swift_name_getter_parameters + : diag::warn_attr_swift_name_setter_parameters; + + // Instance methods have one parameter for "self". + if (SelfLocation) + ++NumExpectedParams; + + // Subscripts may have additional parameters beyond the expected params for + // the index. + if (IsSubscript) { + if (SwiftParamCount < NumExpectedParams) { + S.Diag(Loc, ParamDiag) << AL; + return false; + } + + // A subscript setter must explicitly label its newValue parameter to + // distinguish it from index parameters. + if (IsSetter) { + if (!NewValueLocation) { + S.Diag(Loc, diag::warn_attr_swift_name_subscript_setter_no_newValue) + << AL; + return false; + } + if (NewValueCount > 1) { + S.Diag(Loc, diag::warn_attr_swift_name_subscript_setter_multiple_newValues) + << AL; + return false; + } + } else { + // Subscript getters should have no 'newValue:' parameter. + if (NewValueLocation) { + S.Diag(Loc, diag::warn_attr_swift_name_subscript_getter_newValue) + << AL; + return false; + } + } + } else { + // Property accessors must have exactly the number of expected params. + if (SwiftParamCount != NumExpectedParams) { + S.Diag(Loc, ParamDiag) << AL; + return false; + } + } + } + + return true; +} + +bool Sema::DiagnoseSwiftName(Decl *D, StringRef Name, SourceLocation Loc, + const ParsedAttr &AL, bool IsAsync) { + if (isa<ObjCMethodDecl>(D) || isa<FunctionDecl>(D)) { + ArrayRef<ParmVarDecl*> Params; + unsigned ParamCount; + + if (const auto *Method = dyn_cast<ObjCMethodDecl>(D)) { + ParamCount = Method->getSelector().getNumArgs(); + Params = Method->parameters().slice(0, ParamCount); + } else { + const auto *F = cast<FunctionDecl>(D); + + ParamCount = F->getNumParams(); + Params = F->parameters(); + + if (!F->hasWrittenPrototype()) { + Diag(Loc, diag::warn_attribute_wrong_decl_type) << AL + << ExpectedFunctionWithProtoType; + return false; + } + } + + // The async name drops the last callback parameter. + if (IsAsync) { + if (ParamCount == 0) { + Diag(Loc, diag::warn_attr_swift_name_decl_missing_params) + << AL << isa<ObjCMethodDecl>(D); + return false; + } + ParamCount -= 1; + } + + unsigned SwiftParamCount; + bool IsSingleParamInit; + if (!validateSwiftFunctionName(*this, AL, Loc, Name, + SwiftParamCount, IsSingleParamInit)) + return false; + + bool ParamCountValid; + if (SwiftParamCount == ParamCount) { + ParamCountValid = true; + } else if (SwiftParamCount > ParamCount) { + ParamCountValid = IsSingleParamInit && ParamCount == 0; + } else { + // We have fewer Swift parameters than Objective-C parameters, but that + // might be because we've transformed some of them. Check for potential + // "out" parameters and err on the side of not warning. + unsigned MaybeOutParamCount = + std::count_if(Params.begin(), Params.end(), + [](const ParmVarDecl *Param) -> bool { + QualType ParamTy = Param->getType(); + if (ParamTy->isReferenceType() || ParamTy->isPointerType()) + return !ParamTy->getPointeeType().isConstQualified(); + return false; + }); + + ParamCountValid = SwiftParamCount + MaybeOutParamCount >= ParamCount; + } + + if (!ParamCountValid) { + Diag(Loc, diag::warn_attr_swift_name_num_params) + << (SwiftParamCount > ParamCount) << AL << ParamCount + << SwiftParamCount; + return false; + } + } else if ((isa<EnumConstantDecl>(D) || isa<ObjCProtocolDecl>(D) || + isa<ObjCInterfaceDecl>(D) || isa<ObjCPropertyDecl>(D) || + isa<VarDecl>(D) || isa<TypedefNameDecl>(D) || isa<TagDecl>(D) || + isa<IndirectFieldDecl>(D) || isa<FieldDecl>(D)) && + !IsAsync) { + StringRef ContextName, BaseName; + + std::tie(ContextName, BaseName) = Name.split('.'); + if (BaseName.empty()) { + BaseName = ContextName; + ContextName = StringRef(); + } else if (!isValidIdentifier(ContextName)) { + Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) << AL + << /*context*/1; + return false; + } + + if (!isValidIdentifier(BaseName)) { + Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) << AL + << /*basename*/0; + return false; + } + } else { + Diag(Loc, diag::warn_attr_swift_name_decl_kind) << AL; + return false; + } + return true; +} + +static void handleSwiftName(Sema &S, Decl *D, const ParsedAttr &AL) { + StringRef Name; + SourceLocation Loc; + if (!S.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc)) + return; + + if (!S.DiagnoseSwiftName(D, Name, Loc, AL, /*IsAsync=*/false)) + return; + + D->addAttr(::new (S.Context) SwiftNameAttr(S.Context, AL, Name)); +} + +static void handleSwiftAsyncName(Sema &S, Decl *D, const ParsedAttr &AL) { + StringRef Name; + SourceLocation Loc; + if (!S.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc)) + return; + + if (!S.DiagnoseSwiftName(D, Name, Loc, AL, /*IsAsync=*/true)) + return; + + D->addAttr(::new (S.Context) SwiftAsyncNameAttr(S.Context, AL, Name)); +} + +static void handleSwiftNewType(Sema &S, Decl *D, const ParsedAttr &AL) { + // Make sure that there is an identifier as the annotation's single argument. + if (!checkAttributeNumArgs(S, AL, 1)) + return; + + if (!AL.isArgIdent(0)) { + S.Diag(AL.getLoc(), diag::err_attribute_argument_type) + << AL << AANT_ArgumentIdentifier; + return; + } + + SwiftNewTypeAttr::NewtypeKind Kind; + IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; + if (!SwiftNewTypeAttr::ConvertStrToNewtypeKind(II->getName(), Kind)) { + S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II; + return; + } + + if (!isa<TypedefNameDecl>(D)) { + S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type_str) + << AL << "typedefs"; + return; + } + + D->addAttr(::new (S.Context) SwiftNewTypeAttr(S.Context, AL, Kind)); +} + +static void handleSwiftAsyncAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + if (!AL.isArgIdent(0)) { + S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) + << AL << 1 << AANT_ArgumentIdentifier; + return; + } + + SwiftAsyncAttr::Kind Kind; + IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; + if (!SwiftAsyncAttr::ConvertStrToKind(II->getName(), Kind)) { + S.Diag(AL.getLoc(), diag::err_swift_async_no_access) << AL << II; + return; + } + + ParamIdx Idx; + if (Kind == SwiftAsyncAttr::None) { + // If this is 'none', then there shouldn't be any additional arguments. + if (!checkAttributeNumArgs(S, AL, 1)) + return; + } else { + // Non-none swift_async requires a completion handler index argument. + if (!checkAttributeNumArgs(S, AL, 2)) + return; + + Expr *HandlerIdx = AL.getArgAsExpr(1); + if (!checkFunctionOrMethodParameterIndex(S, D, AL, 2, HandlerIdx, Idx)) + return; + + const ParmVarDecl *CompletionBlock = + getFunctionOrMethodParam(D, Idx.getASTIndex()); + QualType CompletionBlockType = CompletionBlock->getType(); + if (!CompletionBlockType->isBlockPointerType()) { + S.Diag(CompletionBlock->getLocation(), + diag::err_swift_async_bad_block_type) + << CompletionBlock->getType(); + return; + } + QualType BlockTy = + CompletionBlockType->getAs<BlockPointerType>()->getPointeeType(); + if (!BlockTy->getAs<FunctionType>()->getReturnType()->isVoidType()) { + S.Diag(CompletionBlock->getLocation(), + diag::err_swift_async_bad_block_type) + << CompletionBlock->getType(); + return; + } + } + + D->addAttr(::new (S.Context) SwiftAsyncAttr(S.Context, AL, Kind, Idx)); +} + //===----------------------------------------------------------------------===// // Microsoft specific attribute handlers. //===----------------------------------------------------------------------===// @@ -5686,18 +6441,18 @@ static void handleMSP430InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } Expr *NumParamsExpr = static_cast<Expr *>(AL.getArgAsExpr(0)); - llvm::APSInt NumParams(32); - if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) { + Optional<llvm::APSInt> NumParams = llvm::APSInt(32); + if (!(NumParams = NumParamsExpr->getIntegerConstantExpr(S.Context))) { S.Diag(AL.getLoc(), diag::err_attribute_argument_type) << AL << AANT_ArgumentIntegerConstant << NumParamsExpr->getSourceRange(); return; } // The argument should be in range 0..63. - unsigned Num = NumParams.getLimitedValue(255); + unsigned Num = NumParams->getLimitedValue(255); if (Num > 63) { S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) - << AL << (int)NumParams.getSExtValue() + << AL << (int)NumParams->getSExtValue() << NumParamsExpr->getSourceRange(); return; } @@ -6246,14 +7001,14 @@ DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) { if (isa<ClassTemplatePartialSpecializationDecl>(D) && - S.Context.getTargetInfo().getCXXABI().isMicrosoft()) { + (S.Context.getTargetInfo().shouldDLLImportComdatSymbols())) { S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored) << A; return; } if (const auto *FD = dyn_cast<FunctionDecl>(D)) { if (FD->isInlined() && A.getKind() == ParsedAttr::AT_DLLImport && - !S.Context.getTargetInfo().getCXXABI().isMicrosoft()) { + !(S.Context.getTargetInfo().shouldDLLImportComdatSymbols())) { // MinGW doesn't allow dllimport on inline functions. S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored_on_inline) << A; @@ -6262,7 +7017,7 @@ static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) { } if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) { - if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() && + if ((S.Context.getTargetInfo().shouldDLLImportComdatSymbols()) && MD->getParent()->isLambda()) { S.Diag(A.getRange().getBegin(), diag::err_attribute_dll_lambda) << A; return; @@ -6788,6 +7543,75 @@ static void handleCFGuardAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(::new (S.Context) CFGuardAttr(S.Context, AL, Arg)); } + +template <typename AttrTy> +static const AttrTy *findEnforceTCBAttrByName(Decl *D, StringRef Name) { + auto Attrs = D->specific_attrs<AttrTy>(); + auto I = llvm::find_if(Attrs, + [Name](const AttrTy *A) { + return A->getTCBName() == Name; + }); + return I == Attrs.end() ? nullptr : *I; +} + +template <typename AttrTy, typename ConflictingAttrTy> +static void handleEnforceTCBAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + StringRef Argument; + if (!S.checkStringLiteralArgumentAttr(AL, 0, Argument)) + return; + + // A function cannot be have both regular and leaf membership in the same TCB. + if (const ConflictingAttrTy *ConflictingAttr = + findEnforceTCBAttrByName<ConflictingAttrTy>(D, Argument)) { + // We could attach a note to the other attribute but in this case + // there's no need given how the two are very close to each other. + S.Diag(AL.getLoc(), diag::err_tcb_conflicting_attributes) + << AL.getAttrName()->getName() << ConflictingAttr->getAttrName()->getName() + << Argument; + + // Error recovery: drop the non-leaf attribute so that to suppress + // all future warnings caused by erroneous attributes. The leaf attribute + // needs to be kept because it can only suppresses warnings, not cause them. + D->dropAttr<EnforceTCBAttr>(); + return; + } + + D->addAttr(AttrTy::Create(S.Context, Argument, AL)); +} + +template <typename AttrTy, typename ConflictingAttrTy> +static AttrTy *mergeEnforceTCBAttrImpl(Sema &S, Decl *D, const AttrTy &AL) { + // Check if the new redeclaration has different leaf-ness in the same TCB. + StringRef TCBName = AL.getTCBName(); + if (const ConflictingAttrTy *ConflictingAttr = + findEnforceTCBAttrByName<ConflictingAttrTy>(D, TCBName)) { + S.Diag(ConflictingAttr->getLoc(), diag::err_tcb_conflicting_attributes) + << ConflictingAttr->getAttrName()->getName() + << AL.getAttrName()->getName() << TCBName; + + // Add a note so that the user could easily find the conflicting attribute. + S.Diag(AL.getLoc(), diag::note_conflicting_attribute); + + // More error recovery. + D->dropAttr<EnforceTCBAttr>(); + return nullptr; + } + + ASTContext &Context = S.getASTContext(); + return ::new(Context) AttrTy(Context, AL, AL.getTCBName()); +} + +EnforceTCBAttr *Sema::mergeEnforceTCBAttr(Decl *D, const EnforceTCBAttr &AL) { + return mergeEnforceTCBAttrImpl<EnforceTCBAttr, EnforceTCBLeafAttr>( + *this, D, AL); +} + +EnforceTCBLeafAttr *Sema::mergeEnforceTCBLeafAttr( + Decl *D, const EnforceTCBLeafAttr &AL) { + return mergeEnforceTCBAttrImpl<EnforceTCBLeafAttr, EnforceTCBAttr>( + *this, D, AL); +} + //===----------------------------------------------------------------------===// // Top Level Sema Entry Points //===----------------------------------------------------------------------===// @@ -6815,7 +7639,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, AL.isDeclspecAttribute() ? (unsigned)diag::warn_unhandled_ms_attribute_ignored : (unsigned)diag::warn_unknown_attribute_ignored) - << AL; + << AL << AL.getRange(); return; } @@ -6939,19 +7763,12 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handlePassObjectSizeAttr(S, D, AL); break; case ParsedAttr::AT_Constructor: - if (S.Context.getTargetInfo().getTriple().isOSAIX()) - llvm::report_fatal_error( - "'constructor' attribute is not yet supported on AIX"); - else handleConstructorAttr(S, D, AL); break; case ParsedAttr::AT_Deprecated: handleDeprecatedAttr(S, D, AL); break; case ParsedAttr::AT_Destructor: - if (S.Context.getTargetInfo().getTriple().isOSAIX()) - llvm::report_fatal_error("'destructor' attribute is not yet supported on AIX"); - else handleDestructorAttr(S, D, AL); break; case ParsedAttr::AT_EnableIf: @@ -6990,16 +7807,21 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_Callback: handleCallbackAttr(S, D, AL); break; + case ParsedAttr::AT_CalledOnce: + handleCalledOnceAttr(S, D, AL); + break; case ParsedAttr::AT_CUDAGlobal: handleGlobalAttr(S, D, AL); break; case ParsedAttr::AT_CUDADevice: - handleSimpleAttributeWithExclusions<CUDADeviceAttr, CUDAGlobalAttr>(S, D, - AL); + handleDeviceAttr(S, D, AL); break; case ParsedAttr::AT_CUDAHost: handleSimpleAttributeWithExclusions<CUDAHostAttr, CUDAGlobalAttr>(S, D, AL); break; + case ParsedAttr::AT_HIPManaged: + handleManagedAttr(S, D, AL); + break; case ParsedAttr::AT_CUDADeviceBuiltinSurfaceType: handleSimpleAttributeWithExclusions<CUDADeviceBuiltinSurfaceTypeAttr, CUDADeviceBuiltinTextureTypeAttr>(S, D, @@ -7058,6 +7880,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_AnyX86NoCfCheck: handleNoCfCheckAttr(S, D, AL); break; + case ParsedAttr::AT_Leaf: + handleSimpleAttribute<LeafAttr>(S, D, AL); + break; case ParsedAttr::AT_NoThrow: if (!AL.isUsedAsTypeAttr()) handleSimpleAttribute<NoThrowAttr>(S, D, AL); @@ -7098,6 +7923,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_ObjCBoxable: handleObjCBoxable(S, D, AL); break; + case ParsedAttr::AT_NSErrorDomain: + handleNSErrorDomain(S, D, AL); + break; case ParsedAttr::AT_CFAuditedTransfer: handleSimpleAttributeWithExclusions<CFAuditedTransferAttr, CFUnknownTransferAttr>(S, D, AL); @@ -7155,6 +7983,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_Packed: handlePackedAttr(S, D, AL); break; + case ParsedAttr::AT_PreferredName: + handlePreferredName(S, D, AL); + break; case ParsedAttr::AT_Section: handleSectionAttr(S, D, AL); break; @@ -7179,9 +8010,15 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_Unavailable: handleAttrWithMessage<UnavailableAttr>(S, D, AL); break; + case ParsedAttr::AT_Assumption: + handleAssumumptionAttr(S, D, AL); + break; case ParsedAttr::AT_ObjCDirect: handleObjCDirectAttr(S, D, AL); break; + case ParsedAttr::AT_ObjCNonRuntimeProtocol: + handleObjCNonRuntimeProtocolAttr(S, D, AL); + break; case ParsedAttr::AT_ObjCDirectMembers: handleObjCDirectMembersAttr(S, D, AL); handleSimpleAttribute<ObjCDirectMembersAttr>(S, D, AL); @@ -7200,6 +8037,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleSimpleAttributeWithExclusions<DisableTailCallsAttr, NakedAttr>(S, D, AL); break; + case ParsedAttr::AT_NoMerge: + handleSimpleAttribute<NoMergeAttr>(S, D, AL); + break; case ParsedAttr::AT_Visibility: handleVisibilityAttr(S, D, AL, false); break; @@ -7397,6 +8237,38 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleTypeTagForDatatypeAttr(S, D, AL); break; + // Swift attributes. + case ParsedAttr::AT_SwiftAsyncName: + handleSwiftAsyncName(S, D, AL); + break; + case ParsedAttr::AT_SwiftAttr: + handleSwiftAttrAttr(S, D, AL); + break; + case ParsedAttr::AT_SwiftBridge: + handleSwiftBridge(S, D, AL); + break; + case ParsedAttr::AT_SwiftBridgedTypedef: + handleSimpleAttribute<SwiftBridgedTypedefAttr>(S, D, AL); + break; + case ParsedAttr::AT_SwiftError: + handleSwiftError(S, D, AL); + break; + case ParsedAttr::AT_SwiftName: + handleSwiftName(S, D, AL); + break; + case ParsedAttr::AT_SwiftNewType: + handleSwiftNewType(S, D, AL); + break; + case ParsedAttr::AT_SwiftObjCMembers: + handleSimpleAttribute<SwiftObjCMembersAttr>(S, D, AL); + break; + case ParsedAttr::AT_SwiftPrivate: + handleSimpleAttribute<SwiftPrivateAttr>(S, D, AL); + break; + case ParsedAttr::AT_SwiftAsync: + handleSwiftAsyncAttr(S, D, AL); + break; + // XRay attributes. case ParsedAttr::AT_XRayLogArgs: handleXRayLogArgsAttr(S, D, AL); @@ -7446,6 +8318,14 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_UseHandle: handleHandleAttr<UseHandleAttr>(S, D, AL); break; + + case ParsedAttr::AT_EnforceTCB: + handleEnforceTCBAttr<EnforceTCBAttr, EnforceTCBLeafAttr>(S, D, AL); + break; + + case ParsedAttr::AT_EnforceTCBLeaf: + handleEnforceTCBAttr<EnforceTCBLeafAttr, EnforceTCBAttr>(S, D, AL); + break; } } @@ -7600,8 +8480,8 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II, NewFD = FunctionDecl::Create( FD->getASTContext(), FD->getDeclContext(), Loc, Loc, DeclarationName(II), FD->getType(), FD->getTypeSourceInfo(), SC_None, - false /*isInlineSpecified*/, FD->hasPrototype(), CSK_unspecified, - FD->getTrailingRequiresClause()); + false /*isInlineSpecified*/, FD->hasPrototype(), + ConstexprSpecKind::Unspecified, FD->getTrailingRequiresClause()); NewD = NewFD; if (FD->getQualifier()) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 22bf35dbd0cb..8bfaa46162bc 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -655,7 +655,8 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, // contain the constexpr specifier. if (New->getConstexprKind() != Old->getConstexprKind()) { Diag(New->getLocation(), diag::err_constexpr_redecl_mismatch) - << New << New->getConstexprKind() << Old->getConstexprKind(); + << New << static_cast<int>(New->getConstexprKind()) + << static_cast<int>(Old->getConstexprKind()); Diag(Old->getLocation(), diag::note_previous_declaration); Invalid = true; } else if (!Old->getMostRecentDecl()->isInlined() && New->isInlined() && @@ -694,6 +695,17 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Invalid = true; } + // C++11 [temp.friend]p4 (DR329): + // When a function is defined in a friend function declaration in a class + // template, the function is instantiated when the function is odr-used. + // The same restrictions on multiple declarations and definitions that + // apply to non-template function declarations and definitions also apply + // to these implicit definitions. + const FunctionDecl *OldDefinition = nullptr; + if (New->isThisDeclarationInstantiatedFromAFriendDefinition() && + Old->isDefined(OldDefinition, true)) + CheckForFunctionRedefinition(New, OldDefinition); + return Invalid; } @@ -723,7 +735,7 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D, Diag(Decomp.getLSquareLoc(), !getLangOpts().CPlusPlus17 ? diag::ext_decomp_decl - : D.getContext() == DeclaratorContext::ConditionContext + : D.getContext() == DeclaratorContext::Condition ? diag::ext_decomp_decl_cond : diag::warn_cxx14_compat_decomp_decl) << Decomp.getSourceRange(); @@ -890,7 +902,8 @@ static bool checkSimpleDecomposition( llvm::function_ref<ExprResult(SourceLocation, Expr *, unsigned)> GetInit) { if ((int64_t)Bindings.size() != NumElems) { S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings) - << DecompType << (unsigned)Bindings.size() << NumElems.toString(10) + << DecompType << (unsigned)Bindings.size() + << (unsigned)NumElems.getLimitedValue(UINT_MAX) << NumElems.toString(10) << (NumElems < Bindings.size()); return true; } @@ -1066,8 +1079,9 @@ static IsTupleLike isTupleLike(Sema &S, SourceLocation Loc, QualType T, TemplateArgumentListInfo &Args; ICEDiagnoser(LookupResult &R, TemplateArgumentListInfo &Args) : R(R), Args(Args) {} - void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) override { - S.Diag(Loc, diag::err_decomp_decl_std_tuple_size_not_constant) + Sema::SemaDiagnosticBuilder diagnoseNotICE(Sema &S, + SourceLocation Loc) override { + return S.Diag(Loc, diag::err_decomp_decl_std_tuple_size_not_constant) << printTemplateArgs(S.Context.getPrintingPolicy(), Args); } } Diagnoser(R, Args); @@ -1077,7 +1091,7 @@ static IsTupleLike isTupleLike(Sema &S, SourceLocation Loc, QualType T, if (E.isInvalid()) return IsTupleLike::Error; - E = S.VerifyIntegerConstantExpression(E.get(), &Size, Diagnoser, false); + E = S.VerifyIntegerConstantExpression(E.get(), &Size, Diagnoser); if (E.isInvalid()) return IsTupleLike::Error; @@ -1135,8 +1149,9 @@ static bool checkTupleLikeDecomposition(Sema &S, const llvm::APSInt &TupleSize) { if ((int64_t)Bindings.size() != TupleSize) { S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings) - << DecompType << (unsigned)Bindings.size() << TupleSize.toString(10) - << (TupleSize < Bindings.size()); + << DecompType << (unsigned)Bindings.size() + << (unsigned)TupleSize.getLimitedValue(UINT_MAX) + << TupleSize.toString(10) << (TupleSize < Bindings.size()); return true; } @@ -1184,7 +1199,8 @@ static bool checkTupleLikeDecomposition(Sema &S, // an xvalue otherwise if (!Src->getType()->isLValueReferenceType()) E = ImplicitCastExpr::Create(S.Context, E.get()->getType(), CK_NoOp, - E.get(), nullptr, VK_XValue); + E.get(), nullptr, VK_XValue, + FPOptionsOverride()); TemplateArgumentListInfo Args(Loc, Loc); Args.addArgument( @@ -1248,8 +1264,7 @@ static bool checkTupleLikeDecomposition(Sema &S, if (E.isInvalid()) return true; RefVD->setInit(E.get()); - if (!E.get()->isValueDependent()) - RefVD->checkInitIsICE(); + S.CheckCompleteVariableDeclaration(RefVD); E = S.BuildDeclarationNameExpr(CXXScopeSpec(), DeclarationNameInfo(B->getDeclName(), Loc), @@ -1360,7 +1375,7 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings, [](FieldDecl *FD) { return !FD->isUnnamedBitfield(); }); assert(Bindings.size() != NumFields); S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings) - << DecompType << (unsigned)Bindings.size() << NumFields + << DecompType << (unsigned)Bindings.size() << NumFields << NumFields << (NumFields < Bindings.size()); return true; }; @@ -1373,11 +1388,23 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings, if (FD->isUnnamedBitfield()) continue; - if (FD->isAnonymousStructOrUnion()) { - S.Diag(Src->getLocation(), diag::err_decomp_decl_anon_union_member) - << DecompType << FD->getType()->isUnionType(); - S.Diag(FD->getLocation(), diag::note_declared_at); - return true; + // All the non-static data members are required to be nameable, so they + // must all have names. + if (!FD->getDeclName()) { + if (RD->isLambda()) { + S.Diag(Src->getLocation(), diag::err_decomp_decl_lambda); + S.Diag(RD->getLocation(), diag::note_lambda_decl); + return true; + } + + if (FD->isAnonymousStructOrUnion()) { + S.Diag(Src->getLocation(), diag::err_decomp_decl_anon_union_member) + << DecompType << FD->getType()->isUnionType(); + S.Diag(FD->getLocation(), diag::note_declared_at); + return true; + } + + // FIXME: Are there any other ways we could have an anonymous member? } // We have a real field to bind. @@ -1618,7 +1645,7 @@ static bool CheckConstexprDestructorSubobjects(Sema &SemaRef, if (Kind == Sema::CheckConstexprKind::Diagnose) { SemaRef.Diag(DD->getLocation(), diag::err_constexpr_dtor_subobject) - << DD->getConstexprKind() << !FD + << static_cast<int>(DD->getConstexprKind()) << !FD << (FD ? FD->getDeclName() : DeclarationName()) << T; SemaRef.Diag(Loc, diag::note_constexpr_dtor_subobject) << !FD << (FD ? FD->getDeclName() : DeclarationName()) << T; @@ -2588,7 +2615,7 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, Diag(AL.getLoc(), AL.getKind() == ParsedAttr::UnknownAttribute ? (unsigned)diag::warn_unknown_attribute_ignored : (unsigned)diag::err_base_specifier_attribute) - << AL; + << AL << AL.getRange(); } TypeSourceInfo *TInfo = nullptr; @@ -3577,8 +3604,10 @@ namespace { Base = SubME->getBase(); } - if (!isa<CXXThisExpr>(Base->IgnoreParenImpCasts())) + if (!isa<CXXThisExpr>(Base->IgnoreParenImpCasts())) { + Visit(Base); return; + } if (AddressOf && AllPODFields) return; @@ -3905,9 +3934,22 @@ void Sema::ActOnStartTrailingRequiresClause(Scope *S, Declarator &D) { } ExprResult Sema::ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr) { + return ActOnRequiresClause(ConstraintExpr); +} + +ExprResult Sema::ActOnRequiresClause(ExprResult ConstraintExpr) { + if (ConstraintExpr.isInvalid()) + return ExprError(); + + ConstraintExpr = CorrectDelayedTyposInExpr(ConstraintExpr); if (ConstraintExpr.isInvalid()) return ExprError(); - return CorrectDelayedTyposInExpr(ConstraintExpr); + + if (DiagnoseUnexpandedParameterPack(ConstraintExpr.get(), + UPPC_RequiresClause)) + return ExprError(); + + return ConstraintExpr; } /// This is invoked after parsing an in-class initializer for a @@ -5478,8 +5520,9 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, // Bases. for (const auto &Base : ClassDecl->bases()) { - // Bases are always records in a well-formed non-dependent class. const RecordType *RT = Base.getType()->getAs<RecordType>(); + if (!RT) + continue; // Remember direct virtual bases. if (Base.isVirtual()) { @@ -5869,13 +5912,22 @@ static void ReferenceDllExportedMembers(Sema &S, CXXRecordDecl *Class) { // The function will be passed to the consumer when its definition is // encountered. - } else if (!MD->isTrivial() || MD->isExplicitlyDefaulted() || + } else if (MD->isExplicitlyDefaulted()) { + // Synthesize and instantiate explicitly defaulted methods. + S.MarkFunctionReferenced(Class->getLocation(), MD); + + if (TSK != TSK_ExplicitInstantiationDefinition) { + // Except for explicit instantiation defs, we will not see the + // definition again later, so pass it to the consumer now. + S.Consumer.HandleTopLevelDecl(DeclGroupRef(MD)); + } + } else if (!MD->isTrivial() || MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()) { - // Synthesize and instantiate non-trivial implicit methods, explicitly - // defaulted methods, and the copy and move assignment operators. The - // latter are exported even if they are trivial, because the address of - // an operator can be taken and should compare equal across libraries. + // Synthesize and instantiate non-trivial implicit methods, and the copy + // and move assignment operators. The latter are exported even if they + // are trivial, because the address of an operator can be taken and + // should compare equal across libraries. S.MarkFunctionReferenced(Class->getLocation(), MD); // There is no later point when we will see the definition of this @@ -6056,7 +6108,7 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { Attr *ClassAttr = getDLLAttr(Class); // MSVC inherits DLL attributes to partial class template specializations. - if (Context.getTargetInfo().getCXXABI().isMicrosoft() && !ClassAttr) { + if (Context.getTargetInfo().shouldDLLImportComdatSymbols() && !ClassAttr) { if (auto *Spec = dyn_cast<ClassTemplatePartialSpecializationDecl>(Class)) { if (Attr *TemplateAttr = getDLLAttr(Spec->getSpecializedTemplate()->getTemplatedDecl())) { @@ -6076,7 +6128,7 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { return; } - if (Context.getTargetInfo().getCXXABI().isMicrosoft() && + if (Context.getTargetInfo().shouldDLLImportComdatSymbols() && !ClassAttr->isInherited()) { // Diagnose dll attributes on members of class with dll attribute. for (Decl *Member : Class->decls()) { @@ -6141,8 +6193,7 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { if (MD->isInlined()) { // MinGW does not import or export inline methods. But do it for // template instantiations. - if (!Context.getTargetInfo().getCXXABI().isMicrosoft() && - !Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment() && + if (!Context.getTargetInfo().shouldDLLImportComdatSymbols() && TSK != TSK_ExplicitInstantiationDeclaration && TSK != TSK_ExplicitInstantiationDefinition) continue; @@ -7331,9 +7382,10 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, // If a function is explicitly defaulted on its first declaration, it is // implicitly considered to be constexpr if the implicit declaration // would be. - MD->setConstexprKind( - Constexpr ? (MD->isConsteval() ? CSK_consteval : CSK_constexpr) - : CSK_unspecified); + MD->setConstexprKind(Constexpr ? (MD->isConsteval() + ? ConstexprSpecKind::Consteval + : ConstexprSpecKind::Constexpr) + : ConstexprSpecKind::Unspecified); if (!Type->hasExceptionSpec()) { // C++2a [except.spec]p3: @@ -8022,10 +8074,10 @@ private: if (ReturnFalse.isInvalid()) return StmtError(); - return S.ActOnIfStmt(Loc, false, nullptr, + return S.ActOnIfStmt(Loc, false, Loc, nullptr, S.ActOnCondition(nullptr, Loc, NotCond.get(), Sema::ConditionKind::Boolean), - ReturnFalse.get(), SourceLocation(), nullptr); + Loc, ReturnFalse.get(), SourceLocation(), nullptr); } StmtResult visitSubobjectArray(QualType Type, llvm::APInt Size, @@ -8177,9 +8229,9 @@ private: return StmtError(); // if (...) - return S.ActOnIfStmt(Loc, /*IsConstexpr=*/false, InitStmt, Cond, - ReturnStmt.get(), /*ElseLoc=*/SourceLocation(), - /*Else=*/nullptr); + return S.ActOnIfStmt(Loc, /*IsConstexpr=*/false, Loc, InitStmt, Cond, Loc, + ReturnStmt.get(), + /*ElseLoc=*/SourceLocation(), /*Else=*/nullptr); } case DefaultedComparisonKind::NotEqual: @@ -8212,7 +8264,7 @@ static void lookupOperatorsForDefaultedComparison(Sema &Self, Scope *S, UnresolvedSetImpl &Operators, OverloadedOperatorKind Op) { auto Lookup = [&](OverloadedOperatorKind OO) { - Self.LookupOverloadedOperatorName(OO, S, QualType(), QualType(), Operators); + Self.LookupOverloadedOperatorName(OO, S, Operators); }; // Every defaulted operator looks up itself. @@ -8425,7 +8477,7 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD, // FIXME: Only applying this to the first declaration seems problematic, as // simple reorderings can affect the meaning of the program. if (First && !FD->isConstexpr() && Info.Constexpr) - FD->setConstexprKind(CSK_constexpr); + FD->setConstexprKind(ConstexprSpecKind::Constexpr); // C++2a [except.spec]p3: // If a declaration of a function does not have a noexcept-specifier @@ -9399,7 +9451,8 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD, // brace-or-equal-initializer if (CSM == Sema::CXXDefaultConstructor && FI->hasInClassInitializer()) { if (Diagnose) - S.Diag(FI->getLocation(), diag::note_nontrivial_in_class_init) << FI; + S.Diag(FI->getLocation(), diag::note_nontrivial_default_member_init) + << FI; return false; } @@ -11106,8 +11159,8 @@ QualType Sema::CheckComparisonCategoryType(ComparisonCategoryType Kind, // Attempt to diagnose reasons why the STL definition of this type // might be foobar, including it failing to be a constant expression. // TODO Handle more ways the lookup or result can be invalid. - if (!VD->isStaticDataMember() || !VD->isConstexpr() || !VD->hasInit() || - !VD->checkInitIsICE()) + if (!VD->isStaticDataMember() || + !VD->isUsableInConstantExpressions(Context)) return UnsupportedSTLError(USS_InvalidMember, MemName, VD); // Attempt to evaluate the var decl as a constant expression and extract @@ -12936,7 +12989,8 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( Context, ClassDecl, ClassLoc, NameInfo, /*Type*/ QualType(), /*TInfo=*/nullptr, ExplicitSpecifier(), /*isInline=*/true, /*isImplicitlyDeclared=*/true, - Constexpr ? CSK_constexpr : CSK_unspecified); + Constexpr ? ConstexprSpecKind::Constexpr + : ConstexprSpecKind::Unspecified); DefaultCon->setAccess(AS_public); DefaultCon->setDefaulted(); @@ -13057,7 +13111,7 @@ Sema::findInheritingConstructor(SourceLocation Loc, Context, Derived, UsingLoc, NameInfo, TInfo->getType(), TInfo, BaseCtor->getExplicitSpecifier(), /*isInline=*/true, /*isImplicitlyDeclared=*/true, - Constexpr ? BaseCtor->getConstexprKind() : CSK_unspecified, + Constexpr ? BaseCtor->getConstexprKind() : ConstexprSpecKind::Unspecified, InheritedConstructor(Shadow, BaseCtor), BaseCtor->getTrailingRequiresClause()); if (Shadow->isInvalidDecl()) @@ -13214,7 +13268,8 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { CXXDestructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(), nullptr, /*isInline=*/true, /*isImplicitlyDeclared=*/true, - Constexpr ? CSK_constexpr : CSK_unspecified); + Constexpr ? ConstexprSpecKind::Constexpr + : ConstexprSpecKind::Unspecified); Destructor->setAccess(AS_public); Destructor->setDefaulted(); @@ -13849,7 +13904,8 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { CXXMethodDecl *CopyAssignment = CXXMethodDecl::Create( Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr, /*StorageClass=*/SC_None, - /*isInline=*/true, Constexpr ? CSK_constexpr : CSK_unspecified, + /*isInline=*/true, + Constexpr ? ConstexprSpecKind::Constexpr : ConstexprSpecKind::Unspecified, SourceLocation()); CopyAssignment->setAccess(AS_public); CopyAssignment->setDefaulted(); @@ -14174,7 +14230,8 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { CXXMethodDecl *MoveAssignment = CXXMethodDecl::Create( Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr, /*StorageClass=*/SC_None, - /*isInline=*/true, Constexpr ? CSK_constexpr : CSK_unspecified, + /*isInline=*/true, + Constexpr ? ConstexprSpecKind::Constexpr : ConstexprSpecKind::Unspecified, SourceLocation()); MoveAssignment->setAccess(AS_public); MoveAssignment->setDefaulted(); @@ -14558,7 +14615,8 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( ExplicitSpecifier(), /*isInline=*/true, /*isImplicitlyDeclared=*/true, - Constexpr ? CSK_constexpr : CSK_unspecified); + Constexpr ? ConstexprSpecKind::Constexpr + : ConstexprSpecKind::Unspecified); CopyConstructor->setAccess(AS_public); CopyConstructor->setDefaulted(); @@ -14691,7 +14749,8 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( ExplicitSpecifier(), /*isInline=*/true, /*isImplicitlyDeclared=*/true, - Constexpr ? CSK_constexpr : CSK_unspecified); + Constexpr ? ConstexprSpecKind::Constexpr + : ConstexprSpecKind::Unspecified); MoveConstructor->setAccess(AS_public); MoveConstructor->setDefaulted(); @@ -14793,9 +14852,13 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion( SynthesizedFunctionScope Scope(*this, Conv); assert(!Conv->getReturnType()->isUndeducedType()); + QualType ConvRT = Conv->getType()->getAs<FunctionType>()->getReturnType(); + CallingConv CC = + ConvRT->getPointeeType()->getAs<FunctionType>()->getCallConv(); + CXXRecordDecl *Lambda = Conv->getParent(); FunctionDecl *CallOp = Lambda->getLambdaCallOperator(); - FunctionDecl *Invoker = Lambda->getLambdaStaticInvoker(); + FunctionDecl *Invoker = Lambda->getLambdaStaticInvoker(CC); if (auto *TemplateArgs = Conv->getTemplateSpecializationArgs()) { CallOp = InstantiateFunctionDeclaration( @@ -14866,9 +14929,9 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion( // (since it's unusable otherwise); in the case where we inline the // block literal, it has block literal lifetime semantics. if (!BuildBlock.isInvalid() && !getLangOpts().ObjCAutoRefCount) - BuildBlock = ImplicitCastExpr::Create(Context, BuildBlock.get()->getType(), - CK_CopyAndAutoreleaseBlockObject, - BuildBlock.get(), nullptr, VK_RValue); + BuildBlock = ImplicitCastExpr::Create( + Context, BuildBlock.get()->getType(), CK_CopyAndAutoreleaseBlockObject, + BuildBlock.get(), nullptr, VK_RValue, FPOptionsOverride()); if (BuildBlock.isInvalid()) { Diag(CurrentLocation, diag::note_lambda_to_block_conv); @@ -15032,24 +15095,14 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { DeclContext::lookup_result Lookup = ClassPattern->lookup(Field->getDeclName()); - // Lookup can return at most two results: the pattern for the field, or the - // injected class name of the parent record. No other member can have the - // same name as the field. - // In modules mode, lookup can return multiple results (coming from - // different modules). - assert((getLangOpts().Modules || (!Lookup.empty() && Lookup.size() <= 2)) && - "more than two lookup results for field name"); - FieldDecl *Pattern = dyn_cast<FieldDecl>(Lookup[0]); - if (!Pattern) { - assert(isa<CXXRecordDecl>(Lookup[0]) && - "cannot have other non-field member with same name"); - for (auto L : Lookup) - if (isa<FieldDecl>(L)) { - Pattern = cast<FieldDecl>(L); - break; - } - assert(Pattern && "We must have set the Pattern!"); + FieldDecl *Pattern = nullptr; + for (auto L : Lookup) { + if (isa<FieldDecl>(L)) { + Pattern = cast<FieldDecl>(L); + break; + } } + assert(Pattern && "We must have set the Pattern!"); if (!Pattern->hasInClassInitializer() || InstantiateInClassInitializer(Loc, Field, Pattern, @@ -15076,9 +15129,10 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { // constructor before the initializer is lexically complete will ultimately // come here at which point we can diagnose it. RecordDecl *OutermostClass = ParentRD->getOuterLexicalRecordContext(); - Diag(Loc, diag::err_in_class_initializer_not_yet_parsed) + Diag(Loc, diag::err_default_member_initializer_not_yet_parsed) << OutermostClass << Field; - Diag(Field->getEndLoc(), diag::note_in_class_initializer_not_yet_parsed); + Diag(Field->getEndLoc(), + diag::note_default_member_initializer_not_yet_parsed); // Recover by marking the field invalid, unless we're in a SFINAE context. if (!isSFINAEContext()) Field->setInvalidDecl(); @@ -15503,6 +15557,18 @@ checkLiteralOperatorTemplateParameterList(Sema &SemaRef, SemaRef.Context.hasSameType(PmDecl->getType(), SemaRef.Context.CharTy)) return false; + // C++20 [over.literal]p5: + // A string literal operator template is a literal operator template + // whose template-parameter-list comprises a single non-type + // template-parameter of class type. + // + // As a DR resolution, we also allow placeholders for deduced class + // template specializations. + if (SemaRef.getLangOpts().CPlusPlus20 && + !PmDecl->isTemplateParameterPack() && + (PmDecl->getType()->isRecordType() || + PmDecl->getType()->getAs<DeducedTemplateSpecializationType>())) + return false; } else if (TemplateParams->size() == 2) { TemplateTypeParmDecl *PmType = dyn_cast<TemplateTypeParmDecl>(TemplateParams->getParam(0)); @@ -15559,6 +15625,8 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { // template <char...> type operator "" name() and // template <class T, T...> type operator "" name() are the only valid // template signatures, and the only valid signatures with no parameters. + // + // C++20 also allows template <SomeClass T> type operator "" name(). if (TpDecl) { if (FnDecl->param_size() != 0) { Diag(FnDecl->getLocation(), @@ -15988,9 +16056,10 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc, AssertExpr = FullAssertExpr.get(); llvm::APSInt Cond; - if (!Failed && VerifyIntegerConstantExpression(AssertExpr, &Cond, - diag::err_static_assert_expression_is_not_constant, - /*AllowFold=*/false).isInvalid()) + if (!Failed && VerifyIntegerConstantExpression( + AssertExpr, &Cond, + diag::err_static_assert_expression_is_not_constant) + .isInvalid()) Failed = true; if (!Failed && !Cond) { @@ -16282,7 +16351,7 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, // Try to convert the decl specifier to a type. This works for // friend templates because ActOnTag never produces a ClassTemplateDecl // for a TUK_Friend. - Declarator TheDeclarator(DS, DeclaratorContext::MemberContext); + Declarator TheDeclarator(DS, DeclaratorContext::Member); TypeSourceInfo *TSI = GetTypeForDeclarator(TheDeclarator, S); QualType T = TSI->getType(); if (TheDeclarator.isInvalidType()) diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index d376880a40e8..60253a82e93a 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -1066,6 +1066,11 @@ Decl *Sema::ActOnStartClassInterface( ProcessDeclAttributeList(TUScope, IDecl, AttrList); AddPragmaAttributes(TUScope, IDecl); + + // Merge attributes from previous declarations. + if (PrevIDecl) + mergeDeclAttributes(IDecl, PrevIDecl); + PushOnScopeChains(IDecl, TUScope); // Start the definition of this class. If we're in a redefinition case, there @@ -1581,7 +1586,7 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( DS.SetRangeEnd(loc); // Form the declarator. - Declarator D(DS, DeclaratorContext::TypeNameContext); + Declarator D(DS, DeclaratorContext::TypeName); // If we have a typedef of an Objective-C class type that is missing a '*', // add the '*'. @@ -2122,7 +2127,12 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, // Add ivar's to class's DeclContext. for (unsigned i = 0, e = numIvars; i != e; ++i) { ivars[i]->setLexicalDeclContext(ImpDecl); - IDecl->makeDeclVisibleInContext(ivars[i]); + // In a 'fragile' runtime the ivar was added to the implicit + // ObjCInterfaceDecl while in a 'non-fragile' runtime the ivar is + // only in the ObjCImplementationDecl. In the non-fragile case the ivar + // therefore also needs to be propagated to the ObjCInterfaceDecl. + if (!LangOpts.ObjCRuntime.isFragile()) + IDecl->makeDeclVisibleInContext(ivars[i]); ImpDecl->addDecl(ivars[i]); } @@ -3120,6 +3130,9 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, IdentLocs[i]); IDecl->setAtEndRange(IdentLocs[i]); + if (PrevIDecl) + mergeDeclAttributes(IDecl, PrevIDecl); + PushOnScopeChains(IDecl, TUScope); CheckObjCDeclScope(IDecl); DeclsInGroup.push_back(IDecl); @@ -3899,6 +3912,55 @@ static void DiagnoseVariableSizedIvars(Sema &S, ObjCContainerDecl *OCD) { } } +static void DiagnoseCategoryDirectMembersProtocolConformance( + Sema &S, ObjCProtocolDecl *PDecl, ObjCCategoryDecl *CDecl); + +static void DiagnoseCategoryDirectMembersProtocolConformance( + Sema &S, ObjCCategoryDecl *CDecl, + const llvm::iterator_range<ObjCProtocolList::iterator> &Protocols) { + for (auto *PI : Protocols) + DiagnoseCategoryDirectMembersProtocolConformance(S, PI, CDecl); +} + +static void DiagnoseCategoryDirectMembersProtocolConformance( + Sema &S, ObjCProtocolDecl *PDecl, ObjCCategoryDecl *CDecl) { + if (!PDecl->isThisDeclarationADefinition() && PDecl->getDefinition()) + PDecl = PDecl->getDefinition(); + + llvm::SmallVector<const Decl *, 4> DirectMembers; + const auto *IDecl = CDecl->getClassInterface(); + for (auto *MD : PDecl->methods()) { + if (!MD->isPropertyAccessor()) { + if (const auto *CMD = + IDecl->getMethod(MD->getSelector(), MD->isInstanceMethod())) { + if (CMD->isDirectMethod()) + DirectMembers.push_back(CMD); + } + } + } + for (auto *PD : PDecl->properties()) { + if (const auto *CPD = IDecl->FindPropertyVisibleInPrimaryClass( + PD->getIdentifier(), + PD->isClassProperty() + ? ObjCPropertyQueryKind::OBJC_PR_query_class + : ObjCPropertyQueryKind::OBJC_PR_query_instance)) { + if (CPD->isDirectProperty()) + DirectMembers.push_back(CPD); + } + } + if (!DirectMembers.empty()) { + S.Diag(CDecl->getLocation(), diag::err_objc_direct_protocol_conformance) + << CDecl->IsClassExtension() << CDecl << PDecl << IDecl; + for (const auto *MD : DirectMembers) + S.Diag(MD->getLocation(), diag::note_direct_member_here); + return; + } + + // Check on this protocols's referenced protocols, recursively. + DiagnoseCategoryDirectMembersProtocolConformance(S, CDecl, + PDecl->protocols()); +} + // Note: For class/category implementations, allMethods is always null. Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods, ArrayRef<DeclGroupPtrTy> allTUVars) { @@ -3922,15 +3984,11 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods, if (auto *OID = dyn_cast<ObjCImplementationDecl>(CurContext)) { for (auto PropImpl : OID->property_impls()) { if (auto *Getter = PropImpl->getGetterMethodDecl()) - if (Getter->isSynthesizedAccessorStub()) { - OID->makeDeclVisibleInContext(Getter); + if (Getter->isSynthesizedAccessorStub()) OID->addDecl(Getter); - } if (auto *Setter = PropImpl->getSetterMethodDecl()) - if (Setter->isSynthesizedAccessorStub()) { - OID->makeDeclVisibleInContext(Setter); + if (Setter->isSynthesizedAccessorStub()) OID->addDecl(Setter); - } } } @@ -4003,6 +4061,8 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods, ObjCInterfaceDecl *CCPrimary = C->getClassInterface(); DiagnoseClassExtensionDupMethods(C, CCPrimary); } + + DiagnoseCategoryDirectMembersProtocolConformance(*this, C, C->protocols()); } if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(ClassDecl)) { if (CDecl->getIdentifier()) diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index d7695f9d7d7a..851e28741e49 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -99,9 +99,7 @@ ExprResult Sema::ActOnNoexceptSpec(SourceLocation NoexceptLoc, llvm::APSInt Result; Converted = VerifyIntegerConstantExpression( - Converted.get(), &Result, - diag::err_noexcept_needs_constant_expression, - /*AllowFold*/ false); + Converted.get(), &Result, diag::err_noexcept_needs_constant_expression); if (!Converted.isInvalid()) EST = !Result ? EST_NoexceptFalse : EST_NoexceptTrue; return Converted; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index ccae79636f32..45616dadcbee 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -24,10 +24,10 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" +#include "clang/AST/OperationKinds.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/Builtins.h" -#include "clang/Basic/FixedPoint.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -94,7 +94,7 @@ static void DiagnoseUnusedOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc) { A->getSemanticSpelling() != UnusedAttr::C2x_maybe_unused) { const Decl *DC = cast_or_null<Decl>(S.getCurObjCLexicalContext()); if (DC && !DC->hasAttr<UnusedAttr>()) - S.Diag(Loc, diag::warn_used_but_marked_unused) << D->getDeclName(); + S.Diag(Loc, diag::warn_used_but_marked_unused) << D; } } } @@ -339,11 +339,10 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs, // List-items in map clauses on this construct may only refer to the declared // variable var and entities that could be referenced by a procedure defined // at the same location - auto *DMD = dyn_cast<OMPDeclareMapperDecl>(CurContext); - if (LangOpts.OpenMP && DMD && !CurContext->containsDecl(D) && - isa<VarDecl>(D)) { + if (LangOpts.OpenMP && isa<VarDecl>(D) && + !isOpenMPDeclareMapperVarDeclAllowed(cast<VarDecl>(D))) { Diag(Loc, diag::err_omp_declare_mapper_wrong_var) - << DMD->getVarName().getAsString(); + << getOpenMPDeclareMapperVarName(); Diag(D->getLocation(), diag::note_entity_declared_at) << D; return true; } @@ -355,6 +354,24 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs, diagnoseUseOfInternalDeclInInlineFunction(*this, D, Loc); + // CUDA/HIP: Diagnose invalid references of host global variables in device + // functions. Reference of device global variables in host functions is + // allowed through shadow variables therefore it is not diagnosed. + if (LangOpts.CUDAIsDevice) { + auto *FD = dyn_cast_or_null<FunctionDecl>(CurContext); + auto Target = IdentifyCUDATarget(FD); + if (FD && Target != CFT_Host) { + const auto *VD = dyn_cast<VarDecl>(D); + if (VD && VD->hasGlobalStorage() && !VD->hasAttr<CUDADeviceAttr>() && + !VD->hasAttr<CUDAConstantAttr>() && !VD->hasAttr<CUDASharedAttr>() && + !VD->getType()->isCUDADeviceBuiltinSurfaceType() && + !VD->getType()->isCUDADeviceBuiltinTextureType() && + !VD->isConstexpr() && !VD->getType().isConstQualified()) + targetDiag(*Locs.begin(), diag::err_ref_bad_target) + << /*host*/ 2 << /*variable*/ 1 << VD << Target; + } + } + if (LangOpts.SYCLIsDevice || (LangOpts.OpenMP && LangOpts.OpenMPIsDevice)) { if (const auto *VD = dyn_cast<ValueDecl>(D)) checkDeviceDecl(VD, Loc); @@ -697,7 +714,8 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { // C++ [conv.lval]p3: // If T is cv std::nullptr_t, the result is a null pointer constant. CastKind CK = T->isNullPtrType() ? CK_NullToPointer : CK_LValueToRValue; - Res = ImplicitCastExpr::Create(Context, T, CK, E, nullptr, VK_RValue); + Res = ImplicitCastExpr::Create(Context, T, CK, E, nullptr, VK_RValue, + CurFPFeatureOverrides()); // C11 6.3.2.1p2: // ... if the lvalue has atomic type, the value has the non-atomic version @@ -705,7 +723,7 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { if (const AtomicType *Atomic = T->getAs<AtomicType>()) { T = Atomic->getValueType().getUnqualifiedType(); Res = ImplicitCastExpr::Create(Context, T, CK_AtomicToNonAtomic, Res.get(), - nullptr, VK_RValue); + nullptr, VK_RValue, FPOptionsOverride()); } return Res; @@ -1126,6 +1144,17 @@ static QualType handleFloatConversion(Sema &S, ExprResult &LHS, bool LHSFloat = LHSType->isRealFloatingType(); bool RHSFloat = RHSType->isRealFloatingType(); + // N1169 4.1.4: If one of the operands has a floating type and the other + // operand has a fixed-point type, the fixed-point operand + // is converted to the floating type [...] + if (LHSType->isFixedPointType() || RHSType->isFixedPointType()) { + if (LHSFloat) + RHS = S.ImpCastExprToType(RHS.get(), LHSType, CK_FixedPointToFloating); + else if (!IsCompAssign) + LHS = S.ImpCastExprToType(LHS.get(), RHSType, CK_FixedPointToFloating); + return LHSFloat ? LHSType : RHSType; + } + // If we have two real floating types, convert the smaller operand // to the bigger result. if (LHSFloat && RHSFloat) { @@ -1152,8 +1181,8 @@ static QualType handleFloatConversion(Sema &S, ExprResult &LHS, } assert(RHSFloat); return handleIntToFloatConversion(S, RHS, LHS, RHSType, LHSType, - /*convertInt=*/ true, - /*convertFloat=*/!IsCompAssign); + /*ConvertFloat=*/ true, + /*ConvertInt=*/!IsCompAssign); } /// Diagnose attempts to convert between __float128 and long double if @@ -1747,7 +1776,7 @@ static ExprResult BuildCookedLiteralOperatorCall(Sema &S, Scope *Scope, LookupResult R(S, OpName, UDSuffixLoc, Sema::LookupOrdinaryName); if (S.LookupLiteralOperator(Scope, R, llvm::makeArrayRef(ArgTy, Args.size()), /*AllowRaw*/ false, /*AllowTemplate*/ false, - /*AllowStringTemplate*/ false, + /*AllowStringTemplatePack*/ false, /*DiagnoseMissing*/ true) == Sema::LOLR_Error) return ExprError(); @@ -1852,9 +1881,9 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) { LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName); switch (LookupLiteralOperator(UDLScope, R, ArgTy, - /*AllowRaw*/ false, /*AllowTemplate*/ false, - /*AllowStringTemplate*/ true, - /*DiagnoseMissing*/ true)) { + /*AllowRaw*/ false, /*AllowTemplate*/ true, + /*AllowStringTemplatePack*/ true, + /*DiagnoseMissing*/ true, Lit)) { case LOLR_Cooked: { llvm::APInt Len(Context.getIntWidth(SizeType), Literal.GetNumStringChars()); @@ -1865,7 +1894,16 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) { return BuildLiteralOperatorCall(R, OpNameInfo, Args, StringTokLocs.back()); } - case LOLR_StringTemplate: { + case LOLR_Template: { + TemplateArgumentListInfo ExplicitArgs; + TemplateArgument Arg(Lit); + TemplateArgumentLocInfo ArgInfo(Lit); + ExplicitArgs.addArgument(TemplateArgumentLoc(Arg, ArgInfo)); + return BuildLiteralOperatorCall(R, OpNameInfo, None, StringTokLocs.back(), + &ExplicitArgs); + } + + case LOLR_StringTemplatePack: { TemplateArgumentListInfo ExplicitArgs; unsigned CharBits = Context.getIntWidth(CharTy); @@ -1886,7 +1924,6 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) { &ExplicitArgs); } case LOLR_Raw: - case LOLR_Template: case LOLR_ErrorNoDiagnostic: llvm_unreachable("unexpected literal operator lookup result"); case LOLR_Error: @@ -1915,6 +1952,35 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, TemplateArgs); } +// CUDA/HIP: Check whether a captured reference variable is referencing a +// host variable in a device or host device lambda. +static bool isCapturingReferenceToHostVarInCUDADeviceLambda(const Sema &S, + VarDecl *VD) { + if (!S.getLangOpts().CUDA || !VD->hasInit()) + return false; + assert(VD->getType()->isReferenceType()); + + // Check whether the reference variable is referencing a host variable. + auto *DRE = dyn_cast<DeclRefExpr>(VD->getInit()); + if (!DRE) + return false; + auto *Referee = dyn_cast<VarDecl>(DRE->getDecl()); + if (!Referee || !Referee->hasGlobalStorage() || + Referee->hasAttr<CUDADeviceAttr>()) + return false; + + // Check whether the current function is a device or host device lambda. + // Check whether the reference variable is a capture by getDeclContext() + // since refersToEnclosingVariableOrCapture() is not ready at this point. + auto *MD = dyn_cast_or_null<CXXMethodDecl>(S.CurContext); + if (MD && MD->getParent()->isLambda() && + MD->getOverloadedOperator() == OO_Call && MD->hasAttr<CUDADeviceAttr>() && + VD->getDeclContext() != MD) + return true; + + return false; +} + NonOdrUseReason Sema::getNonOdrUseReasonInCurrentContext(ValueDecl *D) { // A declaration named in an unevaluated operand never constitutes an odr-use. if (isUnevaluatedContext()) @@ -1924,9 +1990,16 @@ NonOdrUseReason Sema::getNonOdrUseReasonInCurrentContext(ValueDecl *D) { // A variable x whose name appears as a potentially-evaluated expression e // is odr-used by e unless [...] x is a reference that is usable in // constant expressions. + // CUDA/HIP: + // If a reference variable referencing a host variable is captured in a + // device or host device lambda, the value of the referee must be copied + // to the capture and the reference variable must be treated as odr-use + // since the value of the referee is not known at compile time and must + // be loaded from the captured. if (VarDecl *VD = dyn_cast<VarDecl>(D)) { if (VD->getType()->isReferenceType() && !(getLangOpts().OpenMP && isOpenMPCapturedDecl(D)) && + !isCapturingReferenceToHostVarInCUDADeviceLambda(*this, VD) && VD->isUsableInConstantExpressions(Context)) return NOUR_Constant; } @@ -2061,6 +2134,73 @@ static void emitEmptyLookupTypoDiagnostic( SemaRef.PDiag(NoteID)); } +/// Diagnose a lookup that found results in an enclosing class during error +/// recovery. This usually indicates that the results were found in a dependent +/// base class that could not be searched as part of a template definition. +/// Always issues a diagnostic (though this may be only a warning in MS +/// compatibility mode). +/// +/// Return \c true if the error is unrecoverable, or \c false if the caller +/// should attempt to recover using these lookup results. +bool Sema::DiagnoseDependentMemberLookup(LookupResult &R) { + // During a default argument instantiation the CurContext points + // to a CXXMethodDecl; but we can't apply a this-> fixit inside a + // function parameter list, hence add an explicit check. + bool isDefaultArgument = + !CodeSynthesisContexts.empty() && + CodeSynthesisContexts.back().Kind == + CodeSynthesisContext::DefaultFunctionArgumentInstantiation; + CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext); + bool isInstance = CurMethod && CurMethod->isInstance() && + R.getNamingClass() == CurMethod->getParent() && + !isDefaultArgument; + + // There are two ways we can find a class-scope declaration during template + // instantiation that we did not find in the template definition: if it is a + // member of a dependent base class, or if it is declared after the point of + // use in the same class. Distinguish these by comparing the class in which + // the member was found to the naming class of the lookup. + unsigned DiagID = diag::err_found_in_dependent_base; + unsigned NoteID = diag::note_member_declared_at; + if (R.getRepresentativeDecl()->getDeclContext()->Equals(R.getNamingClass())) { + DiagID = getLangOpts().MSVCCompat ? diag::ext_found_later_in_class + : diag::err_found_later_in_class; + } else if (getLangOpts().MSVCCompat) { + DiagID = diag::ext_found_in_dependent_base; + NoteID = diag::note_dependent_member_use; + } + + if (isInstance) { + // Give a code modification hint to insert 'this->'. + Diag(R.getNameLoc(), DiagID) + << R.getLookupName() + << FixItHint::CreateInsertion(R.getNameLoc(), "this->"); + CheckCXXThisCapture(R.getNameLoc()); + } else { + // FIXME: Add a FixItHint to insert 'Base::' or 'Derived::' (assuming + // they're not shadowed). + Diag(R.getNameLoc(), DiagID) << R.getLookupName(); + } + + for (NamedDecl *D : R) + Diag(D->getLocation(), NoteID); + + // Return true if we are inside a default argument instantiation + // and the found name refers to an instance member function, otherwise + // the caller will try to create an implicit member call and this is wrong + // for default arguments. + // + // FIXME: Is this special case necessary? We could allow the caller to + // diagnose this. + if (isDefaultArgument && ((*R.begin())->isCXXInstanceMember())) { + Diag(R.getNameLoc(), diag::err_member_call_without_object); + return true; + } + + // Tell the callee to try to recover. + return false; +} + /// Diagnose an empty lookup. /// /// \return false if new lookup candidates were found @@ -2092,46 +2232,20 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, // Don't give errors about ambiguities in this lookup. R.suppressDiagnostics(); - // During a default argument instantiation the CurContext points - // to a CXXMethodDecl; but we can't apply a this-> fixit inside a - // function parameter list, hence add an explicit check. - bool isDefaultArgument = - !CodeSynthesisContexts.empty() && - CodeSynthesisContexts.back().Kind == - CodeSynthesisContext::DefaultFunctionArgumentInstantiation; - CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext); - bool isInstance = CurMethod && - CurMethod->isInstance() && - DC == CurMethod->getParent() && !isDefaultArgument; - - // Give a code modification hint to insert 'this->'. - // TODO: fixit for inserting 'Base<T>::' in the other cases. - // Actually quite difficult! - if (getLangOpts().MSVCCompat) - diagnostic = diag::ext_found_via_dependent_bases_lookup; - if (isInstance) { - Diag(R.getNameLoc(), diagnostic) << Name - << FixItHint::CreateInsertion(R.getNameLoc(), "this->"); - CheckCXXThisCapture(R.getNameLoc()); - } else { - Diag(R.getNameLoc(), diagnostic) << Name; - } - - // Do we really want to note all of these? - for (NamedDecl *D : R) - Diag(D->getLocation(), diag::note_dependent_var_use); - - // Return true if we are inside a default argument instantiation - // and the found name refers to an instance member function, otherwise - // the function calling DiagnoseEmptyLookup will try to create an - // implicit member call and this is wrong for default argument. - if (isDefaultArgument && ((*R.begin())->isCXXInstanceMember())) { - Diag(R.getNameLoc(), diag::err_member_call_without_object); - return true; + // If there's a best viable function among the results, only mention + // that one in the notes. + OverloadCandidateSet Candidates(R.getNameLoc(), + OverloadCandidateSet::CSK_Normal); + AddOverloadedCallCandidates(R, ExplicitTemplateArgs, Args, Candidates); + OverloadCandidateSet::iterator Best; + if (Candidates.BestViableFunction(*this, R.getNameLoc(), Best) == + OR_Success) { + R.clear(); + R.addDecl(Best->FoundDecl.getDecl(), Best->FoundDecl.getAccess()); + R.resolveKind(); } - // Tell the callee to try to recover. - return false; + return DiagnoseDependentMemberLookup(R); } R.clear(); @@ -2577,6 +2691,13 @@ ExprResult Sema::BuildQualifiedDeclarationNameExpr( NameInfo, /*TemplateArgs=*/nullptr); if (R.empty()) { + // Don't diagnose problems with invalid record decl, the secondary no_member + // diagnostic during template instantiation is likely bogus, e.g. if a class + // is invalid because it's derived from an invalid base class, then missing + // members were likely supposed to be inherited. + if (const auto *CD = dyn_cast<CXXRecordDecl>(DC)) + if (CD->isInvalidDecl()) + return ExprError(); Diag(NameInfo.getLoc(), diag::err_no_member) << NameInfo.getName() << DC << SS.getRange(); return ExprError(); @@ -2730,8 +2851,7 @@ ExprResult Sema::BuildIvarRefExpr(Scope *S, SourceLocation Loc, // turn this into Self->ivar, just return a BareIVarExpr or something. IdentifierInfo &II = Context.Idents.get("self"); UnqualifiedId SelfName; - SelfName.setIdentifier(&II, SourceLocation()); - SelfName.setKind(UnqualifiedIdKind::IK_ImplicitSelfParam); + SelfName.setImplicitSelfParam(&II); CXXScopeSpec SelfScopeSpec; SourceLocation TemplateKWLoc; ExprResult SelfExpr = @@ -2792,21 +2912,24 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, /// Cast a base object to a member's actual type. /// -/// Logically this happens in three phases: +/// There are two relevant checks: +/// +/// C++ [class.access.base]p7: /// -/// * First we cast from the base type to the naming class. -/// The naming class is the class into which we were looking -/// when we found the member; it's the qualifier type if a -/// qualifier was provided, and otherwise it's the base type. +/// If a class member access operator [...] is used to access a non-static +/// data member or non-static member function, the reference is ill-formed if +/// the left operand [...] cannot be implicitly converted to a pointer to the +/// naming class of the right operand. /// -/// * Next we cast from the naming class to the declaring class. -/// If the member we found was brought into a class's scope by -/// a using declaration, this is that class; otherwise it's -/// the class declaring the member. +/// C++ [expr.ref]p7: /// -/// * Finally we cast from the declaring class to the "true" -/// declaring class of the member. This conversion does not -/// obey access control. +/// If E2 is a non-static data member or a non-static member function, the +/// program is ill-formed if the class of which E2 is directly a member is an +/// ambiguous base (11.8) of the naming class (11.9.3) of E2. +/// +/// Note that the latter check does not consider access; the access of the +/// "real" base class is checked as appropriate when checking the access of the +/// member name. ExprResult Sema::PerformObjectMemberConversion(Expr *From, NestedNameSpecifier *Qualifier, @@ -2930,45 +3053,10 @@ Sema::PerformObjectMemberConversion(Expr *From, } } - bool IgnoreAccess = false; - - // If we actually found the member through a using declaration, cast - // down to the using declaration's type. - // - // Pointer equality is fine here because only one declaration of a - // class ever has member declarations. - if (FoundDecl->getDeclContext() != Member->getDeclContext()) { - assert(isa<UsingShadowDecl>(FoundDecl)); - QualType URecordType = Context.getTypeDeclType( - cast<CXXRecordDecl>(FoundDecl->getDeclContext())); - - // We only need to do this if the naming-class to declaring-class - // conversion is non-trivial. - if (!Context.hasSameUnqualifiedType(FromRecordType, URecordType)) { - assert(IsDerivedFrom(FromLoc, FromRecordType, URecordType)); - CXXCastPath BasePath; - if (CheckDerivedToBaseConversion(FromRecordType, URecordType, - FromLoc, FromRange, &BasePath)) - return ExprError(); - - QualType UType = URecordType; - if (PointerConversions) - UType = Context.getPointerType(UType); - From = ImpCastExprToType(From, UType, CK_UncheckedDerivedToBase, - VK, &BasePath).get(); - FromType = UType; - FromRecordType = URecordType; - } - - // We don't do access control for the conversion from the - // declaring class to the true declaring class. - IgnoreAccess = true; - } - CXXCastPath BasePath; if (CheckDerivedToBaseConversion(FromRecordType, DestRecordType, FromLoc, FromRange, &BasePath, - IgnoreAccess)) + /*IgnoreAccess=*/true)) return ExprError(); return ImpCastExprToType(From, DestType, CK_UncheckedDerivedToBase, @@ -3208,6 +3296,17 @@ ExprResult Sema::BuildDeclarationNameExpr( break; } + // [expr.prim.id.unqual]p2: + // If the entity is a template parameter object for a template + // parameter of type T, the type of the expression is const T. + // [...] The expression is an lvalue if the entity is a [...] template + // parameter object. + if (type->isRecordType()) { + type = type.getUnqualifiedType().withConst(); + valueKind = VK_LValue; + break; + } + // For non-references, we need to strip qualifiers just in case // the template parameter was declared as 'const int' or whatever. valueKind = VK_RValue; @@ -3307,8 +3406,9 @@ ExprResult Sema::BuildDeclarationNameExpr( case Decl::MSProperty: case Decl::MSGuid: - // FIXME: Should MSGuidDecl be subject to capture in OpenMP, - // or duplicated between host and device? + case Decl::TemplateParamObject: + // FIXME: Should MSGuidDecl and template parameter objects be subject to + // capture in OpenMP, or duplicated between host and device? valueKind = VK_LValue; break; @@ -3409,70 +3509,6 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc, return PredefinedExpr::Create(Context, Loc, ResTy, IK, SL); } -static std::pair<QualType, StringLiteral *> -GetUniqueStableNameInfo(ASTContext &Context, QualType OpType, - SourceLocation OpLoc, PredefinedExpr::IdentKind K) { - std::pair<QualType, StringLiteral*> Result{{}, nullptr}; - - if (OpType->isDependentType()) { - Result.first = Context.DependentTy; - return Result; - } - - std::string Str = PredefinedExpr::ComputeName(Context, K, OpType); - llvm::APInt Length(32, Str.length() + 1); - Result.first = - Context.adjustStringLiteralBaseType(Context.CharTy.withConst()); - Result.first = Context.getConstantArrayType( - Result.first, Length, nullptr, ArrayType::Normal, /*IndexTypeQuals*/ 0); - Result.second = StringLiteral::Create(Context, Str, StringLiteral::Ascii, - /*Pascal*/ false, Result.first, OpLoc); - return Result; -} - -ExprResult Sema::BuildUniqueStableName(SourceLocation OpLoc, - TypeSourceInfo *Operand) { - QualType ResultTy; - StringLiteral *SL; - std::tie(ResultTy, SL) = GetUniqueStableNameInfo( - Context, Operand->getType(), OpLoc, PredefinedExpr::UniqueStableNameType); - - return PredefinedExpr::Create(Context, OpLoc, ResultTy, - PredefinedExpr::UniqueStableNameType, SL, - Operand); -} - -ExprResult Sema::BuildUniqueStableName(SourceLocation OpLoc, - Expr *E) { - QualType ResultTy; - StringLiteral *SL; - std::tie(ResultTy, SL) = GetUniqueStableNameInfo( - Context, E->getType(), OpLoc, PredefinedExpr::UniqueStableNameExpr); - - return PredefinedExpr::Create(Context, OpLoc, ResultTy, - PredefinedExpr::UniqueStableNameExpr, SL, E); -} - -ExprResult Sema::ActOnUniqueStableNameExpr(SourceLocation OpLoc, - SourceLocation L, SourceLocation R, - ParsedType Ty) { - TypeSourceInfo *TInfo = nullptr; - QualType T = GetTypeFromParser(Ty, &TInfo); - - if (T.isNull()) - return ExprError(); - if (!TInfo) - TInfo = Context.getTrivialTypeSourceInfo(T, OpLoc); - - return BuildUniqueStableName(OpLoc, TInfo); -} - -ExprResult Sema::ActOnUniqueStableNameExpr(SourceLocation OpLoc, - SourceLocation L, SourceLocation R, - Expr *E) { - return BuildUniqueStableName(OpLoc, E); -} - ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { PredefinedExpr::IdentKind IK; @@ -3675,7 +3711,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName); switch (LookupLiteralOperator(UDLScope, R, CookedTy, /*AllowRaw*/ true, /*AllowTemplate*/ true, - /*AllowStringTemplate*/ false, + /*AllowStringTemplatePack*/ false, /*DiagnoseMissing*/ !Literal.isImaginary)) { case LOLR_ErrorNoDiagnostic: // Lookup failure for imaginary constants isn't fatal, there's still the @@ -3730,7 +3766,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { return BuildLiteralOperatorCall(R, OpNameInfo, None, TokLoc, &ExplicitArgs); } - case LOLR_StringTemplate: + case LOLR_StringTemplatePack: llvm_unreachable("unexpected literal operator lookup result"); } } @@ -3804,8 +3840,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { if (Ty == Context.DoubleTy) { if (getLangOpts().SinglePrecisionConstants) { - const BuiltinType *BTy = Ty->getAs<BuiltinType>(); - if (BTy->getKind() != BuiltinType::Float) { + if (Ty->castAs<BuiltinType>()->getKind() != BuiltinType::Float) { Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get(); } } else if (getLangOpts().OpenCL && @@ -4053,7 +4088,7 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E, bool IsUnevaluatedOperand = (ExprKind == UETT_SizeOf || ExprKind == UETT_AlignOf || - ExprKind == UETT_PreferredAlignOf); + ExprKind == UETT_PreferredAlignOf || ExprKind == UETT_VecStep); if (IsUnevaluatedOperand) { ExprResult Result = CheckUnevaluatedOperand(E); if (Result.isInvalid()) @@ -4061,6 +4096,16 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E, E = Result.get(); } + // The operand for sizeof and alignof is in an unevaluated expression context, + // so side effects could result in unintended consequences. + // Exclude instantiation-dependent expressions, because 'sizeof' is sometimes + // used to build SFINAE gadgets. + // FIXME: Should we consider instantiation-dependent operands to 'alignof'? + if (IsUnevaluatedOperand && !inTemplateInstantiation() && + !E->isInstantiationDependent() && + E->HasSideEffects(Context, false)) + Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context); + if (ExprKind == UETT_VecStep) return CheckVecStepTraitOperandType(*this, ExprTy, E->getExprLoc(), E->getSourceRange()); @@ -4097,12 +4142,6 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E, return true; } - // The operand for sizeof and alignof is in an unevaluated expression context, - // so side effects could result in unintended consequences. - if (IsUnevaluatedOperand && !inTemplateInstantiation() && - E->HasSideEffects(Context, false)) - Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context); - if (CheckObjCTraitOperandConstraints(*this, ExprTy, E->getExprLoc(), E->getSourceRange(), ExprKind)) return true; @@ -4345,7 +4384,6 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T, case Type::UnaryTransform: case Type::Attributed: case Type::SubstTemplateTypeParm: - case Type::PackExpansion: case Type::MacroQualified: // Keep walking after single level desugaring. T = T.getSingleStepDesugaredType(Context); @@ -4593,8 +4631,8 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc, << SourceRange(base->getBeginLoc(), rbLoc); return ExprError(); } - // If the base is either a MatrixSubscriptExpr or a matrix type, try to create - // a new MatrixSubscriptExpr. + // If the base is a MatrixSubscriptExpr, try to create a new + // MatrixSubscriptExpr. auto *matSubscriptE = dyn_cast<MatrixSubscriptExpr>(base); if (matSubscriptE) { if (CheckAndReportCommaError(idx)) @@ -4605,34 +4643,13 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc, return CreateBuiltinMatrixSubscriptExpr( matSubscriptE->getBase(), matSubscriptE->getRowIdx(), idx, rbLoc); } - Expr *matrixBase = base; - bool IsMSPropertySubscript = isMSPropertySubscriptExpr(*this, base); - if (!IsMSPropertySubscript) { - ExprResult result = CheckPlaceholderExpr(base); - if (!result.isInvalid()) - matrixBase = result.get(); - } - if (matrixBase->getType()->isMatrixType()) { - if (CheckAndReportCommaError(idx)) - return ExprError(); - - return CreateBuiltinMatrixSubscriptExpr(matrixBase, idx, nullptr, rbLoc); - } - - // A comma-expression as the index is deprecated in C++2a onwards. - if (getLangOpts().CPlusPlus20 && - ((isa<BinaryOperator>(idx) && cast<BinaryOperator>(idx)->isCommaOp()) || - (isa<CXXOperatorCallExpr>(idx) && - cast<CXXOperatorCallExpr>(idx)->getOperator() == OO_Comma))) { - Diag(idx->getExprLoc(), diag::warn_deprecated_comma_subscript) - << SourceRange(base->getBeginLoc(), rbLoc); - } // Handle any non-overload placeholder types in the base and index // expressions. We can't handle overloads here because the other // operand might be an overloadable type, in which case the overload // resolution for the operator overload should get the first crack // at the overload. + bool IsMSPropertySubscript = false; if (base->getType()->isNonOverloadPlaceholderType()) { IsMSPropertySubscript = isMSPropertySubscriptExpr(*this, base); if (!IsMSPropertySubscript) { @@ -4642,6 +4659,24 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc, base = result.get(); } } + + // If the base is a matrix type, try to create a new MatrixSubscriptExpr. + if (base->getType()->isMatrixType()) { + if (CheckAndReportCommaError(idx)) + return ExprError(); + + return CreateBuiltinMatrixSubscriptExpr(base, idx, nullptr, rbLoc); + } + + // A comma-expression as the index is deprecated in C++2a onwards. + if (getLangOpts().CPlusPlus20 && + ((isa<BinaryOperator>(idx) && cast<BinaryOperator>(idx)->isCommaOp()) || + (isa<CXXOperatorCallExpr>(idx) && + cast<CXXOperatorCallExpr>(idx)->getOperator() == OO_Comma))) { + Diag(idx->getExprLoc(), diag::warn_deprecated_comma_subscript) + << SourceRange(base->getBeginLoc(), rbLoc); + } + if (idx->getType()->isNonOverloadPlaceholderType()) { ExprResult result = CheckPlaceholderExpr(idx); if (result.isInvalid()) return ExprError(); @@ -4741,12 +4776,13 @@ ExprResult Sema::CreateBuiltinMatrixSubscriptExpr(Expr *Base, Expr *RowIdx, return nullptr; } - llvm::APSInt Idx; - if (IndexExpr->isIntegerConstantExpr(Idx, Context) && - (Idx < 0 || Idx >= Dim)) { - Diag(IndexExpr->getBeginLoc(), diag::err_matrix_index_outside_range) - << IsColumnIdx << Dim; - return nullptr; + if (Optional<llvm::APSInt> Idx = + IndexExpr->getIntegerConstantExpr(Context)) { + if ((*Idx < 0 || *Idx >= Dim)) { + Diag(IndexExpr->getBeginLoc(), diag::err_matrix_index_outside_range) + << IsColumnIdx << Dim; + return nullptr; + } } ExprResult ConvExpr = @@ -4780,6 +4816,9 @@ void Sema::CheckAddressOfNoDeref(const Expr *E) { } void Sema::CheckSubscriptAccessOfNoDeref(const ArraySubscriptExpr *E) { + if (isUnevaluatedContext()) + return; + QualType ResultTy = E->getType(); ExpressionEvaluationContextRecord &LastRecord = ExprEvalContexts.back(); @@ -5162,12 +5201,11 @@ ExprResult Sema::ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc, IsCorrect = false; continue; } - llvm::APSInt Result; - bool IsConstant = Step->isIntegerConstantExpr(Result, Context); + Optional<llvm::APSInt> Result = Step->getIntegerConstantExpr(Context); // OpenMP 5.0, 2.1.6 Iterators, Restrictions // If the step expression of a range-specification equals zero, the // behavior is unspecified. - if (IsConstant && Result.isNullValue()) { + if (Result && Result->isNullValue()) { Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero) << Step << Step->getSourceRange(); IsCorrect = false; @@ -5567,9 +5605,8 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, return true; } - Diag(CallLoc, - diag::err_use_of_default_argument_to_function_declared_later) << - FD << cast<CXXRecordDecl>(FD->getDeclContext())->getDeclName(); + Diag(CallLoc, diag::err_use_of_default_argument_to_function_declared_later) + << FD << cast<CXXRecordDecl>(FD->getDeclContext()); Diag(UnparsedDefaultArgLocs[Param], diag::note_default_argument_declared_here); return true; @@ -6021,6 +6058,9 @@ static bool isPlaceholderToRemoveAsArg(QualType type) { #define SVE_TYPE(Name, Id, SingletonId) \ case BuiltinType::Id: #include "clang/Basic/AArch64SVEACLETypes.def" +#define PPC_VECTOR_TYPE(Name, Id, Size) \ + case BuiltinType::Id: +#include "clang/Basic/PPCTypes.def" #define PLACEHOLDER_TYPE(ID, SINGLETON_ID) #define BUILTIN_TYPE(ID, SINGLETON_ID) case BuiltinType::ID: #include "clang/AST/BuiltinTypes.def" @@ -6069,8 +6109,6 @@ static bool checkArgsForPlaceholders(Sema &S, MultiExprArg args) { ExprResult result = S.CheckPlaceholderExpr(args[i]); if (result.isInvalid()) hasInvalid = true; else args[i] = result.get(); - } else if (hasInvalid) { - (void)S.CorrectDelayedTyposInExpr(args[i]); } } return hasInvalid; @@ -6158,6 +6196,7 @@ static FunctionDecl *rewriteBuiltinFunctionDecl(Sema *Sema, ASTContext &Context, Params.push_back(Parm); } OverloadDecl->setParams(Params); + Sema->mergeDeclAttributes(OverloadDecl, FDecl); return OverloadDecl; } @@ -6273,7 +6312,8 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig) { ExprResult Call = - BuildCallExpr(Scope, Fn, LParenLoc, ArgExprs, RParenLoc, ExecConfig); + BuildCallExpr(Scope, Fn, LParenLoc, ArgExprs, RParenLoc, ExecConfig, + /*IsExecConfig=*/false, /*AllowRecovery=*/true); if (Call.isInvalid()) return Call; @@ -6301,7 +6341,8 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, /// locations. ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, - Expr *ExecConfig, bool IsExecConfig) { + Expr *ExecConfig, bool IsExecConfig, + bool AllowRecovery) { // Since this might be a postfix expression, get rid of ParenListExprs. ExprResult Result = MaybeConvertParenListExprToParenExpr(Scope, Fn); if (Result.isInvalid()) return ExprError(); @@ -6322,7 +6363,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, } return CallExpr::Create(Context, Fn, /*Args=*/{}, Context.VoidTy, - VK_RValue, RParenLoc); + VK_RValue, RParenLoc, CurFPFeatureOverrides()); } if (Fn->getType() == Context.PseudoObjectTy) { ExprResult result = CheckPlaceholderExpr(Fn); @@ -6336,7 +6377,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, if (ExecConfig) { return CUDAKernelCallExpr::Create( Context, Fn, cast<CallExpr>(ExecConfig), ArgExprs, - Context.DependentTy, VK_RValue, RParenLoc); + Context.DependentTy, VK_RValue, RParenLoc, CurFPFeatureOverrides()); } else { tryImplicitlyCaptureThisIfImplicitMemberFunctionAccessWithDependentArgs( @@ -6344,7 +6385,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, Fn->getBeginLoc()); return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy, - VK_RValue, RParenLoc); + VK_RValue, RParenLoc, CurFPFeatureOverrides()); } } @@ -6361,7 +6402,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, if (Fn->getType() == Context.BoundMemberTy) { return BuildCallToMemberFunction(Scope, Fn, LParenLoc, ArgExprs, - RParenLoc); + RParenLoc, AllowRecovery); } } @@ -6373,14 +6414,14 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, if (!find.HasFormOfMemberPointer) { if (Expr::hasAnyTypeDependentArguments(ArgExprs)) return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy, - VK_RValue, RParenLoc); + VK_RValue, RParenLoc, CurFPFeatureOverrides()); OverloadExpr *ovl = find.Expression; if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(ovl)) return BuildOverloadedCallExpr( Scope, Fn, ULE, LParenLoc, ArgExprs, RParenLoc, ExecConfig, /*AllowTypoCorrection=*/true, find.IsAddressOfOperand); return BuildCallToMemberFunction(Scope, Fn, LParenLoc, ArgExprs, - RParenLoc); + RParenLoc, AllowRecovery); } } @@ -6433,6 +6474,21 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, checkDirectCallValidity(*this, Fn, FD, ArgExprs); } + if (Context.isDependenceAllowed() && + (Fn->isTypeDependent() || Expr::hasAnyTypeDependentArguments(ArgExprs))) { + assert(!getLangOpts().CPlusPlus); + assert((Fn->containsErrors() || + llvm::any_of(ArgExprs, + [](clang::Expr *E) { return E->containsErrors(); })) && + "should only occur in error-recovery path."); + QualType ReturnType = + llvm::isa_and_nonnull<FunctionDecl>(NDecl) + ? cast<FunctionDecl>(NDecl)->getCallResultType() + : Context.DependentTy; + return CallExpr::Create(Context, Fn, ArgExprs, ReturnType, + Expr::getValueKindForType(ReturnType), RParenLoc, + CurFPFeatureOverrides()); + } return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, ArgExprs, RParenLoc, ExecConfig, IsExecConfig); } @@ -6564,15 +6620,16 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, if (Config) { assert(UsesADL == ADLCallKind::NotADL && "CUDAKernelCallExpr should not use ADL"); - TheCall = - CUDAKernelCallExpr::Create(Context, Fn, cast<CallExpr>(Config), Args, - ResultTy, VK_RValue, RParenLoc, NumParams); + TheCall = CUDAKernelCallExpr::Create(Context, Fn, cast<CallExpr>(Config), + Args, ResultTy, VK_RValue, RParenLoc, + CurFPFeatureOverrides(), NumParams); } else { - TheCall = CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue, - RParenLoc, NumParams, UsesADL); + TheCall = + CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue, RParenLoc, + CurFPFeatureOverrides(), NumParams, UsesADL); } - if (!getLangOpts().CPlusPlus) { + if (!Context.isDependenceAllowed()) { // Forget about the nulled arguments since typo correction // do not handle them well. TheCall->shrinkNumArgs(Args.size()); @@ -6596,10 +6653,11 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, if (Config) TheCall = CUDAKernelCallExpr::Create( Context, Fn, cast<CallExpr>(Config), Args, ResultTy, VK_RValue, - RParenLoc, NumParams); + RParenLoc, CurFPFeatureOverrides(), NumParams); else - TheCall = CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue, - RParenLoc, NumParams, UsesADL); + TheCall = + CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue, RParenLoc, + CurFPFeatureOverrides(), NumParams, UsesADL); } // We can now handle the nulled arguments for the default arguments. TheCall->setNumArgsUnsafe(std::max<unsigned>(Args.size(), NumParams)); @@ -6960,9 +7018,9 @@ void Sema::maybeExtendBlockObject(ExprResult &E) { // Only do this in an r-value context. if (!getLangOpts().ObjCAutoRefCount) return; - E = ImplicitCastExpr::Create(Context, E.get()->getType(), - CK_ARCExtendBlockObject, E.get(), - /*base path*/ nullptr, VK_RValue); + E = ImplicitCastExpr::Create( + Context, E.get()->getType(), CK_ARCExtendBlockObject, E.get(), + /*base path*/ nullptr, VK_RValue, FPOptionsOverride()); Cleanup.setExprNeedsCleanups(true); } @@ -7041,6 +7099,7 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) { case Type::STK_Integral: return CK_FixedPointToIntegral; case Type::STK_Floating: + return CK_FixedPointToFloating; case Type::STK_IntegralComplex: case Type::STK_FloatingComplex: Diag(Src.get()->getExprLoc(), @@ -7113,10 +7172,7 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) { case Type::STK_MemberPointer: llvm_unreachable("member pointer type in C"); case Type::STK_FixedPoint: - Diag(Src.get()->getExprLoc(), - diag::err_unimplemented_conversion_with_fixed_point_type) - << SrcTy; - return CK_IntegralCast; + return CK_FloatingToFixedPoint; } llvm_unreachable("Should have returned before this"); @@ -7211,6 +7267,28 @@ static bool breakDownVectorType(QualType type, uint64_t &len, return true; } +/// Are the two types SVE-bitcast-compatible types? I.e. is bitcasting from the +/// first SVE type (e.g. an SVE VLAT) to the second type (e.g. an SVE VLST) +/// allowed? +/// +/// This will also return false if the two given types do not make sense from +/// the perspective of SVE bitcasts. +bool Sema::isValidSveBitcast(QualType srcTy, QualType destTy) { + assert(srcTy->isVectorType() || destTy->isVectorType()); + + auto ValidScalableConversion = [](QualType FirstType, QualType SecondType) { + if (!FirstType->isSizelessBuiltinType()) + return false; + + const auto *VecTy = SecondType->getAs<VectorType>(); + return VecTy && + VecTy->getVectorKind() == VectorType::SveFixedLengthDataVector; + }; + + return ValidScalableConversion(srcTy, destTy) || + ValidScalableConversion(destTy, srcTy); +} + /// Are the two types lax-compatible vector types? That is, given /// that one of them is a vector, do they have equal storage sizes, /// where the storage size is the number of elements times the element @@ -7401,7 +7479,7 @@ Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, } if (PE || PLE->getNumExprs() == 1) { Expr *E = (PE ? PE->getSubExpr() : PLE->getExpr(0)); - if (!E->getType()->isVectorType()) + if (!E->isTypeDependent() && !E->getType()->isVectorType()) isVectorLiteral = true; } else @@ -8059,6 +8137,16 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, VK = VK_RValue; OK = OK_Ordinary; + if (Context.isDependenceAllowed() && + (Cond.get()->isTypeDependent() || LHS.get()->isTypeDependent() || + RHS.get()->isTypeDependent())) { + assert(!getLangOpts().CPlusPlus); + assert((Cond.get()->containsErrors() || LHS.get()->containsErrors() || + RHS.get()->containsErrors()) && + "should only occur in error-recovery path."); + return Context.DependentTy; + } + // The OpenCL operator with a vector condition is sufficiently // different to merit its own checker. if ((getLangOpts().OpenCL && Cond.get()->getType()->isVectorType()) || @@ -8106,6 +8194,15 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, // If both operands have arithmetic type, do the usual arithmetic conversions // to find a common type: C99 6.5.15p3,5. if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) { + // Disallow invalid arithmetic conversions, such as those between ExtInts of + // different sizes, or between ExtInts and other types. + if (ResTy.isNull() && (LHSTy->isExtIntType() || RHSTy->isExtIntType())) { + Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) + << LHSTy << RHSTy << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + return QualType(); + } + LHS = ImpCastExprToType(LHS.get(), ResTy, PrepareScalarCast(LHS, ResTy)); RHS = ImpCastExprToType(RHS.get(), ResTy, PrepareScalarCast(RHS, ResTy)); @@ -8363,7 +8460,7 @@ static bool IsArithmeticBinaryExpr(Expr *E, BinaryOperatorKind *Opcode, Expr **RHSExprs) { // Don't strip parenthesis: we should not warn if E is in parenthesis. E = E->IgnoreImpCasts(); - E = E->IgnoreConversionOperator(); + E = E->IgnoreConversionOperatorSingleStep(); E = E->IgnoreImpCasts(); if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) { E = MTE->getSubExpr(); @@ -8470,8 +8567,12 @@ static QualType computeConditionalNullability(QualType ResTy, bool IsBin, auto GetNullability = [&Ctx](QualType Ty) { Optional<NullabilityKind> Kind = Ty->getNullability(Ctx); - if (Kind) + if (Kind) { + // For our purposes, treat _Nullable_result as _Nullable. + if (*Kind == NullabilityKind::NullableResult) + return NullabilityKind::Nullable; return *Kind; + } return NullabilityKind::Unspecified; }; @@ -8516,7 +8617,7 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, SourceLocation ColonLoc, Expr *CondExpr, Expr *LHSExpr, Expr *RHSExpr) { - if (!getLangOpts().CPlusPlus) { + if (!Context.isDependenceAllowed()) { // C cannot handle TypoExpr nodes in the condition because it // doesn't handle dependent types properly, so make sure any TypoExprs have // been dealt with before checking the operands. @@ -8997,6 +9098,15 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, } } + // Allow assignments between fixed-length and sizeless SVE vectors. + if ((LHSType->isSizelessBuiltinType() && RHSType->isVectorType()) || + (LHSType->isVectorType() && RHSType->isSizelessBuiltinType())) + if (Context.areCompatibleSveTypes(LHSType, RHSType) || + Context.areLaxCompatibleSveTypes(LHSType, RHSType)) { + Kind = CK_BitCast; + return Compatible; + } + return Incompatible; } @@ -9781,6 +9891,10 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, const VectorType *RHSVecType = RHSType->getAs<VectorType>(); assert(LHSVecType || RHSVecType); + if ((LHSVecType && LHSVecType->getElementType()->isBFloat16Type()) || + (RHSVecType && RHSVecType->getElementType()->isBFloat16Type())) + return InvalidOperands(Loc, LHS, RHS); + // AltiVec-style "vector bool op vector bool" combinations are allowed // for some operators but not others. if (!AllowBothBool && @@ -9827,6 +9941,44 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, } } + // Expressions containing fixed-length and sizeless SVE vectors are invalid + // since the ambiguity can affect the ABI. + auto IsSveConversion = [](QualType FirstType, QualType SecondType) { + const VectorType *VecType = SecondType->getAs<VectorType>(); + return FirstType->isSizelessBuiltinType() && VecType && + (VecType->getVectorKind() == VectorType::SveFixedLengthDataVector || + VecType->getVectorKind() == + VectorType::SveFixedLengthPredicateVector); + }; + + if (IsSveConversion(LHSType, RHSType) || IsSveConversion(RHSType, LHSType)) { + Diag(Loc, diag::err_typecheck_sve_ambiguous) << LHSType << RHSType; + return QualType(); + } + + // Expressions containing GNU and SVE (fixed or sizeless) vectors are invalid + // since the ambiguity can affect the ABI. + auto IsSveGnuConversion = [](QualType FirstType, QualType SecondType) { + const VectorType *FirstVecType = FirstType->getAs<VectorType>(); + const VectorType *SecondVecType = SecondType->getAs<VectorType>(); + + if (FirstVecType && SecondVecType) + return FirstVecType->getVectorKind() == VectorType::GenericVector && + (SecondVecType->getVectorKind() == + VectorType::SveFixedLengthDataVector || + SecondVecType->getVectorKind() == + VectorType::SveFixedLengthPredicateVector); + + return FirstType->isSizelessBuiltinType() && SecondVecType && + SecondVecType->getVectorKind() == VectorType::GenericVector; + }; + + if (IsSveGnuConversion(LHSType, RHSType) || + IsSveGnuConversion(RHSType, LHSType)) { + Diag(Loc, diag::err_typecheck_sve_gnu_ambiguous) << LHSType << RHSType; + return QualType(); + } + // If there's a vector type and a scalar, try to convert the scalar to // the vector element type and splat. unsigned DiagID = diag::err_typecheck_vector_not_convertable; @@ -9981,7 +10133,7 @@ static void DiagnoseDivisionSizeofPointerOrArray(Sema &S, Expr *LHS, Expr *RHS, QualType RHSTy; if (RUE->isArgumentType()) - RHSTy = RUE->getArgumentType(); + RHSTy = RUE->getArgumentType().getNonReferenceType(); else RHSTy = RUE->getArgumentExpr()->IgnoreParens()->getType(); @@ -9999,7 +10151,7 @@ static void DiagnoseDivisionSizeofPointerOrArray(Sema &S, Expr *LHS, Expr *RHS, QualType ArrayElemTy = ArrayTy->getElementType(); if (ArrayElemTy != S.Context.getBaseElementType(ArrayTy) || ArrayElemTy->isDependentType() || RHSTy->isDependentType() || - ArrayElemTy->isCharType() || + RHSTy->isReferenceType() || ArrayElemTy->isCharType() || S.Context.getTypeSize(ArrayElemTy) == S.Context.getTypeSize(RHSTy)) return; S.Diag(Loc, diag::warn_division_sizeof_array) @@ -10589,9 +10741,13 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS, } QualType LHSExprType = LHS.get()->getType(); - uint64_t LeftSize = LHSExprType->isExtIntType() - ? S.Context.getIntWidth(LHSExprType) - : S.Context.getTypeSize(LHSExprType); + uint64_t LeftSize = S.Context.getTypeSize(LHSExprType); + if (LHSExprType->isExtIntType()) + LeftSize = S.Context.getIntWidth(LHSExprType); + else if (LHSExprType->isFixedPointType()) { + auto FXSema = S.Context.getFixedPointSemantics(LHSExprType); + LeftSize = FXSema.getWidth() - (unsigned)FXSema.hasUnsignedPadding(); + } llvm::APInt LeftBits(Right.getBitWidth(), LeftSize); if (Right.uge(LeftBits)) { S.DiagRuntimeBehavior(Loc, RHS.get(), @@ -10600,7 +10756,8 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS, return; } - if (Opc != BO_Shl) + // FIXME: We probably need to handle fixed point types specially here. + if (Opc != BO_Shl || LHSExprType->isFixedPointType()) return; // When left shifting an ICE which is signed, we can check for overflow which @@ -10784,7 +10941,9 @@ QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS, QualType RHSType = RHS.get()->getType(); // C99 6.5.7p2: Each of the operands shall have integer type. - if (!LHSType->hasIntegerRepresentation() || + // Embedded-C 4.1.6.2.2: The LHS may also be fixed-point. + if ((!LHSType->isFixedPointOrIntegerType() && + !LHSType->hasIntegerRepresentation()) || !RHSType->hasIntegerRepresentation()) return InvalidOperands(Loc, LHS, RHS); @@ -13632,7 +13791,7 @@ static std::pair<ExprResult, ExprResult> CorrectDelayedTyposInBinOp(Sema &S, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr) { ExprResult LHS = LHSExpr, RHS = RHSExpr; - if (!S.getLangOpts().CPlusPlus) { + if (!S.Context.isDependenceAllowed()) { // C cannot handle TypoExpr nodes on either side of a binop because it // doesn't handle dependent types properly, so make sure any TypoExprs have // been dealt with before checking the operands. @@ -13889,9 +14048,10 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, // float vectors and truncating the result back to half vector. For now, we do // this only when HalfArgsAndReturn is set (that is, when the target is arm or // arm64). - assert(isVector(RHS.get()->getType(), Context.HalfTy) == - isVector(LHS.get()->getType(), Context.HalfTy) && - "both sides are half vectors or neither sides are"); + assert( + (Opc == BO_Comma || isVector(RHS.get()->getType(), Context.HalfTy) == + isVector(LHS.get()->getType(), Context.HalfTy)) && + "both sides are half vectors or neither sides are"); ConvertHalfVec = needsConversionOfHalfVec(ConvertHalfVec, Context, LHS.get(), RHS.get()); @@ -14169,6 +14329,19 @@ ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, return BuildBinOp(S, TokLoc, Opc, LHSExpr, RHSExpr); } +void Sema::LookupBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, + UnresolvedSetImpl &Functions) { + OverloadedOperatorKind OverOp = BinaryOperator::getOverloadedOperator(Opc); + if (OverOp != OO_None && OverOp != OO_Equal) + LookupOverloadedOperatorName(OverOp, S, Functions); + + // In C++20 onwards, we may have a second operator to look up. + if (getLangOpts().CPlusPlus20) { + if (OverloadedOperatorKind ExtraOp = getRewrittenOverloadedOperator(OverOp)) + LookupOverloadedOperatorName(ExtraOp, S, Functions); + } +} + /// Build an overloaded binary operator expression in the given scope. static ExprResult BuildOverloadedBinOp(Sema &S, Scope *Sc, SourceLocation OpLoc, BinaryOperatorKind Opc, @@ -14188,23 +14361,9 @@ static ExprResult BuildOverloadedBinOp(Sema &S, Scope *Sc, SourceLocation OpLoc, break; } - // Find all of the overloaded operators visible from this - // point. We perform both an operator-name lookup from the local - // scope and an argument-dependent lookup based on the types of - // the arguments. + // Find all of the overloaded operators visible from this point. UnresolvedSet<16> Functions; - OverloadedOperatorKind OverOp - = BinaryOperator::getOverloadedOperator(Opc); - if (Sc && OverOp != OO_None && OverOp != OO_Equal) - S.LookupOverloadedOperatorName(OverOp, Sc, LHS->getType(), - RHS->getType(), Functions); - - // In C++20 onwards, we may have a second operator to look up. - if (S.getLangOpts().CPlusPlus20) { - if (OverloadedOperatorKind ExtraOp = getRewrittenOverloadedOperator(OverOp)) - S.LookupOverloadedOperatorName(ExtraOp, Sc, LHS->getType(), - RHS->getType(), Functions); - } + S.LookupBinOp(Sc, OpLoc, Opc, Functions); // Build the (potentially-overloaded, potentially-dependent) // binary operation. @@ -14313,6 +14472,47 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc, return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr); } + if (getLangOpts().RecoveryAST && + (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent())) { + assert(!getLangOpts().CPlusPlus); + assert((LHSExpr->containsErrors() || RHSExpr->containsErrors()) && + "Should only occur in error-recovery path."); + if (BinaryOperator::isCompoundAssignmentOp(Opc)) + // C [6.15.16] p3: + // An assignment expression has the value of the left operand after the + // assignment, but is not an lvalue. + return CompoundAssignOperator::Create( + Context, LHSExpr, RHSExpr, Opc, + LHSExpr->getType().getUnqualifiedType(), VK_RValue, OK_Ordinary, + OpLoc, CurFPFeatureOverrides()); + QualType ResultType; + switch (Opc) { + case BO_Assign: + ResultType = LHSExpr->getType().getUnqualifiedType(); + break; + case BO_LT: + case BO_GT: + case BO_LE: + case BO_GE: + case BO_EQ: + case BO_NE: + case BO_LAnd: + case BO_LOr: + // These operators have a fixed result type regardless of operands. + ResultType = Context.IntTy; + break; + case BO_Comma: + ResultType = RHSExpr->getType(); + break; + default: + ResultType = Context.DependentTy; + break; + } + return BinaryOperator::Create(Context, LHSExpr, RHSExpr, Opc, ResultType, + VK_RValue, OK_Ordinary, OpLoc, + CurFPFeatureOverrides()); + } + // Build a built-in binary operation. return CreateBuiltinBinOp(OpLoc, Opc, LHSExpr, RHSExpr); } @@ -14540,7 +14740,8 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, OpLoc, CanOverflow, CurFPFeatureOverrides()); if (Opc == UO_Deref && UO->getType()->hasAttr(attr::NoDeref) && - !isa<ArrayType>(UO->getType().getDesugaredType(Context))) + !isa<ArrayType>(UO->getType().getDesugaredType(Context)) && + !isUnevaluatedContext()) ExprEvalContexts.back().PossibleDerefs.insert(UO); // Convert the result back to a half vector. @@ -14620,15 +14821,11 @@ ExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc, if (getLangOpts().CPlusPlus && Input->getType()->isOverloadableType() && UnaryOperator::getOverloadedOperator(Opc) != OO_None && !(Opc == UO_AddrOf && isQualifiedMemberAccess(Input))) { - // Find all of the overloaded operators visible from this - // point. We perform both an operator-name lookup from the local - // scope and an argument-dependent lookup based on the types of - // the arguments. + // Find all of the overloaded operators visible from this point. UnresolvedSet<16> Functions; OverloadedOperatorKind OverOp = UnaryOperator::getOverloadedOperator(Opc); if (S && OverOp != OO_None) - LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(), - Functions); + LookupOverloadedOperatorName(OverOp, S, Functions); return CreateOverloadedUnaryOp(OpLoc, Opc, Functions, Input); } @@ -14935,9 +15132,8 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, } else { // The conditional expression is required to be a constant expression. llvm::APSInt condEval(32); - ExprResult CondICE - = VerifyIntegerConstantExpression(CondExpr, &condEval, - diag::err_typecheck_choose_expr_requires_constant, false); + ExprResult CondICE = VerifyIntegerConstantExpression( + CondExpr, &condEval, diag::err_typecheck_choose_expr_requires_constant); if (CondICE.isInvalid()) return ExprError(); CondExpr = CondICE.get(); @@ -14993,7 +15189,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo, Scope *CurScope) { assert(ParamInfo.getIdentifier() == nullptr && "block-id should have no identifier!"); - assert(ParamInfo.getContext() == DeclaratorContext::BlockLiteralContext); + assert(ParamInfo.getContext() == DeclaratorContext::BlockLiteral); BlockScopeInfo *CurBlock = getCurBlock(); TypeSourceInfo *Sig = GetTypeForDeclarator(ParamInfo, CurScope); @@ -15041,10 +15237,10 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo, CurBlock->TheDecl->setSignatureAsWritten(Sig); CurBlock->FunctionType = T; - const FunctionType *Fn = T->getAs<FunctionType>(); + const auto *Fn = T->castAs<FunctionType>(); QualType RetTy = Fn->getReturnType(); bool isVariadic = - (isa<FunctionProtoType>(Fn) && cast<FunctionProtoType>(Fn)->isVariadic()); + (isa<FunctionProtoType>(Fn) && cast<FunctionProtoType>(Fn)->isVariadic()); CurBlock->TheDecl->setIsVariadic(isVariadic); @@ -15207,10 +15403,6 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, PopDeclContext(); - // Pop the block scope now but keep it alive to the end of this function. - AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy(); - PoppedFunctionScopePtr ScopeRAII = PopFunctionScopeInfo(&WP, BD, BlockTy); - // Set the captured variables on the block. SmallVector<BlockDecl::Capture, 4> Captures; for (Capture &Cap : BSI->Captures) { @@ -15278,6 +15470,10 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, } BD->setCaptures(Context, Captures, BSI->CXXThisCaptureIndex != 0); + // Pop the block scope now but keep it alive to the end of this function. + AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy(); + PoppedFunctionScopePtr ScopeRAII = PopFunctionScopeInfo(&WP, BD, BlockTy); + BlockExpr *Result = new (Context) BlockExpr(BD, BlockTy); // If the block isn't obviously global, i.e. it captures anything at @@ -15543,7 +15739,6 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, bool CheckInferredResultType = false; bool isInvalid = false; unsigned DiagKind = 0; - FixItHint Hint; ConversionFixItGenerator ConvHints; bool MayHaveConvFixit = false; bool MayHaveFunctionDiff = false; @@ -15596,10 +15791,9 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, } CheckInferredResultType = DstType->isObjCObjectPointerType() && SrcType->isObjCObjectPointerType(); - if (Hint.isNull() && !CheckInferredResultType) { + if (!CheckInferredResultType) { ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this); - } - else if (CheckInferredResultType) { + } else if (CheckInferredResultType) { SrcType = SrcType.getUnqualifiedType(); DstType = DstType.getUnqualifiedType(); } @@ -15767,14 +15961,22 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, else FDiag << FirstType << SecondType << Action << SrcExpr->getSourceRange(); + if (DiagKind == diag::ext_typecheck_convert_incompatible_pointer_sign || + DiagKind == diag::err_typecheck_convert_incompatible_pointer_sign) { + auto isPlainChar = [](const clang::Type *Type) { + return Type->isSpecificBuiltinType(BuiltinType::Char_S) || + Type->isSpecificBuiltinType(BuiltinType::Char_U); + }; + FDiag << (isPlainChar(FirstType->getPointeeOrArrayElementType()) || + isPlainChar(SecondType->getPointeeOrArrayElementType())); + } + // If we can fix the conversion, suggest the FixIts. - assert(ConvHints.isNull() || Hint.isNull()); if (!ConvHints.isNull()) { for (FixItHint &H : ConvHints.Hints) FDiag << H; - } else { - FDiag << Hint; } + if (MayHaveConvFixit) { FDiag << (unsigned) (ConvHints.Kind); } if (MayHaveFunctionDiff) @@ -15803,21 +16005,27 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, } ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, - llvm::APSInt *Result) { + llvm::APSInt *Result, + AllowFoldKind CanFold) { class SimpleICEDiagnoser : public VerifyICEDiagnoser { public: - void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) override { - S.Diag(Loc, diag::err_expr_not_ice) << S.LangOpts.CPlusPlus << SR; + SemaDiagnosticBuilder diagnoseNotICEType(Sema &S, SourceLocation Loc, + QualType T) override { + return S.Diag(Loc, diag::err_ice_not_integral) + << T << S.LangOpts.CPlusPlus; + } + SemaDiagnosticBuilder diagnoseNotICE(Sema &S, SourceLocation Loc) override { + return S.Diag(Loc, diag::err_expr_not_ice) << S.LangOpts.CPlusPlus; } } Diagnoser; - return VerifyIntegerConstantExpression(E, Result, Diagnoser); + return VerifyIntegerConstantExpression(E, Result, Diagnoser, CanFold); } ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, unsigned DiagID, - bool AllowFold) { + AllowFoldKind CanFold) { class IDDiagnoser : public VerifyICEDiagnoser { unsigned DiagID; @@ -15825,23 +16033,29 @@ ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, IDDiagnoser(unsigned DiagID) : VerifyICEDiagnoser(DiagID == 0), DiagID(DiagID) { } - void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) override { - S.Diag(Loc, DiagID) << SR; + SemaDiagnosticBuilder diagnoseNotICE(Sema &S, SourceLocation Loc) override { + return S.Diag(Loc, DiagID); } } Diagnoser(DiagID); - return VerifyIntegerConstantExpression(E, Result, Diagnoser, AllowFold); + return VerifyIntegerConstantExpression(E, Result, Diagnoser, CanFold); +} + +Sema::SemaDiagnosticBuilder +Sema::VerifyICEDiagnoser::diagnoseNotICEType(Sema &S, SourceLocation Loc, + QualType T) { + return diagnoseNotICE(S, Loc); } -void Sema::VerifyICEDiagnoser::diagnoseFold(Sema &S, SourceLocation Loc, - SourceRange SR) { - S.Diag(Loc, diag::ext_expr_not_ice) << SR << S.LangOpts.CPlusPlus; +Sema::SemaDiagnosticBuilder +Sema::VerifyICEDiagnoser::diagnoseFold(Sema &S, SourceLocation Loc) { + return S.Diag(Loc, diag::ext_expr_not_ice) << S.LangOpts.CPlusPlus; } ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, VerifyICEDiagnoser &Diagnoser, - bool AllowFold) { + AllowFoldKind CanFold) { SourceLocation DiagLoc = E->getBeginLoc(); if (getLangOpts().CPlusPlus11) { @@ -15852,14 +16066,16 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, // unscoped enumeration type ExprResult Converted; class CXX11ConvertDiagnoser : public ICEConvertDiagnoser { + VerifyICEDiagnoser &BaseDiagnoser; public: - CXX11ConvertDiagnoser(bool Silent) - : ICEConvertDiagnoser(/*AllowScopedEnumerations*/false, - Silent, true) {} + CXX11ConvertDiagnoser(VerifyICEDiagnoser &BaseDiagnoser) + : ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false, + BaseDiagnoser.Suppress, true), + BaseDiagnoser(BaseDiagnoser) {} SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, QualType T) override { - return S.Diag(Loc, diag::err_ice_not_integral) << T; + return BaseDiagnoser.diagnoseNotICEType(S, Loc, T); } SemaDiagnosticBuilder diagnoseIncomplete( @@ -15893,7 +16109,7 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override { llvm_unreachable("conversion functions are permitted"); } - } ConvertDiagnoser(Diagnoser.Suppress); + } ConvertDiagnoser(Diagnoser); Converted = PerformContextualImplicitConversion(DiagLoc, E, ConvertDiagnoser); @@ -15905,7 +16121,8 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, } else if (!E->getType()->isIntegralOrUnscopedEnumerationType()) { // An ICE must be of integral or unscoped enumeration type. if (!Diagnoser.Suppress) - Diagnoser.diagnoseNotICE(*this, DiagLoc, E->getSourceRange()); + Diagnoser.diagnoseNotICEType(*this, DiagLoc, E->getType()) + << E->getSourceRange(); return ExprError(); } @@ -15956,9 +16173,9 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, Notes.clear(); } - if (!Folded || !AllowFold) { + if (!Folded || !CanFold) { if (!Diagnoser.Suppress) { - Diagnoser.diagnoseNotICE(*this, DiagLoc, E->getSourceRange()); + Diagnoser.diagnoseNotICE(*this, DiagLoc) << E->getSourceRange(); for (const PartialDiagnosticAt &Note : Notes) Diag(Note.first, Note.second); } @@ -15966,7 +16183,7 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, return ExprError(); } - Diagnoser.diagnoseFold(*this, DiagLoc, E->getSourceRange()); + Diagnoser.diagnoseFold(*this, DiagLoc) << E->getSourceRange(); for (const PartialDiagnosticAt &Note : Notes) Diag(Note.first, Note.second); @@ -16148,8 +16365,8 @@ static void EvaluateAndDiagnoseImmediateInvocation( Expr::EvalResult Eval; Eval.Diag = &Notes; ConstantExpr *CE = Candidate.getPointer(); - bool Result = CE->EvaluateAsConstantExpr(Eval, Expr::EvaluateForCodeGen, - SemaRef.getASTContext(), true); + bool Result = CE->EvaluateAsConstantExpr( + Eval, SemaRef.getASTContext(), ConstantExprKind::ImmediateInvocation); if (!Result || !Notes.empty()) { Expr *InnerExpr = CE->getSubExpr()->IgnoreImplicit(); if (auto *FunctionalCast = dyn_cast<CXXFunctionalCastExpr>(InnerExpr)) @@ -16532,8 +16749,13 @@ static OdrUseContext isOdrUseContext(Sema &SemaRef) { } static bool isImplicitlyDefinableConstexprFunction(FunctionDecl *Func) { - return Func->isConstexpr() && - (Func->isImplicitlyInstantiable() || !Func->isUserProvided()); + if (!Func->isConstexpr()) + return false; + + if (Func->isImplicitlyInstantiable() || !Func->isUserProvided()) + return true; + auto *CCD = dyn_cast<CXXConstructorDecl>(Func); + return CCD && CCD->getInheritedConstructor(); } /// Mark a function referenced, and check whether it is odr-used @@ -16686,7 +16908,11 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, bool FirstInstantiation = PointOfInstantiation.isInvalid(); if (FirstInstantiation) { PointOfInstantiation = Loc; - Func->setTemplateSpecializationKind(TSK, PointOfInstantiation); + if (auto *MSI = Func->getMemberSpecializationInfo()) + MSI->setPointOfInstantiation(Loc); + // FIXME: Notify listener. + else + Func->setTemplateSpecializationKind(TSK, PointOfInstantiation); } else if (TSK != TSK_ImplicitInstantiation) { // Use the point of use as the point of instantiation, instead of the // point of explicit instantiation (which we track as the actual point @@ -16925,8 +17151,7 @@ static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var, if (Var->getType()->isVariablyModifiedType() && IsBlock) { if (Diagnose) { S.Diag(Loc, diag::err_ref_vm_type); - S.Diag(Var->getLocation(), diag::note_previous_decl) - << Var->getDeclName(); + S.Diag(Var->getLocation(), diag::note_previous_decl) << Var; } return false; } @@ -16938,10 +17163,8 @@ static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var, if (IsBlock) S.Diag(Loc, diag::err_ref_flexarray_type); else - S.Diag(Loc, diag::err_lambda_capture_flexarray_type) - << Var->getDeclName(); - S.Diag(Var->getLocation(), diag::note_previous_decl) - << Var->getDeclName(); + S.Diag(Loc, diag::err_lambda_capture_flexarray_type) << Var; + S.Diag(Var->getLocation(), diag::note_previous_decl) << Var; } return false; } @@ -16951,10 +17174,8 @@ static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var, // variables; they don't support the expected semantics. if (HasBlocksAttr && (IsLambda || isa<CapturedRegionScopeInfo>(CSI))) { if (Diagnose) { - S.Diag(Loc, diag::err_capture_block_variable) - << Var->getDeclName() << !IsLambda; - S.Diag(Var->getLocation(), diag::note_previous_decl) - << Var->getDeclName(); + S.Diag(Loc, diag::err_capture_block_variable) << Var << !IsLambda; + S.Diag(Var->getLocation(), diag::note_previous_decl) << Var; } return false; } @@ -16985,8 +17206,7 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var, if (!Invalid && !S.getLangOpts().OpenCL && CaptureType->isArrayType()) { if (BuildAndDiagnose) { S.Diag(Loc, diag::err_ref_array_type); - S.Diag(Var->getLocation(), diag::note_previous_decl) - << Var->getDeclName(); + S.Diag(Var->getLocation(), diag::note_previous_decl) << Var; Invalid = true; } else { return false; @@ -16999,8 +17219,7 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var, if (BuildAndDiagnose) { S.Diag(Loc, diag::err_arc_autoreleasing_capture) << /*block*/ 0; - S.Diag(Var->getLocation(), diag::note_previous_decl) - << Var->getDeclName(); + S.Diag(Var->getLocation(), diag::note_previous_decl) << Var; Invalid = true; } else { return false; @@ -17270,9 +17489,8 @@ bool Sema::tryCaptureVariable( if (BuildAndDiagnose) { LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI); if (LSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None) { - Diag(ExprLoc, diag::err_lambda_impcap) << Var->getDeclName(); - Diag(Var->getLocation(), diag::note_previous_decl) - << Var->getDeclName(); + Diag(ExprLoc, diag::err_lambda_impcap) << Var; + Diag(Var->getLocation(), diag::note_previous_decl) << Var; Diag(LSI->Lambda->getBeginLoc(), diag::note_lambda_decl); } else diagnoseUncapturableValueReference(*this, ExprLoc, Var, DC); @@ -17335,7 +17553,11 @@ bool Sema::tryCaptureVariable( if (IsTargetCap || IsOpenMPPrivateDecl == OMPC_private || (IsGlobal && !IsGlobalCap)) { Nested = !IsTargetCap; + bool HasConst = DeclRefType.isConstQualified(); DeclRefType = DeclRefType.getUnqualifiedType(); + // Don't lose diagnostics about assignments to const. + if (HasConst) + DeclRefType.addConst(); CaptureType = Context.getLValueReferenceType(DeclRefType); break; } @@ -17346,9 +17568,8 @@ bool Sema::tryCaptureVariable( // No capture-default, and this is not an explicit capture // so cannot capture this variable. if (BuildAndDiagnose) { - Diag(ExprLoc, diag::err_lambda_impcap) << Var->getDeclName(); - Diag(Var->getLocation(), diag::note_previous_decl) - << Var->getDeclName(); + Diag(ExprLoc, diag::err_lambda_impcap) << Var; + Diag(Var->getLocation(), diag::note_previous_decl) << Var; if (cast<LambdaScopeInfo>(CSI)->Lambda) Diag(cast<LambdaScopeInfo>(CSI)->Lambda->getBeginLoc(), diag::note_lambda_decl); @@ -17868,6 +18089,24 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc, if (Var->isInvalidDecl()) return; + // Record a CUDA/HIP static device/constant variable if it is referenced + // by host code. This is done conservatively, when the variable is referenced + // in any of the following contexts: + // - a non-function context + // - a host function + // - a host device function + // This also requires the reference of the static device/constant variable by + // host code to be visible in the device compilation for the compiler to be + // able to externalize the static device/constant variable. + if (SemaRef.getASTContext().mayExternalizeStaticVar(Var)) { + auto *CurContext = SemaRef.CurContext; + if (!CurContext || !isa<FunctionDecl>(CurContext) || + cast<FunctionDecl>(CurContext)->hasAttr<CUDAHostAttr>() || + (!cast<FunctionDecl>(CurContext)->hasAttr<CUDADeviceAttr>() && + !cast<FunctionDecl>(CurContext)->hasAttr<CUDAGlobalAttr>())) + SemaRef.getASTContext().CUDAStaticDeviceVarReferencedByHost.insert(Var); + } + auto *MSI = Var->getMemberSpecializationInfo(); TemplateSpecializationKind TSK = MSI ? MSI->getTemplateSpecializationKind() : Var->getTemplateSpecializationKind(); @@ -17887,8 +18126,6 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc, bool NeedDefinition = OdrUse == OdrUseContext::Used || NeededForConstantEvaluation; - VarTemplateSpecializationDecl *VarSpec = - dyn_cast<VarTemplateSpecializationDecl>(Var); assert(!isa<VarTemplatePartialSpecializationDecl>(Var) && "Can't instantiate a partial template specialization."); @@ -17919,34 +18156,33 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc, PointOfInstantiation = Loc; if (MSI) MSI->setPointOfInstantiation(PointOfInstantiation); + // FIXME: Notify listener. else Var->setTemplateSpecializationKind(TSK, PointOfInstantiation); } - bool InstantiationDependent = false; - bool IsNonDependent = - VarSpec ? !TemplateSpecializationType::anyDependentTemplateArguments( - VarSpec->getTemplateArgsInfo(), InstantiationDependent) - : true; - - // Do not instantiate specializations that are still type-dependent. - if (IsNonDependent) { - if (UsableInConstantExpr) { - // Do not defer instantiations of variables that could be used in a - // constant expression. - SemaRef.runWithSufficientStackSpace(PointOfInstantiation, [&] { - SemaRef.InstantiateVariableDefinition(PointOfInstantiation, Var); - }); - } else if (FirstInstantiation || - isa<VarTemplateSpecializationDecl>(Var)) { - // FIXME: For a specialization of a variable template, we don't - // distinguish between "declaration and type implicitly instantiated" - // and "implicit instantiation of definition requested", so we have - // no direct way to avoid enqueueing the pending instantiation - // multiple times. - SemaRef.PendingInstantiations - .push_back(std::make_pair(Var, PointOfInstantiation)); - } + if (UsableInConstantExpr) { + // Do not defer instantiations of variables that could be used in a + // constant expression. + SemaRef.runWithSufficientStackSpace(PointOfInstantiation, [&] { + SemaRef.InstantiateVariableDefinition(PointOfInstantiation, Var); + }); + + // Re-set the member to trigger a recomputation of the dependence bits + // for the expression. + if (auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) + DRE->setDecl(DRE->getDecl()); + else if (auto *ME = dyn_cast_or_null<MemberExpr>(E)) + ME->setMemberDecl(ME->getMemberDecl()); + } else if (FirstInstantiation || + isa<VarTemplateSpecializationDecl>(Var)) { + // FIXME: For a specialization of a variable template, we don't + // distinguish between "declaration and type implicitly instantiated" + // and "implicit instantiation of definition requested", so we have + // no direct way to avoid enqueueing the pending instantiation + // multiple times. + SemaRef.PendingInstantiations + .push_back(std::make_pair(Var, PointOfInstantiation)); } } } @@ -18072,6 +18308,9 @@ static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc, } /// Perform reference-marking and odr-use handling for a DeclRefExpr. +/// +/// Note, this may change the dependence of the DeclRefExpr, and so needs to be +/// handled with care if the DeclRefExpr is not newly-created. void Sema::MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base) { // TODO: update this with DR# once a defect report is filed. // C++11 defect. The address of a pure member should not be an ODR use, even @@ -18198,6 +18437,10 @@ public: if (VD->hasLocalStorage()) return; } + + // FIXME: This can trigger the instantiation of the initializer of a + // variable, which can cause the expression to become value-dependent + // or error-dependent. Do we need to propagate the new dependence bits? S.MarkDeclRefReferenced(E); } @@ -18312,7 +18555,7 @@ bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc, } S.Diag(Loc, diag::err_call_function_incomplete_return) - << CE->getSourceRange() << FD->getDeclName() << T; + << CE->getSourceRange() << FD << T; S.Diag(FD->getLocation(), diag::note_entity_declared_at) << FD->getDeclName(); } @@ -18462,9 +18705,12 @@ Sema::ConditionResult Sema::ActOnCondition(Scope *S, SourceLocation Loc, Cond = CheckSwitchCondition(Loc, SubExpr); break; } - if (Cond.isInvalid()) - return ConditionError(); - + if (Cond.isInvalid()) { + Cond = CreateRecoveryExpr(SubExpr->getBeginLoc(), SubExpr->getEndLoc(), + {SubExpr}); + if (!Cond.get()) + return ConditionError(); + } // FIXME: FullExprArg doesn't have an invalid bit, so check nullness instead. FullExprArg FullExpr = MakeFullExpr(Cond.get(), Loc); if (!FullExpr.get()) @@ -18853,7 +19099,7 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) { S.Context, FD->getDeclContext(), Loc, Loc, FD->getNameInfo().getName(), DestType, FD->getTypeSourceInfo(), SC_None, false /*isInlineSpecified*/, FD->hasPrototype(), - /*ConstexprKind*/ CSK_unspecified); + /*ConstexprKind*/ ConstexprSpecKind::Unspecified); if (FD->getQualifier()) NewFD->setQualifierInfo(FD->getQualifierLoc()); @@ -19001,7 +19247,7 @@ static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *E) { /// Check for operands with placeholder types and complain if found. /// Returns ExprError() if there was an error and no recovery was possible. ExprResult Sema::CheckPlaceholderExpr(Expr *E) { - if (!getLangOpts().CPlusPlus) { + if (!Context.isDependenceAllowed()) { // C cannot handle TypoExpr nodes on either side of a binop because it // doesn't handle dependent types properly, so make sure any TypoExprs have // been dealt with before checking the operands. @@ -19078,7 +19324,8 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { CK_BuiltinFnToFnPtr) .get(); return CallExpr::Create(Context, E, /*Args=*/{}, Context.IntTy, - VK_RValue, SourceLocation()); + VK_RValue, SourceLocation(), + FPOptionsOverride()); } } @@ -19115,6 +19362,9 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { #define SVE_TYPE(Name, Id, SingletonId) \ case BuiltinType::Id: #include "clang/Basic/AArch64SVEACLETypes.def" +#define PPC_VECTOR_TYPE(Name, Id, Size) \ + case BuiltinType::Id: +#include "clang/Basic/PPCTypes.def" #define BUILTIN_TYPE(Id, SingletonId) case BuiltinType::Id: #define PLACEHOLDER_TYPE(Id, SingletonId) #include "clang/AST/BuiltinTypes.def" diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index d885920b6c14..d91db60f17a0 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -172,7 +172,7 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc, bool Failed = false; llvm::SmallVector<NamedDecl*, 8> FoundDecls; - llvm::SmallSet<CanonicalDeclPtr<Decl>, 8> FoundDeclSet; + llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 8> FoundDeclSet; // If we have an object type, it's because we are in a // pseudo-destructor-expression or a member access expression, and @@ -663,7 +663,16 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, } // The operand is an expression. - return BuildCXXTypeId(TypeInfoType, OpLoc, (Expr*)TyOrExpr, RParenLoc); + ExprResult Result = + BuildCXXTypeId(TypeInfoType, OpLoc, (Expr *)TyOrExpr, RParenLoc); + + if (!getLangOpts().RTTIData && !Result.isInvalid()) + if (auto *CTE = dyn_cast<CXXTypeidExpr>(Result.get())) + if (CTE->isPotentiallyEvaluated() && !CTE->isMostDerived(Context)) + Diag(OpLoc, diag::warn_no_typeid_with_rtti_disabled) + << (getDiagnostics().getDiagnosticOptions().getFormat() == + DiagnosticOptions::MSVC); + return Result; } /// Grabs __declspec(uuid()) off a type, or returns 0 if we cannot resolve to @@ -875,6 +884,10 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex, Ex = Res.get(); } + // PPC MMA non-pointer types are not allowed as throw expr types. + if (Ex && Context.getTargetInfo().getTriple().isPPC64()) + CheckPPCMMAType(Ex->getType(), Ex->getBeginLoc()); + return new (Context) CXXThrowExpr(Ex, Context.VoidTy, OpLoc, IsThrownVarInScope); } @@ -1389,6 +1402,9 @@ Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep, if (!Result.isInvalid() && Result.get()->isInstantiationDependent() && !Result.get()->isTypeDependent()) Result = CorrectDelayedTyposInExpr(Result.get()); + else if (Result.isInvalid()) + Result = CreateRecoveryExpr(TInfo->getTypeLoc().getBeginLoc(), + RParenOrBraceLoc, exprs, Ty); return Result; } @@ -1401,16 +1417,6 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, QualType Ty = TInfo->getType(); SourceLocation TyBeginLoc = TInfo->getTypeLoc().getBeginLoc(); - if (Ty->isDependentType() || CallExpr::hasAnyTypeDependentArguments(Exprs)) { - // FIXME: CXXUnresolvedConstructExpr does not model list-initialization - // directly. We work around this by dropping the locations of the braces. - SourceRange Locs = ListInitialization - ? SourceRange() - : SourceRange(LParenOrBraceLoc, RParenOrBraceLoc); - return CXXUnresolvedConstructExpr::Create(Context, TInfo, Locs.getBegin(), - Exprs, Locs.getEnd()); - } - assert((!ListInitialization || (Exprs.size() == 1 && isa<InitListExpr>(Exprs[0]))) && "List initialization must have initializer list as expression."); @@ -1439,6 +1445,17 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, Entity = InitializedEntity::InitializeTemporary(TInfo, Ty); } + if (Ty->isDependentType() || CallExpr::hasAnyTypeDependentArguments(Exprs)) { + // FIXME: CXXUnresolvedConstructExpr does not model list-initialization + // directly. We work around this by dropping the locations of the braces. + SourceRange Locs = ListInitialization + ? SourceRange() + : SourceRange(LParenOrBraceLoc, RParenOrBraceLoc); + return CXXUnresolvedConstructExpr::Create(Context, Ty.getNonReferenceType(), + TInfo, Locs.getBegin(), Exprs, + Locs.getEnd()); + } + // C++ [expr.type.conv]p1: // If the expression list is a parenthesized single expression, the type // conversion expression is equivalent (in definedness, and if defined in @@ -1500,7 +1517,8 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, : SourceRange(LParenOrBraceLoc, RParenOrBraceLoc); Result = CXXFunctionalCastExpr::Create( Context, ResultType, Expr::getValueKindForType(Ty), TInfo, CK_NoOp, - Result.get(), /*Path=*/nullptr, Locs.getBegin(), Locs.getEnd()); + Result.get(), /*Path=*/nullptr, CurFPFeatureOverrides(), + Locs.getBegin(), Locs.getEnd()); } return Result; @@ -1509,9 +1527,24 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, bool Sema::isUsualDeallocationFunction(const CXXMethodDecl *Method) { // [CUDA] Ignore this function, if we can't call it. const FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext); - if (getLangOpts().CUDA && - IdentifyCUDAPreference(Caller, Method) <= CFP_WrongSide) - return false; + if (getLangOpts().CUDA) { + auto CallPreference = IdentifyCUDAPreference(Caller, Method); + // If it's not callable at all, it's not the right function. + if (CallPreference < CFP_WrongSide) + return false; + if (CallPreference == CFP_WrongSide) { + // Maybe. We have to check if there are better alternatives. + DeclContext::lookup_result R = + Method->getDeclContext()->lookup(Method->getDeclName()); + for (const auto *D : R) { + if (const auto *FD = dyn_cast<FunctionDecl>(D)) { + if (IdentifyCUDAPreference(Caller, FD) > CFP_WrongSide) + return false; + } + } + // We've found no better variants. + } + } SmallVector<const FunctionDecl*, 4> PreventedBy; bool Result = Method->isUsualDeallocationFunction(PreventedBy); @@ -1753,22 +1786,22 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, DeclaratorChunk::ArrayTypeInfo &Array = D.getTypeObject(I).Arr; if (Expr *NumElts = (Expr *)Array.NumElts) { if (!NumElts->isTypeDependent() && !NumElts->isValueDependent()) { + // FIXME: GCC permits constant folding here. We should either do so consistently + // or not do so at all, rather than changing behavior in C++14 onwards. if (getLangOpts().CPlusPlus14) { // C++1y [expr.new]p6: Every constant-expression in a noptr-new-declarator // shall be a converted constant expression (5.19) of type std::size_t // and shall evaluate to a strictly positive value. - unsigned IntWidth = Context.getTargetInfo().getIntWidth(); - assert(IntWidth && "Builtin type of size 0?"); - llvm::APSInt Value(IntWidth); + llvm::APSInt Value(Context.getIntWidth(Context.getSizeType())); Array.NumElts = CheckConvertedConstantExpression(NumElts, Context.getSizeType(), Value, - CCEK_NewExpr) + CCEK_ArrayBound) .get(); } else { - Array.NumElts - = VerifyIntegerConstantExpression(NumElts, nullptr, - diag::err_new_array_nonconst) - .get(); + Array.NumElts = + VerifyIntegerConstantExpression( + NumElts, nullptr, diag::err_new_array_nonconst, AllowFold) + .get(); } if (!Array.NumElts) return ExprError(); @@ -1832,12 +1865,13 @@ void Sema::diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD, const llvm::Triple &T = getASTContext().getTargetInfo().getTriple(); StringRef OSName = AvailabilityAttr::getPlatformNameSourceSpelling( getASTContext().getTargetInfo().getPlatformName()); + VersionTuple OSVersion = alignedAllocMinVersion(T.getOS()); OverloadedOperatorKind Kind = FD.getDeclName().getCXXOverloadedOperator(); bool IsDelete = Kind == OO_Delete || Kind == OO_Array_Delete; Diag(Loc, diag::err_aligned_allocation_unavailable) << IsDelete << FD.getType().getAsString() << OSName - << alignedAllocMinVersion(T.getOS()).getAsString(); + << OSVersion.getAsString() << OSVersion.empty(); Diag(Loc, diag::note_silence_aligned_allocation_unavailable); } } @@ -2073,29 +2107,29 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, // per CWG1464. Otherwise, if it's not a constant, we must have an // unparenthesized array type. if (!(*ArraySize)->isValueDependent()) { - llvm::APSInt Value; // We've already performed any required implicit conversion to integer or // unscoped enumeration type. // FIXME: Per CWG1464, we are required to check the value prior to // converting to size_t. This will never find a negative array size in // C++14 onwards, because Value is always unsigned here! - if ((*ArraySize)->isIntegerConstantExpr(Value, Context)) { - if (Value.isSigned() && Value.isNegative()) { + if (Optional<llvm::APSInt> Value = + (*ArraySize)->getIntegerConstantExpr(Context)) { + if (Value->isSigned() && Value->isNegative()) { return ExprError(Diag((*ArraySize)->getBeginLoc(), diag::err_typecheck_negative_array_size) << (*ArraySize)->getSourceRange()); } if (!AllocType->isDependentType()) { - unsigned ActiveSizeBits = - ConstantArrayType::getNumAddressingBits(Context, AllocType, Value); + unsigned ActiveSizeBits = ConstantArrayType::getNumAddressingBits( + Context, AllocType, *Value); if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) return ExprError( Diag((*ArraySize)->getBeginLoc(), diag::err_array_too_large) - << Value.toString(10) << (*ArraySize)->getSourceRange()); + << Value->toString(10) << (*ArraySize)->getSourceRange()); } - KnownArraySize = Value.getZExtValue(); + KnownArraySize = Value->getZExtValue(); } else if (TypeIdParens.isValid()) { // Can't have dynamic array size when the type-id is in parentheses. Diag((*ArraySize)->getBeginLoc(), diag::ext_new_paren_array_nonconst) @@ -2203,7 +2237,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, SizeTy, SourceLocation()); ImplicitCastExpr DesiredAlignment(ImplicitCastExpr::OnStack, AlignValT, CK_IntegralCast, &AlignmentLiteral, - VK_RValue); + VK_RValue, FPOptionsOverride()); // Adjust placement args by prepending conjured size and alignment exprs. llvm::SmallVector<Expr *, 8> CallArgs; @@ -2611,8 +2645,24 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, if (FoundDelete.isAmbiguous()) return true; // FIXME: clean up expressions? + // Filter out any destroying operator deletes. We can't possibly call such a + // function in this context, because we're handling the case where the object + // was not successfully constructed. + // FIXME: This is not covered by the language rules yet. + { + LookupResult::Filter Filter = FoundDelete.makeFilter(); + while (Filter.hasNext()) { + auto *FD = dyn_cast<FunctionDecl>(Filter.next()->getUnderlyingDecl()); + if (FD && FD->isDestroyingOperatorDelete()) + Filter.erase(); + } + Filter.done(); + } + bool FoundGlobalDelete = FoundDelete.empty(); if (FoundDelete.empty()) { + FoundDelete.clear(LookupOrdinaryName); + if (DeleteScope == AFS_Class) return true; @@ -3914,7 +3964,8 @@ static ExprResult BuildCXXCastArgument(Sema &S, // Record usage of conversion in an implicit cast. Result = ImplicitCastExpr::Create(S.Context, Result.get()->getType(), CK_UserDefinedConversion, Result.get(), - nullptr, Result.get()->getValueKind()); + nullptr, Result.get()->getValueKind(), + S.CurFPFeatureOverrides()); return S.MaybeBindToTemporary(Result.get()); } @@ -4095,7 +4146,8 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, if (const AtomicType *FromAtomic = FromType->getAs<AtomicType>()) { FromType = FromAtomic->getValueType().getUnqualifiedType(); From = ImplicitCastExpr::Create(Context, FromType, CK_AtomicToNonAtomic, - From, /*BasePath=*/nullptr, VK_RValue); + From, /*BasePath=*/nullptr, VK_RValue, + FPOptionsOverride()); } break; @@ -4322,6 +4374,12 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, VK_RValue, /*BasePath=*/nullptr, CCK).get(); break; + case ICK_SVE_Vector_Conversion: + From = ImpCastExprToType(From, ToType, CK_BitCast, VK_RValue, + /*BasePath=*/nullptr, CCK) + .get(); + break; + case ICK_Vector_Splat: { // Vector splat from any arithmetic type to a vector. Expr *Elem = prepareVectorSplat(ToType, From).get(); @@ -5465,9 +5523,9 @@ static uint64_t EvaluateArrayTypeTrait(Sema &Self, ArrayTypeTrait ATT, case ATT_ArrayExtent: { llvm::APSInt Value; uint64_t Dim; - if (Self.VerifyIntegerConstantExpression(DimExpr, &Value, - diag::err_dimension_expr_not_constant_integer, - false).isInvalid()) + if (Self.VerifyIntegerConstantExpression( + DimExpr, &Value, diag::err_dimension_expr_not_constant_integer) + .isInvalid()) return 0; if (Value.isSigned() && Value.isNegative()) { Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer) @@ -6304,6 +6362,8 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, // Similarly, attempt to find composite type of two objective-c pointers. Composite = FindCompositeObjCPointerType(LHS, RHS, QuestionLoc); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); if (!Composite.isNull()) return Composite; @@ -6529,12 +6589,16 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, // FIXME: In C, we merge __strong and none to __strong at the top level. if (Q1.getObjCGCAttr() == Q2.getObjCGCAttr()) Quals.setObjCGCAttr(Q1.getObjCGCAttr()); + else if (T1->isVoidPointerType() || T2->isVoidPointerType()) + assert(Steps.size() == 1); else return QualType(); // Mismatched lifetime qualifiers never compatibly include each other. if (Q1.getObjCLifetime() == Q2.getObjCLifetime()) Quals.setObjCLifetime(Q1.getObjCLifetime()); + else if (T1->isVoidPointerType() || T2->isVoidPointerType()) + assert(Steps.size() == 1); else return QualType(); @@ -6833,7 +6897,7 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) { CastKind ck = (ReturnsRetained ? CK_ARCConsumeObject : CK_ARCReclaimReturnedObject); return ImplicitCastExpr::Create(Context, E->getType(), ck, E, nullptr, - VK_RValue); + VK_RValue, FPOptionsOverride()); } if (E->getType().isDestructedType() == QualType::DK_nontrivial_c_struct) @@ -7226,8 +7290,8 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, return Base; } -static bool CheckArrow(Sema& S, QualType& ObjectType, Expr *&Base, - tok::TokenKind& OpKind, SourceLocation OpLoc) { +static bool CheckArrow(Sema &S, QualType &ObjectType, Expr *&Base, + tok::TokenKind &OpKind, SourceLocation OpLoc) { if (Base->hasPlaceholderType()) { ExprResult result = S.CheckPlaceholderExpr(Base); if (result.isInvalid()) return true; @@ -7242,6 +7306,18 @@ static bool CheckArrow(Sema& S, QualType& ObjectType, Expr *&Base, // Note that this is rather different from the normal handling for the // arrow operator. if (OpKind == tok::arrow) { + // The operator requires a prvalue, so perform lvalue conversions. + // Only do this if we might plausibly end with a pointer, as otherwise + // this was likely to be intended to be a '.'. + if (ObjectType->isPointerType() || ObjectType->isArrayType() || + ObjectType->isFunctionType()) { + ExprResult BaseResult = S.DefaultFunctionArrayLvalueConversion(Base); + if (BaseResult.isInvalid()) + return true; + Base = BaseResult.get(); + ObjectType = Base->getType(); + } + if (const PointerType *Ptr = ObjectType->getAs<PointerType>()) { ObjectType = Ptr->getPointeeType(); } else if (!Base->isTypeDependent()) { @@ -7550,6 +7626,11 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc)) return ExprError(); + if (DS.getTypeSpecType() == DeclSpec::TST_decltype_auto) { + Diag(DS.getTypeSpecTypeLoc(), diag::err_decltype_auto_invalid); + return true; + } + QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc(), false); @@ -7616,7 +7697,8 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, ResultType = ResultType.getNonLValueExprType(Context); CXXMemberCallExpr *CE = CXXMemberCallExpr::Create( - Context, ME, /*Args=*/{}, ResultType, VK, Exp.get()->getEndLoc()); + Context, ME, /*Args=*/{}, ResultType, VK, Exp.get()->getEndLoc(), + CurFPFeatureOverrides()); if (CheckFunctionCall(Method, CE, Method->getType()->castAs<FunctionProtoType>())) @@ -7640,7 +7722,8 @@ ExprResult Sema::BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand, Operand = R.get(); - if (!inTemplateInstantiation() && Operand->HasSideEffects(Context, false)) { + if (!inTemplateInstantiation() && !Operand->isInstantiationDependent() && + Operand->HasSideEffects(Context, false)) { // The expression operand for noexcept is in an unevaluated expression // context, so side effects could result in unintended consequences. Diag(Operand->getExprLoc(), diag::warn_side_effects_unevaluated_context); @@ -7977,19 +8060,26 @@ class TransformTypos : public TreeTransform<TransformTypos> { } } - /// If corrections for the first TypoExpr have been exhausted for a - /// given combination of the other TypoExprs, retry those corrections against - /// the next combination of substitutions for the other TypoExprs by advancing - /// to the next potential correction of the second TypoExpr. For the second - /// and subsequent TypoExprs, if its stream of corrections has been exhausted, - /// the stream is reset and the next TypoExpr's stream is advanced by one (a - /// TypoExpr's correction stream is advanced by removing the TypoExpr from the - /// TransformCache). Returns true if there is still any untried combinations - /// of corrections. + /// Try to advance the typo correction state of the first unfinished TypoExpr. + /// We allow advancement of the correction stream by removing it from the + /// TransformCache which allows `TransformTypoExpr` to advance during the + /// next transformation attempt. + /// + /// Any substitution attempts for the previous TypoExprs (which must have been + /// finished) will need to be retried since it's possible that they will now + /// be invalid given the latest advancement. + /// + /// We need to be sure that we're making progress - it's possible that the + /// tree is so malformed that the transform never makes it to the + /// `TransformTypoExpr`. + /// + /// Returns true if there are any untried correction combinations. bool CheckAndAdvanceTypoExprCorrectionStreams() { for (auto TE : TypoExprs) { auto &State = SemaRef.getTypoExprState(TE); TransformCache.erase(TE); + if (!State.Consumer->hasMadeAnyCorrectionProgress()) + return false; if (!State.Consumer->finished()) return true; State.Consumer->resetCorrectionStream(); @@ -8639,6 +8729,9 @@ Sema::ActOnRequiresExpr(SourceLocation RequiresKWLoc, ArrayRef<ParmVarDecl *> LocalParameters, ArrayRef<concepts::Requirement *> Requirements, SourceLocation ClosingBraceLoc) { - return RequiresExpr::Create(Context, RequiresKWLoc, Body, LocalParameters, - Requirements, ClosingBraceLoc); + auto *RE = RequiresExpr::Create(Context, RequiresKWLoc, Body, LocalParameters, + Requirements, ClosingBraceLoc); + if (DiagnoseUnexpandedParameterPackInRequiresExpr(RE)) + return ExprError(); + return RE; } diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index ebfc1ec4b974..f5afcb76fc96 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -231,12 +231,10 @@ static void diagnoseInstanceReference(Sema &SemaRef, } /// Builds an expression which might be an implicit member expression. -ExprResult -Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - LookupResult &R, - const TemplateArgumentListInfo *TemplateArgs, - const Scope *S) { +ExprResult Sema::BuildPossibleImplicitMemberExpr( + const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs, const Scope *S, + UnresolvedLookupExpr *AsULE) { switch (ClassifyImplicitMemberAccess(*this, R)) { case IMA_Instance: return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true, S); @@ -257,7 +255,7 @@ Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS, case IMA_Unresolved_StaticContext: if (TemplateArgs || TemplateKWLoc.isValid()) return BuildTemplateIdExpr(SS, TemplateKWLoc, R, false, TemplateArgs); - return BuildDeclarationNameExpr(SS, R, false); + return AsULE ? AsULE : BuildDeclarationNameExpr(SS, R, false); case IMA_Error_StaticContext: case IMA_Error_Unrelated: @@ -946,28 +944,6 @@ static bool IsInFnTryBlockHandler(const Scope *S) { return false; } -VarDecl * -Sema::getVarTemplateSpecialization(VarTemplateDecl *VarTempl, - const TemplateArgumentListInfo *TemplateArgs, - const DeclarationNameInfo &MemberNameInfo, - SourceLocation TemplateKWLoc) { - if (!TemplateArgs) { - diagnoseMissingTemplateArguments(TemplateName(VarTempl), - MemberNameInfo.getBeginLoc()); - return nullptr; - } - - DeclResult VDecl = CheckVarTemplateId(VarTempl, TemplateKWLoc, - MemberNameInfo.getLoc(), *TemplateArgs); - if (VDecl.isInvalid()) - return nullptr; - VarDecl *Var = cast<VarDecl>(VDecl.get()); - if (!Var->getTemplateSpecializationKind()) - Var->setTemplateSpecializationKind(TSK_ImplicitInstantiation, - MemberNameInfo.getLoc()); - return Var; -} - ExprResult Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, SourceLocation OpLoc, bool IsArrow, @@ -1099,19 +1075,11 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, if (!BaseExpr) { // If this is not an instance member, convert to a non-member access. if (!MemberDecl->isCXXInstanceMember()) { - // If this is a variable template, get the instantiated variable - // declaration corresponding to the supplied template arguments - // (while emitting diagnostics as necessary) that will be referenced - // by this expression. - assert((!TemplateArgs || isa<VarTemplateDecl>(MemberDecl)) && - "How did we get template arguments here sans a variable template"); - if (isa<VarTemplateDecl>(MemberDecl)) { - MemberDecl = getVarTemplateSpecialization( - cast<VarTemplateDecl>(MemberDecl), TemplateArgs, - R.getLookupNameInfo(), TemplateKWLoc); - if (!MemberDecl) - return ExprError(); - } + // We might have a variable template specialization (or maybe one day a + // member concept-id). + if (TemplateArgs || TemplateKWLoc.isValid()) + return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL*/false, TemplateArgs); + return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), MemberDecl, FoundDecl, TemplateArgs); } @@ -1170,14 +1138,32 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, MemberNameInfo, Enum->getType(), VK_RValue, OK_Ordinary); } + if (VarTemplateDecl *VarTempl = dyn_cast<VarTemplateDecl>(MemberDecl)) { - if (VarDecl *Var = getVarTemplateSpecialization( - VarTempl, TemplateArgs, MemberNameInfo, TemplateKWLoc)) - return BuildMemberExpr( - BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Var, FoundDecl, - /*HadMultipleCandidates=*/false, MemberNameInfo, - Var->getType().getNonReferenceType(), VK_LValue, OK_Ordinary); - return ExprError(); + if (!TemplateArgs) { + diagnoseMissingTemplateArguments(TemplateName(VarTempl), MemberLoc); + return ExprError(); + } + + DeclResult VDecl = CheckVarTemplateId(VarTempl, TemplateKWLoc, + MemberNameInfo.getLoc(), *TemplateArgs); + if (VDecl.isInvalid()) + return ExprError(); + + // Non-dependent member, but dependent template arguments. + if (!VDecl.get()) + return ActOnDependentMemberExpr( + BaseExpr, BaseExpr->getType(), IsArrow, OpLoc, SS, TemplateKWLoc, + FirstQualifierInScope, MemberNameInfo, TemplateArgs); + + VarDecl *Var = cast<VarDecl>(VDecl.get()); + if (!Var->getTemplateSpecializationKind()) + Var->setTemplateSpecializationKind(TSK_ImplicitInstantiation, MemberLoc); + + return BuildMemberExpr( + BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Var, FoundDecl, + /*HadMultipleCandidates=*/false, MemberNameInfo, + Var->getType().getNonReferenceType(), VK_LValue, OK_Ordinary); } // We found something that we didn't expect. Complain. @@ -1748,14 +1734,28 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, } void Sema::CheckMemberAccessOfNoDeref(const MemberExpr *E) { - QualType ResultTy = E->getType(); - - // Do not warn on member accesses to arrays since this returns an array - // lvalue and does not actually dereference memory. - if (isa<ArrayType>(ResultTy)) + if (isUnevaluatedContext()) return; - if (E->isArrow()) { + QualType ResultTy = E->getType(); + + // Member accesses have four cases: + // 1: non-array member via "->": dereferences + // 2: non-array member via ".": nothing interesting happens + // 3: array member access via "->": nothing interesting happens + // (this returns an array lvalue and does not actually dereference memory) + // 4: array member access via ".": *adds* a layer of indirection + if (ResultTy->isArrayType()) { + if (!E->isArrow()) { + // This might be something like: + // (*structPtr).arrayMember + // which behaves roughly like: + // &(*structPtr).pointerMember + // in that the apparent dereference in the base expression does not + // actually happen. + CheckAddressOfNoDeref(E->getBase()); + } + } else if (E->isArrow()) { if (const auto *Ptr = dyn_cast<PointerType>( E->getBase()->getType().getDesugaredType(Context))) { if (Ptr->getPointeeType()->hasAttr(attr::NoDeref)) @@ -1810,6 +1810,14 @@ Sema::BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, Qualifiers Combined = BaseQuals + MemberQuals; if (Combined != MemberQuals) MemberType = Context.getQualifiedType(MemberType, Combined); + + // Pick up NoDeref from the base in case we end up using AddrOf on the + // result. E.g. the expression + // &someNoDerefPtr->pointerMember + // should be a noderef pointer again. + if (BaseType->hasAttr(attr::NoDeref)) + MemberType = + Context.getAttributedType(attr::NoDeref, MemberType, MemberType); } auto *CurMethod = dyn_cast<CXXMethodDecl>(CurContext); @@ -1854,7 +1862,6 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS, // If this is known to be an instance access, go ahead and build an // implicit 'this' expression now. - // 'this' expression now. QualType ThisTy = getCurrentThisType(); assert(!ThisTy.isNull() && "didn't correctly pre-flight capture of 'this'"); diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 228a1ec3ba1f..f5456ee0711e 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -1394,6 +1394,9 @@ ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId, Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId; return true; } + if (PDecl->isNonRuntimeProtocol()) + Diag(ProtoLoc, diag::err_objc_non_runtime_protocol_in_protocol_expr) + << PDecl; if (!PDecl->hasDefinition()) { Diag(ProtoLoc, diag::err_atprotocol_protocol) << PDecl; Diag(PDecl->getLocation(), diag::note_entity_declared_at) << PDecl; @@ -1560,12 +1563,20 @@ QualType Sema::getMessageSendResultType(const Expr *Receiver, // Map the nullability of the result into a table index. unsigned receiverNullabilityIdx = 0; - if (auto nullability = ReceiverType->getNullability(Context)) + if (Optional<NullabilityKind> nullability = + ReceiverType->getNullability(Context)) { + if (*nullability == NullabilityKind::NullableResult) + nullability = NullabilityKind::Nullable; receiverNullabilityIdx = 1 + static_cast<unsigned>(*nullability); + } unsigned resultNullabilityIdx = 0; - if (auto nullability = resultType->getNullability(Context)) + if (Optional<NullabilityKind> nullability = + resultType->getNullability(Context)) { + if (*nullability == NullabilityKind::NullableResult) + nullability = NullabilityKind::Nullable; resultNullabilityIdx = 1 + static_cast<unsigned>(*nullability); + } // The table of nullability mappings, indexed by the receiver's nullability // and then the result type's nullability. @@ -2445,8 +2456,8 @@ static void applyCocoaAPICheck(Sema &S, const ObjCMessageExpr *Msg, SourceManager &SM = S.SourceMgr; edit::Commit ECommit(SM, S.LangOpts); if (refactor(Msg,*S.NSAPIObj, ECommit)) { - DiagnosticBuilder Builder = S.Diag(MsgLoc, DiagID) - << Msg->getSelector() << Msg->getSourceRange(); + auto Builder = S.Diag(MsgLoc, DiagID) + << Msg->getSelector() << Msg->getSourceRange(); // FIXME: Don't emit diagnostic at all if fixits are non-commitable. if (!ECommit.isCommitable()) return; @@ -3139,9 +3150,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, if (ReceiverType->isObjCClassType() && !isImplicit && !(Receiver->isObjCSelfExpr() && getLangOpts().ObjCAutoRefCount)) { { - DiagnosticBuilder Builder = - Diag(Receiver->getExprLoc(), - diag::err_messaging_class_with_direct_method); + auto Builder = Diag(Receiver->getExprLoc(), + diag::err_messaging_class_with_direct_method); if (Receiver->isObjCSelfExpr()) { Builder.AddFixItHint(FixItHint::CreateReplacement( RecRange, Method->getClassInterface()->getName())); @@ -3153,7 +3163,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, if (SuperLoc.isValid()) { { - DiagnosticBuilder Builder = + auto Builder = Diag(SuperLoc, diag::err_messaging_super_with_direct_method); if (ReceiverType->isObjCClassType()) { Builder.AddFixItHint(FixItHint::CreateReplacement( @@ -3736,15 +3746,11 @@ bool Sema::isKnownName(StringRef name) { return LookupName(R, TUScope, false); } -static void addFixitForObjCARCConversion(Sema &S, - DiagnosticBuilder &DiagB, - Sema::CheckedConversionKind CCK, - SourceLocation afterLParen, - QualType castType, - Expr *castExpr, - Expr *realCast, - const char *bridgeKeyword, - const char *CFBridgeName) { +template <typename DiagBuilderT> +static void addFixitForObjCARCConversion( + Sema &S, DiagBuilderT &DiagB, Sema::CheckedConversionKind CCK, + SourceLocation afterLParen, QualType castType, Expr *castExpr, + Expr *realCast, const char *bridgeKeyword, const char *CFBridgeName) { // We handle C-style and implicit casts here. switch (CCK) { case Sema::CCK_ImplicitConversion: @@ -3921,9 +3927,9 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, assert(CreateRule != ACC_bottom && "This cast should already be accepted."); if (CreateRule != ACC_plusOne) { - DiagnosticBuilder DiagB = - (CCK != Sema::CCK_OtherCast) ? S.Diag(noteLoc, diag::note_arc_bridge) - : S.Diag(noteLoc, diag::note_arc_cstyle_bridge); + auto DiagB = (CCK != Sema::CCK_OtherCast) + ? S.Diag(noteLoc, diag::note_arc_bridge) + : S.Diag(noteLoc, diag::note_arc_cstyle_bridge); addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, castType, castExpr, realCast, "__bridge ", @@ -3931,12 +3937,12 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, } if (CreateRule != ACC_plusZero) { - DiagnosticBuilder DiagB = - (CCK == Sema::CCK_OtherCast && !br) ? - S.Diag(noteLoc, diag::note_arc_cstyle_bridge_transfer) << castExprType : - S.Diag(br ? castExpr->getExprLoc() : noteLoc, - diag::note_arc_bridge_transfer) - << castExprType << br; + auto DiagB = (CCK == Sema::CCK_OtherCast && !br) + ? S.Diag(noteLoc, diag::note_arc_cstyle_bridge_transfer) + << castExprType + : S.Diag(br ? castExpr->getExprLoc() : noteLoc, + diag::note_arc_bridge_transfer) + << castExprType << br; addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, castType, castExpr, realCast, "__bridge_transfer ", @@ -3962,21 +3968,21 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, assert(CreateRule != ACC_bottom && "This cast should already be accepted."); if (CreateRule != ACC_plusOne) { - DiagnosticBuilder DiagB = - (CCK != Sema::CCK_OtherCast) ? S.Diag(noteLoc, diag::note_arc_bridge) - : S.Diag(noteLoc, diag::note_arc_cstyle_bridge); + auto DiagB = (CCK != Sema::CCK_OtherCast) + ? S.Diag(noteLoc, diag::note_arc_bridge) + : S.Diag(noteLoc, diag::note_arc_cstyle_bridge); addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, castType, castExpr, realCast, "__bridge ", nullptr); } if (CreateRule != ACC_plusZero) { - DiagnosticBuilder DiagB = - (CCK == Sema::CCK_OtherCast && !br) ? - S.Diag(noteLoc, diag::note_arc_cstyle_bridge_retained) << castType : - S.Diag(br ? castExpr->getExprLoc() : noteLoc, - diag::note_arc_bridge_retained) - << castType << br; + auto DiagB = (CCK == Sema::CCK_OtherCast && !br) + ? S.Diag(noteLoc, diag::note_arc_cstyle_bridge_retained) + << castType + : S.Diag(br ? castExpr->getExprLoc() : noteLoc, + diag::note_arc_bridge_retained) + << castType << br; addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, castType, castExpr, realCast, "__bridge_retained ", @@ -4462,8 +4468,8 @@ Sema::CheckObjCConversion(SourceRange castRange, QualType castType, // If the result is +1, consume it here. case ACC_plusOne: castExpr = ImplicitCastExpr::Create(Context, castExpr->getType(), - CK_ARCConsumeObject, castExpr, - nullptr, VK_RValue); + CK_ARCConsumeObject, castExpr, nullptr, + VK_RValue, FPOptionsOverride()); Cleanup.setExprNeedsCleanups(true); return ACR_okay; } @@ -4689,9 +4695,9 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc, case OBC_BridgeRetained: // Produce the object before casting it. - SubExpr = ImplicitCastExpr::Create(Context, FromType, - CK_ARCProduceObject, - SubExpr, nullptr, VK_RValue); + SubExpr = ImplicitCastExpr::Create(Context, FromType, CK_ARCProduceObject, + SubExpr, nullptr, VK_RValue, + FPOptionsOverride()); break; case OBC_BridgeTransfer: { @@ -4730,7 +4736,7 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc, if (MustConsume) { Cleanup.setExprNeedsCleanups(true); Result = ImplicitCastExpr::Create(Context, T, CK_ARCConsumeObject, Result, - nullptr, VK_RValue); + nullptr, VK_RValue, FPOptionsOverride()); } return Result; diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index eb07de65d266..f4493d84238d 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -141,6 +141,10 @@ static StringInitFailureKind IsStringInit(Expr *init, QualType declType, return IsStringInit(init, arrayType, Context); } +bool Sema::IsStringInit(Expr *Init, const ArrayType *AT) { + return ::IsStringInit(Init, AT, Context) == SIF_None; +} + /// Update the type of a string literal, including any surrounding parentheses, /// to match the type of the object which it is initializing. static void updateStringLiteralType(Expr *E, QualType Ty) { @@ -962,6 +966,8 @@ InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity, FillInEmptyInitializations(Entity, FullyStructuredList, RequiresSecondPass, nullptr, 0); } + if (hadError && FullyStructuredList) + FullyStructuredList->markError(); } int InitListChecker::numArrayElements(QualType DeclType) { @@ -1117,6 +1123,7 @@ static void warnBracedScalarInit(Sema &S, const InitializedEntity &Entity, case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_Parameter: case InitializedEntity::EK_Parameter_CF_Audited: + case InitializedEntity::EK_TemplateParameter: case InitializedEntity::EK_Result: // Extra braces here are suspicious. DiagID = diag::warn_braces_around_init; @@ -1583,10 +1590,7 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity, IList->setInit(Index, ResultExpr); } } - if (hadError) - ++StructuredIndex; - else - UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr); + UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr); ++Index; } @@ -1641,10 +1645,7 @@ void InitListChecker::CheckReferenceType(const InitializedEntity &Entity, if (!VerifyOnly && expr) IList->setInit(Index, expr); - if (hadError) - ++StructuredIndex; - else - UpdateStructuredListElement(StructuredList, StructuredIndex, expr); + UpdateStructuredListElement(StructuredList, StructuredIndex, expr); ++Index; } @@ -1695,11 +1696,7 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity, IList->setInit(Index, ResultExpr); } } - if (hadError) - ++StructuredIndex; - else - UpdateStructuredListElement(StructuredList, StructuredIndex, - ResultExpr); + UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr); ++Index; return; } @@ -2898,8 +2895,9 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, Expr *Init = new (Context) IntegerLiteral( Context, CodeUnit, PromotedCharTy, SubExpr->getExprLoc()); if (CharTy != PromotedCharTy) - Init = ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast, - Init, nullptr, VK_RValue); + Init = + ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast, Init, + nullptr, VK_RValue, FPOptionsOverride()); StructuredList->updateInit(Context, i, Init); } } else { @@ -2920,8 +2918,9 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, Expr *Init = new (Context) IntegerLiteral( Context, CodeUnit, PromotedCharTy, SubExpr->getExprLoc()); if (CharTy != PromotedCharTy) - Init = ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast, - Init, nullptr, VK_RValue); + Init = + ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast, Init, + nullptr, VK_RValue, FPOptionsOverride()); StructuredList->updateInit(Context, i, Init); } } @@ -3098,8 +3097,12 @@ void InitListChecker::UpdateStructuredListElement(InitListExpr *StructuredList, if (Expr *PrevInit = StructuredList->updateInit(SemaRef.Context, StructuredIndex, expr)) { - // This initializer overwrites a previous initializer. Warn. - diagnoseInitOverride(PrevInit, expr->getSourceRange()); + // This initializer overwrites a previous initializer. + // No need to diagnose when `expr` is nullptr because a more relevant + // diagnostic has already been issued and this diagnostic is potentially + // noise. + if (expr) + diagnoseInitOverride(PrevInit, expr->getSourceRange()); } ++StructuredIndex; @@ -3128,7 +3131,8 @@ CheckArrayDesignatorExpr(Sema &S, Expr *Index, llvm::APSInt &Value) { SourceLocation Loc = Index->getBeginLoc(); // Make sure this is an integer constant expression. - ExprResult Result = S.VerifyIntegerConstantExpression(Index, &Value); + ExprResult Result = + S.VerifyIntegerConstantExpression(Index, &Value, Sema::AllowFold); if (Result.isInvalid()) return Result; @@ -3280,6 +3284,7 @@ DeclarationName InitializedEntity::getName() const { case EK_Variable: case EK_Member: case EK_Binding: + case EK_TemplateParameter: return Variable.VariableOrMember->getDeclName(); case EK_LambdaCapture: @@ -3310,6 +3315,7 @@ ValueDecl *InitializedEntity::getDecl() const { case EK_Variable: case EK_Member: case EK_Binding: + case EK_TemplateParameter: return Variable.VariableOrMember; case EK_Parameter: @@ -3347,6 +3353,7 @@ bool InitializedEntity::allowsNRVO() const { case EK_Variable: case EK_Parameter: case EK_Parameter_CF_Audited: + case EK_TemplateParameter: case EK_Member: case EK_Binding: case EK_New: @@ -3378,6 +3385,7 @@ unsigned InitializedEntity::dumpImpl(raw_ostream &OS) const { case EK_Parameter: OS << "Parameter"; break; case EK_Parameter_CF_Audited: OS << "CF audited function Parameter"; break; + case EK_TemplateParameter: OS << "TemplateParameter"; break; case EK_Result: OS << "Result"; break; case EK_StmtExprResult: OS << "StmtExprResult"; break; case EK_Exception: OS << "Exception"; break; @@ -3434,6 +3442,7 @@ void InitializationSequence::Step::Destroy() { case SK_QualificationConversionRValue: case SK_QualificationConversionXValue: case SK_QualificationConversionLValue: + case SK_FunctionReferenceConversion: case SK_AtomicConversion: case SK_ListInitialization: case SK_UnwrapInitList: @@ -3612,6 +3621,13 @@ void InitializationSequence::AddQualificationConversionStep(QualType Ty, Steps.push_back(S); } +void InitializationSequence::AddFunctionReferenceConversionStep(QualType Ty) { + Step S; + S.Kind = SK_FunctionReferenceConversion; + S.Type = Ty; + Steps.push_back(S); +} + void InitializationSequence::AddAtomicConversionStep(QualType Ty) { Step S; S.Kind = SK_AtomicConversion; @@ -4099,11 +4115,13 @@ static void TryConstructorInitialization(Sema &S, IsListInit); } if (Result) { - Sequence.SetOverloadFailure(IsListInit ? - InitializationSequence::FK_ListConstructorOverloadFailed : - InitializationSequence::FK_ConstructorOverloadFailed, - Result); - return; + Sequence.SetOverloadFailure( + IsListInit ? InitializationSequence::FK_ListConstructorOverloadFailed + : InitializationSequence::FK_ConstructorOverloadFailed, + Result); + + if (Result != OR_Deleted) + return; } bool HadMultipleCandidates = (CandidateSet.size() > 1); @@ -4124,31 +4142,45 @@ static void TryConstructorInitialization(Sema &S, return; } - // C++11 [dcl.init]p6: - // If a program calls for the default initialization of an object - // of a const-qualified type T, T shall be a class type with a - // user-provided default constructor. - // C++ core issue 253 proposal: - // If the implicit default constructor initializes all subobjects, no - // initializer should be required. - // The 253 proposal is for example needed to process libstdc++ headers in 5.x. CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function); - if (Kind.getKind() == InitializationKind::IK_Default && - Entity.getType().isConstQualified()) { - if (!CtorDecl->getParent()->allowConstDefaultInit()) { - if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity)) - Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); + if (Result != OR_Deleted) { + // C++11 [dcl.init]p6: + // If a program calls for the default initialization of an object + // of a const-qualified type T, T shall be a class type with a + // user-provided default constructor. + // C++ core issue 253 proposal: + // If the implicit default constructor initializes all subobjects, no + // initializer should be required. + // The 253 proposal is for example needed to process libstdc++ headers + // in 5.x. + if (Kind.getKind() == InitializationKind::IK_Default && + Entity.getType().isConstQualified()) { + if (!CtorDecl->getParent()->allowConstDefaultInit()) { + if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity)) + Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); + return; + } + } + + // C++11 [over.match.list]p1: + // In copy-list-initialization, if an explicit constructor is chosen, the + // initializer is ill-formed. + if (IsListInit && !Kind.AllowExplicit() && CtorDecl->isExplicit()) { + Sequence.SetFailed(InitializationSequence::FK_ExplicitConstructor); return; } } - // C++11 [over.match.list]p1: - // In copy-list-initialization, if an explicit constructor is chosen, the - // initializer is ill-formed. - if (IsListInit && !Kind.AllowExplicit() && CtorDecl->isExplicit()) { - Sequence.SetFailed(InitializationSequence::FK_ExplicitConstructor); + // [class.copy.elision]p3: + // In some copy-initialization contexts, a two-stage overload resolution + // is performed. + // If the first overload resolution selects a deleted function, we also + // need the initialization sequence to decide whether to perform the second + // overload resolution. + // For deleted functions in other contexts, there is no need to get the + // initialization sequence. + if (Result == OR_Deleted && Kind.getKind() != InitializationKind::IK_Copy) return; - } // Add the constructor initialization step. Any cv-qualification conversion is // subsumed by the initialization. @@ -4232,7 +4264,7 @@ static void TryReferenceListInitialization(Sema &S, // bind to that. if (InitList->getNumInits() == 1) { Expr *Initializer = InitList->getInit(0); - QualType cv2T2 = Initializer->getType(); + QualType cv2T2 = S.getCompletedType(Initializer); Qualifiers T2Quals; QualType T2 = S.Context.getUnqualifiedArrayType(cv2T2, T2Quals); @@ -4645,7 +4677,7 @@ static OverloadingResult TryRefInitWithConversionFunction( else if (RefConv & Sema::ReferenceConversions::ObjC) Sequence.AddObjCObjectConversionStep(cv1T1); else if (RefConv & Sema::ReferenceConversions::Function) - Sequence.AddQualificationConversionStep(cv1T1, VK); + Sequence.AddFunctionReferenceConversionStep(cv1T1); else if (RefConv & Sema::ReferenceConversions::Qualification) { if (!S.Context.hasSameType(cv1T4, cv1T1)) Sequence.AddQualificationConversionStep(cv1T1, VK); @@ -4668,7 +4700,7 @@ static void TryReferenceInitialization(Sema &S, QualType cv1T1 = DestType->castAs<ReferenceType>()->getPointeeType(); Qualifiers T1Quals; QualType T1 = S.Context.getUnqualifiedArrayType(cv1T1, T1Quals); - QualType cv2T2 = Initializer->getType(); + QualType cv2T2 = S.getCompletedType(Initializer); Qualifiers T2Quals; QualType T2 = S.Context.getUnqualifiedArrayType(cv2T2, T2Quals); @@ -4747,12 +4779,12 @@ static void TryReferenceInitializationCore(Sema &S, Sequence.AddDerivedToBaseCastStep(cv1T1, VK_LValue); else Sequence.AddObjCObjectConversionStep(cv1T1); - } else if (RefConv & (Sema::ReferenceConversions::Qualification | - Sema::ReferenceConversions::Function)) { + } else if (RefConv & Sema::ReferenceConversions::Qualification) { // Perform a (possibly multi-level) qualification conversion. - // FIXME: Should we use a different step kind for function conversions? Sequence.AddQualificationConversionStep(cv1T1, Initializer->getValueKind()); + } else if (RefConv & Sema::ReferenceConversions::Function) { + Sequence.AddFunctionReferenceConversionStep(cv1T1); } // We only create a temporary here when binding a reference to a @@ -5242,9 +5274,17 @@ static void TryUserDefinedConversion(Sema &S, if (OverloadingResult Result = CandidateSet.BestViableFunction(S, DeclLoc, Best)) { Sequence.SetOverloadFailure( - InitializationSequence::FK_UserConversionOverloadFailed, - Result); - return; + InitializationSequence::FK_UserConversionOverloadFailed, Result); + + // [class.copy.elision]p3: + // In some copy-initialization contexts, a two-stage overload resolution + // is performed. + // If the first overload resolution selects a deleted function, we also + // need the initialization sequence to decide whether to perform the second + // overload resolution. + if (!(Result == OR_Deleted && + Kind.getKind() == InitializationKind::IK_Copy)) + return; } FunctionDecl *Function = Best->Function; @@ -5548,13 +5588,11 @@ static bool TryOCLZeroOpaqueTypeInitialization(Sema &S, return false; } -InitializationSequence::InitializationSequence(Sema &S, - const InitializedEntity &Entity, - const InitializationKind &Kind, - MultiExprArg Args, - bool TopLevelOfInitList, - bool TreatUnavailableAsInvalid) - : FailedCandidateSet(Kind.getLocation(), OverloadCandidateSet::CSK_Normal) { +InitializationSequence::InitializationSequence( + Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, + MultiExprArg Args, bool TopLevelOfInitList, bool TreatUnavailableAsInvalid) + : FailedOverloadResult(OR_Success), + FailedCandidateSet(Kind.getLocation(), OverloadCandidateSet::CSK_Normal) { InitializeFrom(S, Entity, Kind, Args, TopLevelOfInitList, TreatUnavailableAsInvalid); } @@ -5998,6 +6036,11 @@ getAssignmentAction(const InitializedEntity &Entity, bool Diagnose = false) { // FIXME: Can we tell apart casting vs. converting? return Sema::AA_Casting; + case InitializedEntity::EK_TemplateParameter: + // This is really initialization, but refer to it as conversion for + // consistency with CheckConvertedConstantExpression. + return Sema::AA_Converting; + case InitializedEntity::EK_Member: case InitializedEntity::EK_Binding: case InitializedEntity::EK_ArrayElement: @@ -6032,6 +6075,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) { case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_LambdaCapture: case InitializedEntity::EK_CompoundLiteralInit: + case InitializedEntity::EK_TemplateParameter: return false; case InitializedEntity::EK_Parameter: @@ -6066,6 +6110,7 @@ static bool shouldDestroyEntity(const InitializedEntity &Entity) { case InitializedEntity::EK_Variable: case InitializedEntity::EK_Parameter: case InitializedEntity::EK_Parameter_CF_Audited: + case InitializedEntity::EK_TemplateParameter: case InitializedEntity::EK_Temporary: case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_Exception: @@ -6099,6 +6144,7 @@ static SourceLocation getInitializationLoc(const InitializedEntity &Entity, case InitializedEntity::EK_Member: case InitializedEntity::EK_Parameter: case InitializedEntity::EK_Parameter_CF_Audited: + case InitializedEntity::EK_TemplateParameter: case InitializedEntity::EK_Temporary: case InitializedEntity::EK_New: case InitializedEntity::EK_Base: @@ -6342,7 +6388,7 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S, void InitializationSequence::PrintInitLocationNote(Sema &S, const InitializedEntity &Entity) { - if (Entity.isParameterKind() && Entity.getDecl()) { + if (Entity.isParamOrTemplateParamKind() && Entity.getDecl()) { if (Entity.getDecl()->getLocation().isInvalid()) return; @@ -6608,6 +6654,10 @@ static LifetimeResult getEntityLifetime( // the call. return {nullptr, LK_FullExpression}; + case InitializedEntity::EK_TemplateParameter: + // FIXME: This will always be ill-formed; should we eagerly diagnose it here? + return {nullptr, LK_FullExpression}; + case InitializedEntity::EK_Result: // -- The lifetime of a temporary bound to the returned value in a // function return statement is not extended; the temporary is @@ -6690,15 +6740,22 @@ struct IndirectLocalPathEntry { VarInit, LValToRVal, LifetimeBoundCall, + TemporaryCopy, + LambdaCaptureInit, GslReferenceInit, GslPointerInit } Kind; Expr *E; - const Decl *D = nullptr; + union { + const Decl *D = nullptr; + const LambdaCapture *Capture; + }; IndirectLocalPathEntry() {} IndirectLocalPathEntry(EntryKind K, Expr *E) : Kind(K), E(E) {} IndirectLocalPathEntry(EntryKind K, Expr *E, const Decl *D) : Kind(K), E(E), D(D) {} + IndirectLocalPathEntry(EntryKind K, Expr *E, const LambdaCapture *Capture) + : Kind(K), E(E), Capture(Capture) {} }; using IndirectLocalPath = llvm::SmallVectorImpl<IndirectLocalPathEntry>; @@ -6892,6 +6949,26 @@ static bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) { if (ATL.getAttrAs<LifetimeBoundAttr>()) return true; } + + // Assume that all assignment operators with a "normal" return type return + // *this, that is, an lvalue reference that is the same type as the implicit + // object parameter (or the LHS for a non-member operator$=). + OverloadedOperatorKind OO = FD->getDeclName().getCXXOverloadedOperator(); + if (OO == OO_Equal || isCompoundAssignmentOperator(OO)) { + QualType RetT = FD->getReturnType(); + if (RetT->isLValueReferenceType()) { + ASTContext &Ctx = FD->getASTContext(); + QualType LHST; + auto *MD = dyn_cast<CXXMethodDecl>(FD); + if (MD && MD->isCXXInstanceMember()) + LHST = Ctx.getLValueReferenceType(MD->getThisObjectType()); + else + LHST = MD->getParamDecl(0)->getType(); + if (Ctx.hasSameType(RetT, LHST)) + return true; + } + } + return false; } @@ -7237,15 +7314,37 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, // The lifetime of an init-capture is that of the closure object constructed // by a lambda-expression. if (auto *LE = dyn_cast<LambdaExpr>(Init)) { + LambdaExpr::capture_iterator CapI = LE->capture_begin(); for (Expr *E : LE->capture_inits()) { + assert(CapI != LE->capture_end()); + const LambdaCapture &Cap = *CapI++; if (!E) continue; + if (Cap.capturesVariable()) + Path.push_back({IndirectLocalPathEntry::LambdaCaptureInit, E, &Cap}); if (E->isGLValue()) visitLocalsRetainedByReferenceBinding(Path, E, RK_ReferenceBinding, Visit, EnableLifetimeWarnings); else visitLocalsRetainedByInitializer(Path, E, Visit, true, EnableLifetimeWarnings); + if (Cap.capturesVariable()) + Path.pop_back(); + } + } + + // Assume that a copy or move from a temporary references the same objects + // that the temporary does. + if (auto *CCE = dyn_cast<CXXConstructExpr>(Init)) { + if (CCE->getConstructor()->isCopyOrMoveConstructor()) { + if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(CCE->getArg(0))) { + Expr *Arg = MTE->getSubExpr(); + Path.push_back({IndirectLocalPathEntry::TemporaryCopy, Arg, + CCE->getConstructor()}); + visitLocalsRetainedByInitializer(Path, Arg, Visit, true, + /*EnableLifetimeWarnings*/false); + Path.pop_back(); + } } } @@ -7322,14 +7421,31 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, } } +/// Whether a path to an object supports lifetime extension. +enum PathLifetimeKind { + /// Lifetime-extend along this path. + Extend, + /// We should lifetime-extend, but we don't because (due to technical + /// limitations) we can't. This happens for default member initializers, + /// which we don't clone for every use, so we don't have a unique + /// MaterializeTemporaryExpr to update. + ShouldExtend, + /// Do not lifetime extend along this path. + NoExtend +}; + /// Determine whether this is an indirect path to a temporary that we are -/// supposed to lifetime-extend along (but don't). -static bool shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) { +/// supposed to lifetime-extend along. +static PathLifetimeKind +shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) { + PathLifetimeKind Kind = PathLifetimeKind::Extend; for (auto Elem : Path) { - if (Elem.Kind != IndirectLocalPathEntry::DefaultInit) - return false; + if (Elem.Kind == IndirectLocalPathEntry::DefaultInit) + Kind = PathLifetimeKind::ShouldExtend; + else if (Elem.Kind != IndirectLocalPathEntry::LambdaCaptureInit) + return PathLifetimeKind::NoExtend; } - return true; + return Kind; } /// Find the range for the first interesting entry in the path at or after I. @@ -7340,6 +7456,7 @@ static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I, case IndirectLocalPathEntry::AddressOf: case IndirectLocalPathEntry::LValToRVal: case IndirectLocalPathEntry::LifetimeBoundCall: + case IndirectLocalPathEntry::TemporaryCopy: case IndirectLocalPathEntry::GslReferenceInit: case IndirectLocalPathEntry::GslPointerInit: // These exist primarily to mark the path as not permitting or @@ -7352,6 +7469,11 @@ static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I, LLVM_FALLTHROUGH; case IndirectLocalPathEntry::DefaultInit: return Path[I].E->getSourceRange(); + + case IndirectLocalPathEntry::LambdaCaptureInit: + if (!Path[I].Capture->capturesVariable()) + continue; + return Path[I].E->getSourceRange(); } } return E->getSourceRange(); @@ -7429,17 +7551,16 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, return false; } - // Lifetime-extend the temporary. - if (Path.empty()) { + switch (shouldLifetimeExtendThroughPath(Path)) { + case PathLifetimeKind::Extend: // Update the storage duration of the materialized temporary. // FIXME: Rebuild the expression instead of mutating it. MTE->setExtendingDecl(ExtendingEntity->getDecl(), ExtendingEntity->allocateManglingNumber()); // Also visit the temporaries lifetime-extended by this initializer. return true; - } - if (shouldLifetimeExtendThroughPath(Path)) { + case PathLifetimeKind::ShouldExtend: // We're supposed to lifetime-extend the temporary along this path (per // the resolution of DR1815), but we don't support that yet. // @@ -7448,7 +7569,9 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, // lifetime extend its temporaries. Diag(DiagLoc, diag::warn_unsupported_lifetime_extension) << RK << DiagRange; - } else { + break; + + case PathLifetimeKind::NoExtend: // If the path goes through the initialization of a variable or field, // it can't possibly reach a temporary created in this full-expression. // We will have already diagnosed any problems with the initializer. @@ -7459,6 +7582,7 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, << RK << !Entity.getParent() << ExtendingEntity->getDecl()->isImplicit() << ExtendingEntity->getDecl() << Init->isGLValue() << DiagRange; + break; } break; } @@ -7479,7 +7603,8 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, return false; } bool IsSubobjectMember = ExtendingEntity != &Entity; - Diag(DiagLoc, shouldLifetimeExtendThroughPath(Path) + Diag(DiagLoc, shouldLifetimeExtendThroughPath(Path) != + PathLifetimeKind::NoExtend ? diag::err_dangling_member : diag::warn_dangling_member) << ExtendingDecl << IsSubobjectMember << RK << DiagRange; @@ -7586,6 +7711,7 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, break; case IndirectLocalPathEntry::LifetimeBoundCall: + case IndirectLocalPathEntry::TemporaryCopy: case IndirectLocalPathEntry::GslPointerInit: case IndirectLocalPathEntry::GslReferenceInit: // FIXME: Consider adding a note for these. @@ -7598,7 +7724,7 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, break; } - case IndirectLocalPathEntry::VarInit: + case IndirectLocalPathEntry::VarInit: { const VarDecl *VD = cast<VarDecl>(Elem.D); Diag(VD->getLocation(), diag::note_local_var_initializer) << VD->getType()->isReferenceType() @@ -7606,6 +7732,19 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, << nextPathEntryRange(Path, I + 1, L); break; } + + case IndirectLocalPathEntry::LambdaCaptureInit: + if (!Elem.Capture->capturesVariable()) + break; + // FIXME: We can't easily tell apart an init-capture from a nested + // capture of an init-capture. + const VarDecl *VD = Elem.Capture->getCapturedVar(); + Diag(Elem.Capture->getLocation(), diag::note_lambda_capture_initializer) + << VD << VD->isInitCapture() << Elem.Capture->isExplicit() + << (Elem.Capture->getCaptureKind() == LCK_ByRef) << VD + << nextPathEntryRange(Path, I + 1, L); + break; + } } // We didn't lifetime-extend, so don't go any further; we don't need more @@ -7879,7 +8018,7 @@ ExprResult InitializationSequence::Perform(Sema &S, if (S.getLangOpts().CPlusPlus11 && Entity.getType()->isReferenceType() && Args.size() == 1 && isa<InitListExpr>(Args[0]) && - !Entity.isParameterKind()) { + !Entity.isParamOrTemplateParamKind()) { // Produce a C++98 compatibility warning if we are initializing a reference // from an initializer list. For parameters, we produce a better warning // elsewhere. @@ -7929,6 +8068,7 @@ ExprResult InitializationSequence::Perform(Sema &S, case SK_QualificationConversionLValue: case SK_QualificationConversionXValue: case SK_QualificationConversionRValue: + case SK_FunctionReferenceConversion: case SK_AtomicConversion: case SK_ConversionSequence: case SK_ConversionSequenceNoNarrowing: @@ -8023,9 +8163,9 @@ ExprResult InitializationSequence::Perform(Sema &S, (Step->Kind == SK_CastDerivedToBaseXValue ? VK_XValue : VK_RValue); - CurInit = - ImplicitCastExpr::Create(S.Context, Step->Type, CK_DerivedToBase, - CurInit.get(), &BasePath, VK); + CurInit = ImplicitCastExpr::Create(S.Context, Step->Type, + CK_DerivedToBase, CurInit.get(), + &BasePath, VK, FPOptionsOverride()); break; } @@ -8060,9 +8200,21 @@ ExprResult InitializationSequence::Perform(Sema &S, if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType)) return ExprError(); + QualType MTETy = Step->Type; + + // When this is an incomplete array type (such as when this is + // initializing an array of unknown bounds from an init list), use THAT + // type instead so that we propogate the array bounds. + if (MTETy->isIncompleteArrayType() && + !CurInit.get()->getType()->isIncompleteArrayType() && + S.Context.hasSameType( + MTETy->getPointeeOrArrayElementType(), + CurInit.get()->getType()->getPointeeOrArrayElementType())) + MTETy = CurInit.get()->getType(); + // Materialize the temporary into memory. MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr( - Step->Type, CurInit.get(), Entity.getType()->isLValueReferenceType()); + MTETy, CurInit.get(), Entity.getType()->isLValueReferenceType()); CurInit = MTE; // If we're extending this temporary to automatic storage duration -- we @@ -8154,9 +8306,9 @@ ExprResult InitializationSequence::Perform(Sema &S, if (CreatedObject && checkAbstractType(CurInit.get()->getType())) return ExprError(); - CurInit = ImplicitCastExpr::Create(S.Context, CurInit.get()->getType(), - CastKind, CurInit.get(), nullptr, - CurInit.get()->getValueKind()); + CurInit = ImplicitCastExpr::Create( + S.Context, CurInit.get()->getType(), CastKind, CurInit.get(), nullptr, + CurInit.get()->getValueKind(), S.CurFPFeatureOverrides()); if (shouldBindAsTemporary(Entity)) // The overall entity is temporary, so this expression should be @@ -8194,6 +8346,13 @@ ExprResult InitializationSequence::Perform(Sema &S, break; } + case SK_FunctionReferenceConversion: + assert(CurInit.get()->isLValue() && + "function reference should be lvalue"); + CurInit = + S.ImpCastExprToType(CurInit.get(), Step->Type, CK_NoOp, VK_LValue); + break; + case SK_AtomicConversion: { assert(CurInit.get()->isRValue() && "cannot convert glvalue to atomic"); CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type, @@ -8422,7 +8581,8 @@ ExprResult InitializationSequence::Perform(Sema &S, case SK_StringInit: { QualType Ty = Step->Type; - CheckStringInit(CurInit.get(), ResultType ? *ResultType : Ty, + bool UpdateType = ResultType && Entity.getType()->isIncompleteArrayType(); + CheckStringInit(CurInit.get(), UpdateType ? *ResultType : Ty, S.Context.getAsArrayType(Ty), S); break; } @@ -8497,9 +8657,9 @@ ExprResult InitializationSequence::Perform(Sema &S, break; case SK_ProduceObjCObject: - CurInit = - ImplicitCastExpr::Create(S.Context, Step->Type, CK_ARCProduceObject, - CurInit.get(), nullptr, VK_RValue); + CurInit = ImplicitCastExpr::Create( + S.Context, Step->Type, CK_ARCProduceObject, CurInit.get(), nullptr, + VK_RValue, FPOptionsOverride()); break; case SK_StdInitializerList: { @@ -8553,9 +8713,9 @@ ExprResult InitializationSequence::Perform(Sema &S, // Case 1b and 1c // No cast from integer to sampler is needed. if (!Var->hasGlobalStorage()) { - CurInit = ImplicitCastExpr::Create(S.Context, Step->Type, - CK_LValueToRValue, Init, - /*BasePath=*/nullptr, VK_RValue); + CurInit = ImplicitCastExpr::Create( + S.Context, Step->Type, CK_LValueToRValue, Init, + /*BasePath=*/nullptr, VK_RValue, FPOptionsOverride()); break; } // Case 1a @@ -8705,6 +8865,16 @@ static void emitBadConversionNotes(Sema &S, const InitializedEntity &entity, if (entity.getKind() == InitializedEntity::EK_Result) S.EmitRelatedResultTypeNoteForReturn(destType); } + QualType fromType = op->getType(); + auto *fromDecl = fromType.getTypePtr()->getPointeeCXXRecordDecl(); + auto *destDecl = destType.getTypePtr()->getPointeeCXXRecordDecl(); + if (fromDecl && destDecl && fromDecl->getDeclKind() == Decl::CXXRecord && + destDecl->getDeclKind() == Decl::CXXRecord && + !fromDecl->isInvalidDecl() && !destDecl->isInvalidDecl() && + !fromDecl->hasDefinition()) + S.Diag(fromDecl->getLocation(), diag::note_forward_class_conversion) + << S.getASTContext().getTagDeclType(fromDecl) + << S.getASTContext().getTagDeclType(destDecl); } static void diagnoseListInit(Sema &S, const InitializedEntity &Entity, @@ -9443,6 +9613,10 @@ void InitializationSequence::dump(raw_ostream &OS) const { OS << "qualification conversion (lvalue)"; break; + case SK_FunctionReferenceConversion: + OS << "function reference conversion"; + break; + case SK_AtomicConversion: OS << "non-atomic-to-atomic conversion"; break; @@ -9747,7 +9921,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( auto TemplateName = DeducedTST->getTemplateName(); if (TemplateName.isDependent()) - return Context.DependentTy; + return SubstAutoType(TSInfo->getType(), Context.DependentTy); // We can only perform deduction for class templates. auto *Template = @@ -9766,7 +9940,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( Diag(TSInfo->getTypeLoc().getBeginLoc(), diag::warn_cxx14_compat_class_template_argument_deduction) << TSInfo->getTypeLoc().getSourceRange() << 0; - return Context.DependentTy; + return SubstAutoType(TSInfo->getType(), Context.DependentTy); } // FIXME: Perform "exact type" matching first, per CWG discussion? diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 657ed13f207a..af61c82c2002 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -233,7 +233,7 @@ getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) { /*L angle loc*/ LSI->ExplicitTemplateParamsRange.getBegin(), LSI->TemplateParams, /*R angle loc*/LSI->ExplicitTemplateParamsRange.getEnd(), - nullptr); + LSI->RequiresClause.get()); } return LSI->GLTemplateParameterList; } @@ -520,7 +520,8 @@ void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) { void Sema::ActOnLambdaExplicitTemplateParameterList(SourceLocation LAngleLoc, ArrayRef<NamedDecl *> TParams, - SourceLocation RAngleLoc) { + SourceLocation RAngleLoc, + ExprResult RequiresClause) { LambdaScopeInfo *LSI = getCurLambda(); assert(LSI && "Expected a lambda scope"); assert(LSI->NumExplicitTemplateParams == 0 && @@ -533,6 +534,7 @@ void Sema::ActOnLambdaExplicitTemplateParameterList(SourceLocation LAngleLoc, LSI->TemplateParams.append(TParams.begin(), TParams.end()); LSI->NumExplicitTemplateParams = TParams.size(); LSI->ExplicitTemplateParamsRange = {LAngleLoc, RAngleLoc}; + LSI->RequiresClause = RequiresClause; } void Sema::addLambdaParameters( @@ -680,8 +682,9 @@ static void adjustBlockReturnsToEnum(Sema &S, ArrayRef<ReturnStmt*> returns, ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(retValue); Expr *E = (cleanups ? cleanups->getSubExpr() : retValue); - E = ImplicitCastExpr::Create(S.Context, returnType, CK_IntegralCast, - E, /*base path*/ nullptr, VK_RValue); + E = ImplicitCastExpr::Create(S.Context, returnType, CK_IntegralCast, E, + /*base path*/ nullptr, VK_RValue, + FPOptionsOverride()); if (cleanups) { cleanups->setSubExpr(E); } else { @@ -803,7 +806,8 @@ QualType Sema::buildLambdaInitCaptureInitialization( Diag(EllipsisLoc, getLangOpts().CPlusPlus20 ? diag::warn_cxx17_compat_init_capture_pack : diag::ext_init_capture_pack); - DeductType = Context.getPackExpansionType(DeductType, NumExpansions); + DeductType = Context.getPackExpansionType(DeductType, NumExpansions, + /*ExpectPackInType=*/false); TLB.push<PackExpansionTypeLoc>(DeductType).setEllipsisLoc(EllipsisLoc); } else { // Just ignore the ellipsis for now and form a non-pack variable. We'll @@ -994,6 +998,10 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, if (getLangOpts().CUDA) CUDASetLambdaAttrs(Method); + // OpenMP lambdas might get assumumption attributes. + if (LangOpts.OpenMP) + ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Method); + // Number the lambda for linkage purposes if necessary. handleLambdaNumbering(Class, Method); @@ -1261,30 +1269,89 @@ void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope, PopFunctionScopeInfo(); } +template <typename Func> +static void repeatForLambdaConversionFunctionCallingConvs( + Sema &S, const FunctionProtoType &CallOpProto, Func F) { + CallingConv DefaultFree = S.Context.getDefaultCallingConvention( + CallOpProto.isVariadic(), /*IsCXXMethod=*/false); + CallingConv DefaultMember = S.Context.getDefaultCallingConvention( + CallOpProto.isVariadic(), /*IsCXXMethod=*/true); + CallingConv CallOpCC = CallOpProto.getCallConv(); + + /// Implement emitting a version of the operator for many of the calling + /// conventions for MSVC, as described here: + /// https://devblogs.microsoft.com/oldnewthing/20150220-00/?p=44623. + /// Experimentally, we determined that cdecl, stdcall, fastcall, and + /// vectorcall are generated by MSVC when it is supported by the target. + /// Additionally, we are ensuring that the default-free/default-member and + /// call-operator calling convention are generated as well. + /// NOTE: We intentionally generate a 'thiscall' on Win32 implicitly from the + /// 'member default', despite MSVC not doing so. We do this in order to ensure + /// that someone who intentionally places 'thiscall' on the lambda call + /// operator will still get that overload, since we don't have the a way of + /// detecting the attribute by the time we get here. + if (S.getLangOpts().MSVCCompat) { + CallingConv Convs[] = { + CC_C, CC_X86StdCall, CC_X86FastCall, CC_X86VectorCall, + DefaultFree, DefaultMember, CallOpCC}; + llvm::sort(Convs); + llvm::iterator_range<CallingConv *> Range( + std::begin(Convs), std::unique(std::begin(Convs), std::end(Convs))); + const TargetInfo &TI = S.getASTContext().getTargetInfo(); + + for (CallingConv C : Range) { + if (TI.checkCallingConvention(C) == TargetInfo::CCCR_OK) + F(C); + } + return; + } + + if (CallOpCC == DefaultMember && DefaultMember != DefaultFree) { + F(DefaultFree); + F(DefaultMember); + } else { + F(CallOpCC); + } +} + +// Returns the 'standard' calling convention to be used for the lambda +// conversion function, that is, the 'free' function calling convention unless +// it is overridden by a non-default calling convention attribute. +static CallingConv +getLambdaConversionFunctionCallConv(Sema &S, + const FunctionProtoType *CallOpProto) { + CallingConv DefaultFree = S.Context.getDefaultCallingConvention( + CallOpProto->isVariadic(), /*IsCXXMethod=*/false); + CallingConv DefaultMember = S.Context.getDefaultCallingConvention( + CallOpProto->isVariadic(), /*IsCXXMethod=*/true); + CallingConv CallOpCC = CallOpProto->getCallConv(); + + // If the call-operator hasn't been changed, return both the 'free' and + // 'member' function calling convention. + if (CallOpCC == DefaultMember && DefaultMember != DefaultFree) + return DefaultFree; + return CallOpCC; +} + QualType Sema::getLambdaConversionFunctionResultType( - const FunctionProtoType *CallOpProto) { - // The function type inside the pointer type is the same as the call - // operator with some tweaks. The calling convention is the default free - // function convention, and the type qualifications are lost. + const FunctionProtoType *CallOpProto, CallingConv CC) { const FunctionProtoType::ExtProtoInfo CallOpExtInfo = CallOpProto->getExtProtoInfo(); FunctionProtoType::ExtProtoInfo InvokerExtInfo = CallOpExtInfo; - CallingConv CC = Context.getDefaultCallingConvention( - CallOpProto->isVariadic(), /*IsCXXMethod=*/false); InvokerExtInfo.ExtInfo = InvokerExtInfo.ExtInfo.withCallingConv(CC); InvokerExtInfo.TypeQuals = Qualifiers(); assert(InvokerExtInfo.RefQualifier == RQ_None && - "Lambda's call operator should not have a reference qualifier"); + "Lambda's call operator should not have a reference qualifier"); return Context.getFunctionType(CallOpProto->getReturnType(), CallOpProto->getParamTypes(), InvokerExtInfo); } /// Add a lambda's conversion to function pointer, as described in /// C++11 [expr.prim.lambda]p6. -static void addFunctionPointerConversion(Sema &S, - SourceRange IntroducerRange, +static void addFunctionPointerConversion(Sema &S, SourceRange IntroducerRange, CXXRecordDecl *Class, - CXXMethodDecl *CallOperator) { + CXXMethodDecl *CallOperator, + QualType InvokerFunctionTy) { // This conversion is explicitly disabled if the lambda's function has // pass_object_size attributes on any of its parameters. auto HasPassObjectSizeAttr = [](const ParmVarDecl *P) { @@ -1294,8 +1361,6 @@ static void addFunctionPointerConversion(Sema &S, return; // Add the conversion to function pointer. - QualType InvokerFunctionTy = S.getLambdaConversionFunctionResultType( - CallOperator->getType()->castAs<FunctionProtoType>()); QualType PtrToFunctionTy = S.Context.getPointerType(InvokerFunctionTy); // Create the type of the conversion function. @@ -1380,7 +1445,8 @@ static void addFunctionPointerConversion(Sema &S, S.Context, Class, Loc, DeclarationNameInfo(ConversionName, Loc, ConvNameLoc), ConvTy, ConvTSI, /*isInline=*/true, ExplicitSpecifier(), - S.getLangOpts().CPlusPlus17 ? CSK_constexpr : CSK_unspecified, + S.getLangOpts().CPlusPlus17 ? ConstexprSpecKind::Constexpr + : ConstexprSpecKind::Unspecified, CallOperator->getBody()->getEndLoc()); Conversion->setAccess(AS_public); Conversion->setImplicit(true); @@ -1419,7 +1485,8 @@ static void addFunctionPointerConversion(Sema &S, CXXMethodDecl *Invoke = CXXMethodDecl::Create( S.Context, Class, Loc, DeclarationNameInfo(InvokerName, Loc), InvokerFunctionTy, CallOperator->getTypeSourceInfo(), SC_Static, - /*isInline=*/true, CSK_unspecified, CallOperator->getBody()->getEndLoc()); + /*isInline=*/true, ConstexprSpecKind::Unspecified, + CallOperator->getBody()->getEndLoc()); for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) InvokerParams[I]->setOwningFunction(Invoke); Invoke->setParams(InvokerParams); @@ -1440,13 +1507,34 @@ static void addFunctionPointerConversion(Sema &S, Class->addDecl(Invoke); } +/// Add a lambda's conversion to function pointers, as described in +/// C++11 [expr.prim.lambda]p6. Note that in most cases, this should emit only a +/// single pointer conversion. In the event that the default calling convention +/// for free and member functions is different, it will emit both conventions. +static void addFunctionPointerConversions(Sema &S, SourceRange IntroducerRange, + CXXRecordDecl *Class, + CXXMethodDecl *CallOperator) { + const FunctionProtoType *CallOpProto = + CallOperator->getType()->castAs<FunctionProtoType>(); + + repeatForLambdaConversionFunctionCallingConvs( + S, *CallOpProto, [&](CallingConv CC) { + QualType InvokerFunctionTy = + S.getLambdaConversionFunctionResultType(CallOpProto, CC); + addFunctionPointerConversion(S, IntroducerRange, Class, CallOperator, + InvokerFunctionTy); + }); +} + /// Add a lambda's conversion to block pointer. static void addBlockPointerConversion(Sema &S, SourceRange IntroducerRange, CXXRecordDecl *Class, CXXMethodDecl *CallOperator) { + const FunctionProtoType *CallOpProto = + CallOperator->getType()->castAs<FunctionProtoType>(); QualType FunctionTy = S.getLambdaConversionFunctionResultType( - CallOperator->getType()->castAs<FunctionProtoType>()); + CallOpProto, getLambdaConversionFunctionCallConv(S, CallOpProto)); QualType BlockPtrTy = S.Context.getBlockPointerType(FunctionTy); FunctionProtoType::ExtProtoInfo ConversionEPI( @@ -1465,7 +1553,7 @@ static void addBlockPointerConversion(Sema &S, CXXConversionDecl *Conversion = CXXConversionDecl::Create( S.Context, Class, Loc, DeclarationNameInfo(Name, Loc, NameLoc), ConvTy, S.Context.getTrivialTypeSourceInfo(ConvTy, Loc), - /*isInline=*/true, ExplicitSpecifier(), CSK_unspecified, + /*isInline=*/true, ExplicitSpecifier(), ConstexprSpecKind::Unspecified, CallOperator->getBody()->getEndLoc()); Conversion->setAccess(AS_public); Conversion->setImplicit(true); @@ -1623,8 +1711,9 @@ FieldDecl *Sema::BuildCaptureField(RecordDecl *RD, // Build the non-static data member. FieldDecl *Field = - FieldDecl::Create(Context, RD, Loc, Loc, nullptr, FieldType, TSI, nullptr, - false, ICIS_NoInit); + FieldDecl::Create(Context, RD, /*StartLoc=*/Loc, /*IdLoc=*/Loc, + /*Id=*/nullptr, FieldType, TSI, /*BW=*/nullptr, + /*Mutable=*/false, ICIS_NoInit); // If the variable being captured has an invalid type, mark the class as // invalid as well. if (!FieldType->isDependentType()) { @@ -1784,7 +1873,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, CUDACheckLambdaCapture(CallOperator, From); } - Class->setCaptures(Captures); + Class->setCaptures(Context, Captures); // C++11 [expr.prim.lambda]p6: // The closure type for a lambda-expression with no lambda-capture @@ -1792,8 +1881,8 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, // to pointer to function having the same parameter and return // types as the closure type's function call operator. if (Captures.empty() && CaptureDefault == LCD_None) - addFunctionPointerConversion(*this, IntroducerRange, Class, - CallOperator); + addFunctionPointerConversions(*this, IntroducerRange, Class, + CallOperator); // Objective-C++: // The closure type for a lambda-expression has a public non-virtual @@ -1828,8 +1917,8 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, CallOperator->setConstexprKind( CheckConstexprFunctionDefinition(CallOperator, CheckConstexprKind::CheckValid) - ? CSK_constexpr - : CSK_unspecified); + ? ConstexprSpecKind::Constexpr + : ConstexprSpecKind::Unspecified); } // Emit delayed shadowing warnings now that the full capture list is known. diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 5757eaf3fac0..29038ab9fe1c 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -894,10 +894,9 @@ bool Sema::LookupBuiltin(LookupResult &R) { Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) return false; - if (NamedDecl *D = LazilyCreateBuiltin((IdentifierInfo *)II, - BuiltinID, TUScope, - R.isForRedeclaration(), - R.getNameLoc())) { + if (NamedDecl *D = + LazilyCreateBuiltin(II, BuiltinID, TUScope, + R.isForRedeclaration(), R.getNameLoc())) { R.addDecl(D); return true; } @@ -908,6 +907,24 @@ bool Sema::LookupBuiltin(LookupResult &R) { return false; } +/// Looks up the declaration of "struct objc_super" and +/// saves it for later use in building builtin declaration of +/// objc_msgSendSuper and objc_msgSendSuper_stret. +static void LookupPredefedObjCSuperType(Sema &Sema, Scope *S) { + ASTContext &Context = Sema.Context; + LookupResult Result(Sema, &Context.Idents.get("objc_super"), SourceLocation(), + Sema::LookupTagName); + Sema.LookupName(Result, S); + if (Result.getResultKind() == LookupResult::Found) + if (const TagDecl *TD = Result.getAsSingle<TagDecl>()) + Context.setObjCSuperType(Context.getTagDeclType(TD)); +} + +void Sema::LookupNecessaryTypesForBuiltin(Scope *S, unsigned ID) { + if (ID == Builtin::BIobjc_msgSendSuper) + LookupPredefedObjCSuperType(*this, S); +} + /// Determine whether we can declare a special member function within /// the class at this point. static bool CanDeclareSpecialMemberFunction(const CXXRecordDecl *Class) { @@ -2068,47 +2085,6 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R, return Found; } -/// Callback that looks for any member of a class with the given name. -static bool LookupAnyMember(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, DeclarationName Name) { - RecordDecl *BaseRecord = Specifier->getType()->castAs<RecordType>()->getDecl(); - - Path.Decls = BaseRecord->lookup(Name); - return !Path.Decls.empty(); -} - -/// Determine whether the given set of member declarations contains only -/// static members, nested types, and enumerators. -template<typename InputIterator> -static bool HasOnlyStaticMembers(InputIterator First, InputIterator Last) { - Decl *D = (*First)->getUnderlyingDecl(); - if (isa<VarDecl>(D) || isa<TypeDecl>(D) || isa<EnumConstantDecl>(D)) - return true; - - if (isa<CXXMethodDecl>(D)) { - // Determine whether all of the methods are static. - bool AllMethodsAreStatic = true; - for(; First != Last; ++First) { - D = (*First)->getUnderlyingDecl(); - - if (!isa<CXXMethodDecl>(D)) { - assert(isa<TagDecl>(D) && "Non-function must be a tag decl"); - break; - } - - if (!cast<CXXMethodDecl>(D)->isStatic()) { - AllMethodsAreStatic = false; - break; - } - } - - if (AllMethodsAreStatic) - return true; - } - - return false; -} - /// Perform qualified name lookup into a given context. /// /// Qualified name lookup (C++ [basic.lookup.qual]) is used to find @@ -2186,6 +2162,13 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, if (!LookupRec || !LookupRec->getDefinition()) return false; + // We're done for lookups that can never succeed for C++ classes. + if (R.getLookupKind() == LookupOperatorName || + R.getLookupKind() == LookupNamespaceName || + R.getLookupKind() == LookupObjCProtocolName || + R.getLookupKind() == LookupLabel) + return false; + // If we're performing qualified name lookup into a dependent class, // then we are actually looking into a current instantiation. If we have any // dependent base classes, then we either have to delay lookup until @@ -2198,59 +2181,27 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, } // Perform lookup into our base classes. - CXXBasePaths Paths; - Paths.setOrigin(LookupRec); - - // Look for this member in our base classes - bool (*BaseCallback)(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, - DeclarationName Name) = nullptr; - switch (R.getLookupKind()) { - case LookupObjCImplicitSelfParam: - case LookupOrdinaryName: - case LookupMemberName: - case LookupRedeclarationWithLinkage: - case LookupLocalFriendName: - case LookupDestructorName: - BaseCallback = &CXXRecordDecl::FindOrdinaryMember; - break; - - case LookupTagName: - BaseCallback = &CXXRecordDecl::FindTagMember; - break; - - case LookupAnyName: - BaseCallback = &LookupAnyMember; - break; - - case LookupOMPReductionName: - BaseCallback = &CXXRecordDecl::FindOMPReductionMember; - break; - - case LookupOMPMapperName: - BaseCallback = &CXXRecordDecl::FindOMPMapperMember; - break; - - case LookupUsingDeclName: - // This lookup is for redeclarations only. - - case LookupOperatorName: - case LookupNamespaceName: - case LookupObjCProtocolName: - case LookupLabel: - // These lookups will never find a member in a C++ class (or base class). - return false; - - case LookupNestedNameSpecifierName: - BaseCallback = &CXXRecordDecl::FindNestedNameSpecifierMember; - break; - } DeclarationName Name = R.getLookupName(); - if (!LookupRec->lookupInBases( - [=](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { - return BaseCallback(Specifier, Path, Name); - }, - Paths)) + unsigned IDNS = R.getIdentifierNamespace(); + + // Look for this member in our base classes. + auto BaseCallback = [Name, IDNS](const CXXBaseSpecifier *Specifier, + CXXBasePath &Path) -> bool { + CXXRecordDecl *BaseRecord = Specifier->getType()->getAsCXXRecordDecl(); + // Drop leading non-matching lookup results from the declaration list so + // we don't need to consider them again below. + for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty(); + Path.Decls = Path.Decls.slice(1)) { + if (Path.Decls.front()->isInIdentifierNamespace(IDNS)) + return true; + } + return false; + }; + + CXXBasePaths Paths; + Paths.setOrigin(LookupRec); + if (!LookupRec->lookupInBases(BaseCallback, Paths)) return false; R.setNamingClass(LookupRec); @@ -2265,6 +2216,85 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, int SubobjectNumber = 0; AccessSpecifier SubobjectAccess = AS_none; + // Check whether the given lookup result contains only static members. + auto HasOnlyStaticMembers = [&](DeclContextLookupResult Result) { + for (NamedDecl *ND : Result) + if (ND->isInIdentifierNamespace(IDNS) && ND->isCXXInstanceMember()) + return false; + return true; + }; + + bool TemplateNameLookup = R.isTemplateNameLookup(); + + // Determine whether two sets of members contain the same members, as + // required by C++ [class.member.lookup]p6. + auto HasSameDeclarations = [&](DeclContextLookupResult A, + DeclContextLookupResult B) { + using Iterator = DeclContextLookupResult::iterator; + using Result = const void *; + + auto Next = [&](Iterator &It, Iterator End) -> Result { + while (It != End) { + NamedDecl *ND = *It++; + if (!ND->isInIdentifierNamespace(IDNS)) + continue; + + // C++ [temp.local]p3: + // A lookup that finds an injected-class-name (10.2) can result in + // an ambiguity in certain cases (for example, if it is found in + // more than one base class). If all of the injected-class-names + // that are found refer to specializations of the same class + // template, and if the name is used as a template-name, the + // reference refers to the class template itself and not a + // specialization thereof, and is not ambiguous. + if (TemplateNameLookup) + if (auto *TD = getAsTemplateNameDecl(ND)) + ND = TD; + + // C++ [class.member.lookup]p3: + // type declarations (including injected-class-names) are replaced by + // the types they designate + if (const TypeDecl *TD = dyn_cast<TypeDecl>(ND->getUnderlyingDecl())) { + QualType T = Context.getTypeDeclType(TD); + return T.getCanonicalType().getAsOpaquePtr(); + } + + return ND->getUnderlyingDecl()->getCanonicalDecl(); + } + return nullptr; + }; + + // We'll often find the declarations are in the same order. Handle this + // case (and the special case of only one declaration) efficiently. + Iterator AIt = A.begin(), BIt = B.begin(), AEnd = A.end(), BEnd = B.end(); + while (true) { + Result AResult = Next(AIt, AEnd); + Result BResult = Next(BIt, BEnd); + if (!AResult && !BResult) + return true; + if (!AResult || !BResult) + return false; + if (AResult != BResult) { + // Found a mismatch; carefully check both lists, accounting for the + // possibility of declarations appearing more than once. + llvm::SmallDenseMap<Result, bool, 32> AResults; + for (; AResult; AResult = Next(AIt, AEnd)) + AResults.insert({AResult, /*FoundInB*/false}); + unsigned Found = 0; + for (; BResult; BResult = Next(BIt, BEnd)) { + auto It = AResults.find(BResult); + if (It == AResults.end()) + return false; + if (!It->second) { + It->second = true; + ++Found; + } + } + return AResults.size() == Found; + } + } + }; + for (CXXBasePaths::paths_iterator Path = Paths.begin(), PathEnd = Paths.end(); Path != PathEnd; ++Path) { const CXXBasePathElement &PathElement = Path->back(); @@ -2281,51 +2311,25 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, continue; } - if (SubobjectType - != Context.getCanonicalType(PathElement.Base->getType())) { + if (SubobjectType != + Context.getCanonicalType(PathElement.Base->getType())) { // We found members of the given name in two subobjects of // different types. If the declaration sets aren't the same, this // lookup is ambiguous. - if (HasOnlyStaticMembers(Path->Decls.begin(), Path->Decls.end())) { - CXXBasePaths::paths_iterator FirstPath = Paths.begin(); - DeclContext::lookup_iterator FirstD = FirstPath->Decls.begin(); - DeclContext::lookup_iterator CurrentD = Path->Decls.begin(); - - // Get the decl that we should use for deduplicating this lookup. - auto GetRepresentativeDecl = [&](NamedDecl *D) -> Decl * { - // C++ [temp.local]p3: - // A lookup that finds an injected-class-name (10.2) can result in - // an ambiguity in certain cases (for example, if it is found in - // more than one base class). If all of the injected-class-names - // that are found refer to specializations of the same class - // template, and if the name is used as a template-name, the - // reference refers to the class template itself and not a - // specialization thereof, and is not ambiguous. - if (R.isTemplateNameLookup()) - if (auto *TD = getAsTemplateNameDecl(D)) - D = TD; - return D->getUnderlyingDecl()->getCanonicalDecl(); - }; - - while (FirstD != FirstPath->Decls.end() && - CurrentD != Path->Decls.end()) { - if (GetRepresentativeDecl(*FirstD) != - GetRepresentativeDecl(*CurrentD)) - break; - - ++FirstD; - ++CurrentD; - } - - if (FirstD == FirstPath->Decls.end() && - CurrentD == Path->Decls.end()) - continue; - } + // + // FIXME: The language rule says that this applies irrespective of + // whether the sets contain only static members. + if (HasOnlyStaticMembers(Path->Decls) && + HasSameDeclarations(Paths.begin()->Decls, Path->Decls)) + continue; R.setAmbiguousBaseSubobjectTypes(Paths); return true; } + // FIXME: This language rule no longer exists. Checking for ambiguous base + // subobjects should be done as part of formation of a class member access + // expression (when converting the object parameter to the member's type). if (SubobjectNumber != PathElement.SubobjectNumber) { // We have a different subobject of the same type. @@ -2333,7 +2337,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, // A static member, a nested type or an enumerator defined in // a base class T can unambiguously be found even if an object // has more than one base class subobject of type T. - if (HasOnlyStaticMembers(Path->Decls.begin(), Path->Decls.end())) + if (HasOnlyStaticMembers(Path->Decls)) continue; // We have found a nonstatic member name in multiple, distinct @@ -2348,7 +2352,8 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, for (auto *D : Paths.front().Decls) { AccessSpecifier AS = CXXRecordDecl::MergeAccess(SubobjectAccess, D->getAccess()); - R.addDecl(D, AS); + if (NamedDecl *ND = R.getAcceptableDecl(D)) + R.addDecl(ND, AS); } R.resolveKind(); return true; @@ -2504,13 +2509,23 @@ void Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { << Name << LookupRange; CXXBasePaths *Paths = Result.getBasePaths(); - std::set<Decl *> DeclsPrinted; + std::set<const NamedDecl *> DeclsPrinted; for (CXXBasePaths::paths_iterator Path = Paths->begin(), PathEnd = Paths->end(); Path != PathEnd; ++Path) { - Decl *D = Path->Decls.front(); - if (DeclsPrinted.insert(D).second) - Diag(D->getLocation(), diag::note_ambiguous_member_found); + const NamedDecl *D = Path->Decls.front(); + if (!D->isInIdentifierNamespace(Result.getIdentifierNamespace())) + continue; + if (DeclsPrinted.insert(D).second) { + if (const auto *TD = dyn_cast<TypedefNameDecl>(D->getUnderlyingDecl())) + Diag(D->getLocation(), diag::note_ambiguous_member_type_found) + << TD->getUnderlyingType(); + else if (const auto *TD = dyn_cast<TypeDecl>(D->getUnderlyingDecl())) + Diag(D->getLocation(), diag::note_ambiguous_member_type_found) + << Context.getTypeDeclType(TD); + else + Diag(D->getLocation(), diag::note_ambiguous_member_found); + } } break; } @@ -2981,7 +2996,6 @@ ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II, } void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, - QualType T1, QualType T2, UnresolvedSetImpl &Functions) { // C++ [over.match.oper]p3: // -- The set of non-member candidates is the result of the @@ -3319,9 +3333,9 @@ CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) { /// and filter the results to the appropriate set for the given argument types. Sema::LiteralOperatorLookupResult Sema::LookupLiteralOperator(Scope *S, LookupResult &R, - ArrayRef<QualType> ArgTys, - bool AllowRaw, bool AllowTemplate, - bool AllowStringTemplate, bool DiagnoseMissing) { + ArrayRef<QualType> ArgTys, bool AllowRaw, + bool AllowTemplate, bool AllowStringTemplatePack, + bool DiagnoseMissing, StringLiteral *StringLit) { LookupName(R, S); assert(R.getResultKind() != LookupResult::Ambiguous && "literal operator lookup can't be ambiguous"); @@ -3329,10 +3343,11 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, // Filter the lookup results appropriately. LookupResult::Filter F = R.makeFilter(); + bool AllowCooked = true; bool FoundRaw = false; bool FoundTemplate = false; - bool FoundStringTemplate = false; - bool FoundExactMatch = false; + bool FoundStringTemplatePack = false; + bool FoundCooked = false; while (F.hasNext()) { Decl *D = F.next(); @@ -3347,19 +3362,19 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, bool IsRaw = false; bool IsTemplate = false; - bool IsStringTemplate = false; - bool IsExactMatch = false; + bool IsStringTemplatePack = false; + bool IsCooked = false; if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { if (FD->getNumParams() == 1 && FD->getParamDecl(0)->getType()->getAs<PointerType>()) IsRaw = true; else if (FD->getNumParams() == ArgTys.size()) { - IsExactMatch = true; + IsCooked = true; for (unsigned ArgIdx = 0; ArgIdx != ArgTys.size(); ++ArgIdx) { QualType ParamTy = FD->getParamDecl(ArgIdx)->getType(); if (!Context.hasSameUnqualifiedType(ArgTys[ArgIdx], ParamTy)) { - IsExactMatch = false; + IsCooked = false; break; } } @@ -3367,29 +3382,59 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, } if (FunctionTemplateDecl *FD = dyn_cast<FunctionTemplateDecl>(D)) { TemplateParameterList *Params = FD->getTemplateParameters(); - if (Params->size() == 1) + if (Params->size() == 1) { IsTemplate = true; - else - IsStringTemplate = true; + if (!Params->getParam(0)->isTemplateParameterPack() && !StringLit) { + // Implied but not stated: user-defined integer and floating literals + // only ever use numeric literal operator templates, not templates + // taking a parameter of class type. + F.erase(); + continue; + } + + // A string literal template is only considered if the string literal + // is a well-formed template argument for the template parameter. + if (StringLit) { + SFINAETrap Trap(*this); + SmallVector<TemplateArgument, 1> Checked; + TemplateArgumentLoc Arg(TemplateArgument(StringLit), StringLit); + if (CheckTemplateArgument(Params->getParam(0), Arg, FD, + R.getNameLoc(), R.getNameLoc(), 0, + Checked) || + Trap.hasErrorOccurred()) + IsTemplate = false; + } + } else { + IsStringTemplatePack = true; + } } - if (IsExactMatch) { - FoundExactMatch = true; + if (AllowTemplate && StringLit && IsTemplate) { + FoundTemplate = true; AllowRaw = false; - AllowTemplate = false; - AllowStringTemplate = false; - if (FoundRaw || FoundTemplate || FoundStringTemplate) { + AllowCooked = false; + AllowStringTemplatePack = false; + if (FoundRaw || FoundCooked || FoundStringTemplatePack) { + F.restart(); + FoundRaw = FoundCooked = FoundStringTemplatePack = false; + } + } else if (AllowCooked && IsCooked) { + FoundCooked = true; + AllowRaw = false; + AllowTemplate = StringLit; + AllowStringTemplatePack = false; + if (FoundRaw || FoundTemplate || FoundStringTemplatePack) { // Go through again and remove the raw and template decls we've // already found. F.restart(); - FoundRaw = FoundTemplate = FoundStringTemplate = false; + FoundRaw = FoundTemplate = FoundStringTemplatePack = false; } } else if (AllowRaw && IsRaw) { FoundRaw = true; } else if (AllowTemplate && IsTemplate) { FoundTemplate = true; - } else if (AllowStringTemplate && IsStringTemplate) { - FoundStringTemplate = true; + } else if (AllowStringTemplatePack && IsStringTemplatePack) { + FoundStringTemplatePack = true; } else { F.erase(); } @@ -3397,10 +3442,15 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, F.done(); + // Per C++20 [lex.ext]p5, we prefer the template form over the non-template + // form for string literal operator templates. + if (StringLit && FoundTemplate) + return LOLR_Template; + // C++11 [lex.ext]p3, p4: If S contains a literal operator with a matching // parameter type, that is used in preference to a raw literal operator // or literal operator template. - if (FoundExactMatch) + if (FoundCooked) return LOLR_Cooked; // C++11 [lex.ext]p3, p4: S shall contain a raw literal operator or a literal @@ -3418,15 +3468,15 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, if (FoundTemplate) return LOLR_Template; - if (FoundStringTemplate) - return LOLR_StringTemplate; + if (FoundStringTemplatePack) + return LOLR_StringTemplatePack; // Didn't find anything we could use. if (DiagnoseMissing) { Diag(R.getNameLoc(), diag::err_ovl_no_viable_literal_operator) << R.getLookupName() << (int)ArgTys.size() << ArgTys[0] << (ArgTys.size() == 2 ? ArgTys[1] : QualType()) << AllowRaw - << (AllowTemplate || AllowStringTemplate); + << (AllowTemplate || AllowStringTemplatePack); return LOLR_Error; } diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp index 10de0ca91221..af95b1a93cc4 100644 --- a/clang/lib/Sema/SemaModule.cpp +++ b/clang/lib/Sema/SemaModule.cpp @@ -187,7 +187,7 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, Diag(Path[0].second, diag::err_module_redefinition) << ModuleName; if (M->DefinitionLoc.isValid()) Diag(M->DefinitionLoc, diag::note_prev_module_definition); - else if (const auto *FE = M->getASTFile()) + else if (Optional<FileEntryRef> FE = M->getASTFile()) Diag(M->DefinitionLoc, diag::note_prev_module_definition_from_ast_file) << FE->getName(); Mod = M; diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index e301c62dd2c0..fdc30fe6f657 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -1464,10 +1464,9 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, DeclRefExpr(Context, SelfDecl, false, SelfDecl->getType(), VK_LValue, PropertyDiagLoc); MarkDeclRefReferenced(SelfExpr); - Expr *LoadSelfExpr = - ImplicitCastExpr::Create(Context, SelfDecl->getType(), - CK_LValueToRValue, SelfExpr, nullptr, - VK_RValue); + Expr *LoadSelfExpr = ImplicitCastExpr::Create( + Context, SelfDecl->getType(), CK_LValueToRValue, SelfExpr, nullptr, + VK_RValue, FPOptionsOverride()); Expr *IvarRefExpr = new (Context) ObjCIvarRefExpr(Ivar, Ivar->getUsageType(SelfDecl->getType()), @@ -1528,10 +1527,9 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, DeclRefExpr(Context, SelfDecl, false, SelfDecl->getType(), VK_LValue, PropertyDiagLoc); MarkDeclRefReferenced(SelfExpr); - Expr *LoadSelfExpr = - ImplicitCastExpr::Create(Context, SelfDecl->getType(), - CK_LValueToRValue, SelfExpr, nullptr, - VK_RValue); + Expr *LoadSelfExpr = ImplicitCastExpr::Create( + Context, SelfDecl->getType(), CK_LValueToRValue, SelfExpr, nullptr, + VK_RValue, FPOptionsOverride()); Expr *lhs = new (Context) ObjCIvarRefExpr(Ivar, Ivar->getUsageType(SelfDecl->getType()), diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 920463da4027..78707484f588 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -35,6 +35,7 @@ #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/PointerEmbeddedInt.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Frontend/OpenMP/OMPConstants.h" #include <set> @@ -48,7 +49,7 @@ using namespace llvm::omp; static const Expr *checkMapClauseExpressionBase( Sema &SemaRef, Expr *E, OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, - OpenMPClauseKind CKind, bool NoDiagnose); + OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose); namespace { /// Default data sharing attributes, which can be applied to directive. @@ -70,12 +71,15 @@ public: const Expr *RefExpr = nullptr; DeclRefExpr *PrivateCopy = nullptr; SourceLocation ImplicitDSALoc; + bool AppliedToPointee = false; DSAVarData() = default; DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, const Expr *RefExpr, DeclRefExpr *PrivateCopy, - SourceLocation ImplicitDSALoc, unsigned Modifier) + SourceLocation ImplicitDSALoc, unsigned Modifier, + bool AppliedToPointee) : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr), - PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc) {} + PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc), + AppliedToPointee(AppliedToPointee) {} }; using OperatorOffsetTy = llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>; @@ -99,6 +103,9 @@ private: /// variable is marked as lastprivate(true) or not (false). llvm::PointerIntPair<const Expr *, 1, bool> RefExpr; DeclRefExpr *PrivateCopy = nullptr; + /// true if the attribute is applied to the pointee, not the variable + /// itself. + bool AppliedToPointee = false; }; using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>; using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>; @@ -153,6 +160,7 @@ private: OpenMPDirectiveKind Directive = OMPD_unknown; DeclarationNameInfo DirectiveName; Scope *CurScope = nullptr; + DeclContext *Context = nullptr; SourceLocation ConstructLoc; /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to /// get the data (loop counters etc.) about enclosing loop-based construct. @@ -184,6 +192,7 @@ private: llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective; llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind> UsesAllocatorsDecls; + Expr *DeclareMapperVar = nullptr; SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name, Scope *CurScope, SourceLocation Loc) : Directive(DKind), DirectiveName(Name), CurScope(CurScope), @@ -510,7 +519,8 @@ public: /// Adds explicit data sharing attribute to the specified declaration. void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A, - DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0); + DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0, + bool AppliedToPointee = false); /// Adds additional information for the reduction items with the reduction id /// represented as an operator. @@ -562,7 +572,8 @@ public: /// match specified \a CPred predicate in any directive which matches \a DPred /// predicate. const DSAVarData - hasDSA(ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> CPred, + hasDSA(ValueDecl *D, + const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred, const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, bool FromParent) const; /// Checks if the specified variables has data-sharing attributes which @@ -570,15 +581,16 @@ public: /// matches \a DPred predicate. const DSAVarData hasInnermostDSA(ValueDecl *D, - const llvm::function_ref<bool(OpenMPClauseKind)> CPred, + const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred, const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, bool FromParent) const; /// Checks if the specified variables has explicit data-sharing /// attributes which match specified \a CPred predicate at the specified /// OpenMP region. - bool hasExplicitDSA(const ValueDecl *D, - const llvm::function_ref<bool(OpenMPClauseKind)> CPred, - unsigned Level, bool NotLastprivate = false) const; + bool + hasExplicitDSA(const ValueDecl *D, + const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred, + unsigned Level, bool NotLastprivate = false) const; /// Returns true if the directive at level \Level matches in the /// specified \a DPred predicate. @@ -908,6 +920,7 @@ public: const SharingMapTy *Top = getTopOfStackOrNull(); return Top ? Top->CurScope : nullptr; } + void setContext(DeclContext *DC) { getTopOfStack().Context = DC; } SourceLocation getConstructLoc() const { const SharingMapTy *Top = getTopOfStackOrNull(); return Top ? Top->ConstructLoc : SourceLocation(); @@ -1072,6 +1085,15 @@ public: return None; return I->getSecond(); } + + void addDeclareMapperVarRef(Expr *Ref) { + SharingMapTy &StackElem = getTopOfStack(); + StackElem.DeclareMapperVar = Ref; + } + const Expr *getDeclareMapperVarRef() const { + const SharingMapTy *Top = getTopOfStackOrNull(); + return Top ? Top->DeclareMapperVar : nullptr; + } }; bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) { @@ -1175,6 +1197,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter, DVar.CKind = Data.Attributes; DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; DVar.Modifier = Data.Modifier; + DVar.AppliedToPointee = Data.AppliedToPointee; return DVar; } @@ -1331,7 +1354,8 @@ const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const { } void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A, - DeclRefExpr *PrivateCopy, unsigned Modifier) { + DeclRefExpr *PrivateCopy, unsigned Modifier, + bool AppliedToPointee) { D = getCanonicalDecl(D); if (A == OMPC_threadprivate) { DSAInfo &Data = Threadprivates[D]; @@ -1355,12 +1379,14 @@ void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A, Data.Attributes = A; Data.RefExpr.setPointerAndInt(E, IsLastprivate); Data.PrivateCopy = PrivateCopy; + Data.AppliedToPointee = AppliedToPointee; if (PrivateCopy) { DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()]; Data.Modifier = Modifier; Data.Attributes = A; Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate); Data.PrivateCopy = nullptr; + Data.AppliedToPointee = AppliedToPointee; } } } @@ -1470,7 +1496,8 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData( "set."); TaskgroupDescriptor = I->TaskgroupReductionRef; return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(), - Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task); + Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task, + /*AppliedToPointee=*/false); } return DSAVarData(); } @@ -1496,7 +1523,8 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData( "set."); TaskgroupDescriptor = I->TaskgroupReductionRef; return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(), - Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task); + Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task, + /*AppliedToPointee=*/false); } return DSAVarData(); } @@ -1506,11 +1534,17 @@ bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const { for (const_iterator E = end(); I != E; ++I) { if (isImplicitOrExplicitTaskingRegion(I->Directive) || isOpenMPTargetExecutionDirective(I->Directive)) { - Scope *TopScope = I->CurScope ? I->CurScope->getParent() : nullptr; - Scope *CurScope = getCurScope(); - while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D)) - CurScope = CurScope->getParent(); - return CurScope != TopScope; + if (I->CurScope) { + Scope *TopScope = I->CurScope->getParent(); + Scope *CurScope = getCurScope(); + while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D)) + CurScope = CurScope->getParent(); + return CurScope != TopScope; + } + for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent()) + if (I->Context == DC) + return true; + return false; } } return false; @@ -1665,6 +1699,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, DVar.ImplicitDSALoc = I->DefaultAttrLoc; DVar.DKind = I->Directive; DVar.Modifier = Data.Modifier; + DVar.AppliedToPointee = Data.AppliedToPointee; return DVar; } } @@ -1686,7 +1721,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, // listed in a firstprivate clause, even if they are static data members. DSAVarData DVarTemp = hasInnermostDSA( D, - [](OpenMPClauseKind C) { + [](OpenMPClauseKind C, bool) { return C == OMPC_firstprivate || C == OMPC_shared; }, MatchesAlways, FromParent); @@ -1715,6 +1750,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, DVar.ImplicitDSALoc = I->DefaultAttrLoc; DVar.DKind = I->Directive; DVar.Modifier = Data.Modifier; + DVar.AppliedToPointee = Data.AppliedToPointee; } return DVar; @@ -1745,7 +1781,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D, const DSAStackTy::DSAVarData DSAStackTy::hasDSA(ValueDecl *D, - const llvm::function_ref<bool(OpenMPClauseKind)> CPred, + const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred, const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, bool FromParent) const { if (isStackEmpty()) @@ -1761,14 +1797,14 @@ DSAStackTy::hasDSA(ValueDecl *D, continue; const_iterator NewI = I; DSAVarData DVar = getDSA(NewI, D); - if (I == NewI && CPred(DVar.CKind)) + if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee)) return DVar; } return {}; } const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA( - ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> CPred, + ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred, const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, bool FromParent) const { if (isStackEmpty()) @@ -1782,26 +1818,28 @@ const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA( return {}; const_iterator NewI = StartI; DSAVarData DVar = getDSA(NewI, D); - return (NewI == StartI && CPred(DVar.CKind)) ? DVar : DSAVarData(); + return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee)) + ? DVar + : DSAVarData(); } bool DSAStackTy::hasExplicitDSA( - const ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> CPred, + const ValueDecl *D, + const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred, unsigned Level, bool NotLastprivate) const { if (getStackSize() <= Level) return false; D = getCanonicalDecl(D); const SharingMapTy &StackElem = getStackElemAtLevel(Level); auto I = StackElem.SharingMap.find(D); - if (I != StackElem.SharingMap.end() && - I->getSecond().RefExpr.getPointer() && - CPred(I->getSecond().Attributes) && + if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() && + CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) && (!NotLastprivate || !I->getSecond().RefExpr.getInt())) return true; // Check predetermined rules for the loop control variables. auto LI = StackElem.LCVMap.find(D); if (LI != StackElem.LCVMap.end()) - return CPred(OMPC_private); + return CPred(OMPC_private, /*AppliedToPointee=*/false); return false; } @@ -1859,27 +1897,27 @@ enum class FunctionEmissionStatus { }; } // anonymous namespace -Sema::DeviceDiagBuilder Sema::diagIfOpenMPDeviceCode(SourceLocation Loc, - unsigned DiagID) { +Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPDeviceCode(SourceLocation Loc, + unsigned DiagID) { assert(LangOpts.OpenMP && LangOpts.OpenMPIsDevice && "Expected OpenMP device compilation."); FunctionDecl *FD = getCurFunctionDecl(); - DeviceDiagBuilder::Kind Kind = DeviceDiagBuilder::K_Nop; + SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop; if (FD) { FunctionEmissionStatus FES = getEmissionStatus(FD); switch (FES) { case FunctionEmissionStatus::Emitted: - Kind = DeviceDiagBuilder::K_Immediate; + Kind = SemaDiagnosticBuilder::K_Immediate; break; case FunctionEmissionStatus::Unknown: Kind = isOpenMPDeviceDelayedContext(*this) - ? DeviceDiagBuilder::K_Deferred - : DeviceDiagBuilder::K_Immediate; + ? SemaDiagnosticBuilder::K_Deferred + : SemaDiagnosticBuilder::K_Immediate; break; case FunctionEmissionStatus::TemplateDiscarded: case FunctionEmissionStatus::OMPDiscarded: - Kind = DeviceDiagBuilder::K_Nop; + Kind = SemaDiagnosticBuilder::K_Nop; break; case FunctionEmissionStatus::CUDADiscarded: llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation"); @@ -1887,30 +1925,30 @@ Sema::DeviceDiagBuilder Sema::diagIfOpenMPDeviceCode(SourceLocation Loc, } } - return DeviceDiagBuilder(Kind, Loc, DiagID, getCurFunctionDecl(), *this); + return SemaDiagnosticBuilder(Kind, Loc, DiagID, getCurFunctionDecl(), *this); } -Sema::DeviceDiagBuilder Sema::diagIfOpenMPHostCode(SourceLocation Loc, - unsigned DiagID) { +Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPHostCode(SourceLocation Loc, + unsigned DiagID) { assert(LangOpts.OpenMP && !LangOpts.OpenMPIsDevice && "Expected OpenMP host compilation."); FunctionEmissionStatus FES = getEmissionStatus(getCurFunctionDecl()); - DeviceDiagBuilder::Kind Kind = DeviceDiagBuilder::K_Nop; + SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop; switch (FES) { case FunctionEmissionStatus::Emitted: - Kind = DeviceDiagBuilder::K_Immediate; + Kind = SemaDiagnosticBuilder::K_Immediate; break; case FunctionEmissionStatus::Unknown: - Kind = DeviceDiagBuilder::K_Deferred; + Kind = SemaDiagnosticBuilder::K_Deferred; break; case FunctionEmissionStatus::TemplateDiscarded: case FunctionEmissionStatus::OMPDiscarded: case FunctionEmissionStatus::CUDADiscarded: - Kind = DeviceDiagBuilder::K_Nop; + Kind = SemaDiagnosticBuilder::K_Nop; break; } - return DeviceDiagBuilder(Kind, Loc, DiagID, getCurFunctionDecl(), *this); + return SemaDiagnosticBuilder(Kind, Loc, DiagID, getCurFunctionDecl(), *this); } static OpenMPDefaultmapClauseKind @@ -2047,14 +2085,17 @@ bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, // By default, all the data that has a scalar type is mapped by copy // (except for reduction variables). // Defaultmap scalar is mutual exclusive to defaultmap pointer - IsByRef = - (DSAStack->isForceCaptureByReferenceInTargetExecutable() && - !Ty->isAnyPointerType()) || - !Ty->isScalarType() || - DSAStack->isDefaultmapCapturedByRef( - Level, getVariableCategoryFromDecl(LangOpts, D)) || - DSAStack->hasExplicitDSA( - D, [](OpenMPClauseKind K) { return K == OMPC_reduction; }, Level); + IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() && + !Ty->isAnyPointerType()) || + !Ty->isScalarType() || + DSAStack->isDefaultmapCapturedByRef( + Level, getVariableCategoryFromDecl(LangOpts, D)) || + DSAStack->hasExplicitDSA( + D, + [](OpenMPClauseKind K, bool AppliedToPointee) { + return K == OMPC_reduction && !AppliedToPointee; + }, + Level); } } @@ -2065,8 +2106,9 @@ bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, OMPD_target) || !(DSAStack->hasExplicitDSA( D, - [](OpenMPClauseKind K) -> bool { - return K == OMPC_firstprivate; + [](OpenMPClauseKind K, bool AppliedToPointee) -> bool { + return K == OMPC_firstprivate || + (K == OMPC_reduction && AppliedToPointee); }, Level, /*NotLastprivate=*/true) || DSAStack->isUsesAllocatorsDecl(Level, D))) && @@ -2078,7 +2120,8 @@ bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, // copy !(DSAStack->getDefaultDSA() == DSA_firstprivate && !DSAStack->hasExplicitDSA( - D, [](OpenMPClauseKind K) { return K != OMPC_unknown; }, Level) && + D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; }, + Level) && !DSAStack->isLoopControlVariable(D, Level).first); } @@ -2141,7 +2184,8 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo, !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) checkDeclIsAllowedInOpenMPTarget(nullptr, VD); return nullptr; - } else if (isInOpenMPTargetExecutionDirective()) { + } + if (isInOpenMPTargetExecutionDirective()) { // If the declaration is enclosed in a 'declare target' directive, // then it should not be captured. // @@ -2159,6 +2203,7 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo, break; } } + assert(CSI && "Failed to find CapturedRegionScopeInfo"); SmallVector<OpenMPDirectiveKind, 4> Regions; getOpenMPCaptureRegions(Regions, DSAStack->getDirective(CSI->OpenMPLevel)); @@ -2194,7 +2239,8 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo, return VD ? VD : Info.second; DSAStackTy::DSAVarData DVarTop = DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode()); - if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind)) + if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) && + (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee)) return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl()); // Threadprivate variables must not be captured. if (isOpenMPThreadPrivate(DVarTop.CKind)) @@ -2202,7 +2248,11 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo, // The variable is not private or it is the variable in the directive with // default(none) clause and not used in any clause. DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA( - D, isOpenMPPrivate, [](OpenMPDirectiveKind) { return true; }, + D, + [](OpenMPClauseKind C, bool AppliedToPointee) { + return isOpenMPPrivate(C) && !AppliedToPointee; + }, + [](OpenMPDirectiveKind) { return true; }, DSAStack->isClauseParsingMode()); // Global shared must not be captured. if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown && @@ -2244,7 +2294,11 @@ OpenMPClauseKind Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, [](OpenMPDirectiveKind K) { return isOpenMPTaskingDirective(K); }, Level)) { bool IsTriviallyCopyable = - D->getType().getNonReferenceType().isTriviallyCopyableType(Context); + D->getType().getNonReferenceType().isTriviallyCopyableType(Context) && + !D->getType() + .getNonReferenceType() + .getCanonicalType() + ->getAsCXXRecordDecl(); OpenMPDirectiveKind DKind = DSAStack->getDirective(Level); SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; getOpenMPCaptureRegions(CaptureRegions, DKind); @@ -2252,7 +2306,8 @@ OpenMPClauseKind Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, (IsTriviallyCopyable || !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) { if (DSAStack->hasExplicitDSA( - D, [](OpenMPClauseKind K) { return K == OMPC_firstprivate; }, + D, + [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; }, Level, /*NotLastprivate=*/true)) return OMPC_firstprivate; DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level); @@ -2273,7 +2328,8 @@ OpenMPClauseKind Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, if ((DSAStack->getPossiblyLoopCunter() == D->getCanonicalDecl() || DSAStack->isLoopControlVariable(D).first) && !DSAStack->hasExplicitDSA( - D, [](OpenMPClauseKind K) { return K != OMPC_private; }, Level) && + D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; }, + Level) && !isOpenMPSimdDirective(DSAStack->getCurrentDirective())) return OMPC_private; } @@ -2281,7 +2337,8 @@ OpenMPClauseKind Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) && DSAStack->isForceVarCapturing() && !DSAStack->hasExplicitDSA( - D, [](OpenMPClauseKind K) { return K == OMPC_copyin; }, Level)) + D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; }, + Level)) return OMPC_private; } // User-defined allocators are private since they must be defined in the @@ -2292,7 +2349,8 @@ OpenMPClauseKind Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator) return OMPC_private; return (DSAStack->hasExplicitDSA( - D, [](OpenMPClauseKind K) { return K == OMPC_private; }, Level) || + D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; }, + Level) || (DSAStack->isClauseParsingMode() && DSAStack->getClauseParsingMode() == OMPC_private) || // Consider taskgroup reduction descriptor variable a private @@ -2317,15 +2375,16 @@ void Sema::setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D, OpenMPClauseKind OMPC = OMPC_unknown; for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) { const unsigned NewLevel = I - 1; - if (DSAStack->hasExplicitDSA(D, - [&OMPC](const OpenMPClauseKind K) { - if (isOpenMPPrivate(K)) { - OMPC = K; - return true; - } - return false; - }, - NewLevel)) + if (DSAStack->hasExplicitDSA( + D, + [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) { + if (isOpenMPPrivate(K) && !AppliedToPointee) { + OMPC = K; + return true; + } + return false; + }, + NewLevel)) break; if (DSAStack->checkMappableExprComponentListsForDeclAtLevel( D, NewLevel, @@ -2368,17 +2427,20 @@ bool Sema::isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level, if (const auto *VD = dyn_cast<VarDecl>(D)) { if (!VD->hasLocalStorage()) { + if (isInOpenMPTargetExecutionDirective()) + return true; DSAStackTy::DSAVarData TopDVar = DSAStack->getTopDSA(D, /*FromParent=*/false); unsigned NumLevels = getOpenMPCaptureLevels(DSAStack->getDirective(Level)); if (Level == 0) return (NumLevels == CaptureLevel + 1) && TopDVar.CKind != OMPC_shared; - DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level - 1); - return DVar.CKind != OMPC_shared || - isOpenMPGlobalCapturedDecl( - D, Level - 1, - getOpenMPCaptureLevels(DSAStack->getDirective(Level - 1)) - 1); + do { + --Level; + DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level); + if (DVar.CKind != OMPC_shared) + return true; + } while (Level > 0); } } return true; @@ -2388,10 +2450,6 @@ void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; } void Sema::ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI) { - if (!OMPDeclareVariantScopes.empty()) { - Diag(Loc, diag::warn_nested_declare_variant); - return; - } OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI)); } @@ -2424,7 +2482,7 @@ void Sema::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, StringRef HostDevTy = getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host); Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0; - Diag(FD->getAttr<OMPDeclareTargetDeclAttr>()->getLocation(), + Diag(*OMPDeclareTargetDeclAttr::getLocation(FD), diag::note_omp_marked_device_type_here) << HostDevTy; return; @@ -2435,7 +2493,7 @@ void Sema::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName( OMPC_device_type, OMPC_DEVICE_TYPE_nohost); Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1; - Diag(FD->getAttr<OMPDeclareTargetDeclAttr>()->getLocation(), + Diag(*OMPDeclareTargetDeclAttr::getLocation(FD), diag::note_omp_marked_device_type_here) << NoHostDevTy; } @@ -3138,6 +3196,64 @@ Sema::ActOnOpenMPRequiresDirective(SourceLocation Loc, return DeclGroupPtrTy::make(DeclGroupRef(D)); } +void Sema::ActOnOpenMPAssumesDirective(SourceLocation Loc, + OpenMPDirectiveKind DKind, + ArrayRef<StringRef> Assumptions, + bool SkippedClauses) { + if (!SkippedClauses && Assumptions.empty()) + Diag(Loc, diag::err_omp_no_clause_for_directive) + << llvm::omp::getAllAssumeClauseOptions() + << llvm::omp::getOpenMPDirectiveName(DKind); + + auto *AA = AssumptionAttr::Create(Context, llvm::join(Assumptions, ","), Loc); + if (DKind == llvm::omp::Directive::OMPD_begin_assumes) { + OMPAssumeScoped.push_back(AA); + return; + } + + // Global assumes without assumption clauses are ignored. + if (Assumptions.empty()) + return; + + assert(DKind == llvm::omp::Directive::OMPD_assumes && + "Unexpected omp assumption directive!"); + OMPAssumeGlobal.push_back(AA); + + // The OMPAssumeGlobal scope above will take care of new declarations but + // we also want to apply the assumption to existing ones, e.g., to + // declarations in included headers. To this end, we traverse all existing + // declaration contexts and annotate function declarations here. + SmallVector<DeclContext *, 8> DeclContexts; + auto *Ctx = CurContext; + while (Ctx->getLexicalParent()) + Ctx = Ctx->getLexicalParent(); + DeclContexts.push_back(Ctx); + while (!DeclContexts.empty()) { + DeclContext *DC = DeclContexts.pop_back_val(); + for (auto *SubDC : DC->decls()) { + if (SubDC->isInvalidDecl()) + continue; + if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) { + DeclContexts.push_back(CTD->getTemplatedDecl()); + for (auto *S : CTD->specializations()) + DeclContexts.push_back(S); + continue; + } + if (auto *DC = dyn_cast<DeclContext>(SubDC)) + DeclContexts.push_back(DC); + if (auto *F = dyn_cast<FunctionDecl>(SubDC)) { + F->addAttr(AA); + continue; + } + } + } +} + +void Sema::ActOnOpenMPEndAssumesDirective() { + assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!"); + OMPAssumeScoped.pop_back(); +} + OMPRequiresDecl *Sema::CheckOMPRequiresDecl(SourceLocation Loc, ArrayRef<OMPClause *> ClauseList) { /// For target specific clauses, the requires directive cannot be @@ -3249,6 +3365,14 @@ getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M, case OMPC_DEFAULTMAP_MODIFIER_tofrom: Kind = OMPC_MAP_tofrom; break; + case OMPC_DEFAULTMAP_MODIFIER_present: + // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description] + // If implicit-behavior is present, each variable referenced in the + // construct in the category specified by variable-category is treated as if + // it had been listed in a map clause with the map-type of alloc and + // map-type-modifier of present. + Kind = OMPC_MAP_alloc; + break; case OMPC_DEFAULTMAP_MODIFIER_firstprivate: case OMPC_DEFAULTMAP_MODIFIER_last: llvm_unreachable("Unexpected defaultmap implicit behavior"); @@ -3275,8 +3399,11 @@ class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> { bool ErrorFound = false; bool TryCaptureCXXThisMembers = false; CapturedStmt *CS = nullptr; + const static unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_pointer + 1; llvm::SmallVector<Expr *, 4> ImplicitFirstprivate; - llvm::SmallVector<Expr *, 4> ImplicitMap[OMPC_MAP_delete]; + llvm::SmallVector<Expr *, 4> ImplicitMap[DefaultmapKindNum][OMPC_MAP_delete]; + llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers> + ImplicitMapModifier[DefaultmapKindNum]; Sema::VarsWithInheritedDSAType VarsWithInheritedDSA; llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations; @@ -3284,6 +3411,13 @@ class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> { // Check implicitly captured variables. if (!S->hasAssociatedStmt() || !S->getAssociatedStmt()) return; + if (S->getDirectiveKind() == OMPD_atomic || + S->getDirectiveKind() == OMPD_critical || + S->getDirectiveKind() == OMPD_section || + S->getDirectiveKind() == OMPD_master) { + Visit(S->getAssociatedStmt()); + return; + } visitSubCaptures(S->getInnermostCapturedStmt()); // Try to capture inner this->member references to generate correct mappings // and diagnostics. @@ -3405,6 +3539,18 @@ public: } } } + if (SemaRef.getLangOpts().OpenMP > 50) { + bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) == + OMPC_DEFAULTMAP_MODIFIER_present; + if (IsModifierPresent) { + if (llvm::find(ImplicitMapModifier[ClauseKind], + OMPC_MAP_MODIFIER_present) == + std::end(ImplicitMapModifier[ClauseKind])) { + ImplicitMapModifier[ClauseKind].push_back( + OMPC_MAP_MODIFIER_present); + } + } + } if (isOpenMPTargetExecutionDirective(DKind) && !Stack->isLoopControlVariable(VD).first) { @@ -3445,7 +3591,7 @@ public: Stack->getDefaultmapModifier(ClauseKind); OpenMPMapClauseKind Kind = getMapClauseKindFromModifier( M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res); - ImplicitMap[Kind].emplace_back(E); + ImplicitMap[ClauseKind][Kind].emplace_back(E); } return; } @@ -3456,7 +3602,10 @@ public: // enclosing worksharing or parallel construct may not be accessed in an // explicit task. DVar = Stack->hasInnermostDSA( - VD, [](OpenMPClauseKind C) { return C == OMPC_reduction; }, + VD, + [](OpenMPClauseKind C, bool AppliedToPointee) { + return C == OMPC_reduction && !AppliedToPointee; + }, [](OpenMPDirectiveKind K) { return isOpenMPParallelDirective(K) || isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K); @@ -3529,9 +3678,11 @@ public: OpenMPDefaultmapClauseModifier Modifier = Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate); + OpenMPDefaultmapClauseKind ClauseKind = + getVariableCategoryFromDecl(SemaRef.getLangOpts(), FD); OpenMPMapClauseKind Kind = getMapClauseKindFromModifier( Modifier, /*IsAggregateOrDeclareTarget*/ true); - ImplicitMap[Kind].emplace_back(E); + ImplicitMap[ClauseKind][Kind].emplace_back(E); return; } @@ -3541,7 +3692,10 @@ public: // enclosing worksharing or parallel construct may not be accessed in // an explicit task. DVar = Stack->hasInnermostDSA( - FD, [](OpenMPClauseKind C) { return C == OMPC_reduction; }, + FD, + [](OpenMPClauseKind C, bool AppliedToPointee) { + return C == OMPC_reduction && !AppliedToPointee; + }, [](OpenMPDirectiveKind K) { return isOpenMPParallelDirective(K) || isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K); @@ -3570,6 +3724,7 @@ public: if (isOpenMPTargetExecutionDirective(DKind)) { OMPClauseMappableExprCommon::MappableExprComponentList CurComponents; if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map, + Stack->getCurrentDirective(), /*NoDiagnose=*/true)) return; const auto *VD = cast<ValueDecl>( @@ -3619,7 +3774,8 @@ public: // Skip analysis of arguments of implicitly defined map clause for target // directives. if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) && - C->isImplicit())) { + C->isImplicit() && + !isOpenMPTaskingDirective(Stack->getCurrentDirective()))) { for (Stmt *CC : C->children()) { if (CC) Visit(CC); @@ -3662,8 +3818,13 @@ public: ArrayRef<Expr *> getImplicitFirstprivate() const { return ImplicitFirstprivate; } - ArrayRef<Expr *> getImplicitMap(OpenMPDefaultmapClauseKind Kind) const { - return ImplicitMap[Kind]; + ArrayRef<Expr *> getImplicitMap(OpenMPDefaultmapClauseKind DK, + OpenMPMapClauseKind MK) const { + return ImplicitMap[DK][MK]; + } + ArrayRef<OpenMPMapModifierKind> + getImplicitMapModifier(OpenMPDefaultmapClauseKind Kind) const { + return ImplicitMapModifier[Kind]; } const Sema::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const { return VarsWithInheritedDSA; @@ -3784,19 +3945,20 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { /*OpenMPCaptureLevel=*/1); break; } + case OMPD_atomic: + case OMPD_critical: + case OMPD_section: + case OMPD_master: + break; case OMPD_simd: case OMPD_for: case OMPD_for_simd: case OMPD_sections: - case OMPD_section: case OMPD_single: - case OMPD_master: - case OMPD_critical: case OMPD_taskgroup: case OMPD_distribute: case OMPD_distribute_simd: case OMPD_ordered: - case OMPD_atomic: case OMPD_target_data: { Sema::CapturedParamNameType Params[] = { std::make_pair(StringRef(), QualType()) // __context with shared vars @@ -4088,6 +4250,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { default: llvm_unreachable("Unknown OpenMP directive"); } + DSAStack->setContext(CurContext); } int Sema::getNumberOfConstructScopes(unsigned Level) const { @@ -4125,6 +4288,7 @@ static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id, if (!WithInit) CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C)); S.CurContext->addHiddenDecl(CED); + Sema::TentativeAnalysisScope Trap(S); S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false); return CED; } @@ -4262,6 +4426,12 @@ static bool checkOrderedOrderSpecified(Sema &S, StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S, ArrayRef<OMPClause *> Clauses) { + if (DSAStack->getCurrentDirective() == OMPD_atomic || + DSAStack->getCurrentDirective() == OMPD_critical || + DSAStack->getCurrentDirective() == OMPD_section || + DSAStack->getCurrentDirective() == OMPD_master) + return S; + bool ErrorFound = false; CaptureRegionUnwinderRAII CaptureRegionUnwinder( *this, ErrorFound, DSAStack->getCurrentDirective()); @@ -4975,7 +5145,8 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( VarsWithInheritedDSAType VarsWithInheritedDSA; bool ErrorFound = false; ClausesWithImplicit.append(Clauses.begin(), Clauses.end()); - if (AStmt && !CurContext->isDependentContext()) { + if (AStmt && !CurContext->isDependentContext() && Kind != OMPD_atomic && + Kind != OMPD_critical && Kind != OMPD_section && Kind != OMPD_master) { assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); // Check default data sharing attributes for referenced variables. @@ -5004,11 +5175,33 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( SmallVector<Expr *, 4> ImplicitFirstprivates( DSAChecker.getImplicitFirstprivate().begin(), DSAChecker.getImplicitFirstprivate().end()); - SmallVector<Expr *, 4> ImplicitMaps[OMPC_MAP_delete]; - for (unsigned I = 0; I < OMPC_MAP_delete; ++I) { - ArrayRef<Expr *> ImplicitMap = - DSAChecker.getImplicitMap(static_cast<OpenMPDefaultmapClauseKind>(I)); - ImplicitMaps[I].append(ImplicitMap.begin(), ImplicitMap.end()); + const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_pointer + 1; + SmallVector<Expr *, 4> ImplicitMaps[DefaultmapKindNum][OMPC_MAP_delete]; + SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers> + ImplicitMapModifiers[DefaultmapKindNum]; + SmallVector<SourceLocation, NumberOfOMPMapClauseModifiers> + ImplicitMapModifiersLoc[DefaultmapKindNum]; + // Get the original location of present modifier from Defaultmap clause. + SourceLocation PresentModifierLocs[DefaultmapKindNum]; + for (OMPClause *C : Clauses) { + if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C)) + if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present) + PresentModifierLocs[DMC->getDefaultmapKind()] = + DMC->getDefaultmapModifierLoc(); + } + for (unsigned VC = 0; VC < DefaultmapKindNum; ++VC) { + auto Kind = static_cast<OpenMPDefaultmapClauseKind>(VC); + for (unsigned I = 0; I < OMPC_MAP_delete; ++I) { + ArrayRef<Expr *> ImplicitMap = DSAChecker.getImplicitMap( + Kind, static_cast<OpenMPMapClauseKind>(I)); + ImplicitMaps[VC][I].append(ImplicitMap.begin(), ImplicitMap.end()); + } + ArrayRef<OpenMPMapModifierKind> ImplicitModifier = + DSAChecker.getImplicitMapModifier(Kind); + ImplicitMapModifiers[VC].append(ImplicitModifier.begin(), + ImplicitModifier.end()); + std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[VC]), + ImplicitModifier.size(), PresentModifierLocs[VC]); } // Mark taskgroup task_reduction descriptors as implicitly firstprivate. for (OMPClause *C : Clauses) { @@ -5034,23 +5227,26 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( ErrorFound = true; } } - int ClauseKindCnt = -1; - for (ArrayRef<Expr *> ImplicitMap : ImplicitMaps) { - ++ClauseKindCnt; - if (ImplicitMap.empty()) - continue; - CXXScopeSpec MapperIdScopeSpec; - DeclarationNameInfo MapperId; - auto Kind = static_cast<OpenMPMapClauseKind>(ClauseKindCnt); - if (OMPClause *Implicit = ActOnOpenMPMapClause( - llvm::None, llvm::None, MapperIdScopeSpec, MapperId, Kind, - /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), - ImplicitMap, OMPVarListLocTy())) { - ClausesWithImplicit.emplace_back(Implicit); - ErrorFound |= - cast<OMPMapClause>(Implicit)->varlist_size() != ImplicitMap.size(); - } else { - ErrorFound = true; + for (unsigned I = 0, E = DefaultmapKindNum; I < E; ++I) { + int ClauseKindCnt = -1; + for (ArrayRef<Expr *> ImplicitMap : ImplicitMaps[I]) { + ++ClauseKindCnt; + if (ImplicitMap.empty()) + continue; + CXXScopeSpec MapperIdScopeSpec; + DeclarationNameInfo MapperId; + auto Kind = static_cast<OpenMPMapClauseKind>(ClauseKindCnt); + if (OMPClause *Implicit = ActOnOpenMPMapClause( + ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I], + MapperIdScopeSpec, MapperId, Kind, /*IsMapTypeImplicit=*/true, + SourceLocation(), SourceLocation(), ImplicitMap, + OMPVarListLocTy())) { + ClausesWithImplicit.emplace_back(Implicit); + ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() != + ImplicitMap.size(); + } else { + ErrorFound = true; + } } } } @@ -5760,7 +5956,8 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective( NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step) .get(); if (NewStep) - NewStep = VerifyIntegerConstantExpression(NewStep).get(); + NewStep = + VerifyIntegerConstantExpression(NewStep, /*FIXME*/ AllowFold).get(); } NewSteps.push_back(NewStep); } @@ -5798,12 +5995,45 @@ static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto, FD->setParams(Params); } +void Sema::ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D) { + if (D->isInvalidDecl()) + return; + FunctionDecl *FD = nullptr; + if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D)) + FD = UTemplDecl->getTemplatedDecl(); + else + FD = cast<FunctionDecl>(D); + assert(FD && "Expected a function declaration!"); + + // If we are intantiating templates we do *not* apply scoped assumptions but + // only global ones. We apply scoped assumption to the template definition + // though. + if (!inTemplateInstantiation()) { + for (AssumptionAttr *AA : OMPAssumeScoped) + FD->addAttr(AA); + } + for (AssumptionAttr *AA : OMPAssumeGlobal) + FD->addAttr(AA); +} + Sema::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI) : TI(&TI), NameSuffix(TI.getMangledName()) {} -FunctionDecl * -Sema::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S, - Declarator &D) { +void Sema::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope( + Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists, + SmallVectorImpl<FunctionDecl *> &Bases) { + if (!D.getIdentifier()) + return; + + OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back(); + + // Template specialization is an extension, check if we do it. + bool IsTemplated = !TemplateParamLists.empty(); + if (IsTemplated & + !DVScope.TI->isExtensionActive( + llvm::omp::TraitProperty::implementation_extension_allow_templates)) + return; + IdentifierInfo *BaseII = D.getIdentifier(); LookupResult Lookup(*this, DeclarationName(BaseII), D.getIdentifierLoc(), LookupOrdinaryName); @@ -5812,12 +6042,18 @@ Sema::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S, TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); QualType FType = TInfo->getType(); - bool IsConstexpr = D.getDeclSpec().getConstexprSpecifier() == CSK_constexpr; - bool IsConsteval = D.getDeclSpec().getConstexprSpecifier() == CSK_consteval; + bool IsConstexpr = + D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr; + bool IsConsteval = + D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval; - FunctionDecl *BaseFD = nullptr; for (auto *Candidate : Lookup) { - auto *UDecl = dyn_cast<FunctionDecl>(Candidate->getUnderlyingDecl()); + auto *CandidateDecl = Candidate->getUnderlyingDecl(); + FunctionDecl *UDecl = nullptr; + if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) + UDecl = cast<FunctionTemplateDecl>(CandidateDecl)->getTemplatedDecl(); + else if (!IsTemplated) + UDecl = dyn_cast<FunctionDecl>(CandidateDecl); if (!UDecl) continue; @@ -5828,22 +6064,32 @@ Sema::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S, if (UDecl->isConsteval() && !IsConsteval) continue; - QualType NewType = Context.mergeFunctionTypes( - FType, UDecl->getType(), /* OfBlockPointer */ false, - /* Unqualified */ false, /* AllowCXX */ true); - if (NewType.isNull()) - continue; + QualType UDeclTy = UDecl->getType(); + if (!UDeclTy->isDependentType()) { + QualType NewType = Context.mergeFunctionTypes( + FType, UDeclTy, /* OfBlockPointer */ false, + /* Unqualified */ false, /* AllowCXX */ true); + if (NewType.isNull()) + continue; + } // Found a base! - BaseFD = UDecl; - break; - } - if (!BaseFD) { - BaseFD = cast<FunctionDecl>(ActOnDeclarator(S, D)); - BaseFD->setImplicit(true); + Bases.push_back(UDecl); + } + + bool UseImplicitBase = !DVScope.TI->isExtensionActive( + llvm::omp::TraitProperty::implementation_extension_disable_implicit_base); + // If no base was found we create a declaration that we use as base. + if (Bases.empty() && UseImplicitBase) { + D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration); + Decl *BaseD = HandleDeclarator(S, D, TemplateParamLists); + BaseD->setImplicit(true); + if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD)) + Bases.push_back(BaseTemplD->getTemplatedDecl()); + else + Bases.push_back(cast<FunctionDecl>(BaseD)); } - OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back(); std::string MangledName; MangledName += D.getIdentifier()->getName(); MangledName += getOpenMPVariantManglingSeparatorStr(); @@ -5852,17 +6098,21 @@ Sema::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S, VariantII.setMangledOpenMPVariantName(true); D.SetIdentifier(&VariantII, D.getBeginLoc()); - return BaseFD; } void Sema::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope( - FunctionDecl *FD, FunctionDecl *BaseFD) { + Decl *D, SmallVectorImpl<FunctionDecl *> &Bases) { // Do not mark function as is used to prevent its emission if this is the // only place where it is used. EnterExpressionEvaluationContext Unevaluated( *this, Sema::ExpressionEvaluationContext::Unevaluated); - Expr *VariantFuncRef = DeclRefExpr::Create( + FunctionDecl *FD = nullptr; + if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D)) + FD = UTemplDecl->getTemplatedDecl(); + else + FD = cast<FunctionDecl>(D); + auto *VariantFuncRef = DeclRefExpr::Create( Context, NestedNameSpecifierLoc(), SourceLocation(), FD, /* RefersToEnclosingVariableOrCapture */ false, /* NameLoc */ FD->getLocation(), FD->getType(), ExprValueKind::VK_RValue); @@ -5870,7 +6120,8 @@ void Sema::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope( OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back(); auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit( Context, VariantFuncRef, DVScope.TI); - BaseFD->addAttr(OMPDeclareVariantA); + for (FunctionDecl *BaseFD : Bases) + BaseFD->addAttr(OMPDeclareVariantA); } ExprResult Sema::ActOnOpenMPCall(ExprResult Call, Scope *Scope, @@ -5891,8 +6142,17 @@ ExprResult Sema::ActOnOpenMPCall(ExprResult Call, Scope *Scope, return Call; ASTContext &Context = getASTContext(); - OMPContext OMPCtx(getLangOpts().OpenMPIsDevice, - Context.getTargetInfo().getTriple()); + std::function<void(StringRef)> DiagUnknownTrait = [this, + CE](StringRef ISATrait) { + // TODO Track the selector locations in a way that is accessible here to + // improve the diagnostic location. + Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait) + << ISATrait; + }; + TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait), + getCurFunctionDecl()); + + QualType CalleeFnType = CalleeFnDecl->getType(); SmallVector<Expr *, 4> Exprs; SmallVector<VariantMatchInfo, 4> VMIs; @@ -5904,7 +6164,8 @@ ExprResult Sema::ActOnOpenMPCall(ExprResult Call, Scope *Scope, VariantMatchInfo VMI; OMPTraitInfo &TI = A->getTraitInfo(); TI.getAsVariantMatchInfo(Context, VMI); - if (!isVariantApplicableInContext(VMI, OMPCtx, /* DeviceSetOnly */ false)) + if (!isVariantApplicableInContext(VMI, OMPCtx, + /* DeviceSetOnly */ false)) continue; VMIs.push_back(VMI); @@ -5945,8 +6206,19 @@ ExprResult Sema::ActOnOpenMPCall(ExprResult Call, Scope *Scope, } NewCall = BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs, RParenLoc, ExecConfig); - if (NewCall.isUsable()) - break; + if (NewCall.isUsable()) { + if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) { + FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee(); + QualType NewType = Context.mergeFunctionTypes( + CalleeFnType, NewCalleeFnDecl->getType(), + /* OfBlockPointer */ false, + /* Unqualified */ false, /* AllowCXX */ true); + if (!NewType.isNull()) + break; + // Don't use the call if the function type was not compatible. + NewCall = nullptr; + } + } } VMIs.erase(VMIs.begin() + BestIdx); @@ -6027,8 +6299,7 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, // Deal with non-constant score and user condition expressions. auto HandleNonConstantScoresAndConditions = [this](Expr *&E, bool IsScore) -> bool { - llvm::APSInt Result; - if (!E || E->isIntegerConstantExpr(Result, Context)) + if (!E || E->isIntegerConstantExpr(Context)) return false; if (IsScore) { @@ -6051,7 +6322,7 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, // Convert VariantRef expression to the type of the original function to // resolve possible conflicts. - ExprResult VariantRefCast; + ExprResult VariantRefCast = VariantRef; if (LangOpts.CPlusPlus) { QualType FnPtrType; auto *Method = dyn_cast<CXXMethodDecl>(FD); @@ -6076,25 +6347,27 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, } else { FnPtrType = Context.getPointerType(FD->getType()); } - ImplicitConversionSequence ICS = - TryImplicitConversion(VariantRef, FnPtrType.getUnqualifiedType(), - /*SuppressUserConversions=*/false, - AllowedExplicit::None, - /*InOverloadResolution=*/false, - /*CStyle=*/false, - /*AllowObjCWritebackConversion=*/false); - if (ICS.isFailure()) { - Diag(VariantRef->getExprLoc(), - diag::err_omp_declare_variant_incompat_types) - << VariantRef->getType() - << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType()) - << VariantRef->getSourceRange(); - return None; + QualType VarianPtrType = Context.getPointerType(VariantRef->getType()); + if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) { + ImplicitConversionSequence ICS = TryImplicitConversion( + VariantRef, FnPtrType.getUnqualifiedType(), + /*SuppressUserConversions=*/false, AllowedExplicit::None, + /*InOverloadResolution=*/false, + /*CStyle=*/false, + /*AllowObjCWritebackConversion=*/false); + if (ICS.isFailure()) { + Diag(VariantRef->getExprLoc(), + diag::err_omp_declare_variant_incompat_types) + << VariantRef->getType() + << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType()) + << VariantRef->getSourceRange(); + return None; + } + VariantRefCast = PerformImplicitConversion( + VariantRef, FnPtrType.getUnqualifiedType(), AA_Converting); + if (!VariantRefCast.isUsable()) + return None; } - VariantRefCast = PerformImplicitConversion( - VariantRef, FnPtrType.getUnqualifiedType(), AA_Converting); - if (!VariantRefCast.isUsable()) - return None; // Drop previously built artificial addr_of unary op for member functions. if (Method && !Method->isStatic()) { Expr *PossibleAddrOfVariantRef = VariantRefCast.get(); @@ -6102,8 +6375,6 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, PossibleAddrOfVariantRef->IgnoreImplicit())) VariantRefCast = UO->getSubExpr(); } - } else { - VariantRefCast = VariantRef; } ExprResult ER = CheckPlaceholderExpr(VariantRefCast.get()); @@ -6514,14 +6785,14 @@ bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) { // loop. If test-expr is of form b relational-op var and relational-op is // > or >= then incr-expr must cause var to increase on each iteration of // the loop. - llvm::APSInt Result; - bool IsConstant = NewStep->isIntegerConstantExpr(Result, SemaRef.Context); + Optional<llvm::APSInt> Result = + NewStep->getIntegerConstantExpr(SemaRef.Context); bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation(); bool IsConstNeg = - IsConstant && Result.isSigned() && (Subtract != Result.isNegative()); + Result && Result->isSigned() && (Subtract != Result->isNegative()); bool IsConstPos = - IsConstant && Result.isSigned() && (Subtract == Result.isNegative()); - bool IsConstZero = IsConstant && !Result.getBoolValue(); + Result && Result->isSigned() && (Subtract == Result->isNegative()); + bool IsConstZero = Result && !Result->getBoolValue(); // != with increment is treated as <; != with decrement is treated as > if (!TestIsLessOp.hasValue()) @@ -6969,9 +7240,16 @@ calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc, ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures); if (!NewStep.isUsable()) return nullptr; - llvm::APSInt LRes, URes, SRes; - bool IsLowerConst = Lower->isIntegerConstantExpr(LRes, SemaRef.Context); - bool IsStepConst = Step->isIntegerConstantExpr(SRes, SemaRef.Context); + llvm::APSInt LRes, SRes; + bool IsLowerConst = false, IsStepConst = false; + if (Optional<llvm::APSInt> Res = Lower->getIntegerConstantExpr(SemaRef.Context)) { + LRes = *Res; + IsLowerConst = true; + } + if (Optional<llvm::APSInt> Res = Step->getIntegerConstantExpr(SemaRef.Context)) { + SRes = *Res; + IsStepConst = true; + } bool NoNeedToConvert = IsLowerConst && !RoundToStep && ((!TestIsStrictOp && LRes.isNonNegative()) || (TestIsStrictOp && LRes.isStrictlyPositive())); @@ -7004,7 +7282,12 @@ calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc, } NeedToReorganize = NoNeedToConvert; } - bool IsUpperConst = Upper->isIntegerConstantExpr(URes, SemaRef.Context); + llvm::APSInt URes; + bool IsUpperConst = false; + if (Optional<llvm::APSInt> Res = Upper->getIntegerConstantExpr(SemaRef.Context)) { + URes = *Res; + IsUpperConst = true; + } if (NoNeedToConvert && IsLowerConst && IsUpperConst && (!RoundToStep || IsStepConst)) { unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth() @@ -7436,6 +7719,7 @@ std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues( if (!Diff.isUsable()) return std::make_pair(nullptr, nullptr); + Sema::TentativeAnalysisScope Trap(SemaRef); Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false); if (!Diff.isUsable()) return std::make_pair(nullptr, nullptr); @@ -7952,9 +8236,9 @@ static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) { static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) { if (E == nullptr) return false; - llvm::APSInt Result; - if (E->isIntegerConstantExpr(Result, SemaRef.Context)) - return Signed ? Result.isSignedIntN(Bits) : Result.isIntN(Bits); + if (Optional<llvm::APSInt> Result = + E->getIntegerConstantExpr(SemaRef.Context)) + return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits); return false; } @@ -8227,9 +8511,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // Calculate the last iteration number beforehand instead of doing this on // each iteration. Do not do this if the number of iterations may be kfold-ed. - llvm::APSInt Result; - bool IsConstant = - LastIteration.get()->isIntegerConstantExpr(Result, SemaRef.Context); + bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context); ExprResult CalcLastIteration; if (!IsConstant) { ExprResult SaveRef = @@ -8915,8 +9197,6 @@ StmtResult Sema::ActOnOpenMPSectionDirective(Stmt *AStmt, if (!AStmt) return StmtError(); - assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); - setFunctionHasBranchProtectedScope(); DSAStack->setParentCancelRegion(DSAStack->isCancelRegion()); @@ -8961,8 +9241,6 @@ StmtResult Sema::ActOnOpenMPMasterDirective(Stmt *AStmt, if (!AStmt) return StmtError(); - assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); - setFunctionHasBranchProtectedScope(); return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt); @@ -8974,8 +9252,6 @@ StmtResult Sema::ActOnOpenMPCriticalDirective( if (!AStmt) return StmtError(); - assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); - bool ErrorFound = false; llvm::APSInt Hint; SourceLocation HintLoc; @@ -9693,7 +9969,6 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, if (!AStmt) return StmtError(); - auto *CS = cast<CapturedStmt>(AStmt); // 1.2.2 OpenMP Language Terminology // Structured block - An executable statement with a single entry at the // top and a single exit at the bottom. @@ -9757,7 +10032,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, << getOpenMPClauseName(MemOrderKind); } - Stmt *Body = CS->getCapturedStmt(); + Stmt *Body = AStmt; if (auto *EWC = dyn_cast<ExprWithCleanups>(Body)) Body = EWC->getSubExpr(); @@ -12620,15 +12895,16 @@ isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind, ValExpr = Value.get(); // The expression must evaluate to a non-negative integer value. - llvm::APSInt Result; - if (ValExpr->isIntegerConstantExpr(Result, SemaRef.Context) && - Result.isSigned() && - !((!StrictlyPositive && Result.isNonNegative()) || - (StrictlyPositive && Result.isStrictlyPositive()))) { - SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause) - << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0) - << ValExpr->getSourceRange(); - return false; + if (Optional<llvm::APSInt> Result = + ValExpr->getIntegerConstantExpr(SemaRef.Context)) { + if (Result->isSigned() && + !((!StrictlyPositive && Result->isNonNegative()) || + (StrictlyPositive && Result->isStrictlyPositive()))) { + SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause) + << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0) + << ValExpr->getSourceRange(); + return false; + } } if (!BuildCapture) return true; @@ -12681,7 +12957,8 @@ ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E, E->isInstantiationDependent() || E->containsUnexpandedParameterPack()) return E; llvm::APSInt Result; - ExprResult ICE = VerifyIntegerConstantExpression(E, &Result); + ExprResult ICE = + VerifyIntegerConstantExpression(E, &Result, /*FIXME*/ AllowFold); if (ICE.isInvalid()) return ExprError(); if ((StrictlyPositive && !Result.isStrictlyPositive()) || @@ -13263,9 +13540,9 @@ OMPClause *Sema::ActOnOpenMPScheduleClause( // OpenMP [2.7.1, Restrictions] // chunk_size must be a loop invariant integer expression with a positive // value. - llvm::APSInt Result; - if (ValExpr->isIntegerConstantExpr(Result, Context)) { - if (Result.isSigned() && !Result.isStrictlyPositive()) { + if (Optional<llvm::APSInt> Result = + ValExpr->getIntegerConstantExpr(Context)) { + if (Result->isSigned() && !Result->isStrictlyPositive()) { Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause) << "schedule" << 1 << ChunkSize->getSourceRange(); return nullptr; @@ -13522,7 +13799,9 @@ OMPClause *Sema::ActOnOpenMPVarListClause( DeclarationNameInfo &ReductionOrMapperId, int ExtraModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers, ArrayRef<SourceLocation> MapTypeModifiersLoc, bool IsMapTypeImplicit, - SourceLocation ExtraModifierLoc) { + SourceLocation ExtraModifierLoc, + ArrayRef<OpenMPMotionModifierKind> MotionModifiers, + ArrayRef<SourceLocation> MotionModifiersLoc) { SourceLocation StartLoc = Locs.StartLoc; SourceLocation LParenLoc = Locs.LParenLoc; SourceLocation EndLoc = Locs.EndLoc; @@ -13599,12 +13878,14 @@ OMPClause *Sema::ActOnOpenMPVarListClause( IsMapTypeImplicit, ExtraModifierLoc, ColonLoc, VarList, Locs); break; case OMPC_to: - Res = ActOnOpenMPToClause(VarList, ReductionOrMapperIdScopeSpec, - ReductionOrMapperId, Locs); + Res = ActOnOpenMPToClause(MotionModifiers, MotionModifiersLoc, + ReductionOrMapperIdScopeSpec, ReductionOrMapperId, + ColonLoc, VarList, Locs); break; case OMPC_from: - Res = ActOnOpenMPFromClause(VarList, ReductionOrMapperIdScopeSpec, - ReductionOrMapperId, Locs); + Res = ActOnOpenMPFromClause(MotionModifiers, MotionModifiersLoc, + ReductionOrMapperIdScopeSpec, + ReductionOrMapperId, ColonLoc, VarList, Locs); break; case OMPC_use_device_ptr: Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs); @@ -14003,7 +14284,10 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, // from the worksharing construct. if (isOpenMPTaskingDirective(CurrDir)) { DVar = DSAStack->hasInnermostDSA( - D, [](OpenMPClauseKind C) { return C == OMPC_reduction; }, + D, + [](OpenMPClauseKind C, bool AppliedToPointee) { + return C == OMPC_reduction && !AppliedToPointee; + }, [](OpenMPDirectiveKind K) { return isOpenMPParallelDirective(K) || isOpenMPWorksharingDirective(K) || @@ -14296,7 +14580,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause( if (!isOpenMPCapturedDecl(D)) ExprCaptures.push_back(Ref->getDecl()); } - if (TopDVar.CKind == OMPC_firstprivate || + if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) || (!isOpenMPCapturedDecl(D) && Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) { ExprResult RefRes = DefaultLvalueConversion(Ref); @@ -14394,7 +14678,11 @@ public: if (DVar.CKind != OMPC_unknown) return true; DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA( - VD, isOpenMPPrivate, [](OpenMPDirectiveKind) { return true; }, + VD, + [](OpenMPClauseKind C, bool AppliedToPointee) { + return isOpenMPPrivate(C) && !AppliedToPointee; + }, + [](OpenMPDirectiveKind) { return true; }, /*FromParent=*/true); return DVarPrivate.CKind != OMPC_unknown; } @@ -15027,6 +15315,17 @@ static bool actOnOMPReductionKindClause( continue; } } + } else { + // Threadprivates cannot be shared between threads, so dignose if the base + // is a threadprivate variable. + DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false); + if (DVar.CKind == OMPC_threadprivate) { + S.Diag(ELoc, diag::err_omp_wrong_dsa) + << getOpenMPClauseName(DVar.CKind) + << getOpenMPClauseName(OMPC_reduction); + reportOriginalDsa(S, Stack, D, DVar); + continue; + } } // Try to find 'declare reduction' corresponding construct before using @@ -15153,6 +15452,7 @@ static bool actOnOMPReductionKindClause( auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>(); auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl()); if (DRD->getInitializer()) { + S.ActOnUninitializedDecl(PrivateVD); Init = DRDRef; RHSVD->setInit(DRDRef); RHSVD->setInitStyle(VarDecl::CallInit); @@ -15259,10 +15559,19 @@ static bool actOnOMPReductionKindClause( llvm_unreachable("Unexpected reduction operation"); } } - if (Init && DeclareReductionRef.isUnset()) + if (Init && DeclareReductionRef.isUnset()) { S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false); - else if (!Init) + // Store initializer for single element in private copy. Will be used + // during codegen. + PrivateVD->setInit(RHSVD->getInit()); + PrivateVD->setInitStyle(RHSVD->getInitStyle()); + } else if (!Init) { S.ActOnUninitializedDecl(RHSVD); + // Store initializer for single element in private copy. Will be used + // during codegen. + PrivateVD->setInit(RHSVD->getInit()); + PrivateVD->setInitStyle(RHSVD->getInitStyle()); + } if (RHSVD->isInvalidDecl()) continue; if (!RHSVD->hasInit() && @@ -15276,10 +15585,6 @@ static bool actOnOMPReductionKindClause( << D; continue; } - // Store initializer for single element in private copy. Will be used during - // codegen. - PrivateVD->setInit(RHSVD->getInit()); - PrivateVD->setInitStyle(RHSVD->getInitStyle()); DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc); ExprResult ReductionOp; if (DeclareReductionRef.isUsable()) { @@ -15290,12 +15595,12 @@ static bool actOnOMPReductionKindClause( if (!BasePath.empty()) { LHS = S.DefaultLvalueConversion(LHS.get()); RHS = S.DefaultLvalueConversion(RHS.get()); - LHS = ImplicitCastExpr::Create(Context, PtrRedTy, - CK_UncheckedDerivedToBase, LHS.get(), - &BasePath, LHS.get()->getValueKind()); - RHS = ImplicitCastExpr::Create(Context, PtrRedTy, - CK_UncheckedDerivedToBase, RHS.get(), - &BasePath, RHS.get()->getValueKind()); + LHS = ImplicitCastExpr::Create( + Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath, + LHS.get()->getValueKind(), FPOptionsOverride()); + RHS = ImplicitCastExpr::Create( + Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath, + RHS.get()->getValueKind(), FPOptionsOverride()); } FunctionProtoType::ExtProtoInfo EPI; QualType Params[] = {PtrRedTy, PtrRedTy}; @@ -15305,7 +15610,8 @@ static bool actOnOMPReductionKindClause( S.DefaultLvalueConversion(DeclareReductionRef.get()).get()); Expr *Args[] = {LHS.get(), RHS.get()}; ReductionOp = - CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_RValue, ELoc); + CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_RValue, ELoc, + S.CurFPFeatureOverrides()); } else { ReductionOp = S.BuildBinOp( Stack->getCurScope(), ReductionId.getBeginLoc(), BOK, LHSDRE, RHSDRE); @@ -15465,7 +15771,8 @@ static bool actOnOMPReductionKindClause( // correct analysis of in_reduction clauses. if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction) Modifier = OMPC_REDUCTION_task; - Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier); + Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier, + ASE || OASE); if (Modifier == OMPC_REDUCTION_task && (CurrDir == OMPD_taskgroup || ((isOpenMPParallelDirective(CurrDir) || @@ -15736,12 +16043,12 @@ OMPClause *Sema::ActOnOpenMPLinearClause( // Warn about zero linear step (it would be probably better specified as // making corresponding variables 'const'). - llvm::APSInt Result; - bool IsConstant = StepExpr->isIntegerConstantExpr(Result, Context); - if (IsConstant && !Result.isNegative() && !Result.isStrictlyPositive()) - Diag(StepLoc, diag::warn_omp_linear_step_zero) << Vars[0] - << (Vars.size() > 1); - if (!IsConstant && CalcStep.isUsable()) { + if (Optional<llvm::APSInt> Result = + StepExpr->getIntegerConstantExpr(Context)) { + if (!Result->isNegative() && !Result->isStrictlyPositive()) + Diag(StepLoc, diag::warn_omp_linear_step_zero) + << Vars[0] << (Vars.size() > 1); + } else if (CalcStep.isUsable()) { // Calculate the step beforehand instead of doing this on each iteration. // (This is not used if the number of iterations may be kfold-ed). CalcStepExpr = CalcStep.get(); @@ -16645,11 +16952,14 @@ namespace { class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> { Sema &SemaRef; OpenMPClauseKind CKind = OMPC_unknown; + OpenMPDirectiveKind DKind = OMPD_unknown; OMPClauseMappableExprCommon::MappableExprComponentList &Components; + bool IsNonContiguous = false; bool NoDiagnose = false; const Expr *RelevantExpr = nullptr; bool AllowUnitySizeArraySection = true; bool AllowWholeSizeArraySection = true; + bool AllowAnotherPtr = true; SourceLocation ELoc; SourceRange ERange; @@ -16674,7 +16984,7 @@ public: assert(!RelevantExpr && "RelevantExpr is expected to be nullptr"); RelevantExpr = DRE; // Record the component. - Components.emplace_back(DRE, DRE->getDecl()); + Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous); return true; } @@ -16746,7 +17056,7 @@ public: AllowWholeSizeArraySection = false; // Record the component. - Components.emplace_back(ME, FD); + Components.emplace_back(ME, FD, IsNonContiguous); return RelevantExpr || Visit(E); } @@ -16784,7 +17094,7 @@ public: } // Record the component - we don't have any declaration associated. - Components.emplace_back(AE, nullptr); + Components.emplace_back(AE, nullptr, IsNonContiguous); return RelevantExpr || Visit(E); } @@ -16823,6 +17133,13 @@ public: // pointer. Otherwise, only unitary sections are accepted. if (NotWhole || IsPointer) AllowWholeSizeArraySection = false; + } else if (DKind == OMPD_target_update && + SemaRef.getLangOpts().OpenMP >= 50) { + if (IsPointer && !AllowAnotherPtr) + SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined) + << /*array of unknown bound */ 1; + else + IsNonContiguous = true; } else if (AllowUnitySizeArraySection && NotUnity) { // A unity or whole array section is not allowed and that is not // compatible with the properties of the current array section. @@ -16832,6 +17149,9 @@ public: return false; } + if (IsPointer) + AllowAnotherPtr = false; + if (const auto *TE = dyn_cast<CXXThisExpr>(E)) { Expr::EvalResult ResultR; Expr::EvalResult ResultL; @@ -16857,14 +17177,14 @@ public: } // Record the component - we don't have any declaration associated. - Components.emplace_back(OASE, nullptr); + Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false); return RelevantExpr || Visit(E); } bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) { Expr *Base = E->getBase(); // Record the component - we don't have any declaration associated. - Components.emplace_back(E, nullptr); + Components.emplace_back(E, nullptr, IsNonContiguous); return Visit(Base->IgnoreParenImpCasts()); } @@ -16877,7 +17197,7 @@ public: } if (!RelevantExpr) { // Record the component if haven't found base decl. - Components.emplace_back(UO, nullptr); + Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false); } return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts()); } @@ -16893,7 +17213,7 @@ public: // know the other subtree is just an offset) Expr *LE = BO->getLHS()->IgnoreParenImpCasts(); Expr *RE = BO->getRHS()->IgnoreParenImpCasts(); - Components.emplace_back(BO, nullptr); + Components.emplace_back(BO, nullptr, false); assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() || RE->getType().getTypePtr() == BO->getType().getTypePtr()) && "Either LHS or RHS have base decl inside"); @@ -16904,7 +17224,12 @@ public: bool VisitCXXThisExpr(CXXThisExpr *CTE) { assert(!RelevantExpr && "RelevantExpr is expected to be nullptr"); RelevantExpr = CTE; - Components.emplace_back(CTE, nullptr); + Components.emplace_back(CTE, nullptr, IsNonContiguous); + return true; + } + bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) { + assert(!RelevantExpr && "RelevantExpr is expected to be nullptr"); + Components.emplace_back(COCE, nullptr, IsNonContiguous); return true; } bool VisitStmt(Stmt *) { @@ -16915,10 +17240,10 @@ public: return RelevantExpr; } explicit MapBaseChecker( - Sema &SemaRef, OpenMPClauseKind CKind, + Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, OMPClauseMappableExprCommon::MappableExprComponentList &Components, bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange) - : SemaRef(SemaRef), CKind(CKind), Components(Components), + : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components), NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {} }; } // namespace @@ -16930,13 +17255,30 @@ public: static const Expr *checkMapClauseExpressionBase( Sema &SemaRef, Expr *E, OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, - OpenMPClauseKind CKind, bool NoDiagnose) { + OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) { SourceLocation ELoc = E->getExprLoc(); SourceRange ERange = E->getSourceRange(); - MapBaseChecker Checker(SemaRef, CKind, CurComponents, NoDiagnose, ELoc, + MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc, ERange); - if (Checker.Visit(E->IgnoreParens())) + if (Checker.Visit(E->IgnoreParens())) { + // Check if the highest dimension array section has length specified + if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() && + (CKind == OMPC_to || CKind == OMPC_from)) { + auto CI = CurComponents.rbegin(); + auto CE = CurComponents.rend(); + for (; CI != CE; ++CI) { + const auto *OASE = + dyn_cast<OMPArraySectionExpr>(CI->getAssociatedExpression()); + if (!OASE) + continue; + if (OASE && OASE->getLength()) + break; + SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length) + << ERange; + } + } return Checker.getFoundBase(); + } return nullptr; } @@ -17347,6 +17689,7 @@ static void checkMappableExpressionList( auto &DeclNames = SemaRef.getASTContext().DeclarationNames; MapperId.setName(DeclNames.getIdentifier( &SemaRef.getASTContext().Idents.get("default"))); + MapperId.setLoc(StartLoc); } // Iterators to find the current unresolved mapper expression. @@ -17413,7 +17756,8 @@ static void checkMappableExpressionList( // Obtain the array or member expression bases if required. Also, fill the // components array with all the components identified in the process. const Expr *BE = checkMapClauseExpressionBase( - SemaRef, SimpleExpr, CurComponents, CKind, /*NoDiagnose=*/false); + SemaRef, SimpleExpr, CurComponents, CKind, DSAS->getCurrentDirective(), + /*NoDiagnose=*/false); if (!BE) continue; @@ -17478,6 +17822,7 @@ static void checkMappableExpressionList( /*CurrentRegionOnly=*/true, CurComponents, CKind)) break; if (CKind == OMPC_map && + (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) && checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr, /*CurrentRegionOnly=*/false, CurComponents, CKind)) break; @@ -17623,9 +17968,9 @@ OMPClause *Sema::ActOnOpenMPMapClause( OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList, const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) { - OpenMPMapModifierKind Modifiers[] = {OMPC_MAP_MODIFIER_unknown, - OMPC_MAP_MODIFIER_unknown, - OMPC_MAP_MODIFIER_unknown}; + OpenMPMapModifierKind Modifiers[] = { + OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown, + OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown}; SourceLocation ModifiersLoc[NumberOfOMPMapClauseModifiers]; // Process map-type-modifiers, flag errors for duplicate modifiers. @@ -17944,10 +18289,10 @@ QualType Sema::ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, return MapperType; } -OMPDeclareMapperDecl *Sema::ActOnOpenMPDeclareMapperDirectiveStart( +Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareMapperDirective( Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType, SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS, - Decl *PrevDeclInScope) { + Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) { LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPMapperName, forRedeclarationInCurContext()); // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions @@ -18007,48 +18352,51 @@ OMPDeclareMapperDecl *Sema::ActOnOpenMPDeclareMapperDirectiveStart( Invalid = true; } auto *DMD = OMPDeclareMapperDecl::Create(Context, DC, StartLoc, Name, - MapperType, VN, PrevDMD); - DC->addDecl(DMD); + MapperType, VN, Clauses, PrevDMD); + if (S) + PushOnScopeChains(DMD, S); + else + DC->addDecl(DMD); DMD->setAccess(AS); if (Invalid) DMD->setInvalidDecl(); - // Enter new function scope. - PushFunctionScope(); - setFunctionHasBranchProtectedScope(); - - CurContext = DMD; + auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl(); + VD->setDeclContext(DMD); + VD->setLexicalDeclContext(DMD); + DMD->addDecl(VD); + DMD->setMapperVarRef(MapperVarRef); - return DMD; + return DeclGroupPtrTy::make(DeclGroupRef(DMD)); } -void Sema::ActOnOpenMPDeclareMapperDirectiveVarDecl(OMPDeclareMapperDecl *DMD, - Scope *S, - QualType MapperType, - SourceLocation StartLoc, - DeclarationName VN) { - VarDecl *VD = buildVarDecl(*this, StartLoc, MapperType, VN.getAsString()); +ExprResult +Sema::ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType, + SourceLocation StartLoc, + DeclarationName VN) { + TypeSourceInfo *TInfo = + Context.getTrivialTypeSourceInfo(MapperType, StartLoc); + auto *VD = VarDecl::Create(Context, Context.getTranslationUnitDecl(), + StartLoc, StartLoc, VN.getAsIdentifierInfo(), + MapperType, TInfo, SC_None); if (S) - PushOnScopeChains(VD, S); - else - DMD->addDecl(VD); - Expr *MapperVarRefExpr = buildDeclRefExpr(*this, VD, MapperType, StartLoc); - DMD->setMapperVarRef(MapperVarRefExpr); + PushOnScopeChains(VD, S, /*AddToContext=*/false); + Expr *E = buildDeclRefExpr(*this, VD, MapperType, StartLoc); + DSAStack->addDeclareMapperVarRef(E); + return E; } -Sema::DeclGroupPtrTy -Sema::ActOnOpenMPDeclareMapperDirectiveEnd(OMPDeclareMapperDecl *D, Scope *S, - ArrayRef<OMPClause *> ClauseList) { - PopDeclContext(); - PopFunctionScopeInfo(); - - if (D) { - if (S) - PushOnScopeChains(D, S, /*AddToContext=*/false); - D->CreateClauses(Context, ClauseList); - } +bool Sema::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const { + assert(LangOpts.OpenMP && "Expected OpenMP mode."); + const Expr *Ref = DSAStack->getDeclareMapperVarRef(); + if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) + return VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl(); + return true; +} - return DeclGroupPtrTy::make(DeclGroupRef(D)); +const ValueDecl *Sema::getOpenMPDeclareMapperVarName() const { + assert(LangOpts.OpenMP && "Expected OpenMP mode."); + return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl(); } OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams, @@ -18273,9 +18621,9 @@ OMPClause *Sema::ActOnOpenMPDistScheduleClause( // OpenMP [2.7.1, Restrictions] // chunk_size must be a loop invariant integer expression with a positive // value. - llvm::APSInt Result; - if (ValExpr->isIntegerConstantExpr(Result, Context)) { - if (Result.isSigned() && !Result.isStrictlyPositive()) { + if (Optional<llvm::APSInt> Result = + ValExpr->getIntegerConstantExpr(Context)) { + if (Result->isSigned() && !Result->isStrictlyPositive()) { Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause) << "dist_schedule" << ChunkSize->getSourceRange(); return nullptr; @@ -18326,20 +18674,38 @@ OMPClause *Sema::ActOnOpenMPDefaultmapClause( bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) || (LangOpts.OpenMP >= 50 && KindLoc.isInvalid()); if (!isDefaultmapKind || !isDefaultmapModifier) { - std::string ModifierValue = "'alloc', 'from', 'to', 'tofrom', " + StringRef KindValue = "'scalar', 'aggregate', 'pointer'"; + if (LangOpts.OpenMP == 50) { + StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', " "'firstprivate', 'none', 'default'"; - std::string KindValue = "'scalar', 'aggregate', 'pointer'"; - if (!isDefaultmapKind && isDefaultmapModifier) { - Diag(KindLoc, diag::err_omp_unexpected_clause_value) - << KindValue << getOpenMPClauseName(OMPC_defaultmap); - } else if (isDefaultmapKind && !isDefaultmapModifier) { - Diag(MLoc, diag::err_omp_unexpected_clause_value) - << ModifierValue << getOpenMPClauseName(OMPC_defaultmap); + if (!isDefaultmapKind && isDefaultmapModifier) { + Diag(KindLoc, diag::err_omp_unexpected_clause_value) + << KindValue << getOpenMPClauseName(OMPC_defaultmap); + } else if (isDefaultmapKind && !isDefaultmapModifier) { + Diag(MLoc, diag::err_omp_unexpected_clause_value) + << ModifierValue << getOpenMPClauseName(OMPC_defaultmap); + } else { + Diag(MLoc, diag::err_omp_unexpected_clause_value) + << ModifierValue << getOpenMPClauseName(OMPC_defaultmap); + Diag(KindLoc, diag::err_omp_unexpected_clause_value) + << KindValue << getOpenMPClauseName(OMPC_defaultmap); + } } else { - Diag(MLoc, diag::err_omp_unexpected_clause_value) - << ModifierValue << getOpenMPClauseName(OMPC_defaultmap); - Diag(KindLoc, diag::err_omp_unexpected_clause_value) - << KindValue << getOpenMPClauseName(OMPC_defaultmap); + StringRef ModifierValue = + "'alloc', 'from', 'to', 'tofrom', " + "'firstprivate', 'none', 'default', 'present'"; + if (!isDefaultmapKind && isDefaultmapModifier) { + Diag(KindLoc, diag::err_omp_unexpected_clause_value) + << KindValue << getOpenMPClauseName(OMPC_defaultmap); + } else if (isDefaultmapKind && !isDefaultmapModifier) { + Diag(MLoc, diag::err_omp_unexpected_clause_value) + << ModifierValue << getOpenMPClauseName(OMPC_defaultmap); + } else { + Diag(MLoc, diag::err_omp_unexpected_clause_value) + << ModifierValue << getOpenMPClauseName(OMPC_defaultmap); + Diag(KindLoc, diag::err_omp_unexpected_clause_value) + << KindValue << getOpenMPClauseName(OMPC_defaultmap); + } } return nullptr; } @@ -18377,14 +18743,14 @@ bool Sema::ActOnStartOpenMPDeclareTargetDirective(SourceLocation Loc) { Diag(Loc, diag::err_omp_region_not_file_context); return false; } - ++DeclareTargetNestingLevel; + DeclareTargetNesting.push_back(Loc); return true; } void Sema::ActOnFinishOpenMPDeclareTargetDirective() { - assert(DeclareTargetNestingLevel > 0 && + assert(!DeclareTargetNesting.empty() && "Unexpected ActOnFinishOpenMPDeclareTargetDirective"); - --DeclareTargetNestingLevel; + DeclareTargetNesting.pop_back(); } NamedDecl * @@ -18437,19 +18803,25 @@ void Sema::ActOnOpenMPDeclareTargetName( (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced())) Diag(Loc, diag::warn_omp_declare_target_after_first_use); + auto *VD = cast<ValueDecl>(ND); Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = - OMPDeclareTargetDeclAttr::getDeviceType(cast<ValueDecl>(ND)); - if (DevTy.hasValue() && *DevTy != DT) { + OMPDeclareTargetDeclAttr::getDeviceType(VD); + Optional<SourceLocation> AttrLoc = OMPDeclareTargetDeclAttr::getLocation(VD); + if (DevTy.hasValue() && *DevTy != DT && + (DeclareTargetNesting.empty() || + *AttrLoc != DeclareTargetNesting.back())) { Diag(Loc, diag::err_omp_device_type_mismatch) << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DT) << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(*DevTy); return; } Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = - OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(cast<ValueDecl>(ND)); - if (!Res) { - auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(Context, MT, DT, - SourceRange(Loc, Loc)); + OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); + if (!Res || (!DeclareTargetNesting.empty() && + *AttrLoc == DeclareTargetNesting.back())) { + auto *A = OMPDeclareTargetDeclAttr::CreateImplicit( + Context, MT, DT, DeclareTargetNesting.size() + 1, + SourceRange(Loc, Loc)); ND->addAttr(A); if (ASTMutationListener *ML = Context.getASTMutationListener()) ML->DeclarationMarkedOpenMPDeclareTarget(ND, A); @@ -18541,7 +18913,9 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, isa<FunctionTemplateDecl>(D)) { auto *A = OMPDeclareTargetDeclAttr::CreateImplicit( Context, OMPDeclareTargetDeclAttr::MT_To, - OMPDeclareTargetDeclAttr::DT_Any, SourceRange(IdLoc, IdLoc)); + OMPDeclareTargetDeclAttr::DT_Any, DeclareTargetNesting.size(), + SourceRange(DeclareTargetNesting.back(), + DeclareTargetNesting.back())); D->addAttr(A); if (ASTMutationListener *ML = Context.getASTMutationListener()) ML->DeclarationMarkedOpenMPDeclareTarget(D, A); @@ -18554,11 +18928,31 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, checkDeclInTargetContext(E->getExprLoc(), E->getSourceRange(), *this, D); } -OMPClause *Sema::ActOnOpenMPToClause(ArrayRef<Expr *> VarList, - CXXScopeSpec &MapperIdScopeSpec, - DeclarationNameInfo &MapperId, - const OMPVarListLocTy &Locs, - ArrayRef<Expr *> UnresolvedMappers) { +OMPClause *Sema::ActOnOpenMPToClause( + ArrayRef<OpenMPMotionModifierKind> MotionModifiers, + ArrayRef<SourceLocation> MotionModifiersLoc, + CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, + SourceLocation ColonLoc, ArrayRef<Expr *> VarList, + const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) { + OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown, + OMPC_MOTION_MODIFIER_unknown}; + SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers]; + + // Process motion-modifiers, flag errors for duplicate modifiers. + unsigned Count = 0; + for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) { + if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown && + llvm::find(Modifiers, MotionModifiers[I]) != std::end(Modifiers)) { + Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier); + continue; + } + assert(Count < NumberOfOMPMotionModifiers && + "Modifiers exceed the allowed number of motion modifiers"); + Modifiers[Count] = MotionModifiers[I]; + ModifiersLoc[Count] = MotionModifiersLoc[I]; + ++Count; + } + MappableVarListInfo MVLI(VarList); checkMappableExpressionList(*this, DSAStack, OMPC_to, MVLI, Locs.StartLoc, MapperIdScopeSpec, MapperId, UnresolvedMappers); @@ -18567,15 +18961,35 @@ OMPClause *Sema::ActOnOpenMPToClause(ArrayRef<Expr *> VarList, return OMPToClause::Create( Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations, - MVLI.VarComponents, MVLI.UDMapperList, + MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(Context), MapperId); } -OMPClause *Sema::ActOnOpenMPFromClause(ArrayRef<Expr *> VarList, - CXXScopeSpec &MapperIdScopeSpec, - DeclarationNameInfo &MapperId, - const OMPVarListLocTy &Locs, - ArrayRef<Expr *> UnresolvedMappers) { +OMPClause *Sema::ActOnOpenMPFromClause( + ArrayRef<OpenMPMotionModifierKind> MotionModifiers, + ArrayRef<SourceLocation> MotionModifiersLoc, + CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, + SourceLocation ColonLoc, ArrayRef<Expr *> VarList, + const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) { + OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown, + OMPC_MOTION_MODIFIER_unknown}; + SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers]; + + // Process motion-modifiers, flag errors for duplicate modifiers. + unsigned Count = 0; + for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) { + if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown && + llvm::find(Modifiers, MotionModifiers[I]) != std::end(Modifiers)) { + Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier); + continue; + } + assert(Count < NumberOfOMPMotionModifiers && + "Modifiers exceed the allowed number of motion modifiers"); + Modifiers[Count] = MotionModifiers[I]; + ModifiersLoc[Count] = MotionModifiersLoc[I]; + ++Count; + } + MappableVarListInfo MVLI(VarList); checkMappableExpressionList(*this, DSAStack, OMPC_from, MVLI, Locs.StartLoc, MapperIdScopeSpec, MapperId, UnresolvedMappers); @@ -18584,7 +18998,7 @@ OMPClause *Sema::ActOnOpenMPFromClause(ArrayRef<Expr *> VarList, return OMPFromClause::Create( Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations, - MVLI.VarComponents, MVLI.UDMapperList, + MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(Context), MapperId); } @@ -18661,8 +19075,8 @@ OMPClause *Sema::ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList, // only need a component. MVLI.VarBaseDeclarations.push_back(D); MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1); - MVLI.VarComponents.back().push_back( - OMPClauseMappableExprCommon::MappableComponent(SimpleRefExpr, D)); + MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D, + /*IsNonContiguous=*/false); } if (MVLI.ProcessedVarList.empty()) @@ -18713,8 +19127,8 @@ OMPClause *Sema::ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr *> VarList, if (VD && (isa<OMPArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) || isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts()))) Component = DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get(); - MVLI.VarComponents.back().push_back( - OMPClauseMappableExprCommon::MappableComponent(Component, D)); + MVLI.VarComponents.back().emplace_back(Component, D, + /*IsNonContiguous=*/false); } if (MVLI.ProcessedVarList.empty()) @@ -18780,7 +19194,8 @@ OMPClause *Sema::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList, // Store the components in the stack so that they can be used to check // against other clauses later on. - OMPClauseMappableExprCommon::MappableComponent MC(SimpleRefExpr, D); + OMPClauseMappableExprCommon::MappableComponent MC( + SimpleRefExpr, D, /*IsNonContiguous=*/false); DSAStack->addMappableExpressionComponents( D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr); @@ -19022,7 +19437,7 @@ OMPClause *Sema::ActOnOpenMPUsesAllocatorClause( [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) && !findOMPAlloctraitT(*this, StartLoc, DSAStack)) return nullptr; - llvm::SmallSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators; + llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators; for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) { auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I); StringRef Allocator = diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 8635397f4806..7fe7466725fa 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -137,6 +137,7 @@ ImplicitConversionRank clang::GetConversionRank(ImplicitConversionKind Kind) { ICR_Conversion, ICR_Conversion, ICR_Conversion, + ICR_Conversion, ICR_OCL_Scalar_Widening, ICR_Complex_Real_Conversion, ICR_Conversion, @@ -174,6 +175,7 @@ static const char* GetImplicitConversionName(ImplicitConversionKind Kind) { "Compatible-types conversion", "Derived-to-base conversion", "Vector conversion", + "SVE Vector conversion", "Vector splat", "Complex-real conversion", "Block Pointer conversion", @@ -346,7 +348,6 @@ NarrowingKind StandardConversionSequence::getNarrowingKind( ToType->isRealFloatingType()) { if (IgnoreFloatToIntegralConversion) return NK_Not_Narrowing; - llvm::APSInt IntConstantValue; const Expr *Initializer = IgnoreNarrowingConversion(Ctx, Converted); assert(Initializer && "Unknown conversion expression"); @@ -354,19 +355,20 @@ NarrowingKind StandardConversionSequence::getNarrowingKind( if (Initializer->isValueDependent()) return NK_Dependent_Narrowing; - if (Initializer->isIntegerConstantExpr(IntConstantValue, Ctx)) { + if (Optional<llvm::APSInt> IntConstantValue = + Initializer->getIntegerConstantExpr(Ctx)) { // Convert the integer to the floating type. llvm::APFloat Result(Ctx.getFloatTypeSemantics(ToType)); - Result.convertFromAPInt(IntConstantValue, IntConstantValue.isSigned(), + Result.convertFromAPInt(*IntConstantValue, IntConstantValue->isSigned(), llvm::APFloat::rmNearestTiesToEven); // And back. - llvm::APSInt ConvertedValue = IntConstantValue; + llvm::APSInt ConvertedValue = *IntConstantValue; bool ignored; Result.convertToInteger(ConvertedValue, llvm::APFloat::rmTowardZero, &ignored); // If the resulting value is different, this was a narrowing conversion. - if (IntConstantValue != ConvertedValue) { - ConstantValue = APValue(IntConstantValue); + if (*IntConstantValue != ConvertedValue) { + ConstantValue = APValue(*IntConstantValue); ConstantType = Initializer->getType(); return NK_Constant_Narrowing; } @@ -430,17 +432,18 @@ NarrowingKind StandardConversionSequence::getNarrowingKind( (FromWidth == ToWidth && FromSigned != ToSigned) || (FromSigned && !ToSigned)) { // Not all values of FromType can be represented in ToType. - llvm::APSInt InitializerValue; const Expr *Initializer = IgnoreNarrowingConversion(Ctx, Converted); // If it's value-dependent, we can't tell whether it's narrowing. if (Initializer->isValueDependent()) return NK_Dependent_Narrowing; - if (!Initializer->isIntegerConstantExpr(InitializerValue, Ctx)) { + Optional<llvm::APSInt> OptInitializerValue; + if (!(OptInitializerValue = Initializer->getIntegerConstantExpr(Ctx))) { // Such conversions on variables are always narrowing. return NK_Variable_Narrowing; } + llvm::APSInt &InitializerValue = *OptInitializerValue; bool Narrowing = false; if (FromWidth < ToWidth) { // Negative -> unsigned is narrowing. Otherwise, more bits is never @@ -1491,17 +1494,9 @@ Sema::TryImplicitConversion(Expr *From, QualType ToType, /// converted expression. Flavor is the kind of conversion we're /// performing, used in the error message. If @p AllowExplicit, /// explicit user-defined conversions are permitted. -ExprResult -Sema::PerformImplicitConversion(Expr *From, QualType ToType, - AssignmentAction Action, bool AllowExplicit) { - ImplicitConversionSequence ICS; - return PerformImplicitConversion(From, ToType, Action, AllowExplicit, ICS); -} - -ExprResult -Sema::PerformImplicitConversion(Expr *From, QualType ToType, - AssignmentAction Action, bool AllowExplicit, - ImplicitConversionSequence& ICS) { +ExprResult Sema::PerformImplicitConversion(Expr *From, QualType ToType, + AssignmentAction Action, + bool AllowExplicit) { if (checkPlaceholderForOverload(*this, From)) return ExprError(); @@ -1512,13 +1507,13 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, if (getLangOpts().ObjC) CheckObjCBridgeRelatedConversions(From->getBeginLoc(), ToType, From->getType(), From); - ICS = ::TryImplicitConversion(*this, From, ToType, - /*SuppressUserConversions=*/false, - AllowExplicit ? AllowedExplicit::All - : AllowedExplicit::None, - /*InOverloadResolution=*/false, - /*CStyle=*/false, AllowObjCWritebackConversion, - /*AllowObjCConversionOnExplicit=*/false); + ImplicitConversionSequence ICS = ::TryImplicitConversion( + *this, From, ToType, + /*SuppressUserConversions=*/false, + AllowExplicit ? AllowedExplicit::All : AllowedExplicit::None, + /*InOverloadResolution=*/false, + /*CStyle=*/false, AllowObjCWritebackConversion, + /*AllowObjCConversionOnExplicit=*/false); return PerformImplicitConversion(From, ToType, ICS, Action); } @@ -1649,6 +1644,13 @@ static bool IsVectorConversion(Sema &S, QualType FromType, } } + if (ToType->isSizelessBuiltinType() || FromType->isSizelessBuiltinType()) + if (S.Context.areCompatibleSveTypes(FromType, ToType) || + S.Context.areLaxCompatibleSveTypes(FromType, ToType)) { + ICK = ICK_SVE_Vector_Conversion; + return true; + } + // We can perform the conversion between vector types in the following cases: // 1)vector types are equivalent AltiVec and GCC vector types // 2)lax vector conversions are permitted and the vector types are of the @@ -2183,21 +2185,22 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { // compatibility. if (From) { if (FieldDecl *MemberDecl = From->getSourceBitField()) { - llvm::APSInt BitWidth; + Optional<llvm::APSInt> BitWidth; if (FromType->isIntegralType(Context) && - MemberDecl->getBitWidth()->isIntegerConstantExpr(BitWidth, Context)) { - llvm::APSInt ToSize(BitWidth.getBitWidth(), BitWidth.isUnsigned()); + (BitWidth = + MemberDecl->getBitWidth()->getIntegerConstantExpr(Context))) { + llvm::APSInt ToSize(BitWidth->getBitWidth(), BitWidth->isUnsigned()); ToSize = Context.getTypeSize(ToType); // Are we promoting to an int from a bitfield that fits in an int? - if (BitWidth < ToSize || - (FromType->isSignedIntegerType() && BitWidth <= ToSize)) { + if (*BitWidth < ToSize || + (FromType->isSignedIntegerType() && *BitWidth <= ToSize)) { return To->getKind() == BuiltinType::Int; } // Are we promoting to an unsigned int from an unsigned bitfield // that fits into an unsigned int? - if (FromType->isUnsignedIntegerType() && BitWidth <= ToSize) { + if (FromType->isUnsignedIntegerType() && *BitWidth <= ToSize) { return To->getKind() == BuiltinType::UInt; } @@ -3643,13 +3646,32 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) { return true; } +// Helper for compareConversionFunctions that gets the FunctionType that the +// conversion-operator return value 'points' to, or nullptr. +static const FunctionType * +getConversionOpReturnTyAsFunction(CXXConversionDecl *Conv) { + const FunctionType *ConvFuncTy = Conv->getType()->castAs<FunctionType>(); + const PointerType *RetPtrTy = + ConvFuncTy->getReturnType()->getAs<PointerType>(); + + if (!RetPtrTy) + return nullptr; + + return RetPtrTy->getPointeeType()->getAs<FunctionType>(); +} + /// Compare the user-defined conversion functions or constructors /// of two user-defined conversion sequences to determine whether any ordering /// is possible. static ImplicitConversionSequence::CompareKind compareConversionFunctions(Sema &S, FunctionDecl *Function1, FunctionDecl *Function2) { - if (!S.getLangOpts().ObjC || !S.getLangOpts().CPlusPlus11) + CXXConversionDecl *Conv1 = dyn_cast_or_null<CXXConversionDecl>(Function1); + CXXConversionDecl *Conv2 = dyn_cast_or_null<CXXConversionDecl>(Function2); + if (!Conv1 || !Conv2) + return ImplicitConversionSequence::Indistinguishable; + + if (!Conv1->getParent()->isLambda() || !Conv2->getParent()->isLambda()) return ImplicitConversionSequence::Indistinguishable; // Objective-C++: @@ -3658,15 +3680,7 @@ compareConversionFunctions(Sema &S, FunctionDecl *Function1, // respectively, always prefer the conversion to a function pointer, // because the function pointer is more lightweight and is more likely // to keep code working. - CXXConversionDecl *Conv1 = dyn_cast_or_null<CXXConversionDecl>(Function1); - if (!Conv1) - return ImplicitConversionSequence::Indistinguishable; - - CXXConversionDecl *Conv2 = dyn_cast<CXXConversionDecl>(Function2); - if (!Conv2) - return ImplicitConversionSequence::Indistinguishable; - - if (Conv1->getParent()->isLambda() && Conv2->getParent()->isLambda()) { + if (S.getLangOpts().ObjC && S.getLangOpts().CPlusPlus11) { bool Block1 = Conv1->getConversionType()->isBlockPointerType(); bool Block2 = Conv2->getConversionType()->isBlockPointerType(); if (Block1 != Block2) @@ -3674,6 +3688,39 @@ compareConversionFunctions(Sema &S, FunctionDecl *Function1, : ImplicitConversionSequence::Better; } + // In order to support multiple calling conventions for the lambda conversion + // operator (such as when the free and member function calling convention is + // different), prefer the 'free' mechanism, followed by the calling-convention + // of operator(). The latter is in place to support the MSVC-like solution of + // defining ALL of the possible conversions in regards to calling-convention. + const FunctionType *Conv1FuncRet = getConversionOpReturnTyAsFunction(Conv1); + const FunctionType *Conv2FuncRet = getConversionOpReturnTyAsFunction(Conv2); + + if (Conv1FuncRet && Conv2FuncRet && + Conv1FuncRet->getCallConv() != Conv2FuncRet->getCallConv()) { + CallingConv Conv1CC = Conv1FuncRet->getCallConv(); + CallingConv Conv2CC = Conv2FuncRet->getCallConv(); + + CXXMethodDecl *CallOp = Conv2->getParent()->getLambdaCallOperator(); + const FunctionProtoType *CallOpProto = + CallOp->getType()->getAs<FunctionProtoType>(); + + CallingConv CallOpCC = + CallOp->getType()->getAs<FunctionType>()->getCallConv(); + CallingConv DefaultFree = S.Context.getDefaultCallingConvention( + CallOpProto->isVariadic(), /*IsCXXMethod=*/false); + CallingConv DefaultMember = S.Context.getDefaultCallingConvention( + CallOpProto->isVariadic(), /*IsCXXMethod=*/true); + + CallingConv PrefOrder[] = {DefaultFree, DefaultMember, CallOpCC}; + for (CallingConv CC : PrefOrder) { + if (Conv1CC == CC) + return ImplicitConversionSequence::Better; + if (Conv2CC == CC) + return ImplicitConversionSequence::Worse; + } + } + return ImplicitConversionSequence::Indistinguishable; } @@ -4102,6 +4149,20 @@ CompareStandardConversionSequences(Sema &S, SourceLocation Loc, : ImplicitConversionSequence::Worse; } + if (SCS1.Second == ICK_SVE_Vector_Conversion && + SCS2.Second == ICK_SVE_Vector_Conversion) { + bool SCS1IsCompatibleSVEVectorConversion = + S.Context.areCompatibleSveTypes(SCS1.getFromType(), SCS1.getToType(2)); + bool SCS2IsCompatibleSVEVectorConversion = + S.Context.areCompatibleSveTypes(SCS2.getFromType(), SCS2.getToType(2)); + + if (SCS1IsCompatibleSVEVectorConversion != + SCS2IsCompatibleSVEVectorConversion) + return SCS1IsCompatibleSVEVectorConversion + ? ImplicitConversionSequence::Better + : ImplicitConversionSequence::Worse; + } + return ImplicitConversionSequence::Indistinguishable; } @@ -4772,8 +4833,11 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, // -- Otherwise, the reference shall be an lvalue reference to a // non-volatile const type (i.e., cv1 shall be const), or the reference // shall be an rvalue reference. - if (!isRValRef && (!T1.isConstQualified() || T1.isVolatileQualified())) + if (!isRValRef && (!T1.isConstQualified() || T1.isVolatileQualified())) { + if (InitCategory.isRValue() && RefRelationship != Sema::Ref_Incompatible) + ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, Init, DeclType); return ICS; + } // -- If the initializer expression // @@ -4863,9 +4927,11 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, // If T1 is reference-related to T2 and the reference is an rvalue // reference, the initializer expression shall not be an lvalue. - if (RefRelationship >= Sema::Ref_Related && - isRValRef && Init->Classify(S.Context).isLValue()) + if (RefRelationship >= Sema::Ref_Related && isRValRef && + Init->Classify(S.Context).isLValue()) { + ICS.setBad(BadConversionSequence::rvalue_ref_to_lvalue, Init, DeclType); return ICS; + } // C++ [over.ics.ref]p2: // When a parameter of reference type is not bound directly to @@ -4903,11 +4969,8 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, // binding an rvalue reference to an lvalue other than a function // lvalue. // Note that the function case is not possible here. - if (DeclType->isRValueReferenceType() && LValRefType) { - // FIXME: This is the wrong BadConversionSequence. The problem is binding - // an rvalue reference to a (non-function) lvalue, not binding an lvalue - // reference to an rvalue! - ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, Init, DeclType); + if (isRValRef && LValRefType) { + ICS.setBad(BadConversionSequence::no_conversion, Init, DeclType); return ICS; } @@ -4968,18 +5031,19 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, InOverloadResolution, AllowObjCWritebackConversion); } - // FIXME: Check the other conditions here: array of character type, - // initializer is a string literal. - if (ToType->isArrayType()) { - InitializedEntity Entity = - InitializedEntity::InitializeParameter(S.Context, ToType, - /*Consumed=*/false); - if (S.CanPerformCopyInitialization(Entity, From)) { - Result.setStandard(); - Result.Standard.setAsIdentityConversion(); - Result.Standard.setFromType(ToType); - Result.Standard.setAllToTypes(ToType); - return Result; + + if (const auto *AT = S.Context.getAsArrayType(ToType)) { + if (S.IsStringInit(From->getInit(0), AT)) { + InitializedEntity Entity = + InitializedEntity::InitializeParameter(S.Context, ToType, + /*Consumed=*/false); + if (S.CanPerformCopyInitialization(Entity, From)) { + Result.setStandard(); + Result.Standard.setAsIdentityConversion(); + Result.Standard.setFromType(ToType); + Result.Standard.setAllToTypes(ToType); + return Result; + } } } } @@ -5491,7 +5555,6 @@ static bool CheckConvertedConstantConversions(Sema &S, // conversions are fine. switch (SCS.Second) { case ICK_Identity: - case ICK_Function_Conversion: case ICK_Integral_Promotion: case ICK_Integral_Conversion: // Narrowing conversions are checked elsewhere. case ICK_Zero_Queue_Conversion: @@ -5522,6 +5585,7 @@ static bool CheckConvertedConstantConversions(Sema &S, case ICK_Compatible_Conversion: case ICK_Derived_To_Base: case ICK_Vector_Conversion: + case ICK_SVE_Vector_Conversion: case ICK_Vector_Splat: case ICK_Complex_Real: case ICK_Block_Pointer_Conversion: @@ -5537,6 +5601,7 @@ static bool CheckConvertedConstantConversions(Sema &S, case ICK_Function_To_Pointer: llvm_unreachable("found a first conversion kind in Second"); + case ICK_Function_Conversion: case ICK_Qualification: llvm_unreachable("found a third conversion kind in Second"); @@ -5553,7 +5618,8 @@ static bool CheckConvertedConstantConversions(Sema &S, static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From, QualType T, APValue &Value, Sema::CCEKind CCE, - bool RequireInt) { + bool RequireInt, + NamedDecl *Dest) { assert(S.getLangOpts().CPlusPlus11 && "converted constant expression outside C++11"); @@ -5583,9 +5649,10 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From, SCS = &ICS.Standard; break; case ImplicitConversionSequence::UserDefinedConversion: - // We are converting to a non-class type, so the Before sequence - // must be trivial. - SCS = &ICS.UserDefined.After; + if (T->isRecordType()) + SCS = &ICS.UserDefined.Before; + else + SCS = &ICS.UserDefined.After; break; case ImplicitConversionSequence::AmbiguousConversion: case ImplicitConversionSequence::BadConversion: @@ -5612,8 +5679,20 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From, << From->getType() << From->getSourceRange() << T; } - ExprResult Result = - S.PerformImplicitConversion(From, T, ICS, Sema::AA_Converting); + // Usually we can simply apply the ImplicitConversionSequence we formed + // earlier, but that's not guaranteed to work when initializing an object of + // class type. + ExprResult Result; + if (T->isRecordType()) { + assert(CCE == Sema::CCEK_TemplateArg && + "unexpected class type converted constant expr"); + Result = S.PerformCopyInitialization( + InitializedEntity::InitializeTemplateParameter( + T, cast<NonTypeTemplateParmDecl>(Dest)), + SourceLocation(), From); + } else { + Result = S.PerformImplicitConversion(From, T, ICS, Sema::AA_Converting); + } if (Result.isInvalid()) return Result; @@ -5626,6 +5705,7 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From, return Result; // Check for a narrowing implicit conversion. + bool ReturnPreNarrowingValue = false; APValue PreNarrowingValue; QualType PreNarrowingType; switch (SCS->getNarrowingKind(S.Context, Result.get(), PreNarrowingValue, @@ -5640,12 +5720,22 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From, break; case NK_Constant_Narrowing: + if (CCE == Sema::CCEK_ArrayBound && + PreNarrowingType->isIntegralOrEnumerationType() && + PreNarrowingValue.isInt()) { + // Don't diagnose array bound narrowing here; we produce more precise + // errors by allowing the un-narrowed value through. + ReturnPreNarrowingValue = true; + break; + } S.Diag(From->getBeginLoc(), diag::ext_cce_narrowing) << CCE << /*Constant*/ 1 << PreNarrowingValue.getAsString(S.Context, PreNarrowingType) << T; break; case NK_Type_Narrowing: + // FIXME: It would be better to diagnose that the expression is not a + // constant expression. S.Diag(From->getBeginLoc(), diag::ext_cce_narrowing) << CCE << /*Constant*/ 0 << From->getType() << T; break; @@ -5660,11 +5750,16 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From, SmallVector<PartialDiagnosticAt, 8> Notes; Expr::EvalResult Eval; Eval.Diag = &Notes; - Expr::ConstExprUsage Usage = CCE == Sema::CCEK_TemplateArg - ? Expr::EvaluateForMangling - : Expr::EvaluateForCodeGen; - if (!Result.get()->EvaluateAsConstantExpr(Eval, Usage, S.Context) || + ConstantExprKind Kind; + if (CCE == Sema::CCEK_TemplateArg && T->isRecordType()) + Kind = ConstantExprKind::ClassTemplateArgument; + else if (CCE == Sema::CCEK_TemplateArg) + Kind = ConstantExprKind::NonClassTemplateArgument; + else + Kind = ConstantExprKind::Normal; + + if (!Result.get()->EvaluateAsConstantExpr(Eval, S.Context, Kind) || (RequireInt && !Eval.Val.isInt())) { // The expression can't be folded, so we can't keep it at this position in // the AST. @@ -5674,15 +5769,23 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From, if (Notes.empty()) { // It's a constant expression. - return ConstantExpr::Create(S.Context, Result.get(), Value); + Expr *E = ConstantExpr::Create(S.Context, Result.get(), Value); + if (ReturnPreNarrowingValue) + Value = std::move(PreNarrowingValue); + return E; } } // It's not a constant expression. Produce an appropriate diagnostic. if (Notes.size() == 1 && - Notes[0].second.getDiagID() == diag::note_invalid_subexpr_in_const_expr) + Notes[0].second.getDiagID() == diag::note_invalid_subexpr_in_const_expr) { S.Diag(Notes[0].first, diag::err_expr_not_cce) << CCE; - else { + } else if (!Notes.empty() && Notes[0].second.getDiagID() == + diag::note_constexpr_invalid_template_arg) { + Notes[0].second.setDiagID(diag::err_constexpr_invalid_template_arg); + for (unsigned I = 0; I < Notes.size(); ++I) + S.Diag(Notes[I].first, Notes[I].second); + } else { S.Diag(From->getBeginLoc(), diag::err_expr_not_cce) << CCE << From->getSourceRange(); for (unsigned I = 0; I < Notes.size(); ++I) @@ -5692,8 +5795,10 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From, } ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T, - APValue &Value, CCEKind CCE) { - return ::CheckConvertedConstantExpression(*this, From, T, Value, CCE, false); + APValue &Value, CCEKind CCE, + NamedDecl *Dest) { + return ::CheckConvertedConstantExpression(*this, From, T, Value, CCE, false, + Dest); } ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T, @@ -5702,7 +5807,8 @@ ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T, assert(T->isIntegralOrEnumerationType() && "unexpected converted const type"); APValue V; - auto R = ::CheckConvertedConstantExpression(*this, From, T, V, CCE, true); + auto R = ::CheckConvertedConstantExpression(*this, From, T, V, CCE, true, + /*Dest=*/nullptr); if (!R.isInvalid() && !R.get()->isValueDependent()) Value = V.getInt(); return R; @@ -5831,7 +5937,8 @@ diagnoseNoViableConversion(Sema &SemaRef, SourceLocation Loc, Expr *&From, // Record usage of conversion in an implicit cast. From = ImplicitCastExpr::Create(SemaRef.Context, Result.get()->getType(), CK_UserDefinedConversion, Result.get(), - nullptr, Result.get()->getValueKind()); + nullptr, Result.get()->getValueKind(), + SemaRef.CurFPFeatureOverrides()); } return false; } @@ -5860,7 +5967,8 @@ static bool recordConversion(Sema &SemaRef, SourceLocation Loc, Expr *&From, // Record usage of conversion in an implicit cast. From = ImplicitCastExpr::Create(SemaRef.Context, Result.get()->getType(), CK_UserDefinedConversion, Result.get(), - nullptr, Result.get()->getValueKind()); + nullptr, Result.get()->getValueKind(), + SemaRef.CurFPFeatureOverrides()); return false; } @@ -7265,8 +7373,8 @@ void Sema::AddConversionCandidate( VK_LValue, From->getBeginLoc()); ImplicitCastExpr ConversionFn(ImplicitCastExpr::OnStack, Context.getPointerType(Conversion->getType()), - CK_FunctionToPointerDecay, - &ConversionRef, VK_RValue); + CK_FunctionToPointerDecay, &ConversionRef, + VK_RValue, FPOptionsOverride()); QualType ConversionType = Conversion->getConversionType(); if (!isCompleteType(From->getBeginLoc(), ConversionType)) { @@ -7735,26 +7843,14 @@ public: bool AllowExplicitConversions, const Qualifiers &VisibleTypeConversionsQuals); - /// pointer_begin - First pointer type found; - iterator pointer_begin() { return PointerTypes.begin(); } - - /// pointer_end - Past the last pointer type found; - iterator pointer_end() { return PointerTypes.end(); } - - /// member_pointer_begin - First member pointer type found; - iterator member_pointer_begin() { return MemberPointerTypes.begin(); } - - /// member_pointer_end - Past the last member pointer type found; - iterator member_pointer_end() { return MemberPointerTypes.end(); } - - /// enumeration_begin - First enumeration type found; - iterator enumeration_begin() { return EnumerationTypes.begin(); } - - /// enumeration_end - Past the last enumeration type found; - iterator enumeration_end() { return EnumerationTypes.end(); } - + llvm::iterator_range<iterator> pointer_types() { return PointerTypes; } + llvm::iterator_range<iterator> member_pointer_types() { + return MemberPointerTypes; + } + llvm::iterator_range<iterator> enumeration_types() { + return EnumerationTypes; + } llvm::iterator_range<iterator> vector_types() { return VectorTypes; } - llvm::iterator_range<iterator> matrix_types() { return MatrixTypes; } bool containsMatrixType(QualType Ty) const { return MatrixTypes.count(Ty); } @@ -8091,12 +8187,16 @@ class BuiltinOperatorOverloadBuilder { ArithmeticTypes.push_back(S.Context.IntTy); ArithmeticTypes.push_back(S.Context.LongTy); ArithmeticTypes.push_back(S.Context.LongLongTy); - if (S.Context.getTargetInfo().hasInt128Type()) + if (S.Context.getTargetInfo().hasInt128Type() || + (S.Context.getAuxTargetInfo() && + S.Context.getAuxTargetInfo()->hasInt128Type())) ArithmeticTypes.push_back(S.Context.Int128Ty); ArithmeticTypes.push_back(S.Context.UnsignedIntTy); ArithmeticTypes.push_back(S.Context.UnsignedLongTy); ArithmeticTypes.push_back(S.Context.UnsignedLongLongTy); - if (S.Context.getTargetInfo().hasInt128Type()) + if (S.Context.getTargetInfo().hasInt128Type() || + (S.Context.getAuxTargetInfo() && + S.Context.getAuxTargetInfo()->hasInt128Type())) ArithmeticTypes.push_back(S.Context.UnsignedInt128Ty); LastPromotedIntegralType = ArithmeticTypes.size(); LastPromotedArithmeticType = ArithmeticTypes.size(); @@ -8238,19 +8338,17 @@ public: // T* operator++(T*VQ&, int); // T* operator--(T*VQ&, int); void addPlusPlusMinusMinusPointerOverloads() { - for (BuiltinCandidateTypeSet::iterator - Ptr = CandidateTypes[0].pointer_begin(), - PtrEnd = CandidateTypes[0].pointer_end(); - Ptr != PtrEnd; ++Ptr) { + for (QualType PtrTy : CandidateTypes[0].pointer_types()) { // Skip pointer types that aren't pointers to object types. - if (!(*Ptr)->getPointeeType()->isObjectType()) + if (!PtrTy->getPointeeType()->isObjectType()) continue; - addPlusPlusMinusMinusStyleOverloads(*Ptr, - (!(*Ptr).isVolatileQualified() && - VisibleTypeConversionsQuals.hasVolatile()), - (!(*Ptr).isRestrictQualified() && - VisibleTypeConversionsQuals.hasRestrict())); + addPlusPlusMinusMinusStyleOverloads( + PtrTy, + (!PtrTy.isVolatileQualified() && + VisibleTypeConversionsQuals.hasVolatile()), + (!PtrTy.isRestrictQualified() && + VisibleTypeConversionsQuals.hasRestrict())); } } @@ -8265,11 +8363,7 @@ public: // ref-qualifier, there exist candidate operator functions of the form // T& operator*(T*); void addUnaryStarPointerOverloads() { - for (BuiltinCandidateTypeSet::iterator - Ptr = CandidateTypes[0].pointer_begin(), - PtrEnd = CandidateTypes[0].pointer_end(); - Ptr != PtrEnd; ++Ptr) { - QualType ParamTy = *Ptr; + for (QualType ParamTy : CandidateTypes[0].pointer_types()) { QualType PointeeTy = ParamTy->getPointeeType(); if (!PointeeTy->isObjectType() && !PointeeTy->isFunctionType()) continue; @@ -8309,13 +8403,8 @@ public: // // T* operator+(T*); void addUnaryPlusPointerOverloads() { - for (BuiltinCandidateTypeSet::iterator - Ptr = CandidateTypes[0].pointer_begin(), - PtrEnd = CandidateTypes[0].pointer_end(); - Ptr != PtrEnd; ++Ptr) { - QualType ParamTy = *Ptr; + for (QualType ParamTy : CandidateTypes[0].pointer_types()) S.AddBuiltinCandidate(&ParamTy, Args, CandidateSet); - } } // C++ [over.built]p10: @@ -8349,16 +8438,12 @@ public: llvm::SmallPtrSet<QualType, 8> AddedTypes; for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) { - for (BuiltinCandidateTypeSet::iterator - MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(), - MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end(); - MemPtr != MemPtrEnd; - ++MemPtr) { + for (QualType MemPtrTy : CandidateTypes[ArgIdx].member_pointer_types()) { // Don't add the same builtin candidate twice. - if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr)).second) + if (!AddedTypes.insert(S.Context.getCanonicalType(MemPtrTy)).second) continue; - QualType ParamTypes[2] = { *MemPtr, *MemPtr }; + QualType ParamTypes[2] = {MemPtrTy, MemPtrTy}; S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } @@ -8401,8 +8486,7 @@ public: UserDefinedBinaryOperators; for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) { - if (CandidateTypes[ArgIdx].enumeration_begin() != - CandidateTypes[ArgIdx].enumeration_end()) { + if (!CandidateTypes[ArgIdx].enumeration_types().empty()) { for (OverloadCandidateSet::iterator C = CandidateSet.begin(), CEnd = CandidateSet.end(); C != CEnd; ++C) { @@ -8440,22 +8524,16 @@ public: llvm::SmallPtrSet<QualType, 8> AddedTypes; for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) { - for (BuiltinCandidateTypeSet::iterator - Ptr = CandidateTypes[ArgIdx].pointer_begin(), - PtrEnd = CandidateTypes[ArgIdx].pointer_end(); - Ptr != PtrEnd; ++Ptr) { + for (QualType PtrTy : CandidateTypes[ArgIdx].pointer_types()) { // Don't add the same builtin candidate twice. - if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)).second) + if (!AddedTypes.insert(S.Context.getCanonicalType(PtrTy)).second) continue; - QualType ParamTypes[2] = { *Ptr, *Ptr }; + QualType ParamTypes[2] = {PtrTy, PtrTy}; S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } - for (BuiltinCandidateTypeSet::iterator - Enum = CandidateTypes[ArgIdx].enumeration_begin(), - EnumEnd = CandidateTypes[ArgIdx].enumeration_end(); - Enum != EnumEnd; ++Enum) { - CanQualType CanonType = S.Context.getCanonicalType(*Enum); + for (QualType EnumTy : CandidateTypes[ArgIdx].enumeration_types()) { + CanQualType CanonType = S.Context.getCanonicalType(EnumTy); // Don't add the same builtin candidate twice, or if a user defined // candidate exists. @@ -8463,7 +8541,7 @@ public: UserDefinedBinaryOperators.count(std::make_pair(CanonType, CanonType))) continue; - QualType ParamTypes[2] = { *Enum, *Enum }; + QualType ParamTypes[2] = {EnumTy, EnumTy}; S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } } @@ -8495,15 +8573,12 @@ public: S.Context.getPointerDiffType(), S.Context.getPointerDiffType(), }; - for (BuiltinCandidateTypeSet::iterator - Ptr = CandidateTypes[Arg].pointer_begin(), - PtrEnd = CandidateTypes[Arg].pointer_end(); - Ptr != PtrEnd; ++Ptr) { - QualType PointeeTy = (*Ptr)->getPointeeType(); + for (QualType PtrTy : CandidateTypes[Arg].pointer_types()) { + QualType PointeeTy = PtrTy->getPointeeType(); if (!PointeeTy->isObjectType()) continue; - AsymmetricParamTypes[Arg] = *Ptr; + AsymmetricParamTypes[Arg] = PtrTy; if (Arg == 0 || Op == OO_Plus) { // operator+(T*, ptrdiff_t) or operator-(T*, ptrdiff_t) // T* operator+(ptrdiff_t, T*); @@ -8511,10 +8586,10 @@ public: } if (Op == OO_Minus) { // ptrdiff_t operator-(T, T); - if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)).second) + if (!AddedTypes.insert(S.Context.getCanonicalType(PtrTy)).second) continue; - QualType ParamTypes[2] = { *Ptr, *Ptr }; + QualType ParamTypes[2] = {PtrTy, PtrTy}; S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } } @@ -8670,24 +8745,18 @@ public: llvm::SmallPtrSet<QualType, 8> AddedTypes; for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) { - for (BuiltinCandidateTypeSet::iterator - Enum = CandidateTypes[ArgIdx].enumeration_begin(), - EnumEnd = CandidateTypes[ArgIdx].enumeration_end(); - Enum != EnumEnd; ++Enum) { - if (!AddedTypes.insert(S.Context.getCanonicalType(*Enum)).second) + for (QualType EnumTy : CandidateTypes[ArgIdx].enumeration_types()) { + if (!AddedTypes.insert(S.Context.getCanonicalType(EnumTy)).second) continue; - AddBuiltinAssignmentOperatorCandidates(S, *Enum, Args, CandidateSet); + AddBuiltinAssignmentOperatorCandidates(S, EnumTy, Args, CandidateSet); } - for (BuiltinCandidateTypeSet::iterator - MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(), - MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end(); - MemPtr != MemPtrEnd; ++MemPtr) { - if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr)).second) + for (QualType MemPtrTy : CandidateTypes[ArgIdx].member_pointer_types()) { + if (!AddedTypes.insert(S.Context.getCanonicalType(MemPtrTy)).second) continue; - AddBuiltinAssignmentOperatorCandidates(S, *MemPtr, Args, CandidateSet); + AddBuiltinAssignmentOperatorCandidates(S, MemPtrTy, Args, CandidateSet); } } } @@ -8712,49 +8781,44 @@ public: /// Set of (canonical) types that we've already handled. llvm::SmallPtrSet<QualType, 8> AddedTypes; - for (BuiltinCandidateTypeSet::iterator - Ptr = CandidateTypes[0].pointer_begin(), - PtrEnd = CandidateTypes[0].pointer_end(); - Ptr != PtrEnd; ++Ptr) { + for (QualType PtrTy : CandidateTypes[0].pointer_types()) { // If this is operator=, keep track of the builtin candidates we added. if (isEqualOp) - AddedTypes.insert(S.Context.getCanonicalType(*Ptr)); - else if (!(*Ptr)->getPointeeType()->isObjectType()) + AddedTypes.insert(S.Context.getCanonicalType(PtrTy)); + else if (!PtrTy->getPointeeType()->isObjectType()) continue; // non-volatile version QualType ParamTypes[2] = { - S.Context.getLValueReferenceType(*Ptr), - isEqualOp ? *Ptr : S.Context.getPointerDiffType(), + S.Context.getLValueReferenceType(PtrTy), + isEqualOp ? PtrTy : S.Context.getPointerDiffType(), }; S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssignmentOperator=*/ isEqualOp); - bool NeedVolatile = !(*Ptr).isVolatileQualified() && + bool NeedVolatile = !PtrTy.isVolatileQualified() && VisibleTypeConversionsQuals.hasVolatile(); if (NeedVolatile) { // volatile version ParamTypes[0] = - S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr)); + S.Context.getLValueReferenceType(S.Context.getVolatileType(PtrTy)); S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssignmentOperator=*/isEqualOp); } - if (!(*Ptr).isRestrictQualified() && + if (!PtrTy.isRestrictQualified() && VisibleTypeConversionsQuals.hasRestrict()) { // restrict version - ParamTypes[0] - = S.Context.getLValueReferenceType(S.Context.getRestrictType(*Ptr)); + ParamTypes[0] = + S.Context.getLValueReferenceType(S.Context.getRestrictType(PtrTy)); S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssignmentOperator=*/isEqualOp); if (NeedVolatile) { // volatile restrict version - ParamTypes[0] - = S.Context.getLValueReferenceType( - S.Context.getCVRQualifiedType(*Ptr, - (Qualifiers::Volatile | - Qualifiers::Restrict))); + ParamTypes[0] = + S.Context.getLValueReferenceType(S.Context.getCVRQualifiedType( + PtrTy, (Qualifiers::Volatile | Qualifiers::Restrict))); S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssignmentOperator=*/isEqualOp); } @@ -8762,48 +8826,43 @@ public: } if (isEqualOp) { - for (BuiltinCandidateTypeSet::iterator - Ptr = CandidateTypes[1].pointer_begin(), - PtrEnd = CandidateTypes[1].pointer_end(); - Ptr != PtrEnd; ++Ptr) { + for (QualType PtrTy : CandidateTypes[1].pointer_types()) { // Make sure we don't add the same candidate twice. - if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)).second) + if (!AddedTypes.insert(S.Context.getCanonicalType(PtrTy)).second) continue; QualType ParamTypes[2] = { - S.Context.getLValueReferenceType(*Ptr), - *Ptr, + S.Context.getLValueReferenceType(PtrTy), + PtrTy, }; // non-volatile version S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssignmentOperator=*/true); - bool NeedVolatile = !(*Ptr).isVolatileQualified() && - VisibleTypeConversionsQuals.hasVolatile(); + bool NeedVolatile = !PtrTy.isVolatileQualified() && + VisibleTypeConversionsQuals.hasVolatile(); if (NeedVolatile) { // volatile version - ParamTypes[0] = - S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr)); + ParamTypes[0] = S.Context.getLValueReferenceType( + S.Context.getVolatileType(PtrTy)); S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssignmentOperator=*/true); } - if (!(*Ptr).isRestrictQualified() && + if (!PtrTy.isRestrictQualified() && VisibleTypeConversionsQuals.hasRestrict()) { // restrict version - ParamTypes[0] - = S.Context.getLValueReferenceType(S.Context.getRestrictType(*Ptr)); + ParamTypes[0] = S.Context.getLValueReferenceType( + S.Context.getRestrictType(PtrTy)); S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssignmentOperator=*/true); if (NeedVolatile) { // volatile restrict version - ParamTypes[0] - = S.Context.getLValueReferenceType( - S.Context.getCVRQualifiedType(*Ptr, - (Qualifiers::Volatile | - Qualifiers::Restrict))); + ParamTypes[0] = + S.Context.getLValueReferenceType(S.Context.getCVRQualifiedType( + PtrTy, (Qualifiers::Volatile | Qualifiers::Restrict))); S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssignmentOperator=*/true); } @@ -8938,12 +8997,9 @@ public: // T* operator+(ptrdiff_t, T*); [ABOVE] // T& operator[](ptrdiff_t, T*); void addSubscriptOverloads() { - for (BuiltinCandidateTypeSet::iterator - Ptr = CandidateTypes[0].pointer_begin(), - PtrEnd = CandidateTypes[0].pointer_end(); - Ptr != PtrEnd; ++Ptr) { - QualType ParamTypes[2] = { *Ptr, S.Context.getPointerDiffType() }; - QualType PointeeType = (*Ptr)->getPointeeType(); + for (QualType PtrTy : CandidateTypes[0].pointer_types()) { + QualType ParamTypes[2] = {PtrTy, S.Context.getPointerDiffType()}; + QualType PointeeType = PtrTy->getPointeeType(); if (!PointeeType->isObjectType()) continue; @@ -8951,12 +9007,9 @@ public: S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } - for (BuiltinCandidateTypeSet::iterator - Ptr = CandidateTypes[1].pointer_begin(), - PtrEnd = CandidateTypes[1].pointer_end(); - Ptr != PtrEnd; ++Ptr) { - QualType ParamTypes[2] = { S.Context.getPointerDiffType(), *Ptr }; - QualType PointeeType = (*Ptr)->getPointeeType(); + for (QualType PtrTy : CandidateTypes[1].pointer_types()) { + QualType ParamTypes[2] = {S.Context.getPointerDiffType(), PtrTy}; + QualType PointeeType = PtrTy->getPointeeType(); if (!PointeeType->isObjectType()) continue; @@ -8975,11 +9028,8 @@ public: // // where CV12 is the union of CV1 and CV2. void addArrowStarOverloads() { - for (BuiltinCandidateTypeSet::iterator - Ptr = CandidateTypes[0].pointer_begin(), - PtrEnd = CandidateTypes[0].pointer_end(); - Ptr != PtrEnd; ++Ptr) { - QualType C1Ty = (*Ptr); + for (QualType PtrTy : CandidateTypes[0].pointer_types()) { + QualType C1Ty = PtrTy; QualType C1; QualifierCollector Q1; C1 = QualType(Q1.strip(C1Ty->getPointeeType()), 0); @@ -8992,16 +9042,13 @@ public: continue; if (!VisibleTypeConversionsQuals.hasRestrict() && Q1.hasRestrict()) continue; - for (BuiltinCandidateTypeSet::iterator - MemPtr = CandidateTypes[1].member_pointer_begin(), - MemPtrEnd = CandidateTypes[1].member_pointer_end(); - MemPtr != MemPtrEnd; ++MemPtr) { - const MemberPointerType *mptr = cast<MemberPointerType>(*MemPtr); + for (QualType MemPtrTy : CandidateTypes[1].member_pointer_types()) { + const MemberPointerType *mptr = cast<MemberPointerType>(MemPtrTy); QualType C2 = QualType(mptr->getClass(), 0); C2 = C2.getUnqualifiedType(); if (C1 != C2 && !S.IsDerivedFrom(CandidateSet.getLocation(), C1, C2)) break; - QualType ParamTypes[2] = { *Ptr, *MemPtr }; + QualType ParamTypes[2] = {PtrTy, MemPtrTy}; // build CV12 T& QualType T = mptr->getPointeeType(); if (!VisibleTypeConversionsQuals.hasVolatile() && @@ -9031,40 +9078,31 @@ public: llvm::SmallPtrSet<QualType, 8> AddedTypes; for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) { - for (BuiltinCandidateTypeSet::iterator - Ptr = CandidateTypes[ArgIdx].pointer_begin(), - PtrEnd = CandidateTypes[ArgIdx].pointer_end(); - Ptr != PtrEnd; ++Ptr) { - if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)).second) + for (QualType PtrTy : CandidateTypes[ArgIdx].pointer_types()) { + if (!AddedTypes.insert(S.Context.getCanonicalType(PtrTy)).second) continue; - QualType ParamTypes[2] = { *Ptr, *Ptr }; + QualType ParamTypes[2] = {PtrTy, PtrTy}; S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } - for (BuiltinCandidateTypeSet::iterator - MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(), - MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end(); - MemPtr != MemPtrEnd; ++MemPtr) { - if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr)).second) + for (QualType MemPtrTy : CandidateTypes[ArgIdx].member_pointer_types()) { + if (!AddedTypes.insert(S.Context.getCanonicalType(MemPtrTy)).second) continue; - QualType ParamTypes[2] = { *MemPtr, *MemPtr }; + QualType ParamTypes[2] = {MemPtrTy, MemPtrTy}; S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } if (S.getLangOpts().CPlusPlus11) { - for (BuiltinCandidateTypeSet::iterator - Enum = CandidateTypes[ArgIdx].enumeration_begin(), - EnumEnd = CandidateTypes[ArgIdx].enumeration_end(); - Enum != EnumEnd; ++Enum) { - if (!(*Enum)->castAs<EnumType>()->getDecl()->isScoped()) + for (QualType EnumTy : CandidateTypes[ArgIdx].enumeration_types()) { + if (!EnumTy->castAs<EnumType>()->getDecl()->isScoped()) continue; - if (!AddedTypes.insert(S.Context.getCanonicalType(*Enum)).second) + if (!AddedTypes.insert(S.Context.getCanonicalType(EnumTy)).second) continue; - QualType ParamTypes[2] = { *Enum, *Enum }; + QualType ParamTypes[2] = {EnumTy, EnumTy}; S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } } @@ -9508,6 +9546,75 @@ bool clang::isBetterOverloadCandidate( else if (!Cand1.Viable) return false; + // [CUDA] A function with 'never' preference is marked not viable, therefore + // is never shown up here. The worst preference shown up here is 'wrong side', + // e.g. an H function called by a HD function in device compilation. This is + // valid AST as long as the HD function is not emitted, e.g. it is an inline + // function which is called only by an H function. A deferred diagnostic will + // be triggered if it is emitted. However a wrong-sided function is still + // a viable candidate here. + // + // If Cand1 can be emitted and Cand2 cannot be emitted in the current + // context, Cand1 is better than Cand2. If Cand1 can not be emitted and Cand2 + // can be emitted, Cand1 is not better than Cand2. This rule should have + // precedence over other rules. + // + // If both Cand1 and Cand2 can be emitted, or neither can be emitted, then + // other rules should be used to determine which is better. This is because + // host/device based overloading resolution is mostly for determining + // viability of a function. If two functions are both viable, other factors + // should take precedence in preference, e.g. the standard-defined preferences + // like argument conversion ranks or enable_if partial-ordering. The + // preference for pass-object-size parameters is probably most similar to a + // type-based-overloading decision and so should take priority. + // + // If other rules cannot determine which is better, CUDA preference will be + // used again to determine which is better. + // + // TODO: Currently IdentifyCUDAPreference does not return correct values + // for functions called in global variable initializers due to missing + // correct context about device/host. Therefore we can only enforce this + // rule when there is a caller. We should enforce this rule for functions + // in global variable initializers once proper context is added. + // + // TODO: We can only enable the hostness based overloading resolution when + // -fgpu-exclude-wrong-side-overloads is on since this requires deferring + // overloading resolution diagnostics. + if (S.getLangOpts().CUDA && Cand1.Function && Cand2.Function && + S.getLangOpts().GPUExcludeWrongSideOverloads) { + if (FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext)) { + bool IsCallerImplicitHD = Sema::isCUDAImplicitHostDeviceFunction(Caller); + bool IsCand1ImplicitHD = + Sema::isCUDAImplicitHostDeviceFunction(Cand1.Function); + bool IsCand2ImplicitHD = + Sema::isCUDAImplicitHostDeviceFunction(Cand2.Function); + auto P1 = S.IdentifyCUDAPreference(Caller, Cand1.Function); + auto P2 = S.IdentifyCUDAPreference(Caller, Cand2.Function); + assert(P1 != Sema::CFP_Never && P2 != Sema::CFP_Never); + // The implicit HD function may be a function in a system header which + // is forced by pragma. In device compilation, if we prefer HD candidates + // over wrong-sided candidates, overloading resolution may change, which + // may result in non-deferrable diagnostics. As a workaround, we let + // implicit HD candidates take equal preference as wrong-sided candidates. + // This will preserve the overloading resolution. + // TODO: We still need special handling of implicit HD functions since + // they may incur other diagnostics to be deferred. We should make all + // host/device related diagnostics deferrable and remove special handling + // of implicit HD functions. + auto EmitThreshold = + (S.getLangOpts().CUDAIsDevice && IsCallerImplicitHD && + (IsCand1ImplicitHD || IsCand2ImplicitHD)) + ? Sema::CFP_Never + : Sema::CFP_WrongSide; + auto Cand1Emittable = P1 > EmitThreshold; + auto Cand2Emittable = P2 > EmitThreshold; + if (Cand1Emittable && !Cand2Emittable) + return true; + if (!Cand1Emittable && Cand2Emittable) + return false; + } + } + // C++ [over.match.best]p1: // // -- if F is a static member function, ICS1(F) is defined such @@ -9742,12 +9849,6 @@ bool clang::isBetterOverloadCandidate( return Cmp == Comparison::Better; } - if (S.getLangOpts().CUDA && Cand1.Function && Cand2.Function) { - FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext); - return S.IdentifyCUDAPreference(Caller, Cand1.Function) > - S.IdentifyCUDAPreference(Caller, Cand2.Function); - } - bool HasPS1 = Cand1.Function != nullptr && functionHasPassObjectSizeParams(Cand1.Function); bool HasPS2 = Cand2.Function != nullptr && @@ -9755,8 +9856,21 @@ bool clang::isBetterOverloadCandidate( if (HasPS1 != HasPS2 && HasPS1) return true; - Comparison MV = isBetterMultiversionCandidate(Cand1, Cand2); - return MV == Comparison::Better; + auto MV = isBetterMultiversionCandidate(Cand1, Cand2); + if (MV == Comparison::Better) + return true; + if (MV == Comparison::Worse) + return false; + + // If other rules cannot determine which is better, CUDA preference is used + // to determine which is better. + if (S.getLangOpts().CUDA && Cand1.Function && Cand2.Function) { + FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext); + return S.IdentifyCUDAPreference(Caller, Cand1.Function) > + S.IdentifyCUDAPreference(Caller, Cand2.Function); + } + + return false; } /// Determine whether two declarations are "equivalent" for the purposes of @@ -9812,6 +9926,7 @@ bool Sema::isEquivalentInternalLinkageDeclaration(const NamedDecl *A, void Sema::diagnoseEquivalentInternalLinkageDeclarations( SourceLocation Loc, const NamedDecl *D, ArrayRef<const NamedDecl *> Equiv) { + assert(D && "Unknown declaration"); Diag(Loc, diag::ext_equivalent_internal_linkage_decl_in_modules) << D; Module *M = getOwningModule(D); @@ -9849,7 +9964,11 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc, // only on their host/device attributes. Specifically, if one // candidate call is WrongSide and the other is SameSide, we ignore // the WrongSide candidate. - if (S.getLangOpts().CUDA) { + // We only need to remove wrong-sided candidates here if + // -fgpu-exclude-wrong-side-overloads is off. When + // -fgpu-exclude-wrong-side-overloads is on, all candidates are compared + // uniformly in isBetterOverloadCandidate. + if (S.getLangOpts().CUDA && !S.getLangOpts().GPUExcludeWrongSideOverloads) { const FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext); bool ContainsSameSideCandidate = llvm::any_of(Candidates, [&](OverloadCandidate *Cand) { @@ -10110,6 +10229,27 @@ bool Sema::checkAddressOfFunctionIsAvailable(const FunctionDecl *Function, Loc); } +// Don't print candidates other than the one that matches the calling +// convention of the call operator, since that is guaranteed to exist. +static bool shouldSkipNotingLambdaConversionDecl(FunctionDecl *Fn) { + const auto *ConvD = dyn_cast<CXXConversionDecl>(Fn); + + if (!ConvD) + return false; + const auto *RD = cast<CXXRecordDecl>(Fn->getParent()); + if (!RD->isLambda()) + return false; + + CXXMethodDecl *CallOp = RD->getLambdaCallOperator(); + CallingConv CallOpCC = + CallOp->getType()->getAs<FunctionType>()->getCallConv(); + QualType ConvRTy = ConvD->getType()->getAs<FunctionType>()->getReturnType(); + CallingConv ConvToCC = + ConvRTy->getPointeeType()->getAs<FunctionType>()->getCallConv(); + + return ConvToCC != CallOpCC; +} + // Notes the location of an overload candidate. void Sema::NoteOverloadCandidate(NamedDecl *Found, FunctionDecl *Fn, OverloadCandidateRewriteKind RewriteKind, @@ -10119,6 +10259,8 @@ void Sema::NoteOverloadCandidate(NamedDecl *Found, FunctionDecl *Fn, if (Fn->isMultiVersion() && Fn->hasAttr<TargetAttr>() && !Fn->getAttr<TargetAttr>()->isDefaultVersion()) return; + if (shouldSkipNotingLambdaConversionDecl(Fn)) + return; std::string FnDesc; std::pair<OverloadCandidateKind, OverloadCandidateSelect> KSPair = @@ -10337,7 +10479,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, } unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers(); - assert(CVR && "unexpected qualifiers mismatch"); + assert(CVR && "expected qualifiers mismatch"); if (isObjectArgument) { S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr_this) @@ -10354,6 +10496,17 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, return; } + if (Conv.Bad.Kind == BadConversionSequence::lvalue_ref_to_rvalue || + Conv.Bad.Kind == BadConversionSequence::rvalue_ref_to_lvalue) { + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_value_category) + << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc + << (unsigned)isObjectArgument << I + 1 + << (Conv.Bad.Kind == BadConversionSequence::rvalue_ref_to_lvalue) + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()); + MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); + return; + } + // Special diagnostic for failure to convert an initializer list, since // telling the user that it has type void is not useful. if (FromExpr && isa<InitListExpr>(FromExpr)) { @@ -10411,15 +10564,6 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, !ToRefTy->getPointeeType()->isIncompleteType() && S.IsDerivedFrom(SourceLocation(), ToRefTy->getPointeeType(), FromTy)) { BaseToDerivedConversion = 3; - } else if (ToTy->isLValueReferenceType() && !FromExpr->isLValue() && - ToTy.getNonReferenceType().getCanonicalType() == - FromTy.getNonReferenceType().getCanonicalType()) { - S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_lvalue) - << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc - << (unsigned)isObjectArgument << I + 1 - << (FromExpr ? FromExpr->getSourceRange() : SourceRange()); - MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); - return; } } @@ -10976,6 +11120,8 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, bool TakingCandidateAddress, LangAS CtorDestAS = LangAS::Default) { FunctionDecl *Fn = Cand->Function; + if (shouldSkipNotingLambdaConversionDecl(Fn)) + return; // Note deleted candidates, but only if they're viable. if (Cand->Viable) { @@ -11092,6 +11238,9 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, } static void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) { + if (shouldSkipNotingLambdaConversionDecl(Cand->Surrogate)) + return; + // Desugar the type of the surrogate down to a function type, // retaining as many typedefs as possible while still showing // the function type (and, therefore, its parameter types). @@ -11482,16 +11631,34 @@ SmallVector<OverloadCandidate *, 32> OverloadCandidateSet::CompleteCandidates( return Cands; } +bool OverloadCandidateSet::shouldDeferDiags(Sema &S, ArrayRef<Expr *> Args, + SourceLocation OpLoc) { + bool DeferHint = false; + if (S.getLangOpts().CUDA && S.getLangOpts().GPUDeferDiag) { + // Defer diagnostic for CUDA/HIP if there are wrong-sided candidates or + // host device candidates. + auto WrongSidedCands = + CompleteCandidates(S, OCD_AllCandidates, Args, OpLoc, [](auto &Cand) { + return (Cand.Viable == false && + Cand.FailureKind == ovl_fail_bad_target) || + (Cand.Function->template hasAttr<CUDAHostAttr>() && + Cand.Function->template hasAttr<CUDADeviceAttr>()); + }); + DeferHint = WrongSidedCands.size(); + } + return DeferHint; +} + /// When overload resolution fails, prints diagnostic messages containing the /// candidates in the candidate set. -void OverloadCandidateSet::NoteCandidates(PartialDiagnosticAt PD, - Sema &S, OverloadCandidateDisplayKind OCD, ArrayRef<Expr *> Args, - StringRef Opc, SourceLocation OpLoc, +void OverloadCandidateSet::NoteCandidates( + PartialDiagnosticAt PD, Sema &S, OverloadCandidateDisplayKind OCD, + ArrayRef<Expr *> Args, StringRef Opc, SourceLocation OpLoc, llvm::function_ref<bool(OverloadCandidate &)> Filter) { auto Cands = CompleteCandidates(S, OCD, Args, OpLoc, Filter); - S.Diag(PD.first, PD.second); + S.Diag(PD.first, PD.second, shouldDeferDiags(S, Args, OpLoc)); NoteCandidates(S, Args, Cands, Opc, OpLoc); @@ -11543,7 +11710,9 @@ void OverloadCandidateSet::NoteCandidates(Sema &S, ArrayRef<Expr *> Args, } if (I != E) - S.Diag(OpLoc, diag::note_ovl_too_many_candidates) << int(E - I); + S.Diag(OpLoc, diag::note_ovl_too_many_candidates, + shouldDeferDiags(S, Args, OpLoc)) + << int(E - I); } static SourceLocation @@ -12512,6 +12681,16 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, CandidateSet, PartialOverloading); } +/// Add the call candidates from the given set of lookup results to the given +/// overload set. Non-function lookup results are ignored. +void Sema::AddOverloadedCallCandidates( + LookupResult &R, TemplateArgumentListInfo *ExplicitTemplateArgs, + ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet) { + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) + AddOverloadedCallCandidate(*this, I.getPair(), ExplicitTemplateArgs, Args, + CandidateSet, false, /*KnownValid*/ false); +} + /// Determine whether a declaration with the specified name could be moved into /// a different namespace. static bool canBeDeclaredInNamespace(const DeclarationName &Name) { @@ -12531,13 +12710,11 @@ static bool canBeDeclaredInNamespace(const DeclarationName &Name) { /// correctly implement two-stage name lookup. /// /// Returns true if a viable candidate was found and a diagnostic was issued. -static bool -DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc, - const CXXScopeSpec &SS, LookupResult &R, - OverloadCandidateSet::CandidateSetKind CSK, - TemplateArgumentListInfo *ExplicitTemplateArgs, - ArrayRef<Expr *> Args, - bool *DoDiagnoseEmptyLookup = nullptr) { +static bool DiagnoseTwoPhaseLookup( + Sema &SemaRef, SourceLocation FnLoc, const CXXScopeSpec &SS, + LookupResult &R, OverloadCandidateSet::CandidateSetKind CSK, + TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, + CXXRecordDecl **FoundInClass = nullptr) { if (!SemaRef.inTemplateInstantiation() || !SS.isEmpty()) return false; @@ -12550,26 +12727,32 @@ DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc, if (!R.empty()) { R.suppressDiagnostics(); - if (isa<CXXRecordDecl>(DC)) { - // Don't diagnose names we find in classes; we get much better - // diagnostics for these from DiagnoseEmptyLookup. - R.clear(); - if (DoDiagnoseEmptyLookup) - *DoDiagnoseEmptyLookup = true; - return false; - } - OverloadCandidateSet Candidates(FnLoc, CSK); - for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) - AddOverloadedCallCandidate(SemaRef, I.getPair(), - ExplicitTemplateArgs, Args, - Candidates, false, /*KnownValid*/ false); + SemaRef.AddOverloadedCallCandidates(R, ExplicitTemplateArgs, Args, + Candidates); OverloadCandidateSet::iterator Best; - if (Candidates.BestViableFunction(SemaRef, FnLoc, Best) != OR_Success) { - // No viable functions. Don't bother the user with notes for functions - // which don't work and shouldn't be found anyway. - R.clear(); + OverloadingResult OR = + Candidates.BestViableFunction(SemaRef, FnLoc, Best); + + if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) { + // We either found non-function declarations or a best viable function + // at class scope. A class-scope lookup result disables ADL. Don't + // look past this, but let the caller know that we found something that + // either is, or might be, usable in this class. + if (FoundInClass) { + *FoundInClass = RD; + if (OR == OR_Success) { + R.clear(); + R.addDecl(Best->FoundDecl.getDecl(), Best->FoundDecl.getAccess()); + R.resolveKind(); + } + } + return false; + } + + if (OR != OR_Success) { + // There wasn't a unique best function or function template. return false; } @@ -12665,7 +12848,11 @@ public: /// Attempts to recover from a call where no functions were found. /// -/// Returns true if new candidates were found. +/// This function will do one of three things: +/// * Diagnose, recover, and return a recovery expression. +/// * Diagnose, fail to recover, and return ExprError(). +/// * Do not diagnose, do not recover, and return ExprResult(). The caller is +/// expected to diagnose as appropriate. static ExprResult BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, @@ -12678,9 +12865,8 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, // // template <typename T> auto foo(T t) -> decltype(foo(t)) {} // template <typename T> auto foo(T t) -> decltype(foo(&t)) {} - // if (SemaRef.IsBuildingRecoveryCallExpr) - return ExprError(); + return ExprResult(); BuildRecoveryCallExprRAII RCE(SemaRef); CXXScopeSpec SS; @@ -12696,10 +12882,14 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(), Sema::LookupOrdinaryName); - bool DoDiagnoseEmptyLookup = EmptyLookup; - if (!DiagnoseTwoPhaseLookup( - SemaRef, Fn->getExprLoc(), SS, R, OverloadCandidateSet::CSK_Normal, - ExplicitTemplateArgs, Args, &DoDiagnoseEmptyLookup)) { + CXXRecordDecl *FoundInClass = nullptr; + if (DiagnoseTwoPhaseLookup(SemaRef, Fn->getExprLoc(), SS, R, + OverloadCandidateSet::CSK_Normal, + ExplicitTemplateArgs, Args, &FoundInClass)) { + // OK, diagnosed a two-phase lookup issue. + } else if (EmptyLookup) { + // Try to recover from an empty lookup with typo correction. + R.clear(); NoTypoCorrectionCCC NoTypoValidator{}; FunctionCallFilterCCC FunctionCallValidator(SemaRef, Args.size(), ExplicitTemplateArgs != nullptr, @@ -12708,12 +12898,24 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, AllowTypoCorrection ? static_cast<CorrectionCandidateCallback &>(FunctionCallValidator) : static_cast<CorrectionCandidateCallback &>(NoTypoValidator); - if (!DoDiagnoseEmptyLookup || - SemaRef.DiagnoseEmptyLookup(S, SS, R, Validator, ExplicitTemplateArgs, + if (SemaRef.DiagnoseEmptyLookup(S, SS, R, Validator, ExplicitTemplateArgs, Args)) return ExprError(); + } else if (FoundInClass && SemaRef.getLangOpts().MSVCCompat) { + // We found a usable declaration of the name in a dependent base of some + // enclosing class. + // FIXME: We should also explain why the candidates found by name lookup + // were not viable. + if (SemaRef.DiagnoseDependentMemberLookup(R)) + return ExprError(); + } else { + // We had viable candidates and couldn't recover; let the caller diagnose + // this. + return ExprResult(); } + // If we get here, we should have issued a diagnostic and formed a recovery + // lookup result. assert(!R.empty() && "lookup results empty despite recovery"); // If recovery created an ambiguity, just bail out. @@ -12795,8 +12997,9 @@ bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn, // then create a type dependent CallExpr. The goal is to postpone name // lookup to instantiation time to be able to search into type dependent // base classes. - CallExpr *CE = CallExpr::Create(Context, Fn, Args, Context.DependentTy, - VK_RValue, RParenLoc); + CallExpr *CE = + CallExpr::Create(Context, Fn, Args, Context.DependentTy, VK_RValue, + RParenLoc, CurFPFeatureOverrides()); CE->markDependentForPostponedNameLookup(); *Result = CE; return true; @@ -12818,6 +13021,8 @@ static QualType chooseRecoveryType(OverloadCandidateSet &CS, auto ConsiderCandidate = [&](const OverloadCandidate &Candidate) { if (!Candidate.Function) return; + if (Candidate.Function->isInvalidDecl()) + return; QualType T = Candidate.Function->getReturnType(); if (T.isNull()) return; @@ -12843,7 +13048,12 @@ static QualType chooseRecoveryType(OverloadCandidateSet &CS, for (const auto &C : CS) ConsiderCandidate(C); - return Result.getValueOr(QualType()); + if (!Result) + return QualType(); + auto Value = Result.getValue(); + if (Value.isNull() || Value->isUndeducedType()) + return QualType(); + return Value; } /// FinishOverloadedCallExpr - given an OverloadCandidateSet, builds and returns @@ -12859,11 +13069,6 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, OverloadCandidateSet::iterator *Best, OverloadingResult OverloadResult, bool AllowTypoCorrection) { - if (CandidateSet->empty()) - return BuildRecoveryCallExpr(SemaRef, S, Fn, ULE, LParenLoc, Args, - RParenLoc, /*EmptyLookup=*/true, - AllowTypoCorrection); - switch (OverloadResult) { case OR_Success: { FunctionDecl *FDecl = (*Best)->Function; @@ -12881,9 +13086,9 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, // have meant to call. ExprResult Recovery = BuildRecoveryCallExpr(SemaRef, S, Fn, ULE, LParenLoc, Args, RParenLoc, - /*EmptyLookup=*/false, + CandidateSet->empty(), AllowTypoCorrection); - if (!Recovery.isInvalid()) + if (Recovery.isInvalid() || Recovery.isUsable()) return Recovery; // If the user passes in a function that we can't take the address of, we @@ -12991,7 +13196,18 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, static bool IsOverloaded(const UnresolvedSetImpl &Functions) { return Functions.size() > 1 || - (Functions.size() == 1 && isa<FunctionTemplateDecl>(*Functions.begin())); + (Functions.size() == 1 && + isa<FunctionTemplateDecl>((*Functions.begin())->getUnderlyingDecl())); +} + +ExprResult Sema::CreateUnresolvedLookupExpr(CXXRecordDecl *NamingClass, + NestedNameSpecifierLoc NNSLoc, + DeclarationNameInfo DNI, + const UnresolvedSetImpl &Fns, + bool PerformADL) { + return UnresolvedLookupExpr::Create(Context, NamingClass, NNSLoc, DNI, + PerformADL, IsOverloaded(Fns), + Fns.begin(), Fns.end()); } /// Create a unary operation that may resolve to an overloaded @@ -13044,10 +13260,11 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, CurFPFeatureOverrides()); CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators - UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create( - Context, NamingClass, NestedNameSpecifierLoc(), OpNameInfo, - /*ADL*/ true, IsOverloaded(Fns), Fns.begin(), Fns.end()); - return CXXOperatorCallExpr::Create(Context, Op, Fn, ArgsArray, + ExprResult Fn = CreateUnresolvedLookupExpr( + NamingClass, NestedNameSpecifierLoc(), OpNameInfo, Fns); + if (Fn.isInvalid()) + return ExprError(); + return CXXOperatorCallExpr::Create(Context, Op, Fn.get(), ArgsArray, Context.DependentTy, VK_RValue, OpLoc, CurFPFeatureOverrides()); } @@ -13291,14 +13508,14 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc, if (Fns.empty()) { // If there are no functions to store, just build a dependent // BinaryOperator or CompoundAssignment. - if (Opc <= BO_Assign || Opc > BO_OrAssign) - return BinaryOperator::Create( - Context, Args[0], Args[1], Opc, Context.DependentTy, VK_RValue, - OK_Ordinary, OpLoc, CurFPFeatureOverrides()); - return CompoundAssignOperator::Create( - Context, Args[0], Args[1], Opc, Context.DependentTy, VK_LValue, - OK_Ordinary, OpLoc, CurFPFeatureOverrides(), Context.DependentTy, - Context.DependentTy); + if (BinaryOperator::isCompoundAssignmentOp(Opc)) + return CompoundAssignOperator::Create( + Context, Args[0], Args[1], Opc, Context.DependentTy, VK_LValue, + OK_Ordinary, OpLoc, CurFPFeatureOverrides(), Context.DependentTy, + Context.DependentTy); + return BinaryOperator::Create(Context, Args[0], Args[1], Opc, + Context.DependentTy, VK_RValue, OK_Ordinary, + OpLoc, CurFPFeatureOverrides()); } // FIXME: save results of ADL from here? @@ -13306,10 +13523,11 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // TODO: provide better source location info in DNLoc component. DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op); DeclarationNameInfo OpNameInfo(OpName, OpLoc); - UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create( - Context, NamingClass, NestedNameSpecifierLoc(), OpNameInfo, - /*ADL*/ PerformADL, IsOverloaded(Fns), Fns.begin(), Fns.end()); - return CXXOperatorCallExpr::Create(Context, Op, Fn, Args, + ExprResult Fn = CreateUnresolvedLookupExpr( + NamingClass, NestedNameSpecifierLoc(), OpNameInfo, Fns, PerformADL); + if (Fn.isInvalid()) + return ExprError(); + return CXXOperatorCallExpr::Create(Context, Op, Fn.get(), Args, Context.DependentTy, VK_RValue, OpLoc, CurFPFeatureOverrides()); } @@ -13773,15 +13991,13 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // CHECKME: no 'operator' keyword? DeclarationNameInfo OpNameInfo(OpName, LLoc); OpNameInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc)); - UnresolvedLookupExpr *Fn - = UnresolvedLookupExpr::Create(Context, NamingClass, - NestedNameSpecifierLoc(), OpNameInfo, - /*ADL*/ true, /*Overloaded*/ false, - UnresolvedSetIterator(), - UnresolvedSetIterator()); + ExprResult Fn = CreateUnresolvedLookupExpr( + NamingClass, NestedNameSpecifierLoc(), OpNameInfo, UnresolvedSet<0>()); + if (Fn.isInvalid()) + return ExprError(); // Can't add any actual overloads yet - return CXXOperatorCallExpr::Create(Context, OO_Subscript, Fn, Args, + return CXXOperatorCallExpr::Create(Context, OO_Subscript, Fn.get(), Args, Context.DependentTy, VK_RValue, RLoc, CurFPFeatureOverrides()); } @@ -13932,11 +14148,11 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, /// parameter). The caller needs to validate that the member /// expression refers to a non-static member function or an overloaded /// member function. -ExprResult -Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, - SourceLocation LParenLoc, - MultiExprArg Args, - SourceLocation RParenLoc) { +ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, + SourceLocation LParenLoc, + MultiExprArg Args, + SourceLocation RParenLoc, + bool AllowRecovery) { assert(MemExprE->getType() == Context.BoundMemberTy || MemExprE->getType() == Context.OverloadTy); @@ -13976,9 +14192,9 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, << (qualsString.find(' ') == std::string::npos ? 1 : 2); } - CXXMemberCallExpr *call = - CXXMemberCallExpr::Create(Context, MemExprE, Args, resultType, - valueKind, RParenLoc, proto->getNumParams()); + CXXMemberCallExpr *call = CXXMemberCallExpr::Create( + Context, MemExprE, Args, resultType, valueKind, RParenLoc, + CurFPFeatureOverrides(), proto->getNumParams()); if (CheckCallReturnType(proto->getReturnType(), op->getRHS()->getBeginLoc(), call, nullptr)) @@ -13993,9 +14209,20 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, return MaybeBindToTemporary(call); } + // We only try to build a recovery expr at this level if we can preserve + // the return type, otherwise we return ExprError() and let the caller + // recover. + auto BuildRecoveryExpr = [&](QualType Type) { + if (!AllowRecovery) + return ExprError(); + std::vector<Expr *> SubExprs = {MemExprE}; + llvm::for_each(Args, [&SubExprs](Expr *E) { SubExprs.push_back(E); }); + return CreateRecoveryExpr(MemExprE->getBeginLoc(), RParenLoc, SubExprs, + Type); + }; if (isa<CXXPseudoDestructorExpr>(NakedMemExpr)) return CallExpr::Create(Context, MemExprE, Args, Context.VoidTy, VK_RValue, - RParenLoc); + RParenLoc, CurFPFeatureOverrides()); UnbridgedCastsSet UnbridgedCasts; if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts)) @@ -14067,6 +14294,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, UnbridgedCasts.restore(); OverloadCandidateSet::iterator Best; + bool Succeeded = false; switch (CandidateSet.BestViableFunction(*this, UnresExpr->getBeginLoc(), Best)) { case OR_Success: @@ -14074,7 +14302,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, FoundDecl = Best->FoundDecl; CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl); if (DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc())) - return ExprError(); + break; // If FoundDecl is different from Method (such as if one is a template // and the other a specialization), make sure DiagnoseUseOfDecl is // called on both. @@ -14083,7 +14311,8 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, // being used. if (Method != FoundDecl.getDecl() && DiagnoseUseOfDecl(Method, UnresExpr->getNameLoc())) - return ExprError(); + break; + Succeeded = true; break; case OR_No_Viable_Function: @@ -14093,27 +14322,25 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, PDiag(diag::err_ovl_no_viable_member_function_in_call) << DeclName << MemExprE->getSourceRange()), *this, OCD_AllCandidates, Args); - // FIXME: Leaking incoming expressions! - return ExprError(); - + break; case OR_Ambiguous: CandidateSet.NoteCandidates( PartialDiagnosticAt(UnresExpr->getMemberLoc(), PDiag(diag::err_ovl_ambiguous_member_call) << DeclName << MemExprE->getSourceRange()), *this, OCD_AmbiguousCandidates, Args); - // FIXME: Leaking incoming expressions! - return ExprError(); - + break; case OR_Deleted: CandidateSet.NoteCandidates( PartialDiagnosticAt(UnresExpr->getMemberLoc(), PDiag(diag::err_ovl_deleted_member_call) << DeclName << MemExprE->getSourceRange()), *this, OCD_AllCandidates, Args); - // FIXME: Leaking incoming expressions! - return ExprError(); + break; } + // Overload resolution fails, try to recover. + if (!Succeeded) + return BuildRecoveryExpr(chooseRecoveryType(CandidateSet, &Best)); MemExprE = FixOverloadedFunctionReference(MemExprE, FoundDecl, Method); @@ -14133,14 +14360,14 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, assert(Method && "Member call to something that isn't a method?"); const auto *Proto = Method->getType()->castAs<FunctionProtoType>(); - CXXMemberCallExpr *TheCall = - CXXMemberCallExpr::Create(Context, MemExprE, Args, ResultType, VK, - RParenLoc, Proto->getNumParams()); + CXXMemberCallExpr *TheCall = CXXMemberCallExpr::Create( + Context, MemExprE, Args, ResultType, VK, RParenLoc, + CurFPFeatureOverrides(), Proto->getNumParams()); // Check for a valid return type. if (CheckCallReturnType(Method->getReturnType(), MemExpr->getMemberLoc(), TheCall, Method)) - return ExprError(); + return BuildRecoveryExpr(ResultType); // Convert the object argument (for a non-static member function call). // We only need to do this if there was actually an overload; otherwise @@ -14157,7 +14384,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, // Convert the rest of the arguments if (ConvertArgumentsForCall(TheCall, MemExpr, Method, Proto, Args, RParenLoc)) - return ExprError(); + return BuildRecoveryExpr(ResultType); DiagnoseSentinelCalls(Method, LParenLoc, Args); @@ -14190,12 +14417,12 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, Diag(MemExpr->getBeginLoc(), diag::warn_call_to_pure_virtual_member_function_from_ctor_dtor) << MD->getDeclName() << isa<CXXDestructorDecl>(CurContext) - << MD->getParent()->getDeclName(); + << MD->getParent(); Diag(MD->getBeginLoc(), diag::note_previous_decl) << MD->getDeclName(); if (getLangOpts().AppleKext) Diag(MemExpr->getBeginLoc(), diag::note_pure_qualified_call_kext) - << MD->getParent()->getDeclName() << MD->getDeclName(); + << MD->getParent() << MD->getDeclName(); } } @@ -14377,9 +14604,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, if (Call.isInvalid()) return ExprError(); // Record usage of conversion in an implicit cast. - Call = ImplicitCastExpr::Create(Context, Call.get()->getType(), - CK_UserDefinedConversion, Call.get(), - nullptr, VK_RValue); + Call = ImplicitCastExpr::Create( + Context, Call.get()->getType(), CK_UserDefinedConversion, Call.get(), + nullptr, VK_RValue, CurFPFeatureOverrides()); return BuildCallExpr(S, Call.get(), LParenLoc, Args, RParenLoc); } @@ -14678,7 +14905,7 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R, UserDefinedLiteral *UDL = UserDefinedLiteral::Create( Context, Fn.get(), llvm::makeArrayRef(ConvArgs, Args.size()), ResultTy, - VK, LitEndLoc, UDSuffixLoc); + VK, LitEndLoc, UDSuffixLoc, CurFPFeatureOverrides()); if (CheckCallReturnType(FD->getReturnType(), UDSuffixLoc, UDL, FD)) return ExprError(); @@ -14724,12 +14951,12 @@ Sema::BuildForRangeBeginEndCall(SourceLocation Loc, return FRS_DiagnosticIssued; } } else { - UnresolvedSet<0> FoundNames; - UnresolvedLookupExpr *Fn = - UnresolvedLookupExpr::Create(Context, /*NamingClass=*/nullptr, - NestedNameSpecifierLoc(), NameInfo, - /*NeedsADL=*/true, /*Overloaded=*/false, - FoundNames.begin(), FoundNames.end()); + ExprResult FnR = CreateUnresolvedLookupExpr(/*NamingClass=*/nullptr, + NestedNameSpecifierLoc(), + NameInfo, UnresolvedSet<0>()); + if (FnR.isInvalid()) + return FRS_DiagnosticIssued; + UnresolvedLookupExpr *Fn = cast<UnresolvedLookupExpr>(FnR.get()); bool CandidateSetError = buildOverloadedCallSet(S, Fn, Fn, Range, Loc, CandidateSet, CallExpr); @@ -14784,10 +15011,9 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, if (SubExpr == ICE->getSubExpr()) return ICE; - return ImplicitCastExpr::Create(Context, ICE->getType(), - ICE->getCastKind(), - SubExpr, nullptr, - ICE->getValueKind()); + return ImplicitCastExpr::Create(Context, ICE->getType(), ICE->getCastKind(), + SubExpr, nullptr, ICE->getValueKind(), + CurFPFeatureOverrides()); } if (auto *GSE = dyn_cast<GenericSelectionExpr>(E)) { diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index db7603b42f7b..af35052ee1e3 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -17,19 +17,19 @@ using namespace clang; // SYCL device specific diagnostics implementation // ----------------------------------------------------------------------------- -Sema::DeviceDiagBuilder Sema::SYCLDiagIfDeviceCode(SourceLocation Loc, - unsigned DiagID) { +Sema::SemaDiagnosticBuilder Sema::SYCLDiagIfDeviceCode(SourceLocation Loc, + unsigned DiagID) { assert(getLangOpts().SYCLIsDevice && "Should only be called during SYCL compilation"); FunctionDecl *FD = dyn_cast<FunctionDecl>(getCurLexicalContext()); - DeviceDiagBuilder::Kind DiagKind = [this, FD] { + SemaDiagnosticBuilder::Kind DiagKind = [this, FD] { if (!FD) - return DeviceDiagBuilder::K_Nop; + return SemaDiagnosticBuilder::K_Nop; if (getEmissionStatus(FD) == Sema::FunctionEmissionStatus::Emitted) - return DeviceDiagBuilder::K_ImmediateWithCallStack; - return DeviceDiagBuilder::K_Deferred; + return SemaDiagnosticBuilder::K_ImmediateWithCallStack; + return SemaDiagnosticBuilder::K_Deferred; }(); - return DeviceDiagBuilder(DiagKind, Loc, DiagID, FD, *this); + return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, FD, *this); } bool Sema::checkSYCLDeviceFunction(SourceLocation Loc, FunctionDecl *Callee) { @@ -42,8 +42,8 @@ bool Sema::checkSYCLDeviceFunction(SourceLocation Loc, FunctionDecl *Callee) { if (isUnevaluatedContext() || isConstantEvaluated()) return true; - DeviceDiagBuilder::Kind DiagKind = DeviceDiagBuilder::K_Nop; + SemaDiagnosticBuilder::Kind DiagKind = SemaDiagnosticBuilder::K_Nop; - return DiagKind != DeviceDiagBuilder::K_Immediate && - DiagKind != DeviceDiagBuilder::K_ImmediateWithCallStack; + return DiagKind != SemaDiagnosticBuilder::K_Immediate && + DiagKind != SemaDiagnosticBuilder::K_ImmediateWithCallStack; } diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 73f3183c163f..b24a8ab110b2 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -385,6 +385,14 @@ void Sema::ActOnStartOfCompoundStmt(bool IsStmtExpr) { PushCompoundScope(IsStmtExpr); } +void Sema::ActOnAfterCompoundStatementLeadingPragmas() { + if (getCurFPFeatures().isFPConstrained()) { + FunctionScopeInfo *FSI = getCurFunction(); + assert(FSI); + FSI->setUsesFPIntrin(); + } +} + void Sema::ActOnFinishOfCompoundStmt() { PopCompoundScope(); } @@ -397,11 +405,6 @@ StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef<Stmt *> Elts, bool isStmtExpr) { const unsigned NumElts = Elts.size(); - // Mark the current function as usng floating point constrained intrinsics - if (getCurFPFeatures().isFPConstrained()) - if (FunctionDecl *F = dyn_cast<FunctionDecl>(CurContext)) - F->setUsesFPIntrin(true); - // If we're in C89 mode, check that we don't have any decls after stmts. If // so, emit an extension diagnostic. if (!getLangOpts().C99 && !getLangOpts().CPlusPlus) { @@ -467,7 +470,7 @@ Sema::ActOnCaseExpr(SourceLocation CaseLoc, ExprResult Val) { ExprResult ER = E; if (!E->isValueDependent()) - ER = VerifyIntegerConstantExpression(E); + ER = VerifyIntegerConstantExpression(E, AllowFold); if (!ER.isInvalid()) ER = DefaultLvalueConversion(ER.get()); if (!ER.isInvalid()) @@ -574,11 +577,11 @@ public: }; } -StmtResult -Sema::ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr, Stmt *InitStmt, - ConditionResult Cond, - Stmt *thenStmt, SourceLocation ElseLoc, - Stmt *elseStmt) { +StmtResult Sema::ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr, + SourceLocation LParenLoc, Stmt *InitStmt, + ConditionResult Cond, SourceLocation RParenLoc, + Stmt *thenStmt, SourceLocation ElseLoc, + Stmt *elseStmt) { if (Cond.isInvalid()) Cond = ConditionResult( *this, nullptr, @@ -597,12 +600,40 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr, Stmt *InitStmt, DiagnoseEmptyStmtBody(CondExpr->getEndLoc(), thenStmt, diag::warn_empty_if_body); - return BuildIfStmt(IfLoc, IsConstexpr, InitStmt, Cond, thenStmt, ElseLoc, - elseStmt); + if (IsConstexpr) { + auto DiagnoseLikelihood = [&](const Stmt *S) { + if (const Attr *A = Stmt::getLikelihoodAttr(S)) { + Diags.Report(A->getLocation(), + diag::warn_attribute_has_no_effect_on_if_constexpr) + << A << A->getRange(); + Diags.Report(IfLoc, + diag::note_attribute_has_no_effect_on_if_constexpr_here) + << SourceRange(IfLoc, LParenLoc.getLocWithOffset(-1)); + } + }; + DiagnoseLikelihood(thenStmt); + DiagnoseLikelihood(elseStmt); + } else { + std::tuple<bool, const Attr *, const Attr *> LHC = + Stmt::determineLikelihoodConflict(thenStmt, elseStmt); + if (std::get<0>(LHC)) { + const Attr *ThenAttr = std::get<1>(LHC); + const Attr *ElseAttr = std::get<2>(LHC); + Diags.Report(ThenAttr->getLocation(), + diag::warn_attributes_likelihood_ifstmt_conflict) + << ThenAttr << ThenAttr->getRange(); + Diags.Report(ElseAttr->getLocation(), diag::note_conflicting_attribute) + << ElseAttr << ElseAttr->getRange(); + } + } + + return BuildIfStmt(IfLoc, IsConstexpr, LParenLoc, InitStmt, Cond, RParenLoc, + thenStmt, ElseLoc, elseStmt); } StmtResult Sema::BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr, - Stmt *InitStmt, ConditionResult Cond, + SourceLocation LParenLoc, Stmt *InitStmt, + ConditionResult Cond, SourceLocation RParenLoc, Stmt *thenStmt, SourceLocation ElseLoc, Stmt *elseStmt) { if (Cond.isInvalid()) @@ -612,7 +643,8 @@ StmtResult Sema::BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr, setFunctionHasBranchProtectedScope(); return IfStmt::Create(Context, IfLoc, IsConstexpr, InitStmt, Cond.get().first, - Cond.get().second, thenStmt, ElseLoc, elseStmt); + Cond.get().second, LParenLoc, RParenLoc, thenStmt, + ElseLoc, elseStmt); } namespace { @@ -640,8 +672,7 @@ static bool CmpCaseVals(const std::pair<llvm::APSInt, CaseStmt*>& lhs, return true; if (lhs.first == rhs.first && - lhs.second->getCaseLoc().getRawEncoding() - < rhs.second->getCaseLoc().getRawEncoding()) + lhs.second->getCaseLoc() < rhs.second->getCaseLoc()) return true; return false; } @@ -739,7 +770,9 @@ ExprResult Sema::CheckSwitchCondition(SourceLocation SwitchLoc, Expr *Cond) { } StmtResult Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, - Stmt *InitStmt, ConditionResult Cond) { + SourceLocation LParenLoc, + Stmt *InitStmt, ConditionResult Cond, + SourceLocation RParenLoc) { Expr *CondExpr = Cond.get().second; assert((Cond.isInvalid() || CondExpr) && "switch with no condition"); @@ -761,7 +794,8 @@ StmtResult Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, setFunctionHasBranchIntoScope(); - auto *SS = SwitchStmt::Create(Context, InitStmt, Cond.get().first, CondExpr); + auto *SS = SwitchStmt::Create(Context, InitStmt, Cond.get().first, CondExpr, + LParenLoc, RParenLoc); getCurFunction()->SwitchStack.push_back( FunctionScopeInfo::SwitchInfo(SS, false)); return SS; @@ -1244,10 +1278,10 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, // Produce a nice diagnostic if multiple values aren't handled. if (!UnhandledNames.empty()) { - DiagnosticBuilder DB = Diag(CondExpr->getExprLoc(), - TheDefaultStmt ? diag::warn_def_missing_case + auto DB = Diag(CondExpr->getExprLoc(), TheDefaultStmt + ? diag::warn_def_missing_case : diag::warn_missing_case) - << (int)UnhandledNames.size(); + << (int)UnhandledNames.size(); for (size_t I = 0, E = std::min(UnhandledNames.size(), (size_t)3); I != E; ++I) @@ -1787,15 +1821,27 @@ StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, // C99 6.8.5p3: The declaration part of a 'for' statement shall only // declare identifiers for objects having storage class 'auto' or // 'register'. + const Decl *NonVarSeen = nullptr; + bool VarDeclSeen = false; for (auto *DI : DS->decls()) { - VarDecl *VD = dyn_cast<VarDecl>(DI); - if (VD && VD->isLocalVarDecl() && !VD->hasLocalStorage()) - VD = nullptr; - if (!VD) { - Diag(DI->getLocation(), diag::err_non_local_variable_decl_in_for); - DI->setInvalidDecl(); + if (VarDecl *VD = dyn_cast<VarDecl>(DI)) { + VarDeclSeen = true; + if (VD->isLocalVarDecl() && !VD->hasLocalStorage()) { + Diag(DI->getLocation(), diag::err_non_local_variable_decl_in_for); + DI->setInvalidDecl(); + } + } else if (!NonVarSeen) { + // Keep track of the first non-variable declaration we saw so that + // we can diagnose if we don't see any variable declarations. This + // covers a case like declaring a typedef, function, or structure + // type rather than a variable. + NonVarSeen = DI; } } + // Diagnose if we saw a non-variable declaration but no variable + // declarations. + if (NonVarSeen && !VarDeclSeen) + Diag(NonVarSeen->getLocation(), diag::err_non_variable_decl_in_for); } } @@ -3039,12 +3085,13 @@ bool Sema::isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD, // variable will no longer be used. if (VD->hasAttr<BlocksAttr>()) return false; + // ...non-volatile... + if (VD->getType().isVolatileQualified()) + return false; + if (CESK & CES_AllowDifferentTypes) return true; - // ...non-volatile... - if (VD->getType().isVolatileQualified()) return false; - // Variables with higher required alignment than their type's ABI // alignment cannot use NRVO. if (!VD->getType()->isDependentType() && VD->hasAttr<AlignedAttr>() && @@ -3070,15 +3117,18 @@ bool Sema::isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD, /// If move-initialization is not possible, such that we must fall back to /// treating the operand as an lvalue, we will leave Res in its original /// invalid state. -static void TryMoveInitialization(Sema& S, - const InitializedEntity &Entity, +/// +/// \returns Whether we need to do the second overload resolution. If the first +/// overload resolution fails, or if the first overload resolution succeeds but +/// the selected constructor/operator doesn't match the additional criteria, we +/// need to do the second overload resolution. +static bool TryMoveInitialization(Sema &S, const InitializedEntity &Entity, const VarDecl *NRVOCandidate, - QualType ResultType, - Expr *&Value, + QualType ResultType, Expr *&Value, bool ConvertingConstructorsOnly, - ExprResult &Res) { + bool IsDiagnosticsCheck, ExprResult &Res) { ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, Value->getType(), - CK_NoOp, Value, VK_XValue); + CK_NoOp, Value, VK_XValue, FPOptionsOverride()); Expr *InitExpr = &AsRvalue; @@ -3087,8 +3137,11 @@ static void TryMoveInitialization(Sema& S, InitializationSequence Seq(S, Entity, Kind, InitExpr); - if (!Seq) - return; + bool NeedSecondOverloadResolution = true; + if (!Seq && + (IsDiagnosticsCheck || Seq.getFailedOverloadResult() != OR_Deleted)) { + return NeedSecondOverloadResolution; + } for (const InitializationSequence::Step &Step : Seq.steps()) { if (Step.Kind != InitializationSequence::SK_ConstructorInitialization && @@ -3131,15 +3184,19 @@ static void TryMoveInitialization(Sema& S, } } + NeedSecondOverloadResolution = false; // Promote "AsRvalue" to the heap, since we now need this // expression node to persist. - Value = ImplicitCastExpr::Create(S.Context, Value->getType(), CK_NoOp, - Value, nullptr, VK_XValue); + Value = + ImplicitCastExpr::Create(S.Context, Value->getType(), CK_NoOp, Value, + nullptr, VK_XValue, FPOptionsOverride()); // Complete type-checking the initialization of the return type // using the constructor we found. Res = Seq.Perform(S, Entity, Kind, Value); } + + return NeedSecondOverloadResolution; } /// Perform the initialization of a potentially-movable value, which @@ -3164,6 +3221,7 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity, // select the constructor for the copy is first performed as if the object // were designated by an rvalue. ExprResult Res = ExprError(); + bool NeedSecondOverloadResolution = true; if (AllowNRVO) { bool AffectedByCWG1579 = false; @@ -3180,15 +3238,14 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity, } if (NRVOCandidate) { - TryMoveInitialization(*this, Entity, NRVOCandidate, ResultType, Value, - true, Res); + NeedSecondOverloadResolution = TryMoveInitialization( + *this, Entity, NRVOCandidate, ResultType, Value, true, false, Res); } - if (!Res.isInvalid() && AffectedByCWG1579) { + if (!NeedSecondOverloadResolution && AffectedByCWG1579) { QualType QT = NRVOCandidate->getType(); - if (QT.getNonReferenceType() - .getUnqualifiedType() - .isTriviallyCopyableType(Context)) { + if (QT.getNonReferenceType().getUnqualifiedType().isTriviallyCopyableType( + Context)) { // Adding 'std::move' around a trivially copyable variable is probably // pointless. Don't suggest it. } else { @@ -3202,12 +3259,12 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity, Str += NRVOCandidate->getDeclName().getAsString(); Str += ")"; Diag(Value->getExprLoc(), diag::warn_return_std_move_in_cxx11) - << Value->getSourceRange() - << NRVOCandidate->getDeclName() << ResultType << QT; + << Value->getSourceRange() << NRVOCandidate->getDeclName() + << ResultType << QT; Diag(Value->getExprLoc(), diag::note_add_std_move_in_cxx11) << FixItHint::CreateReplacement(Value->getSourceRange(), Str); } - } else if (Res.isInvalid() && + } else if (NeedSecondOverloadResolution && !getDiagnostics().isIgnored(diag::warn_return_std_move, Value->getExprLoc())) { const VarDecl *FakeNRVOCandidate = @@ -3226,7 +3283,7 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity, ExprResult FakeRes = ExprError(); Expr *FakeValue = Value; TryMoveInitialization(*this, Entity, FakeNRVOCandidate, ResultType, - FakeValue, false, FakeRes); + FakeValue, false, true, FakeRes); if (!FakeRes.isInvalid()) { bool IsThrow = (Entity.getKind() == InitializedEntity::EK_Exception); @@ -3248,7 +3305,7 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity, // Either we didn't meet the criteria for treating an lvalue as an rvalue, // above, or overload resolution failed. Either way, we need to try // (again) now with the return value expression as written. - if (Res.isInvalid()) + if (NeedSecondOverloadResolution) Res = PerformCopyInitialization(Entity, SourceLocation(), Value); return Res; @@ -3290,9 +3347,14 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } if (HasDeducedReturnType) { + FunctionDecl *FD = CurLambda->CallOperator; + // If we've already decided this lambda is invalid, e.g. because + // we saw a `return` whose expression had an error, don't keep + // trying to deduce its return type. + if (FD->isInvalidDecl()) + return StmtError(); // In C++1y, the return type may involve 'auto'. // FIXME: Blocks might have a return type of 'auto' explicitly specified. - FunctionDecl *FD = CurLambda->CallOperator; if (CurCap->ReturnType.isNull()) CurCap->ReturnType = FD->getReturnType(); @@ -3587,7 +3649,8 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, Scope *CurScope) { // Correct typos, in case the containing function returns 'auto' and // RetValExp should determine the deduced type. - ExprResult RetVal = CorrectDelayedTyposInExpr(RetValExp); + ExprResult RetVal = CorrectDelayedTyposInExpr( + RetValExp, nullptr, /*RecoverUncorrectedTypos=*/true); if (RetVal.isInvalid()) return StmtError(); StmtResult R = BuildReturnStmt(ReturnLoc, RetVal.get()); @@ -3625,12 +3688,11 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { if (FD->hasAttrs()) Attrs = &FD->getAttrs(); if (FD->isNoReturn()) - Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr) - << FD->getDeclName(); + Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr) << FD; if (FD->isMain() && RetValExp) if (isa<CXXBoolLiteralExpr>(RetValExp)) Diag(ReturnLoc, diag::warn_main_returns_bool_literal) - << RetValExp->getSourceRange(); + << RetValExp->getSourceRange(); if (FD->hasAttr<CmseNSEntryAttr>() && RetValExp) { if (const auto *RT = dyn_cast<RecordType>(FnRetType.getCanonicalType())) { if (RT->getDecl()->isOrContainsUnion()) @@ -3673,6 +3735,11 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { if (getLangOpts().CPlusPlus14) { if (AutoType *AT = FnRetType->getContainedAutoType()) { FunctionDecl *FD = cast<FunctionDecl>(CurContext); + // If we've already decided this function is invalid, e.g. because + // we saw a `return` whose expression had an error, don't keep + // trying to deduce its return type. + if (FD->isInvalidDecl()) + return StmtError(); if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) { FD->setInvalidDecl(); return StmtError(); @@ -3701,8 +3768,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { FunctionKind = 3; Diag(ReturnLoc, diag::err_return_init_list) - << CurDecl->getDeclName() << FunctionKind - << RetValExp->getSourceRange(); + << CurDecl << FunctionKind << RetValExp->getSourceRange(); // Drop the expression. RetValExp = nullptr; @@ -3729,9 +3795,8 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // return of void in constructor/destructor is illegal in C++. if (D == diag::err_ctor_dtor_returns_void) { NamedDecl *CurDecl = getCurFunctionOrMethodDecl(); - Diag(ReturnLoc, D) - << CurDecl->getDeclName() << isa<CXXDestructorDecl>(CurDecl) - << RetValExp->getSourceRange(); + Diag(ReturnLoc, D) << CurDecl << isa<CXXDestructorDecl>(CurDecl) + << RetValExp->getSourceRange(); } // return (some void expression); is legal in C++. else if (D != diag::ext_return_has_void_expr || @@ -3747,8 +3812,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { FunctionKind = 3; Diag(ReturnLoc, D) - << CurDecl->getDeclName() << FunctionKind - << RetValExp->getSourceRange(); + << CurDecl << FunctionKind << RetValExp->getSourceRange(); } } @@ -3766,25 +3830,26 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } else if (!RetValExp && !HasDependentReturnType) { FunctionDecl *FD = getCurFunctionDecl(); - unsigned DiagID; if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) { // C++11 [stmt.return]p2 - DiagID = diag::err_constexpr_return_missing_expr; + Diag(ReturnLoc, diag::err_constexpr_return_missing_expr) + << FD << FD->isConsteval(); FD->setInvalidDecl(); - } else if (getLangOpts().C99) { - // C99 6.8.6.4p1 (ext_ since GCC warns) - DiagID = diag::ext_return_missing_expr; } else { + // C99 6.8.6.4p1 (ext_ since GCC warns) // C90 6.6.6.4p4 - DiagID = diag::warn_return_missing_expr; + unsigned DiagID = getLangOpts().C99 ? diag::ext_return_missing_expr + : diag::warn_return_missing_expr; + // Note that at this point one of getCurFunctionDecl() or + // getCurMethodDecl() must be non-null (see above). + assert((getCurFunctionDecl() || getCurMethodDecl()) && + "Not in a FunctionDecl or ObjCMethodDecl?"); + bool IsMethod = FD == nullptr; + const NamedDecl *ND = + IsMethod ? cast<NamedDecl>(getCurMethodDecl()) : cast<NamedDecl>(FD); + Diag(ReturnLoc, DiagID) << ND << IsMethod; } - if (FD) - Diag(ReturnLoc, DiagID) - << FD->getIdentifier() << 0 /*fn*/ << FD->isConsteval(); - else - Diag(ReturnLoc, DiagID) << getCurMethodDecl()->getDeclName() << 1/*meth*/; - Result = ReturnStmt::Create(Context, ReturnLoc, /* RetExpr=*/nullptr, /* NRVOCandidate=*/nullptr); } else { diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp index 10fa24682f9c..3b631bf747c6 100644 --- a/clang/lib/Sema/SemaStmtAsm.cpp +++ b/clang/lib/Sema/SemaStmtAsm.cpp @@ -448,9 +448,9 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, unsigned Size = Context.getTypeSize(Ty); if (!Context.getTargetInfo().validateInputSize(FeatureMap, Literal->getString(), Size)) - return StmtResult( - targetDiag(InputExpr->getBeginLoc(), diag::err_asm_invalid_input_size) - << Info.getConstraintStr()); + return targetDiag(InputExpr->getBeginLoc(), + diag::err_asm_invalid_input_size) + << Info.getConstraintStr(); } // Check that the clobbers are valid. diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index e9d3c755eb23..8031aa6b0ece 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -10,13 +10,14 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/EvaluatedExprVisitor.h" -#include "clang/Sema/SemaInternal.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/EvaluatedExprVisitor.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Sema/DelayedDiagnostic.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaInternal.h" #include "llvm/ADT/StringExtras.h" using namespace clang; @@ -139,10 +140,18 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A, LoopHintAttr::PipelineInitiationInterval) .Case("distribute", LoopHintAttr::Distribute) .Default(LoopHintAttr::Vectorize); - if (Option == LoopHintAttr::VectorizeWidth || - Option == LoopHintAttr::InterleaveCount || - Option == LoopHintAttr::UnrollCount || - Option == LoopHintAttr::PipelineInitiationInterval) { + if (Option == LoopHintAttr::VectorizeWidth) { + assert((ValueExpr || (StateLoc && StateLoc->Ident)) && + "Attribute must have a valid value expression or argument."); + if (ValueExpr && S.CheckLoopHintExpr(ValueExpr, St->getBeginLoc())) + return nullptr; + if (StateLoc && StateLoc->Ident && StateLoc->Ident->isStr("scalable")) + State = LoopHintAttr::ScalableWidth; + else + State = LoopHintAttr::FixedWidth; + } else if (Option == LoopHintAttr::InterleaveCount || + Option == LoopHintAttr::UnrollCount || + Option == LoopHintAttr::PipelineInitiationInterval) { assert(ValueExpr && "Attribute must have a valid value expression."); if (S.CheckLoopHintExpr(ValueExpr, St->getBeginLoc())) return nullptr; @@ -183,6 +192,7 @@ public: bool foundCallExpr() { return FoundCallExpr; } void VisitCallExpr(const CallExpr *E) { FoundCallExpr = true; } + void VisitAsmStmt(const AsmStmt *S) { FoundCallExpr = true; } void Visit(const Stmt *St) { if (!St) @@ -209,6 +219,24 @@ static Attr *handleNoMergeAttr(Sema &S, Stmt *St, const ParsedAttr &A, return ::new (S.Context) NoMergeAttr(S.Context, A); } +static Attr *handleLikely(Sema &S, Stmt *St, const ParsedAttr &A, + SourceRange Range) { + + if (!S.getLangOpts().CPlusPlus20 && A.isCXX11Attribute() && !A.getScopeName()) + S.Diag(A.getLoc(), diag::ext_cxx20_attr) << A << Range; + + return ::new (S.Context) LikelyAttr(S.Context, A); +} + +static Attr *handleUnlikely(Sema &S, Stmt *St, const ParsedAttr &A, + SourceRange Range) { + + if (!S.getLangOpts().CPlusPlus20 && A.isCXX11Attribute() && !A.getScopeName()) + S.Diag(A.getLoc(), diag::ext_cxx20_attr) << A << Range; + + return ::new (S.Context) UnlikelyAttr(S.Context, A); +} + static void CheckForIncompatibleAttributes(Sema &S, const SmallVectorImpl<const Attr *> &Attrs) { @@ -314,6 +342,32 @@ CheckForIncompatibleAttributes(Sema &S, << CategoryState.NumericAttr->getDiagnosticName(Policy); } } + + // C++20 [dcl.attr.likelihood]p1 The attribute-token likely shall not appear + // in an attribute-specifier-seq that contains the attribute-token unlikely. + const LikelyAttr *Likely = nullptr; + const UnlikelyAttr *Unlikely = nullptr; + for (const auto *I : Attrs) { + if (const auto *Attr = dyn_cast<LikelyAttr>(I)) { + if (Unlikely) { + S.Diag(Attr->getLocation(), diag::err_attributes_are_not_compatible) + << Attr << Unlikely << Attr->getRange(); + S.Diag(Unlikely->getLocation(), diag::note_conflicting_attribute) + << Unlikely->getRange(); + return; + } + Likely = Attr; + } else if (const auto *Attr = dyn_cast<UnlikelyAttr>(I)) { + if (Likely) { + S.Diag(Attr->getLocation(), diag::err_attributes_are_not_compatible) + << Attr << Likely << Attr->getRange(); + S.Diag(Likely->getLocation(), diag::note_conflicting_attribute) + << Likely->getRange(); + return; + } + Unlikely = Attr; + } + } } static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A, @@ -335,15 +389,15 @@ static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A, if (NumArgs == 1) { Expr *E = A.getArgAsExpr(0); - llvm::APSInt ArgVal(32); + Optional<llvm::APSInt> ArgVal; - if (!E->isIntegerConstantExpr(ArgVal, S.Context)) { + if (!(ArgVal = E->getIntegerConstantExpr(S.Context))) { S.Diag(A.getLoc(), diag::err_attribute_argument_type) << A << AANT_ArgumentIntegerConstant << E->getSourceRange(); return nullptr; } - int Val = ArgVal.getSExtValue(); + int Val = ArgVal->getSExtValue(); if (Val <= 0) { S.Diag(A.getRange().getBegin(), @@ -364,7 +418,7 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A, S.Diag(A.getLoc(), A.isDeclspecAttribute() ? (unsigned)diag::warn_unhandled_ms_attribute_ignored : (unsigned)diag::warn_unknown_attribute_ignored) - << A; + << A << A.getRange(); return nullptr; case ParsedAttr::AT_FallThrough: return handleFallThroughAttr(S, St, A, Range); @@ -376,6 +430,10 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A, return handleSuppressAttr(S, St, A, Range); case ParsedAttr::AT_NoMerge: return handleNoMergeAttr(S, St, A, Range); + case ParsedAttr::AT_Likely: + return handleLikely(S, St, A, Range); + case ParsedAttr::AT_Unlikely: + return handleUnlikely(S, St, A, Range); default: // if we're here, then we parsed a known attribute, but didn't recognize // it as a statement attribute => it is declaration attribute diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index c05ed0b14e3e..12880b95b9c6 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -23,6 +23,7 @@ #include "clang/Basic/Stack.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Overload.h" #include "clang/Sema/ParsedTemplate.h" @@ -938,11 +939,10 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef, TArg = TemplateArgument(Template, Optional<unsigned int>()); else TArg = Template; - return TemplateArgumentLoc(TArg, - Arg.getScopeSpec().getWithLocInContext( - SemaRef.Context), - Arg.getLocation(), - Arg.getEllipsisLoc()); + return TemplateArgumentLoc( + SemaRef.Context, TArg, + Arg.getScopeSpec().getWithLocInContext(SemaRef.Context), + Arg.getLocation(), Arg.getEllipsisLoc()); } } @@ -1176,7 +1176,11 @@ static ExprResult formImmediatelyDeclaredConstraint( // template<C1... T> struct s1; // // The constraint: (C1<T> && ...) - return S.BuildCXXFoldExpr(/*LParenLoc=*/SourceLocation(), + // + // Note that the type of C1<T> is known to be 'bool', so we don't need to do + // any unqualified lookups for 'operator&&' here. + return S.BuildCXXFoldExpr(/*UnqualifiedLookup=*/nullptr, + /*LParenLoc=*/SourceLocation(), ImmediatelyDeclaredConstraint.get(), BO_LAnd, EllipsisLoc, /*RHS=*/nullptr, /*RParenLoc=*/SourceLocation(), @@ -1274,6 +1278,108 @@ QualType Sema::CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI, return CheckNonTypeTemplateParameterType(TSI->getType(), Loc); } +/// Require the given type to be a structural type, and diagnose if it is not. +/// +/// \return \c true if an error was produced. +bool Sema::RequireStructuralType(QualType T, SourceLocation Loc) { + if (T->isDependentType()) + return false; + + if (RequireCompleteType(Loc, T, diag::err_template_nontype_parm_incomplete)) + return true; + + if (T->isStructuralType()) + return false; + + // Structural types are required to be object types or lvalue references. + if (T->isRValueReferenceType()) { + Diag(Loc, diag::err_template_nontype_parm_rvalue_ref) << T; + return true; + } + + // Don't mention structural types in our diagnostic prior to C++20. Also, + // there's not much more we can say about non-scalar non-class types -- + // because we can't see functions or arrays here, those can only be language + // extensions. + if (!getLangOpts().CPlusPlus20 || + (!T->isScalarType() && !T->isRecordType())) { + Diag(Loc, diag::err_template_nontype_parm_bad_type) << T; + return true; + } + + // Structural types are required to be literal types. + if (RequireLiteralType(Loc, T, diag::err_template_nontype_parm_not_literal)) + return true; + + Diag(Loc, diag::err_template_nontype_parm_not_structural) << T; + + // Drill down into the reason why the class is non-structural. + while (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) { + // All members are required to be public and non-mutable, and can't be of + // rvalue reference type. Check these conditions first to prefer a "local" + // reason over a more distant one. + for (const FieldDecl *FD : RD->fields()) { + if (FD->getAccess() != AS_public) { + Diag(FD->getLocation(), diag::note_not_structural_non_public) << T << 0; + return true; + } + if (FD->isMutable()) { + Diag(FD->getLocation(), diag::note_not_structural_mutable_field) << T; + return true; + } + if (FD->getType()->isRValueReferenceType()) { + Diag(FD->getLocation(), diag::note_not_structural_rvalue_ref_field) + << T; + return true; + } + } + + // All bases are required to be public. + for (const auto &BaseSpec : RD->bases()) { + if (BaseSpec.getAccessSpecifier() != AS_public) { + Diag(BaseSpec.getBaseTypeLoc(), diag::note_not_structural_non_public) + << T << 1; + return true; + } + } + + // All subobjects are required to be of structural types. + SourceLocation SubLoc; + QualType SubType; + int Kind = -1; + + for (const FieldDecl *FD : RD->fields()) { + QualType T = Context.getBaseElementType(FD->getType()); + if (!T->isStructuralType()) { + SubLoc = FD->getLocation(); + SubType = T; + Kind = 0; + break; + } + } + + if (Kind == -1) { + for (const auto &BaseSpec : RD->bases()) { + QualType T = BaseSpec.getType(); + if (!T->isStructuralType()) { + SubLoc = BaseSpec.getBaseTypeLoc(); + SubType = T; + Kind = 1; + break; + } + } + } + + assert(Kind != -1 && "couldn't find reason why type is not structural"); + Diag(SubLoc, diag::note_not_structural_subobject) + << T << Kind << SubType; + T = SubType; + RD = T->getAsCXXRecordDecl(); + } + + return true; +} + QualType Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) { // We don't allow variably-modified types as the type of non-type template @@ -1293,13 +1399,13 @@ QualType Sema::CheckNonTypeTemplateParameterType(QualType T, if (T->isIntegralOrEnumerationType() || // -- pointer to object or pointer to function, T->isPointerType() || - // -- reference to object or reference to function, - T->isReferenceType() || + // -- lvalue reference to object or lvalue reference to function, + T->isLValueReferenceType() || // -- pointer to member, T->isMemberPointerType() || - // -- std::nullptr_t. + // -- std::nullptr_t, or T->isNullPtrType() || - // Allow use of auto in template parameter declarations. + // -- a type that contains a placeholder type. T->isUndeducedType()) { // C++ [temp.param]p5: The top-level cv-qualifiers on the template-parameter // are ignored when determining its type. @@ -1323,10 +1429,21 @@ QualType Sema::CheckNonTypeTemplateParameterType(QualType T, if (T->isDependentType()) return T.getUnqualifiedType(); - Diag(Loc, diag::err_template_nontype_parm_bad_type) - << T; + // C++20 [temp.param]p6: + // -- a structural type + if (RequireStructuralType(T, Loc)) + return QualType(); + + if (!getLangOpts().CPlusPlus20) { + // FIXME: Consider allowing structural types as an extension in C++17. (In + // earlier language modes, the template argument evaluation rules are too + // inflexible.) + Diag(Loc, diag::err_template_nontype_parm_bad_structural_type) << T; + return QualType(); + } - return QualType(); + Diag(Loc, diag::warn_cxx17_compat_template_nontype_parm_type) << T; + return T.getUnqualifiedType(); } NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, @@ -1960,27 +2077,27 @@ public: QualType TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) { ASTContext &Context = SemaRef.getASTContext(); TypedefNameDecl *OrigDecl = TL.getTypedefNameDecl(); - TypeLocBuilder InnerTLB; - QualType Transformed = - TransformType(InnerTLB, OrigDecl->getTypeSourceInfo()->getTypeLoc()); - TypeSourceInfo *TSI = - TransformType(InnerTLB.getTypeSourceInfo(Context, Transformed)); - - TypedefNameDecl *Decl = nullptr; - - if (isa<TypeAliasDecl>(OrigDecl)) - Decl = TypeAliasDecl::Create( - Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(), - OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI); - else { - assert(isa<TypedefDecl>(OrigDecl) && "Not a Type alias or typedef"); - Decl = TypedefDecl::Create( - Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(), - OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI); + TypedefNameDecl *Decl = OrigDecl; + // Transform the underlying type of the typedef and clone the Decl only if + // the typedef has a dependent context. + if (OrigDecl->getDeclContext()->isDependentContext()) { + TypeLocBuilder InnerTLB; + QualType Transformed = + TransformType(InnerTLB, OrigDecl->getTypeSourceInfo()->getTypeLoc()); + TypeSourceInfo *TSI = InnerTLB.getTypeSourceInfo(Context, Transformed); + if (isa<TypeAliasDecl>(OrigDecl)) + Decl = TypeAliasDecl::Create( + Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(), + OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI); + else { + assert(isa<TypedefDecl>(OrigDecl) && "Not a Type alias or typedef"); + Decl = TypedefDecl::Create( + Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(), + OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI); + } + MaterializedTypedefs.push_back(Decl); } - MaterializedTypedefs.push_back(Decl); - QualType TDTy = Context.getTypedefType(Decl); TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(TDTy); TypedefTL.setNameLoc(TL.getNameLoc()); @@ -3544,7 +3661,6 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, QualType CanonType; - bool InstantiationDependent = false; if (TypeAliasTemplateDecl *AliasTemplate = dyn_cast<TypeAliasTemplateDecl>(Template)) { @@ -3607,7 +3723,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, } } else if (Name.isDependent() || TemplateSpecializationType::anyDependentTemplateArguments( - TemplateArgs, InstantiationDependent)) { + TemplateArgs, Converted)) { // This class template specialization is a dependent // type. Therefore, its canonical type is another class template // specialization type that contains all of the converted @@ -3675,11 +3791,15 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext()); } - if (Decl->getSpecializationKind() == TSK_Undeclared) { - MultiLevelTemplateArgumentList TemplateArgLists; - TemplateArgLists.addOuterTemplateArguments(Converted); - InstantiateAttrsForDecl(TemplateArgLists, ClassTemplate->getTemplatedDecl(), - Decl); + if (Decl->getSpecializationKind() == TSK_Undeclared && + ClassTemplate->getTemplatedDecl()->hasAttrs()) { + InstantiatingTemplate Inst(*this, TemplateLoc, Decl); + if (!Inst.isInvalid()) { + MultiLevelTemplateArgumentList TemplateArgLists; + TemplateArgLists.addOuterTemplateArguments(Converted); + InstantiateAttrsForDecl(TemplateArgLists, + ClassTemplate->getTemplatedDecl(), Decl); + } } // Diagnose uses of this specialization. @@ -4194,11 +4314,9 @@ DeclResult Sema::ActOnVarTemplateSpecialization( // FIXME: Move these checks to CheckTemplatePartialSpecializationArgs so we // also do them during instantiation. - bool InstantiationDependent; if (!Name.isDependent() && - !TemplateSpecializationType::anyDependentTemplateArguments( - TemplateArgs.arguments(), - InstantiationDependent)) { + !TemplateSpecializationType::anyDependentTemplateArguments(TemplateArgs, + Converted)) { Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized) << VarTemplate->getDeclName(); IsPartialSpecialization = false; @@ -4358,6 +4476,12 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, Converted, /*UpdateArgsWithConversion=*/true)) return true; + // Produce a placeholder value if the specialization is dependent. + if (Template->getDeclContext()->isDependentContext() || + TemplateSpecializationType::anyDependentTemplateArguments(TemplateArgs, + Converted)) + return DeclResult(); + // Find the variable template specialization declaration that // corresponds to these arguments. void *InsertPos = nullptr; @@ -4385,84 +4509,75 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, // 1. Attempt to find the closest partial specialization that this // specializes, if any. - // If any of the template arguments is dependent, then this is probably - // a placeholder for an incomplete declarative context; which must be - // complete by instantiation time. Thus, do not search through the partial - // specializations yet. // TODO: Unify with InstantiateClassTemplateSpecialization()? // Perhaps better after unification of DeduceTemplateArguments() and // getMoreSpecializedPartialSpecialization(). - bool InstantiationDependent = false; - if (!TemplateSpecializationType::anyDependentTemplateArguments( - TemplateArgs, InstantiationDependent)) { + SmallVector<VarTemplatePartialSpecializationDecl *, 4> PartialSpecs; + Template->getPartialSpecializations(PartialSpecs); - SmallVector<VarTemplatePartialSpecializationDecl *, 4> PartialSpecs; - Template->getPartialSpecializations(PartialSpecs); - - for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) { - VarTemplatePartialSpecializationDecl *Partial = PartialSpecs[I]; - TemplateDeductionInfo Info(FailedCandidates.getLocation()); + for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) { + VarTemplatePartialSpecializationDecl *Partial = PartialSpecs[I]; + TemplateDeductionInfo Info(FailedCandidates.getLocation()); - if (TemplateDeductionResult Result = - DeduceTemplateArguments(Partial, TemplateArgList, Info)) { - // Store the failed-deduction information for use in diagnostics, later. - // TODO: Actually use the failed-deduction info? - FailedCandidates.addCandidate().set( - DeclAccessPair::make(Template, AS_public), Partial, - MakeDeductionFailureInfo(Context, Result, Info)); - (void)Result; - } else { - Matched.push_back(PartialSpecMatchResult()); - Matched.back().Partial = Partial; - Matched.back().Args = Info.take(); - } + if (TemplateDeductionResult Result = + DeduceTemplateArguments(Partial, TemplateArgList, Info)) { + // Store the failed-deduction information for use in diagnostics, later. + // TODO: Actually use the failed-deduction info? + FailedCandidates.addCandidate().set( + DeclAccessPair::make(Template, AS_public), Partial, + MakeDeductionFailureInfo(Context, Result, Info)); + (void)Result; + } else { + Matched.push_back(PartialSpecMatchResult()); + Matched.back().Partial = Partial; + Matched.back().Args = Info.take(); } + } - if (Matched.size() >= 1) { - SmallVector<MatchResult, 4>::iterator Best = Matched.begin(); - if (Matched.size() == 1) { - // -- If exactly one matching specialization is found, the - // instantiation is generated from that specialization. - // We don't need to do anything for this. - } else { - // -- If more than one matching specialization is found, the - // partial order rules (14.5.4.2) are used to determine - // whether one of the specializations is more specialized - // than the others. If none of the specializations is more - // specialized than all of the other matching - // specializations, then the use of the variable template is - // ambiguous and the program is ill-formed. - for (SmallVector<MatchResult, 4>::iterator P = Best + 1, - PEnd = Matched.end(); - P != PEnd; ++P) { - if (getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial, - PointOfInstantiation) == - P->Partial) - Best = P; - } + if (Matched.size() >= 1) { + SmallVector<MatchResult, 4>::iterator Best = Matched.begin(); + if (Matched.size() == 1) { + // -- If exactly one matching specialization is found, the + // instantiation is generated from that specialization. + // We don't need to do anything for this. + } else { + // -- If more than one matching specialization is found, the + // partial order rules (14.5.4.2) are used to determine + // whether one of the specializations is more specialized + // than the others. If none of the specializations is more + // specialized than all of the other matching + // specializations, then the use of the variable template is + // ambiguous and the program is ill-formed. + for (SmallVector<MatchResult, 4>::iterator P = Best + 1, + PEnd = Matched.end(); + P != PEnd; ++P) { + if (getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial, + PointOfInstantiation) == + P->Partial) + Best = P; + } - // Determine if the best partial specialization is more specialized than - // the others. - for (SmallVector<MatchResult, 4>::iterator P = Matched.begin(), - PEnd = Matched.end(); - P != PEnd; ++P) { - if (P != Best && getMoreSpecializedPartialSpecialization( - P->Partial, Best->Partial, - PointOfInstantiation) != Best->Partial) { - AmbiguousPartialSpec = true; - break; - } + // Determine if the best partial specialization is more specialized than + // the others. + for (SmallVector<MatchResult, 4>::iterator P = Matched.begin(), + PEnd = Matched.end(); + P != PEnd; ++P) { + if (P != Best && getMoreSpecializedPartialSpecialization( + P->Partial, Best->Partial, + PointOfInstantiation) != Best->Partial) { + AmbiguousPartialSpec = true; + break; } } - - // Instantiate using the best variable template partial specialization. - InstantiationPattern = Best->Partial; - InstantiationArgs = Best->Args; - } else { - // -- If no match is found, the instantiation is generated - // from the primary template. - // InstantiationPattern = Template->getTemplatedDecl(); } + + // Instantiate using the best variable template partial specialization. + InstantiationPattern = Best->Partial; + InstantiationArgs = Best->Args; + } else { + // -- If no match is found, the instantiation is generated + // from the primary template. + // InstantiationPattern = Template->getTemplatedDecl(); } // 2. Create the canonical declaration. @@ -4471,7 +4586,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, // FIXME: LateAttrs et al.? VarTemplateSpecializationDecl *Decl = BuildVarTemplateInstantiation( Template, InstantiationPattern, *InstantiationArgs, TemplateArgs, - Converted, TemplateNameLoc, InsertPos /*, LateAttrs, StartingScope*/); + Converted, TemplateNameLoc /*, LateAttrs, StartingScope*/); if (!Decl) return true; @@ -4510,6 +4625,9 @@ Sema::CheckVarTemplateId(const CXXScopeSpec &SS, if (Decl.isInvalid()) return ExprError(); + if (!Decl.get()) + return ExprResult(); + VarDecl *Var = cast<VarDecl>(Decl.get()); if (!Var->getTemplateSpecializationKind()) Var->setTemplateSpecializationKind(TSK_ImplicitInstantiation, @@ -4547,22 +4665,16 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS, return ExprError(); ConstraintSatisfaction Satisfaction; - bool AreArgsDependent = false; - for (TemplateArgument &Arg : Converted) { - if (Arg.isDependent()) { - AreArgsDependent = true; - break; - } - } + bool AreArgsDependent = + TemplateSpecializationType::anyDependentTemplateArguments(*TemplateArgs, + Converted); if (!AreArgsDependent && - CheckConstraintSatisfaction(NamedConcept, - {NamedConcept->getConstraintExpr()}, - Converted, - SourceRange(SS.isSet() ? SS.getBeginLoc() : - ConceptNameInfo.getLoc(), - TemplateArgs->getRAngleLoc()), - Satisfaction)) - return ExprError(); + CheckConstraintSatisfaction( + NamedConcept, {NamedConcept->getConstraintExpr()}, Converted, + SourceRange(SS.isSet() ? SS.getBeginLoc() : ConceptNameInfo.getLoc(), + TemplateArgs->getRAngleLoc()), + Satisfaction)) + return ExprError(); return ConceptSpecializationExpr::Create(Context, SS.isSet() ? SS.getWithLocInContext(Context) : NestedNameSpecifierLoc{}, @@ -4597,18 +4709,14 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, } } - auto AnyDependentArguments = [&]() -> bool { - bool InstantiationDependent; - return TemplateArgs && - TemplateSpecializationType::anyDependentTemplateArguments( - *TemplateArgs, InstantiationDependent); - }; - // In C++1y, check variable template ids. - if (R.getAsSingle<VarTemplateDecl>() && !AnyDependentArguments()) { - return CheckVarTemplateId(SS, R.getLookupNameInfo(), - R.getAsSingle<VarTemplateDecl>(), - TemplateKWLoc, TemplateArgs); + if (R.getAsSingle<VarTemplateDecl>()) { + ExprResult Res = CheckVarTemplateId(SS, R.getLookupNameInfo(), + R.getAsSingle<VarTemplateDecl>(), + TemplateKWLoc, TemplateArgs); + if (Res.isInvalid() || Res.isUsable()) + return Res; + // Result is dependent. Carry on to build an UnresolvedLookupEpxr. } if (R.getAsSingle<ConceptDecl>()) { @@ -5158,15 +5266,17 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, if (TName.isNull()) return TemplateArgumentLoc(); - return TemplateArgumentLoc(TemplateArgument(TName), - TempTempParm->getDefaultArgument().getTemplateQualifierLoc(), - TempTempParm->getDefaultArgument().getTemplateNameLoc()); + return TemplateArgumentLoc( + Context, TemplateArgument(TName), + TempTempParm->getDefaultArgument().getTemplateQualifierLoc(), + TempTempParm->getDefaultArgument().getTemplateNameLoc()); } /// Convert a template-argument that we parsed as a type into a template, if /// possible. C++ permits injected-class-names to perform dual service as /// template template arguments and as template type arguments. -static TemplateArgumentLoc convertTypeTemplateArgumentToTemplate(TypeLoc TLoc) { +static TemplateArgumentLoc +convertTypeTemplateArgumentToTemplate(ASTContext &Context, TypeLoc TLoc) { // Extract and step over any surrounding nested-name-specifier. NestedNameSpecifierLoc QualLoc; if (auto ETLoc = TLoc.getAs<ElaboratedTypeLoc>()) { @@ -5176,11 +5286,10 @@ static TemplateArgumentLoc convertTypeTemplateArgumentToTemplate(TypeLoc TLoc) { QualLoc = ETLoc.getQualifierLoc(); TLoc = ETLoc.getNamedTypeLoc(); } - // If this type was written as an injected-class-name, it can be used as a // template template argument. if (auto InjLoc = TLoc.getAs<InjectedClassNameTypeLoc>()) - return TemplateArgumentLoc(InjLoc.getTypePtr()->getTemplateName(), + return TemplateArgumentLoc(Context, InjLoc.getTypePtr()->getTemplateName(), QualLoc, InjLoc.getNameLoc()); // If this type was written as an injected-class-name, it may have been @@ -5190,7 +5299,8 @@ static TemplateArgumentLoc convertTypeTemplateArgumentToTemplate(TypeLoc TLoc) { if (auto RecLoc = TLoc.getAs<RecordTypeLoc>()) if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RecLoc.getDecl())) - return TemplateArgumentLoc(TemplateName(CTSD->getSpecializedTemplate()), + return TemplateArgumentLoc(Context, + TemplateName(CTSD->getSpecializedTemplate()), QualLoc, RecLoc.getNameLoc()); return TemplateArgumentLoc(); @@ -5429,7 +5539,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, // itself. if (Arg.getArgument().getKind() == TemplateArgument::Type) { TemplateArgumentLoc ConvertedArg = convertTypeTemplateArgumentToTemplate( - Arg.getTypeSourceInfo()->getTypeLoc()); + Context, Arg.getTypeSourceInfo()->getTypeLoc()); if (!ConvertedArg.getArgument().isNull()) Arg = ConvertedArg; } @@ -5468,39 +5578,6 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, return false; } -/// Check whether the template parameter is a pack expansion, and if so, -/// determine the number of parameters produced by that expansion. For instance: -/// -/// \code -/// template<typename ...Ts> struct A { -/// template<Ts ...NTs, template<Ts> class ...TTs, typename ...Us> struct B; -/// }; -/// \endcode -/// -/// In \c A<int,int>::B, \c NTs and \c TTs have expanded pack size 2, and \c Us -/// is not a pack expansion, so returns an empty Optional. -static Optional<unsigned> getExpandedPackSize(NamedDecl *Param) { - if (TemplateTypeParmDecl *TTP - = dyn_cast<TemplateTypeParmDecl>(Param)) { - if (TTP->isExpandedParameterPack()) - return TTP->getNumExpansionParameters(); - } - - if (NonTypeTemplateParmDecl *NTTP - = dyn_cast<NonTypeTemplateParmDecl>(Param)) { - if (NTTP->isExpandedParameterPack()) - return NTTP->getNumExpansionTypes(); - } - - if (TemplateTemplateParmDecl *TTP - = dyn_cast<TemplateTemplateParmDecl>(Param)) { - if (TTP->isExpandedParameterPack()) - return TTP->getNumExpansionTemplateParameters(); - } - - return None; -} - /// Diagnose a missing template argument. template<typename TemplateParmDecl> static bool diagnoseMissingArgument(Sema &S, SourceLocation Loc, @@ -5748,8 +5825,9 @@ bool Sema::CheckTemplateArgumentList( if (Name.isNull()) return true; - Arg = TemplateArgumentLoc(TemplateArgument(Name), QualifierLoc, - TempParm->getDefaultArgument().getTemplateNameLoc()); + Arg = TemplateArgumentLoc( + Context, TemplateArgument(Name), QualifierLoc, + TempParm->getDefaultArgument().getTemplateNameLoc()); } // Introduce an instantiation record that describes where we are using @@ -6543,8 +6621,8 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, return true; // Create the template argument. - Converted = - TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()), ParamType); + Converted = TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()), + S.Context.getCanonicalType(ParamType)); S.MarkAnyDeclReferenced(Arg->getBeginLoc(), Entity, false); return false; } @@ -6665,7 +6743,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S, Converted = TemplateArgument(Arg); } else { ValueDecl *D = cast<ValueDecl>(DRE->getDecl()->getCanonicalDecl()); - Converted = TemplateArgument(D, ParamType); + Converted = TemplateArgument(D, S.Context.getCanonicalType(ParamType)); } return Invalid; } @@ -6691,14 +6769,15 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, SourceLocation StartLoc = Arg->getBeginLoc(); // If the parameter type somehow involves auto, deduce the type now. - if (getLangOpts().CPlusPlus17 && ParamType->isUndeducedType()) { + DeducedType *DeducedT = ParamType->getContainedDeducedType(); + if (getLangOpts().CPlusPlus17 && DeducedT && !DeducedT->isDeduced()) { // During template argument deduction, we allow 'decltype(auto)' to // match an arbitrary dependent argument. // FIXME: The language rules don't say what happens in this case. // FIXME: We get an opaque dependent type out of decltype(auto) if the // expression is merely instantiation-dependent; is this enough? if (CTAK == CTAK_Deduced && Arg->isTypeDependent()) { - auto *AT = dyn_cast<AutoType>(ParamType); + auto *AT = dyn_cast<AutoType>(DeducedT); if (AT && AT->isDecltypeAuto()) { Converted = TemplateArgument(Arg); return Arg; @@ -6712,14 +6791,26 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, Expr *DeductionArg = Arg; if (auto *PE = dyn_cast<PackExpansionExpr>(DeductionArg)) DeductionArg = PE->getPattern(); - if (DeduceAutoType( - Context.getTrivialTypeSourceInfo(ParamType, Param->getLocation()), - DeductionArg, ParamType, Depth, - // We do not check constraints right now because the - // immediately-declared constraint of the auto type is also an - // associated constraint, and will be checked along with the other - // associated constraints after checking the template argument list. - /*IgnoreConstraints=*/true) == DAR_Failed) { + TypeSourceInfo *TSI = + Context.getTrivialTypeSourceInfo(ParamType, Param->getLocation()); + if (isa<DeducedTemplateSpecializationType>(DeducedT)) { + InitializedEntity Entity = + InitializedEntity::InitializeTemplateParameter(ParamType, Param); + InitializationKind Kind = InitializationKind::CreateForInit( + DeductionArg->getBeginLoc(), /*DirectInit*/false, DeductionArg); + Expr *Inits[1] = {DeductionArg}; + ParamType = + DeduceTemplateSpecializationFromInitializer(TSI, Entity, Kind, Inits); + if (ParamType.isNull()) + return ExprError(); + } else if (DeduceAutoType( + TSI, DeductionArg, ParamType, Depth, + // We do not check constraints right now because the + // immediately-declared constraint of the auto type is also + // an associated constraint, and will be checked along with + // the other associated constraints after checking the + // template argument list. + /*IgnoreConstraints=*/true) == DAR_Failed) { Diag(Arg->getExprLoc(), diag::err_non_type_template_parm_type_deduction_failure) << Param->getDeclName() << Param->getType() << Arg->getType() @@ -6742,18 +6833,21 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, assert(!ParamType.hasQualifiers() && "non-type template parameter type cannot be qualified"); + // FIXME: When Param is a reference, should we check that Arg is an lvalue? if (CTAK == CTAK_Deduced && - !Context.hasSameType(ParamType.getNonLValueExprType(Context), - Arg->getType())) { + (ParamType->isReferenceType() + ? !Context.hasSameType(ParamType.getNonReferenceType(), + Arg->getType()) + : !Context.hasSameUnqualifiedType(ParamType, Arg->getType()))) { // FIXME: If either type is dependent, we skip the check. This isn't // correct, since during deduction we're supposed to have replaced each // template parameter with some unique (non-dependent) placeholder. // FIXME: If the argument type contains 'auto', we carry on and fail the // type check in order to force specific types to be more specialized than // 'auto'. It's not clear how partial ordering with 'auto' is supposed to - // work. + // work. Similarly for CTAD, when comparing 'A<x>' against 'A'. if ((ParamType->isDependentType() || Arg->isTypeDependent()) && - !Arg->getType()->getContainedAutoType()) { + !Arg->getType()->getContainedDeducedType()) { Converted = TemplateArgument(Arg); return Arg; } @@ -6800,12 +6894,36 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, *this, Sema::ExpressionEvaluationContext::ConstantEvaluated); if (getLangOpts().CPlusPlus17) { + QualType CanonParamType = Context.getCanonicalType(ParamType); + + // Avoid making a copy when initializing a template parameter of class type + // from a template parameter object of the same type. This is going beyond + // the standard, but is required for soundness: in + // template<A a> struct X { X *p; X<a> *q; }; + // ... we need p and q to have the same type. + // + // Similarly, don't inject a call to a copy constructor when initializing + // from a template parameter of the same type. + Expr *InnerArg = Arg->IgnoreParenImpCasts(); + if (ParamType->isRecordType() && isa<DeclRefExpr>(InnerArg) && + Context.hasSameUnqualifiedType(ParamType, InnerArg->getType())) { + NamedDecl *ND = cast<DeclRefExpr>(InnerArg)->getDecl(); + if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND)) { + Converted = TemplateArgument(TPO, CanonParamType); + return Arg; + } + if (isa<NonTypeTemplateParmDecl>(ND)) { + Converted = TemplateArgument(Arg); + return Arg; + } + } + // C++17 [temp.arg.nontype]p1: // A template-argument for a non-type template parameter shall be // a converted constant expression of the type of the template-parameter. APValue Value; ExprResult ArgResult = CheckConvertedConstantExpression( - Arg, ParamType, Value, CCEK_TemplateArg); + Arg, ParamType, Value, CCEK_TemplateArg, Param); if (ArgResult.isInvalid()) return ExprError(); @@ -6816,8 +6934,6 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return ArgResult; } - QualType CanonParamType = Context.getCanonicalType(ParamType); - // Convert the APValue to a TemplateArgument. switch (Value.getKind()) { case APValue::None: @@ -6865,6 +6981,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return ExprError(); } // -- a subobject + // FIXME: Until C++20 if (Value.hasLValuePath() && Value.getLValuePath().size() == 1 && VD && VD->getType()->isArrayType() && Value.getLValuePath()[0].getAsArrayIndex() == 0 && @@ -6886,6 +7003,13 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, : TemplateArgument(CanonParamType, /*isNullPtr*/true); break; } + case APValue::Struct: + case APValue::Union: + // Get or create the corresponding template parameter object. + Converted = TemplateArgument( + Context.getTemplateParamObjectDecl(CanonParamType, Value), + CanonParamType); + break; case APValue::AddrLabelDiff: return Diag(StartLoc, diag::err_non_type_template_arg_addr_label_diff); case APValue::FixedPoint: @@ -6894,9 +7018,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, case APValue::ComplexFloat: case APValue::Vector: case APValue::Array: - case APValue::Struct: - case APValue::Union: - llvm_unreachable("invalid kind for template argument"); + return Diag(StartLoc, diag::err_non_type_template_arg_unsupported) + << ParamType; } return ArgResult.get(); @@ -6982,14 +7105,13 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, public: TmplArgICEDiagnoser(QualType T) : T(T) { } - void diagnoseNotICE(Sema &S, SourceLocation Loc, - SourceRange SR) override { - S.Diag(Loc, diag::err_template_arg_not_ice) << T << SR; + SemaDiagnosticBuilder diagnoseNotICE(Sema &S, + SourceLocation Loc) override { + return S.Diag(Loc, diag::err_template_arg_not_ice) << T; } } Diagnoser(ArgType); - Arg = VerifyIntegerConstantExpression(Arg, &Value, Diagnoser, - false).get(); + Arg = VerifyIntegerConstantExpression(Arg, &Value, Diagnoser).get(); if (!Arg) return ExprError(); } @@ -7389,6 +7511,11 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, RefExpr = CreateBuiltinUnaryOp(Loc, UO_AddrOf, RefExpr.get()); if (RefExpr.isInvalid()) return ExprError(); + } else if (ParamType->isRecordType()) { + assert(isa<TemplateParamObjectDecl>(VD) && + "arg for class template param not a template parameter object"); + // No conversions apply in this case. + return RefExpr; } else { assert(ParamType->isReferenceType() && "unexpected type for decl template argument"); @@ -7477,7 +7604,7 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, // FIXME: This is a hack. We need a better way to handle substituted // non-type template parameters. E = CStyleCastExpr::Create(Context, OrigT, VK_RValue, CK_IntegralCast, E, - nullptr, + nullptr, CurFPFeatureOverrides(), Context.getTrivialTypeSourceInfo(OrigT, Loc), Loc, Loc); } @@ -7771,22 +7898,28 @@ Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) { (S->getFlags() & Scope::TemplateParamScope) != 0) S = S->getParent(); - // C++ [temp]p4: - // A template [...] shall not have C linkage. + // C++ [temp.pre]p6: [P2096] + // A template, explicit specialization, or partial specialization shall not + // have C linkage. DeclContext *Ctx = S->getEntity(); - assert(Ctx && "Unknown context"); - if (Ctx->isExternCContext()) { + if (Ctx && Ctx->isExternCContext()) { Diag(TemplateParams->getTemplateLoc(), diag::err_template_linkage) << TemplateParams->getSourceRange(); if (const LinkageSpecDecl *LSD = Ctx->getExternCContext()) Diag(LSD->getExternLoc(), diag::note_extern_c_begins_here); return true; } - Ctx = Ctx->getRedeclContext(); + Ctx = Ctx ? Ctx->getRedeclContext() : nullptr; // C++ [temp]p2: // A template-declaration can appear only as a namespace scope or // class scope declaration. + // C++ [temp.expl.spec]p3: + // An explicit specialization may be declared in any scope in which the + // corresponding primary template may be defined. + // C++ [temp.class.spec]p6: [P2096] + // A partial specialization may be declared in any scope in which the + // corresponding primary template may be defined. if (Ctx) { if (Ctx->isFileContext()) return false; @@ -8106,6 +8239,10 @@ DeclResult Sema::ActOnClassTemplateSpecialization( if (Invalid) return true; + // Check that we can declare a template specialization here. + if (TemplateParams && CheckTemplateDeclScope(S, TemplateParams)) + return true; + if (TemplateParams && TemplateParams->size() > 0) { isPartialSpecialization = true; @@ -8198,10 +8335,9 @@ DeclResult Sema::ActOnClassTemplateSpecialization( // FIXME: Move this to CheckTemplatePartialSpecializationArgs so we // also do it during instantiation. - bool InstantiationDependent; if (!Name.isDependent() && - !TemplateSpecializationType::anyDependentTemplateArguments( - TemplateArgs.arguments(), InstantiationDependent)) { + !TemplateSpecializationType::anyDependentTemplateArguments(TemplateArgs, + Converted)) { Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized) << ClassTemplate->getDeclName(); isPartialSpecialization = false; @@ -8462,6 +8598,9 @@ Decl *Sema::ActOnConceptDefinition(Scope *S, return nullptr; } + if (DiagnoseUnexpandedParameterPack(ConstraintExpr)) + return nullptr; + ConceptDecl *NewDecl = ConceptDecl::Create(Context, DC, NameLoc, Name, TemplateParameterLists.front(), ConstraintExpr); @@ -9580,11 +9719,11 @@ DeclResult Sema::ActOnExplicitInstantiation( Def->setTemplateSpecializationKind(TSK); if (!getDLLAttr(Def) && getDLLAttr(Specialization) && - (Context.getTargetInfo().getCXXABI().isMicrosoft() || - Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) { - // In the MS ABI, an explicit instantiation definition can add a dll - // attribute to a template with a previous instantiation declaration. - // MinGW doesn't allow this. + (Context.getTargetInfo().shouldDLLImportComdatSymbols() && + !Context.getTargetInfo().getTriple().isPS4CPU())) { + // An explicit instantiation definition can add a dll attribute to a + // template with a previous instantiation declaration. MinGW doesn't + // allow this. auto *A = cast<InheritableAttr>( getDLLAttr(Specialization)->clone(getASTContext())); A->setInherited(true); @@ -9598,19 +9737,19 @@ DeclResult Sema::ActOnExplicitInstantiation( bool NewlyDLLExported = !PreviouslyDLLExported && Specialization->hasAttr<DLLExportAttr>(); if (Old_TSK == TSK_ImplicitInstantiation && NewlyDLLExported && - (Context.getTargetInfo().getCXXABI().isMicrosoft() || - Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) { - // In the MS ABI, an explicit instantiation definition can add a dll - // attribute to a template with a previous implicit instantiation. - // MinGW doesn't allow this. We limit clang to only adding dllexport, to - // avoid potentially strange codegen behavior. For example, if we extend - // this conditional to dllimport, and we have a source file calling a - // method on an implicitly instantiated template class instance and then - // declaring a dllimport explicit instantiation definition for the same - // template class, the codegen for the method call will not respect the - // dllimport, while it will with cl. The Def will already have the DLL - // attribute, since the Def and Specialization will be the same in the - // case of Old_TSK == TSK_ImplicitInstantiation, and we already added the + (Context.getTargetInfo().shouldDLLImportComdatSymbols() && + !Context.getTargetInfo().getTriple().isPS4CPU())) { + // An explicit instantiation definition can add a dll attribute to a + // template with a previous implicit instantiation. MinGW doesn't allow + // this. We limit clang to only adding dllexport, to avoid potentially + // strange codegen behavior. For example, if we extend this conditional + // to dllimport, and we have a source file calling a method on an + // implicitly instantiated template class instance and then declaring a + // dllimport explicit instantiation definition for the same template + // class, the codegen for the method call will not respect the dllimport, + // while it will with cl. The Def will already have the DLL attribute, + // since the Def and Specialization will be the same in the case of + // Old_TSK == TSK_ImplicitInstantiation, and we already added the // attribute to the Specialization; we just need to make it take effect. assert(Def == Specialization && "Def and Specialization should match for implicit instantiation"); @@ -9625,6 +9764,11 @@ DeclResult Sema::ActOnExplicitInstantiation( dllExportImportClassTemplateSpecialization(*this, Def); } + if (Def->hasAttr<MSInheritanceAttr>()) { + Specialization->addAttr(Def->getAttr<MSInheritanceAttr>()); + Consumer.AssignInheritanceModel(Specialization); + } + // Set the template specialization kind. Make sure it is set before // instantiating the members which will trigger ASTConsumer callbacks. Specialization->setTemplateSpecializationKind(TSK); @@ -9904,6 +10048,14 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, if (Res.isInvalid()) return true; + if (!Res.isUsable()) { + // We somehow specified dependent template arguments in an explicit + // instantiation. This should probably only happen during error + // recovery. + Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_dependent); + return true; + } + // Ignore access control bits, we don't need them for redeclaration // checking. Prev = cast<VarDecl>(Res.get()); @@ -10583,7 +10735,7 @@ namespace { /// For the purposes of type reconstruction, a type has already been /// transformed if it is NULL or if it is not dependent. bool AlreadyTransformed(QualType T) { - return T.isNull() || !T->isDependentType(); + return T.isNull() || !T->isInstantiationDependentType(); } /// Returns the location of the entity whose type is being @@ -10636,7 +10788,7 @@ namespace { TypeSourceInfo *Sema::RebuildTypeInCurrentInstantiation(TypeSourceInfo *T, SourceLocation Loc, DeclarationName Name) { - if (!T || !T->getType()->isDependentType()) + if (!T || !T->getType()->isInstantiationDependentType()) return T; CurrentInstantiationRebuilder Rebuilder(*this, Loc, Name); @@ -10926,14 +11078,3 @@ void Sema::checkSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec) { ExplicitSpecializationVisibilityChecker(*this, Loc).check(Spec); } - -/// Check whether a template partial specialization that we've discovered -/// is hidden, and produce suitable diagnostics if so. -void Sema::checkPartialSpecializationVisibility(SourceLocation Loc, - NamedDecl *Spec) { - llvm::SmallVector<Module *, 8> Modules; - if (!hasVisibleDeclaration(Spec, &Modules)) - diagnoseMissingImport(Loc, Spec, Spec->getLocation(), Modules, - MissingImportKind::PartialSpecialization, - /*Recover*/true); -} diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 5392be57a3aa..ee4316e7a632 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -171,30 +171,41 @@ static void MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, /// If the given expression is of a form that permits the deduction /// of a non-type template parameter, return the declaration of that /// non-type template parameter. -static NonTypeTemplateParmDecl * -getDeducedParameterFromExpr(TemplateDeductionInfo &Info, Expr *E) { +static const NonTypeTemplateParmDecl * +getDeducedParameterFromExpr(const Expr *E, unsigned Depth) { // If we are within an alias template, the expression may have undergone // any number of parameter substitutions already. while (true) { - if (ImplicitCastExpr *IC = dyn_cast<ImplicitCastExpr>(E)) + if (const auto *IC = dyn_cast<ImplicitCastExpr>(E)) E = IC->getSubExpr(); - else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(E)) + else if (const auto *CE = dyn_cast<ConstantExpr>(E)) E = CE->getSubExpr(); - else if (SubstNonTypeTemplateParmExpr *Subst = - dyn_cast<SubstNonTypeTemplateParmExpr>(E)) + else if (const auto *Subst = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) E = Subst->getReplacement(); - else + else if (const auto *CCE = dyn_cast<CXXConstructExpr>(E)) { + // Look through implicit copy construction from an lvalue of the same type. + if (CCE->getParenOrBraceRange().isValid()) + break; + // Note, there could be default arguments. + assert(CCE->getNumArgs() >= 1 && "implicit construct expr should have 1 arg"); + E = CCE->getArg(0); + } else break; } - if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) - if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl())) - if (NTTP->getDepth() == Info.getDeducedDepth()) + if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) + if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl())) + if (NTTP->getDepth() == Depth) return NTTP; return nullptr; } +static const NonTypeTemplateParmDecl * +getDeducedParameterFromExpr(TemplateDeductionInfo &Info, Expr *E) { + return getDeducedParameterFromExpr(E, Info.getDeducedDepth()); +} + /// Determine whether two declaration pointers refer to the same /// declaration. static bool isSameDeclaration(Decl *X, Decl *Y) { @@ -374,7 +385,7 @@ checkDeducedTemplateArguments(ASTContext &Context, /// deduction is funneled through here. static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument( Sema &S, TemplateParameterList *TemplateParams, - NonTypeTemplateParmDecl *NTTP, const DeducedTemplateArgument &NewDeduced, + const NonTypeTemplateParmDecl *NTTP, const DeducedTemplateArgument &NewDeduced, QualType ValueType, TemplateDeductionInfo &Info, SmallVectorImpl<DeducedTemplateArgument> &Deduced) { assert(NTTP->getDepth() == Info.getDeducedDepth() && @@ -383,7 +394,7 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument( DeducedTemplateArgument Result = checkDeducedTemplateArguments( S.Context, Deduced[NTTP->getIndex()], NewDeduced); if (Result.isNull()) { - Info.Param = NTTP; + Info.Param = const_cast<NonTypeTemplateParmDecl*>(NTTP); Info.FirstArg = Deduced[NTTP->getIndex()]; Info.SecondArg = NewDeduced; return Sema::TDK_Inconsistent; @@ -410,10 +421,16 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument( // type from an argument (of non-reference type) should be performed. // For now, we just remove reference types from both sides and let // the final check for matching types sort out the mess. + ValueType = ValueType.getNonReferenceType(); + if (ParamType->isReferenceType()) + ParamType = ParamType.getNonReferenceType(); + else + // Top-level cv-qualifiers are irrelevant for a non-reference type. + ValueType = ValueType.getUnqualifiedType(); + return DeduceTemplateArgumentsByTypeMatch( - S, TemplateParams, ParamType.getNonReferenceType(), - ValueType.getNonReferenceType(), Info, Deduced, TDF_SkipNonDependent, - /*PartialOrdering=*/false, + S, TemplateParams, ParamType, ValueType, Info, Deduced, + TDF_SkipNonDependent, /*PartialOrdering=*/false, /*ArrayBound=*/NewDeduced.wasDeducedFromArrayBound()); } @@ -421,7 +438,7 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument( /// from the given integral constant. static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument( Sema &S, TemplateParameterList *TemplateParams, - NonTypeTemplateParmDecl *NTTP, const llvm::APSInt &Value, + const NonTypeTemplateParmDecl *NTTP, const llvm::APSInt &Value, QualType ValueType, bool DeducedFromArrayBound, TemplateDeductionInfo &Info, SmallVectorImpl<DeducedTemplateArgument> &Deduced) { return DeduceNonTypeTemplateArgument( @@ -435,7 +452,7 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument( /// from the given null pointer template argument type. static Sema::TemplateDeductionResult DeduceNullPtrTemplateArgument( Sema &S, TemplateParameterList *TemplateParams, - NonTypeTemplateParmDecl *NTTP, QualType NullPtrType, + const NonTypeTemplateParmDecl *NTTP, QualType NullPtrType, TemplateDeductionInfo &Info, SmallVectorImpl<DeducedTemplateArgument> &Deduced) { Expr *Value = @@ -454,7 +471,7 @@ static Sema::TemplateDeductionResult DeduceNullPtrTemplateArgument( /// \returns true if deduction succeeded, false otherwise. static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument( Sema &S, TemplateParameterList *TemplateParams, - NonTypeTemplateParmDecl *NTTP, Expr *Value, TemplateDeductionInfo &Info, + const NonTypeTemplateParmDecl *NTTP, Expr *Value, TemplateDeductionInfo &Info, SmallVectorImpl<DeducedTemplateArgument> &Deduced) { return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP, DeducedTemplateArgument(Value), @@ -467,7 +484,7 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument( /// \returns true if deduction succeeded, false otherwise. static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument( Sema &S, TemplateParameterList *TemplateParams, - NonTypeTemplateParmDecl *NTTP, ValueDecl *D, QualType T, + const NonTypeTemplateParmDecl *NTTP, ValueDecl *D, QualType T, TemplateDeductionInfo &Info, SmallVectorImpl<DeducedTemplateArgument> &Deduced) { D = D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; @@ -641,23 +658,6 @@ static TemplateParameter makeTemplateParameter(Decl *D) { return TemplateParameter(cast<TemplateTemplateParmDecl>(D)); } -/// If \p Param is an expanded parameter pack, get the number of expansions. -static Optional<unsigned> getExpandedPackSize(NamedDecl *Param) { - if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) - if (TTP->isExpandedParameterPack()) - return TTP->getNumExpansionParameters(); - - if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) - if (NTTP->isExpandedParameterPack()) - return NTTP->getNumExpansionTypes(); - - if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Param)) - if (TTP->isExpandedParameterPack()) - return TTP->getNumExpansionTemplateParameters(); - - return None; -} - /// A pack that we're currently deducing. struct clang::DeducedPack { // The index of the pack. @@ -1201,6 +1201,120 @@ static bool isForwardingReference(QualType Param, unsigned FirstInnerIndex) { return false; } +/// Attempt to deduce the template arguments by checking the base types +/// according to (C++20 [temp.deduct.call] p4b3. +/// +/// \param S the semantic analysis object within which we are deducing. +/// +/// \param RecordT the top level record object we are deducing against. +/// +/// \param TemplateParams the template parameters that we are deducing. +/// +/// \param SpecParam the template specialization parameter type. +/// +/// \param Info information about the template argument deduction itself. +/// +/// \param Deduced the deduced template arguments. +/// +/// \returns the result of template argument deduction with the bases. "invalid" +/// means no matches, "success" found a single item, and the +/// "MiscellaneousDeductionFailure" result happens when the match is ambiguous. +static Sema::TemplateDeductionResult DeduceTemplateBases( + Sema &S, const RecordType *RecordT, TemplateParameterList *TemplateParams, + const TemplateSpecializationType *SpecParam, TemplateDeductionInfo &Info, + SmallVectorImpl<DeducedTemplateArgument> &Deduced) { + // C++14 [temp.deduct.call] p4b3: + // If P is a class and P has the form simple-template-id, then the + // transformed A can be a derived class of the deduced A. Likewise if + // P is a pointer to a class of the form simple-template-id, the + // transformed A can be a pointer to a derived class pointed to by the + // deduced A. However, if there is a class C that is a (direct or + // indirect) base class of D and derived (directly or indirectly) from a + // class B and that would be a valid deduced A, the deduced A cannot be + // B or pointer to B, respectively. + // + // These alternatives are considered only if type deduction would + // otherwise fail. If they yield more than one possible deduced A, the + // type deduction fails. + + // Use a breadth-first search through the bases to collect the set of + // successful matches. Visited contains the set of nodes we have already + // visited, while ToVisit is our stack of records that we still need to + // visit. Matches contains a list of matches that have yet to be + // disqualified. + llvm::SmallPtrSet<const RecordType *, 8> Visited; + SmallVector<const RecordType *, 8> ToVisit; + // We iterate over this later, so we have to use MapVector to ensure + // determinism. + llvm::MapVector<const RecordType *, SmallVector<DeducedTemplateArgument, 8>> + Matches; + + auto AddBases = [&Visited, &ToVisit](const RecordType *RT) { + CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + for (const auto &Base : RD->bases()) { + assert(Base.getType()->isRecordType() && + "Base class that isn't a record?"); + const RecordType *RT = Base.getType()->getAs<RecordType>(); + if (Visited.insert(RT).second) + ToVisit.push_back(Base.getType()->getAs<RecordType>()); + } + }; + + // Set up the loop by adding all the bases. + AddBases(RecordT); + + // Search each path of bases until we either run into a successful match + // (where all bases of it are invalid), or we run out of bases. + while (!ToVisit.empty()) { + const RecordType *NextT = ToVisit.pop_back_val(); + + SmallVector<DeducedTemplateArgument, 8> DeducedCopy(Deduced.begin(), + Deduced.end()); + TemplateDeductionInfo BaseInfo(TemplateDeductionInfo::ForBase, Info); + Sema::TemplateDeductionResult BaseResult = + DeduceTemplateArguments(S, TemplateParams, SpecParam, + QualType(NextT, 0), BaseInfo, DeducedCopy); + + // If this was a successful deduction, add it to the list of matches, + // otherwise we need to continue searching its bases. + if (BaseResult == Sema::TDK_Success) + Matches.insert({NextT, DeducedCopy}); + else + AddBases(NextT); + } + + // At this point, 'Matches' contains a list of seemingly valid bases, however + // in the event that we have more than 1 match, it is possible that the base + // of one of the matches might be disqualified for being a base of another + // valid match. We can count on cyclical instantiations being invalid to + // simplify the disqualifications. That is, if A & B are both matches, and B + // inherits from A (disqualifying A), we know that A cannot inherit from B. + if (Matches.size() > 1) { + Visited.clear(); + for (const auto &Match : Matches) + AddBases(Match.first); + + // We can give up once we have a single item (or have run out of things to + // search) since cyclical inheritence isn't valid. + while (Matches.size() > 1 && !ToVisit.empty()) { + const RecordType *NextT = ToVisit.pop_back_val(); + Matches.erase(NextT); + + // Always add all bases, since the inheritence tree can contain + // disqualifications for multiple matches. + AddBases(NextT); + } + } + + if (Matches.empty()) + return Sema::TDK_Invalid; + if (Matches.size() > 1) + return Sema::TDK_MiscellaneousDeductionFailure; + + std::swap(Matches.front().second, Deduced); + return Sema::TDK_Success; +} + /// Deduce the template arguments by comparing the parameter type and /// the argument type (C++ [temp.deduct.type]). /// @@ -1484,14 +1598,18 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, return Sema::TDK_Success; } } else if (!Param->isDependentType()) { - CanQualType ParamUnqualType = CanParam.getUnqualifiedType(), - ArgUnqualType = CanArg.getUnqualifiedType(); - bool Success = - (TDF & TDF_AllowCompatibleFunctionType) - ? S.isSameOrCompatibleFunctionType(ParamUnqualType, ArgUnqualType) - : ParamUnqualType == ArgUnqualType; - if (Success) + if (!(TDF & TDF_SkipNonDependent)) { + CanQualType ParamUnqualType = CanParam.getUnqualifiedType(), + ArgUnqualType = CanArg.getUnqualifiedType(); + bool Success = + (TDF & TDF_AllowCompatibleFunctionType) + ? S.isSameOrCompatibleFunctionType(ParamUnqualType, ArgUnqualType) + : ParamUnqualType == ArgUnqualType; + if (Success) + return Sema::TDK_Success; + } else { return Sema::TDK_Success; + } } switch (Param->getTypeClass()) { @@ -1643,7 +1761,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, return Result; // Determine the array bound is something we can deduce. - NonTypeTemplateParmDecl *NTTP + const NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(Info, DependentArrayParm->getSizeExpr()); if (!NTTP) return Sema::TDK_Success; @@ -1712,7 +1830,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, // deducing through the noexcept-specifier if it's part of the canonical // type. libstdc++ relies on this. Expr *NoexceptExpr = FunctionProtoParam->getNoexceptExpr(); - if (NonTypeTemplateParmDecl *NTTP = + if (const NonTypeTemplateParmDecl *NTTP = NoexceptExpr ? getDeducedParameterFromExpr(Info, NoexceptExpr) : nullptr) { assert(NTTP->getDepth() == Info.getDeducedDepth() && @@ -1787,78 +1905,15 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, if (!S.isCompleteType(Info.getLocation(), Arg)) return Result; - // C++14 [temp.deduct.call] p4b3: - // If P is a class and P has the form simple-template-id, then the - // transformed A can be a derived class of the deduced A. Likewise if - // P is a pointer to a class of the form simple-template-id, the - // transformed A can be a pointer to a derived class pointed to by the - // deduced A. - // - // These alternatives are considered only if type deduction would - // otherwise fail. If they yield more than one possible deduced A, the - // type deduction fails. - // Reset the incorrectly deduced argument from above. Deduced = DeducedOrig; - // Use data recursion to crawl through the list of base classes. - // Visited contains the set of nodes we have already visited, while - // ToVisit is our stack of records that we still need to visit. - llvm::SmallPtrSet<const RecordType *, 8> Visited; - SmallVector<const RecordType *, 8> ToVisit; - ToVisit.push_back(RecordT); - bool Successful = false; - SmallVector<DeducedTemplateArgument, 8> SuccessfulDeduced; - while (!ToVisit.empty()) { - // Retrieve the next class in the inheritance hierarchy. - const RecordType *NextT = ToVisit.pop_back_val(); - - // If we have already seen this type, skip it. - if (!Visited.insert(NextT).second) - continue; - - // If this is a base class, try to perform template argument - // deduction from it. - if (NextT != RecordT) { - TemplateDeductionInfo BaseInfo(TemplateDeductionInfo::ForBase, Info); - Sema::TemplateDeductionResult BaseResult = - DeduceTemplateArguments(S, TemplateParams, SpecParam, - QualType(NextT, 0), BaseInfo, Deduced); - - // If template argument deduction for this base was successful, - // note that we had some success. Otherwise, ignore any deductions - // from this base class. - if (BaseResult == Sema::TDK_Success) { - // If we've already seen some success, then deduction fails due to - // an ambiguity (temp.deduct.call p5). - if (Successful) - return Sema::TDK_MiscellaneousDeductionFailure; - - Successful = true; - std::swap(SuccessfulDeduced, Deduced); - - Info.Param = BaseInfo.Param; - Info.FirstArg = BaseInfo.FirstArg; - Info.SecondArg = BaseInfo.SecondArg; - } - - Deduced = DeducedOrig; - } - - // Visit base classes - CXXRecordDecl *Next = cast<CXXRecordDecl>(NextT->getDecl()); - for (const auto &Base : Next->bases()) { - assert(Base.getType()->isRecordType() && - "Base class that isn't a record?"); - ToVisit.push_back(Base.getType()->getAs<RecordType>()); - } - } - - if (Successful) { - std::swap(SuccessfulDeduced, Deduced); - return Sema::TDK_Success; - } + // Check bases according to C++14 [temp.deduct.call] p4b3: + Sema::TemplateDeductionResult BaseResult = DeduceTemplateBases( + S, RecordT, TemplateParams, SpecParam, Info, Deduced); + if (BaseResult != Sema::TDK_Invalid) + return BaseResult; return Result; } @@ -1964,7 +2019,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, return Result; // Perform deduction on the vector size, if we can. - NonTypeTemplateParmDecl *NTTP = + const NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr()); if (!NTTP) return Sema::TDK_Success; @@ -1988,7 +2043,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, return Result; // Perform deduction on the vector size, if we can. - NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr( + const NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr( Info, VectorParam->getSizeExpr()); if (!NTTP) return Sema::TDK_Success; @@ -2017,8 +2072,8 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, return Result; // Perform deduction on the vector size, if we can. - NonTypeTemplateParmDecl *NTTP - = getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr()); + const NonTypeTemplateParmDecl *NTTP = + getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr()); if (!NTTP) return Sema::TDK_Success; @@ -2043,8 +2098,8 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, return Result; // Perform deduction on the vector size, if we can. - NonTypeTemplateParmDecl *NTTP - = getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr()); + const NonTypeTemplateParmDecl *NTTP = + getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr()); if (!NTTP) return Sema::TDK_Success; @@ -2100,28 +2155,27 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, const auto *ArgConstMatrix = dyn_cast<ConstantMatrixType>(Arg); const auto *ArgDepMatrix = dyn_cast<DependentSizedMatrixType>(Arg); if (!ParamExpr->isValueDependent()) { - llvm::APSInt ParamConst( - S.Context.getTypeSize(S.Context.getSizeType())); - if (!ParamExpr->isIntegerConstantExpr(ParamConst, S.Context)) + Optional<llvm::APSInt> ParamConst = + ParamExpr->getIntegerConstantExpr(S.Context); + if (!ParamConst) return Sema::TDK_NonDeducedMismatch; if (ArgConstMatrix) { - if ((ArgConstMatrix->*GetArgDimension)() == ParamConst) + if ((ArgConstMatrix->*GetArgDimension)() == *ParamConst) return Sema::TDK_Success; return Sema::TDK_NonDeducedMismatch; } Expr *ArgExpr = (ArgDepMatrix->*GetArgDimensionExpr)(); - llvm::APSInt ArgConst( - S.Context.getTypeSize(S.Context.getSizeType())); - if (!ArgExpr->isValueDependent() && - ArgExpr->isIntegerConstantExpr(ArgConst, S.Context) && - ArgConst == ParamConst) - return Sema::TDK_Success; + if (!ArgExpr->isValueDependent()) + if (Optional<llvm::APSInt> ArgConst = + ArgExpr->getIntegerConstantExpr(S.Context)) + if (*ArgConst == *ParamConst) + return Sema::TDK_Success; return Sema::TDK_NonDeducedMismatch; } - NonTypeTemplateParmDecl *NTTP = + const NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(Info, ParamExpr); if (!NTTP) return Sema::TDK_Success; @@ -2168,7 +2222,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, return Result; // Perform deduction on the address space, if we can. - NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr( + const NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr( Info, AddressSpaceParam->getAddrSpaceExpr()); if (!NTTP) return Sema::TDK_Success; @@ -2191,7 +2245,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, return Result; // Perform deduction on the address space, if we can. - NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr( + const NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr( Info, AddressSpaceParam->getAddrSpaceExpr()); if (!NTTP) return Sema::TDK_Success; @@ -2210,7 +2264,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, if (IntParam->isUnsigned() != IntArg->isUnsigned()) return Sema::TDK_NonDeducedMismatch; - NonTypeTemplateParmDecl *NTTP = + const NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(Info, IntParam->getNumBitsExpr()); if (!NTTP) return Sema::TDK_Success; @@ -2327,8 +2381,8 @@ DeduceTemplateArguments(Sema &S, return Sema::TDK_NonDeducedMismatch; case TemplateArgument::Expression: - if (NonTypeTemplateParmDecl *NTTP - = getDeducedParameterFromExpr(Info, Param.getAsExpr())) { + if (const NonTypeTemplateParmDecl *NTTP = + getDeducedParameterFromExpr(Info, Param.getAsExpr())) { if (Arg.getKind() == TemplateArgument::Integral) return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP, Arg.getAsIntegral(), @@ -2620,11 +2674,11 @@ Sema::getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, Builder.MakeTrivial(Context, QTN->getQualifier(), Loc); if (Arg.getKind() == TemplateArgument::Template) - return TemplateArgumentLoc(Arg, Builder.getWithLocInContext(Context), - Loc); + return TemplateArgumentLoc(Context, Arg, + Builder.getWithLocInContext(Context), Loc); - return TemplateArgumentLoc(Arg, Builder.getWithLocInContext(Context), - Loc, Loc); + return TemplateArgumentLoc( + Context, Arg, Builder.getWithLocInContext(Context), Loc, Loc); } case TemplateArgument::Expression: @@ -3807,17 +3861,18 @@ static bool AdjustFunctionParmAndArgTypesForDeduction( if (ParamRefType) { // If the argument has incomplete array type, try to complete its type. - if (ArgType->isIncompleteArrayType()) { - S.completeExprArrayBound(Arg); - ArgType = Arg->getType(); - } + if (ArgType->isIncompleteArrayType()) + ArgType = S.getCompletedType(Arg); // C++1z [temp.deduct.call]p3: // If P is a forwarding reference and the argument is an lvalue, the type // "lvalue reference to A" is used in place of A for type deduction. if (isForwardingReference(QualType(ParamRefType, 0), FirstInnerIndex) && - Arg->isLValue()) + Arg->isLValue()) { + if (S.getLangOpts().OpenCL) + ArgType = S.Context.getAddrSpaceQualType(ArgType, LangAS::opencl_generic); ArgType = S.Context.getLValueReferenceType(ArgType); + } } else { // C++ [temp.deduct.call]p2: // If P is not a reference type: @@ -3929,7 +3984,7 @@ static Sema::TemplateDeductionResult DeduceFromInitializerList( // from the length of the initializer list. if (auto *DependentArrTy = dyn_cast_or_null<DependentSizedArrayType>(ArrTy)) { // Determine the array bound is something we can deduce. - if (NonTypeTemplateParmDecl *NTTP = + if (const NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(Info, DependentArrTy->getSizeExpr())) { // We can perform template argument deduction for the given non-type // template parameter. @@ -4894,6 +4949,13 @@ QualType Sema::ReplaceAutoType(QualType TypeWithAuto, .TransformType(TypeWithAuto); } +TypeSourceInfo *Sema::ReplaceAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto, + QualType TypeToReplaceAuto) { + return SubstituteDeducedTypeTransform(*this, TypeToReplaceAuto, + /*UseTypeSugar*/ false) + .TransformType(TypeWithAuto); +} + void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) { if (isa<InitListExpr>(Init)) Diag(VDecl->getLocation(), @@ -4941,8 +5003,12 @@ bool Sema::DeduceReturnType(FunctionDecl *FD, SourceLocation Loc, "failed to deduce lambda return type"); // Build the new return type from scratch. + CallingConv RetTyCC = FD->getReturnType() + ->getPointeeType() + ->castAs<FunctionType>() + ->getCallConv(); QualType RetType = getLambdaConversionFunctionResultType( - CallOp->getType()->castAs<FunctionProtoType>()); + CallOp->getType()->castAs<FunctionProtoType>(), RetTyCC); if (FD->getReturnType()->getAs<PointerType>()) RetType = Context.getPointerType(RetType); else { @@ -5668,26 +5734,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, if (const PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(E)) E = Expansion->getPattern(); - // Skip through any implicit casts we added while type-checking, and any - // substitutions performed by template alias expansion. - while (true) { - if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) - E = ICE->getSubExpr(); - else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(E)) - E = CE->getSubExpr(); - else if (const SubstNonTypeTemplateParmExpr *Subst = - dyn_cast<SubstNonTypeTemplateParmExpr>(E)) - E = Subst->getReplacement(); - else - break; - } - - const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E); - if (!DRE) - return; - - const NonTypeTemplateParmDecl *NTTP - = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl()); + const NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(E, Depth); if (!NTTP) return; diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 11e03c517d01..8bd812b39de4 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -141,7 +141,12 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D, TSK_ExplicitSpecialization) break; - if (const TemplateArgumentList *TemplateArgs + if (!RelativeToPrimary && Function->getTemplateSpecializationKind() == + TSK_ExplicitSpecialization) { + // This is an implicit instantiation of an explicit specialization. We + // don't get any template arguments from this function but might get + // some from an enclosing template. + } else if (const TemplateArgumentList *TemplateArgs = Function->getTemplateSpecializationArgs()) { // Add the template arguments for this specialization. Result.addOuterTemplateArguments(TemplateArgs); @@ -237,7 +242,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate( // error have occurred. Any diagnostics we might have raised will not be // visible, and we do not need to construct a correct AST. if (SemaRef.Diags.hasFatalErrorOccurred() && - SemaRef.Diags.hasUncompilableErrorOccurred()) { + SemaRef.hasUncompilableErrorOccurred()) { Invalid = true; return; } @@ -256,7 +261,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate( AlreadyInstantiating = !Inst.Entity ? false : !SemaRef.InstantiatingSpecializations - .insert(std::make_pair(Inst.Entity->getCanonicalDecl(), Inst.Kind)) + .insert({Inst.Entity->getCanonicalDecl(), Inst.Kind}) .second; atTemplateBegin(SemaRef.TemplateInstCallbacks, SemaRef, Inst); } @@ -475,7 +480,7 @@ void Sema::InstantiatingTemplate::Clear() { auto &Active = SemaRef.CodeSynthesisContexts.back(); if (Active.Entity) SemaRef.InstantiatingSpecializations.erase( - std::make_pair(Active.Entity, Active.Kind)); + {Active.Entity->getCanonicalDecl(), Active.Kind}); } atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef, @@ -579,7 +584,7 @@ void Sema::PrintInstantiationStack() { case CodeSynthesisContext::DefaultTemplateArgumentInstantiation: { TemplateDecl *Template = cast<TemplateDecl>(Active->Template); - SmallVector<char, 128> TemplateArgsStr; + SmallString<128> TemplateArgsStr; llvm::raw_svector_ostream OS(TemplateArgsStr); Template->printName(OS); printTemplateArgumentList(OS, Active->template_arguments(), @@ -645,7 +650,7 @@ void Sema::PrintInstantiationStack() { ParmVarDecl *Param = cast<ParmVarDecl>(Active->Entity); FunctionDecl *FD = cast<FunctionDecl>(Param->getDeclContext()); - SmallVector<char, 128> TemplateArgsStr; + SmallString<128> TemplateArgsStr; llvm::raw_svector_ostream OS(TemplateArgsStr); FD->printName(OS); printTemplateArgumentList(OS, Active->template_arguments(), @@ -797,7 +802,7 @@ void Sema::PrintInstantiationStack() { assert(isa<FunctionDecl>(Active->Entity)); DiagID = diag::note_checking_constraints_for_function_here; } - SmallVector<char, 128> TemplateArgsStr; + SmallString<128> TemplateArgsStr; llvm::raw_svector_ostream OS(TemplateArgsStr); cast<NamedDecl>(Active->Entity)->printName(OS); if (!isa<FunctionDecl>(Active->Entity)) @@ -856,6 +861,7 @@ Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const { case CodeSynthesisContext::DefaultTemplateArgumentInstantiation: case CodeSynthesisContext::PriorTemplateArgumentSubstitution: case CodeSynthesisContext::DefaultTemplateArgumentChecking: + case CodeSynthesisContext::RewritingOperatorAsSpaceship: // A default template argument instantiation and substitution into // template parameters with arguments for prior parameters may or may // not be a SFINAE context; look further up the stack. @@ -874,7 +880,6 @@ Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const { case CodeSynthesisContext::DeclaringSpecialMember: case CodeSynthesisContext::DeclaringImplicitEqualityComparison: case CodeSynthesisContext::DefiningSynthesizedFunction: - case CodeSynthesisContext::RewritingOperatorAsSpaceship: case CodeSynthesisContext::InitializingStructuredBinding: case CodeSynthesisContext::MarkingClassDllexported: // This happens in a context unrelated to template instantiation, so @@ -1414,47 +1419,11 @@ TemplateName TemplateInstantiator::TransformTemplateName( AllowInjectedClassName); } -static ExprResult TransformUniqueStableName(TemplateInstantiator &TI, - PredefinedExpr *E) { - if (E->getIdentKind() == PredefinedExpr::UniqueStableNameType) { - TypeSourceInfo *Info = - TI.getDerived().TransformType(E->getTypeSourceInfo()); - - if (!Info) - return ExprError(); - - if (!TI.getDerived().AlwaysRebuild() && Info == E->getTypeSourceInfo()) - return E; - - return TI.getSema().BuildUniqueStableName(E->getLocation(), Info); - } - - if (E->getIdentKind() == PredefinedExpr::UniqueStableNameExpr) { - EnterExpressionEvaluationContext Unevaluated( - TI.getSema(), Sema::ExpressionEvaluationContext::Unevaluated); - ExprResult SubExpr = TI.getDerived().TransformExpr(E->getExpr()); - - if (SubExpr.isInvalid()) - return ExprError(); - - if (!TI.getDerived().AlwaysRebuild() && SubExpr.get() == E->getExpr()) - return E; - - return TI.getSema().BuildUniqueStableName(E->getLocation(), SubExpr.get()); - } - - llvm_unreachable("Only valid for UniqueStableNameType/Expr"); -} - ExprResult TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) { if (!E->isTypeDependent()) return E; - if (E->getIdentKind() == PredefinedExpr::UniqueStableNameType || - E->getIdentKind() == PredefinedExpr::UniqueStableNameExpr) - return TransformUniqueStableName(*this, E); - return getSema().BuildPredefinedExpr(E->getLocation(), E->getIdentKind()); } @@ -1500,9 +1469,12 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E, if (TargetType.isNull()) return ExprError(); + QualType ExprType = TargetType.getNonLValueExprType(SemaRef.Context); + if (TargetType->isRecordType()) + ExprType.addConst(); + return new (SemaRef.Context) SubstNonTypeTemplateParmPackExpr( - TargetType.getNonLValueExprType(SemaRef.Context), - TargetType->isReferenceType() ? VK_LValue : VK_RValue, NTTP, + ExprType, TargetType->isReferenceType() ? VK_LValue : VK_RValue, NTTP, E->getLocation(), Arg); } @@ -1534,15 +1506,39 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef( SourceLocation loc, TemplateArgument arg) { ExprResult result; - QualType type; - // The template argument itself might be an expression, in which - // case we just return that expression. + // Determine the substituted parameter type. We can usually infer this from + // the template argument, but not always. + auto SubstParamType = [&] { + QualType T; + if (parm->isExpandedParameterPack()) + T = parm->getExpansionType(SemaRef.ArgumentPackSubstitutionIndex); + else + T = parm->getType(); + if (parm->isParameterPack() && isa<PackExpansionType>(T)) + T = cast<PackExpansionType>(T)->getPattern(); + return SemaRef.SubstType(T, TemplateArgs, loc, parm->getDeclName()); + }; + + bool refParam = false; + + // The template argument itself might be an expression, in which case we just + // return that expression. This happens when substituting into an alias + // template. if (arg.getKind() == TemplateArgument::Expression) { Expr *argExpr = arg.getAsExpr(); result = argExpr; - type = argExpr->getType(); - + if (argExpr->isLValue()) { + if (argExpr->getType()->isRecordType()) { + // Check whether the parameter was actually a reference. + QualType paramType = SubstParamType(); + if (paramType.isNull()) + return ExprError(); + refParam = paramType->isReferenceType(); + } else { + refParam = true; + } + } } else if (arg.getKind() == TemplateArgument::Declaration || arg.getKind() == TemplateArgument::NullPtr) { ValueDecl *VD; @@ -1560,36 +1556,25 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef( VD = nullptr; } - // Derive the type we want the substituted decl to have. This had - // better be non-dependent, or these checks will have serious problems. - if (parm->isExpandedParameterPack()) { - type = parm->getExpansionType(SemaRef.ArgumentPackSubstitutionIndex); - } else if (parm->isParameterPack() && - isa<PackExpansionType>(parm->getType())) { - type = SemaRef.SubstType( - cast<PackExpansionType>(parm->getType())->getPattern(), - TemplateArgs, loc, parm->getDeclName()); - } else { - type = SemaRef.SubstType(VD ? arg.getParamTypeForDecl() : arg.getNullPtrType(), - TemplateArgs, loc, parm->getDeclName()); - } - assert(!type.isNull() && "type substitution failed for param type"); - assert(!type->isDependentType() && "param type still dependent"); - result = SemaRef.BuildExpressionFromDeclTemplateArgument(arg, type, loc); - - if (!result.isInvalid()) type = result.get()->getType(); + QualType paramType = VD ? arg.getParamTypeForDecl() : arg.getNullPtrType(); + assert(!paramType.isNull() && "type substitution failed for param type"); + assert(!paramType->isDependentType() && "param type still dependent"); + result = SemaRef.BuildExpressionFromDeclTemplateArgument(arg, paramType, loc); + refParam = paramType->isReferenceType(); } else { result = SemaRef.BuildExpressionFromIntegralTemplateArgument(arg, loc); - - // Note that this type can be different from the type of 'result', - // e.g. if it's an enum type. - type = arg.getIntegralType(); + assert(result.isInvalid() || + SemaRef.Context.hasSameType(result.get()->getType(), + arg.getIntegralType())); } - if (result.isInvalid()) return ExprError(); + + if (result.isInvalid()) + return ExprError(); Expr *resultExpr = result.get(); return new (SemaRef.Context) SubstNonTypeTemplateParmExpr( - type, resultExpr->getValueKind(), loc, parm, resultExpr); + resultExpr->getType(), resultExpr->getValueKind(), loc, parm, refParam, + resultExpr); } ExprResult @@ -1610,10 +1595,12 @@ TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr( ExprResult TemplateInstantiator::TransformSubstNonTypeTemplateParmExpr( SubstNonTypeTemplateParmExpr *E) { - ExprResult SubstReplacement = TransformExpr(E->getReplacement()); + ExprResult SubstReplacement = E->getReplacement(); + if (!isa<ConstantExpr>(SubstReplacement.get())) + SubstReplacement = TransformExpr(E->getReplacement()); if (SubstReplacement.isInvalid()) return true; - QualType SubstType = TransformType(E->getType()); + QualType SubstType = TransformType(E->getParameterType(getSema().Context)); if (SubstType.isNull()) return true; // The type may have been previously dependent and not now, which means we @@ -2732,7 +2719,10 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, // BlockDecls can appear in a default-member-initializer. They must be the // child of a BlockExpr, so we only know how to instantiate them from there. - if (isa<BlockDecl>(Member)) + // Similarly, lambda closure types are recreated when instantiating the + // corresponding LambdaExpr. + if (isa<BlockDecl>(Member) || + (isa<CXXRecordDecl>(Member) && cast<CXXRecordDecl>(Member)->isLambda())) continue; if (Member->isInvalidDecl()) { @@ -2806,7 +2796,8 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, Attr *NewAttr = instantiateTemplateAttribute(I->TmplAttr, Context, *this, TemplateArgs); - I->NewDecl->addAttr(NewAttr); + if (NewAttr) + I->NewDecl->addAttr(NewAttr); LocalInstantiationScope::deleteScopes(I->Scope, Instantiator.getStartingScope()); } @@ -2858,8 +2849,6 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, SavedContext.pop(); if (!Instantiation->isInvalidDecl()) { - Consumer.HandleTagDeclDefinition(Instantiation); - // Always emit the vtable for an explicit instantiation definition // of a polymorphic class template specialization. Otherwise, eagerly // instantiate only constexpr virtual functions in preparation for their use @@ -2871,6 +2860,8 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, /*ConstexprOnly*/ true); } + Consumer.HandleTagDeclDefinition(Instantiation); + return Instantiation->isInvalidDecl(); } @@ -2972,9 +2963,10 @@ bool Sema::InstantiateInClassInitializer( RecordDecl *PatternRD = Pattern->getParent(); RecordDecl *OutermostClass = PatternRD->getOuterLexicalRecordContext(); Diag(PointOfInstantiation, - diag::err_in_class_initializer_not_yet_parsed) + diag::err_default_member_initializer_not_yet_parsed) << OutermostClass << Pattern; - Diag(Pattern->getEndLoc(), diag::note_in_class_initializer_not_yet_parsed); + Diag(Pattern->getEndLoc(), + diag::note_default_member_initializer_not_yet_parsed); Instantiation->setInvalidDecl(); return true; } @@ -2984,7 +2976,7 @@ bool Sema::InstantiateInClassInitializer( return true; if (Inst.isAlreadyInstantiating()) { // Error out if we hit an instantiation cycle for this initializer. - Diag(PointOfInstantiation, diag::err_in_class_initializer_cycle) + Diag(PointOfInstantiation, diag::err_default_member_initializer_cycle) << Instantiation; return true; } @@ -3048,14 +3040,16 @@ bool Sema::usesPartialOrExplicitSpecialization( /// Get the instantiation pattern to use to instantiate the definition of a /// given ClassTemplateSpecializationDecl (either the pattern of the primary /// template or of a partial specialization). -static CXXRecordDecl * +static ActionResult<CXXRecordDecl *> getPatternForClassTemplateSpecialization( Sema &S, SourceLocation PointOfInstantiation, ClassTemplateSpecializationDecl *ClassTemplateSpec, - TemplateSpecializationKind TSK, bool Complain) { + TemplateSpecializationKind TSK) { Sema::InstantiatingTemplate Inst(S, PointOfInstantiation, ClassTemplateSpec); - if (Inst.isInvalid() || Inst.isAlreadyInstantiating()) - return nullptr; + if (Inst.isInvalid()) + return {/*Invalid=*/true}; + if (Inst.isAlreadyInstantiating()) + return {/*Invalid=*/false}; llvm::PointerUnion<ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *> @@ -3152,7 +3146,7 @@ getPatternForClassTemplateSpecialization( << S.getTemplateArgumentBindingsText( P->Partial->getTemplateParameters(), *P->Args); - return nullptr; + return {/*Invalid=*/true}; } } @@ -3203,14 +3197,15 @@ bool Sema::InstantiateClassTemplateSpecialization( if (ClassTemplateSpec->isInvalidDecl()) return true; - CXXRecordDecl *Pattern = getPatternForClassTemplateSpecialization( - *this, PointOfInstantiation, ClassTemplateSpec, TSK, Complain); - if (!Pattern) - return true; + ActionResult<CXXRecordDecl *> Pattern = + getPatternForClassTemplateSpecialization(*this, PointOfInstantiation, + ClassTemplateSpec, TSK); + if (!Pattern.isUsable()) + return Pattern.isInvalid(); - return InstantiateClass(PointOfInstantiation, ClassTemplateSpec, Pattern, - getTemplateInstantiationArgs(ClassTemplateSpec), TSK, - Complain); + return InstantiateClass( + PointOfInstantiation, ClassTemplateSpec, Pattern.get(), + getTemplateInstantiationArgs(ClassTemplateSpec), TSK, Complain); } /// Instantiates the definitions of all of the member diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 2efb7acb9724..dc1e0ef60cac 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -181,6 +181,22 @@ static void instantiateDependentAllocAlignAttr( S.AddAllocAlignAttr(New, *Align, Param); } +static void instantiateDependentAnnotationAttr( + Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, + const AnnotateAttr *Attr, Decl *New) { + EnterExpressionEvaluationContext Unevaluated( + S, Sema::ExpressionEvaluationContext::ConstantEvaluated); + SmallVector<Expr *, 4> Args; + Args.reserve(Attr->args_size()); + for (auto *E : Attr->args()) { + ExprResult Result = S.SubstExpr(E, TemplateArgs); + if (!Result.isUsable()) + return; + Args.push_back(Result.get()); + } + S.AddAnnotationAttr(New, *Attr, Attr->getAnnotation(), Args); +} + static Expr *instantiateDependentFunctionAttrCondition( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, const Attr *A, Expr *OldCond, const Decl *Tmpl, FunctionDecl *New) { @@ -417,7 +433,9 @@ static void instantiateOMPDeclareVariantAttr( if (TI.anyScoreOrCondition(SubstScoreOrConditionExpr)) return; - // Check function/variant ref. + Expr *E = VariantFuncRef.get(); + // Check function/variant ref for `omp declare variant` but not for `omp + // begin declare variant` (which use implicit attributes). Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData = S.checkOpenMPDeclareVariantFunction(S.ConvertDeclToDeclGroup(New), VariantFuncRef.get(), TI, @@ -426,9 +444,42 @@ static void instantiateOMPDeclareVariantAttr( if (!DeclVarData) return; - S.ActOnOpenMPDeclareVariantDirective(DeclVarData.getValue().first, - DeclVarData.getValue().second, TI, - Attr.getRange()); + E = DeclVarData.getValue().second; + FD = DeclVarData.getValue().first; + + if (auto *VariantDRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts())) { + if (auto *VariantFD = dyn_cast<FunctionDecl>(VariantDRE->getDecl())) { + if (auto *VariantFTD = VariantFD->getDescribedFunctionTemplate()) { + if (!VariantFTD->isThisDeclarationADefinition()) + return; + Sema::TentativeAnalysisScope Trap(S); + const TemplateArgumentList *TAL = TemplateArgumentList::CreateCopy( + S.Context, TemplateArgs.getInnermost()); + + auto *SubstFD = S.InstantiateFunctionDeclaration(VariantFTD, TAL, + New->getLocation()); + if (!SubstFD) + return; + QualType NewType = S.Context.mergeFunctionTypes( + SubstFD->getType(), FD->getType(), + /* OfBlockPointer */ false, + /* Unqualified */ false, /* AllowCXX */ true); + if (NewType.isNull()) + return; + S.InstantiateFunctionDefinition( + New->getLocation(), SubstFD, /* Recursive */ true, + /* DefinitionRequired */ false, /* AtEndOfTU */ false); + SubstFD->setInstantiationIsPending(!SubstFD->isDefined()); + E = DeclRefExpr::Create(S.Context, NestedNameSpecifierLoc(), + SourceLocation(), SubstFD, + /* RefersToEnclosingVariableOrCapture */ false, + /* NameLoc */ SubstFD->getLocation(), + SubstFD->getType(), ExprValueKind::VK_RValue); + } + } + } + + S.ActOnOpenMPDeclareVariantDirective(FD, E, TI, Attr.getRange()); } static void instantiateDependentAMDGPUFlatWorkGroupSizeAttr( @@ -497,12 +548,40 @@ static void instantiateDependentAMDGPUWavesPerEUAttr( S.addAMDGPUWavesPerEUAttr(New, Attr, MinExpr, MaxExpr); } +/// Determine whether the attribute A might be relevent to the declaration D. +/// If not, we can skip instantiating it. The attribute may or may not have +/// been instantiated yet. +static bool isRelevantAttr(Sema &S, const Decl *D, const Attr *A) { + // 'preferred_name' is only relevant to the matching specialization of the + // template. + if (const auto *PNA = dyn_cast<PreferredNameAttr>(A)) { + QualType T = PNA->getTypedefType(); + const auto *RD = cast<CXXRecordDecl>(D); + if (!T->isDependentType() && !RD->isDependentContext() && + !declaresSameEntity(T->getAsCXXRecordDecl(), RD)) + return false; + for (const auto *ExistingPNA : D->specific_attrs<PreferredNameAttr>()) + if (S.Context.hasSameType(ExistingPNA->getTypedefType(), + PNA->getTypedefType())) + return false; + return true; + } + + return true; +} + void Sema::InstantiateAttrsForDecl( const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Tmpl, Decl *New, LateInstantiatedAttrVec *LateAttrs, LocalInstantiationScope *OuterMostScope) { if (NamedDecl *ND = dyn_cast<NamedDecl>(New)) { + // FIXME: This function is called multiple times for the same template + // specialization. We should only instantiate attributes that were added + // since the previous instantiation. for (const auto *TmplAttr : Tmpl->attrs()) { + if (!isRelevantAttr(*this, New, TmplAttr)) + continue; + // FIXME: If any of the special case versions from InstantiateAttrs become // applicable to template declaration, we'll need to add them here. CXXThisScopeRAII ThisScope( @@ -511,7 +590,7 @@ void Sema::InstantiateAttrsForDecl( Attr *NewAttr = sema::instantiateTemplateAttributeForDecl( TmplAttr, Context, *this, TemplateArgs); - if (NewAttr) + if (NewAttr && isRelevantAttr(*this, New, NewAttr)) New->addAttr(NewAttr); } } @@ -536,6 +615,9 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, LateInstantiatedAttrVec *LateAttrs, LocalInstantiationScope *OuterMostScope) { for (const auto *TmplAttr : Tmpl->attrs()) { + if (!isRelevantAttr(*this, New, TmplAttr)) + continue; + // FIXME: This should be generalized to more than just the AlignedAttr. const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr); if (Aligned && Aligned->isAlignmentDependent()) { @@ -558,6 +640,10 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, continue; } + if (const auto *Annotate = dyn_cast<AnnotateAttr>(TmplAttr)) { + instantiateDependentAnnotationAttr(*this, TemplateArgs, Annotate, New); + continue; + } if (const auto *EnableIf = dyn_cast<EnableIfAttr>(TmplAttr)) { instantiateDependentEnableIfAttr(*this, TemplateArgs, EnableIf, Tmpl, @@ -654,12 +740,32 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context, *this, TemplateArgs); - if (NewAttr) + if (NewAttr && isRelevantAttr(*this, New, TmplAttr)) New->addAttr(NewAttr); } } } +/// In the MS ABI, we need to instantiate default arguments of dllexported +/// default constructors along with the constructor definition. This allows IR +/// gen to emit a constructor closure which calls the default constructor with +/// its default arguments. +void Sema::InstantiateDefaultCtorDefaultArgs(CXXConstructorDecl *Ctor) { + assert(Context.getTargetInfo().getCXXABI().isMicrosoft() && + Ctor->isDefaultConstructor()); + unsigned NumParams = Ctor->getNumParams(); + if (NumParams == 0) + return; + DLLExportAttr *Attr = Ctor->getAttr<DLLExportAttr>(); + if (!Attr) + return; + for (unsigned I = 0; I != NumParams; ++I) { + (void)CheckCXXDefaultArgExpr(Attr->getLocation(), Ctor, + Ctor->getParamDecl(I)); + DiscardCleanupsInEvaluationContext(); + } +} + /// Get the previous declaration of a declaration for the purposes of template /// instantiation. If this finds a previous declaration, then the previous /// declaration of the instantiation of D should be an instantiation of the @@ -702,6 +808,11 @@ Decl *TemplateDeclInstantiator::VisitMSGuidDecl(MSGuidDecl *D) { llvm_unreachable("GUID declaration cannot be instantiated"); } +Decl *TemplateDeclInstantiator::VisitTemplateParamObjectDecl( + TemplateParamObjectDecl *D) { + llvm_unreachable("template parameter objects cannot be instantiated"); +} + Decl * TemplateDeclInstantiator::VisitLabelDecl(LabelDecl *D) { LabelDecl *Inst = LabelDecl::Create(SemaRef.Context, Owner, D->getLocation(), @@ -1911,7 +2022,6 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( D->hasWrittenPrototype(), D->getConstexprKind(), TrailingRequiresClause); Function->setRangeEnd(D->getSourceRange().getEnd()); - Function->setUsesFPIntrin(D->usesFPIntrin()); } if (D->isInlined()) @@ -1981,8 +2091,11 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( Function->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation); } - if (isFriend) + if (isFriend) { Function->setObjectOfFriendDecl(); + if (FunctionTemplateDecl *FT = Function->getDescribedFunctionTemplate()) + FT->setObjectOfFriendDecl(); + } if (InitFunctionInstantiation(Function, D)) Function->setInvalidDecl(); @@ -2053,68 +2166,45 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( // typedef (C++ [dcl.typedef]p4). if (Previous.isSingleTagDecl()) Previous.clear(); + + // Filter out previous declarations that don't match the scope. The only + // effect this has is to remove declarations found in inline namespaces + // for friend declarations with unqualified names. + SemaRef.FilterLookupForScope(Previous, DC, /*Scope*/ nullptr, + /*ConsiderLinkage*/ true, + QualifierLoc.hasQualifier()); } SemaRef.CheckFunctionDeclaration(/*Scope*/ nullptr, Function, Previous, IsExplicitSpecialization); - NamedDecl *PrincipalDecl = (TemplateParams - ? cast<NamedDecl>(FunctionTemplate) - : Function); - - // If the original function was part of a friend declaration, - // inherit its namespace state and add it to the owner. - if (isFriend) { - Function->setObjectOfFriendDecl(); - if (FunctionTemplateDecl *FT = Function->getDescribedFunctionTemplate()) - FT->setObjectOfFriendDecl(); - DC->makeDeclVisibleInContext(PrincipalDecl); - - bool QueuedInstantiation = false; - - // C++11 [temp.friend]p4 (DR329): - // When a function is defined in a friend function declaration in a class - // template, the function is instantiated when the function is odr-used. - // The same restrictions on multiple declarations and definitions that - // apply to non-template function declarations and definitions also apply - // to these implicit definitions. - if (D->isThisDeclarationADefinition()) { - SemaRef.CheckForFunctionRedefinition(Function); - if (!Function->isInvalidDecl()) { - for (auto R : Function->redecls()) { - if (R == Function) - continue; - - // If some prior declaration of this function has been used, we need - // to instantiate its definition. - if (!QueuedInstantiation && R->isUsed(false)) { - if (MemberSpecializationInfo *MSInfo = - Function->getMemberSpecializationInfo()) { - if (MSInfo->getPointOfInstantiation().isInvalid()) { - SourceLocation Loc = R->getLocation(); // FIXME - MSInfo->setPointOfInstantiation(Loc); - SemaRef.PendingLocalImplicitInstantiations.push_back( - std::make_pair(Function, Loc)); - QueuedInstantiation = true; - } - } - } - } + // Check the template parameter list against the previous declaration. The + // goal here is to pick up default arguments added since the friend was + // declared; we know the template parameter lists match, since otherwise + // we would not have picked this template as the previous declaration. + if (isFriend && TemplateParams && FunctionTemplate->getPreviousDecl()) { + SemaRef.CheckTemplateParameterList( + TemplateParams, + FunctionTemplate->getPreviousDecl()->getTemplateParameters(), + Function->isThisDeclarationADefinition() + ? Sema::TPC_FriendFunctionTemplateDefinition + : Sema::TPC_FriendFunctionTemplate); + } + + // If we're introducing a friend definition after the first use, trigger + // instantiation. + // FIXME: If this is a friend function template definition, we should check + // to see if any specializations have been used. + if (isFriend && D->isThisDeclarationADefinition() && Function->isUsed(false)) { + if (MemberSpecializationInfo *MSInfo = + Function->getMemberSpecializationInfo()) { + if (MSInfo->getPointOfInstantiation().isInvalid()) { + SourceLocation Loc = D->getLocation(); // FIXME + MSInfo->setPointOfInstantiation(Loc); + SemaRef.PendingLocalImplicitInstantiations.push_back( + std::make_pair(Function, Loc)); } } - - // Check the template parameter list against the previous declaration. The - // goal here is to pick up default arguments added since the friend was - // declared; we know the template parameter lists match, since otherwise - // we would not have picked this template as the previous declaration. - if (TemplateParams && FunctionTemplate->getPreviousDecl()) { - SemaRef.CheckTemplateParameterList( - TemplateParams, - FunctionTemplate->getPreviousDecl()->getTemplateParameters(), - Function->isThisDeclarationADefinition() - ? Sema::TPC_FriendFunctionTemplateDefinition - : Sema::TPC_FriendFunctionTemplate); - } } if (D->isExplicitlyDefaulted()) { @@ -2124,7 +2214,13 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( if (D->isDeleted()) SemaRef.SetDeclDeleted(Function, D->getLocation()); - if (Function->isLocalExternDecl() && !Function->getPreviousDecl()) + NamedDecl *PrincipalDecl = + (TemplateParams ? cast<NamedDecl>(FunctionTemplate) : Function); + + // If this declaration lives in a different context from its lexical context, + // add it to the corresponding lookup table. + if (isFriend || + (Function->isLocalExternDecl() && !Function->getPreviousDecl())) DC->makeDeclVisibleInContext(PrincipalDecl); if (Function->isOverloadedOperator() && !DC->isRecord() && @@ -2879,7 +2975,7 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl( if (!TName.isNull()) Param->setDefaultArgument( SemaRef.Context, - TemplateArgumentLoc(TemplateArgument(TName), + TemplateArgumentLoc(SemaRef.Context, TemplateArgument(TName), D->getDefaultArgument().getTemplateQualifierLoc(), D->getDefaultArgument().getTemplateNameLoc())); } @@ -3326,67 +3422,58 @@ TemplateDeclInstantiator::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) { SemaRef.CurrentInstantiationScope->findInstantiationOf(PrevDeclInScope) ->get<Decl *>()); } - OMPDeclareMapperDecl *NewDMD = SemaRef.ActOnOpenMPDeclareMapperDirectiveStart( - /*S=*/nullptr, Owner, D->getDeclName(), SubstMapperTy, D->getLocation(), - VN, D->getAccess(), PrevDeclInScope); - SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewDMD); - SmallVector<OMPClause *, 6> Clauses; bool IsCorrect = true; - if (!RequiresInstantiation) { - // Copy the mapper variable. - NewDMD->setMapperVarRef(D->getMapperVarRef()); - // Copy map clauses from the original mapper. - for (OMPClause *C : D->clauselists()) - Clauses.push_back(C); - } else { - // Instantiate the mapper variable. - DeclarationNameInfo DirName; - SemaRef.StartOpenMPDSABlock(llvm::omp::OMPD_declare_mapper, DirName, - /*S=*/nullptr, - (*D->clauselist_begin())->getBeginLoc()); - SemaRef.ActOnOpenMPDeclareMapperDirectiveVarDecl( - NewDMD, /*S=*/nullptr, SubstMapperTy, D->getLocation(), VN); - SemaRef.CurrentInstantiationScope->InstantiatedLocal( - cast<DeclRefExpr>(D->getMapperVarRef())->getDecl(), - cast<DeclRefExpr>(NewDMD->getMapperVarRef())->getDecl()); - auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(Owner); - Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, Qualifiers(), - ThisContext); - // Instantiate map clauses. - for (OMPClause *C : D->clauselists()) { - auto *OldC = cast<OMPMapClause>(C); - SmallVector<Expr *, 4> NewVars; - for (Expr *OE : OldC->varlists()) { - Expr *NE = SemaRef.SubstExpr(OE, TemplateArgs).get(); - if (!NE) { - IsCorrect = false; - break; - } - NewVars.push_back(NE); - } - if (!IsCorrect) + SmallVector<OMPClause *, 6> Clauses; + // Instantiate the mapper variable. + DeclarationNameInfo DirName; + SemaRef.StartOpenMPDSABlock(llvm::omp::OMPD_declare_mapper, DirName, + /*S=*/nullptr, + (*D->clauselist_begin())->getBeginLoc()); + ExprResult MapperVarRef = SemaRef.ActOnOpenMPDeclareMapperDirectiveVarDecl( + /*S=*/nullptr, SubstMapperTy, D->getLocation(), VN); + SemaRef.CurrentInstantiationScope->InstantiatedLocal( + cast<DeclRefExpr>(D->getMapperVarRef())->getDecl(), + cast<DeclRefExpr>(MapperVarRef.get())->getDecl()); + auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(Owner); + Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, Qualifiers(), + ThisContext); + // Instantiate map clauses. + for (OMPClause *C : D->clauselists()) { + auto *OldC = cast<OMPMapClause>(C); + SmallVector<Expr *, 4> NewVars; + for (Expr *OE : OldC->varlists()) { + Expr *NE = SemaRef.SubstExpr(OE, TemplateArgs).get(); + if (!NE) { + IsCorrect = false; break; - NestedNameSpecifierLoc NewQualifierLoc = - SemaRef.SubstNestedNameSpecifierLoc(OldC->getMapperQualifierLoc(), - TemplateArgs); - CXXScopeSpec SS; - SS.Adopt(NewQualifierLoc); - DeclarationNameInfo NewNameInfo = SemaRef.SubstDeclarationNameInfo( - OldC->getMapperIdInfo(), TemplateArgs); - OMPVarListLocTy Locs(OldC->getBeginLoc(), OldC->getLParenLoc(), - OldC->getEndLoc()); - OMPClause *NewC = SemaRef.ActOnOpenMPMapClause( - OldC->getMapTypeModifiers(), OldC->getMapTypeModifiersLoc(), SS, - NewNameInfo, OldC->getMapType(), OldC->isImplicitMapType(), - OldC->getMapLoc(), OldC->getColonLoc(), NewVars, Locs); - Clauses.push_back(NewC); + } + NewVars.push_back(NE); } - SemaRef.EndOpenMPDSABlock(nullptr); - } - (void)SemaRef.ActOnOpenMPDeclareMapperDirectiveEnd(NewDMD, /*S=*/nullptr, - Clauses); + if (!IsCorrect) + break; + NestedNameSpecifierLoc NewQualifierLoc = + SemaRef.SubstNestedNameSpecifierLoc(OldC->getMapperQualifierLoc(), + TemplateArgs); + CXXScopeSpec SS; + SS.Adopt(NewQualifierLoc); + DeclarationNameInfo NewNameInfo = + SemaRef.SubstDeclarationNameInfo(OldC->getMapperIdInfo(), TemplateArgs); + OMPVarListLocTy Locs(OldC->getBeginLoc(), OldC->getLParenLoc(), + OldC->getEndLoc()); + OMPClause *NewC = SemaRef.ActOnOpenMPMapClause( + OldC->getMapTypeModifiers(), OldC->getMapTypeModifiersLoc(), SS, + NewNameInfo, OldC->getMapType(), OldC->isImplicitMapType(), + OldC->getMapLoc(), OldC->getColonLoc(), NewVars, Locs); + Clauses.push_back(NewC); + } + SemaRef.EndOpenMPDSABlock(nullptr); if (!IsCorrect) return nullptr; + Sema::DeclGroupPtrTy DG = SemaRef.ActOnOpenMPDeclareMapperDirective( + /*S=*/nullptr, Owner, D->getDeclName(), SubstMapperTy, D->getLocation(), + VN, D->getAccess(), MapperVarRef.get(), Clauses, PrevDeclInScope); + Decl *NewDMD = DG.get().getSingleDecl(); + SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewDMD); return NewDMD; } @@ -3595,11 +3682,11 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( return nullptr; return VisitVarTemplateSpecializationDecl( - InstVarTemplate, D, InsertPos, VarTemplateArgsInfo, Converted, PrevDecl); + InstVarTemplate, D, VarTemplateArgsInfo, Converted, PrevDecl); } Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( - VarTemplateDecl *VarTemplate, VarDecl *D, void *InsertPos, + VarTemplateDecl *VarTemplate, VarDecl *D, const TemplateArgumentListInfo &TemplateArgsInfo, ArrayRef<TemplateArgument> Converted, VarTemplateSpecializationDecl *PrevDecl) { @@ -3622,8 +3709,11 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( SemaRef.Context, Owner, D->getInnerLocStart(), D->getLocation(), VarTemplate, DI->getType(), DI, D->getStorageClass(), Converted); Var->setTemplateArgsInfo(TemplateArgsInfo); - if (InsertPos) + if (!PrevDecl) { + void *InsertPos = nullptr; + VarTemplate->findSpecialization(Converted, InsertPos); VarTemplate->AddSpecialization(Var, InsertPos); + } if (SemaRef.getLangOpts().OpenCL) SemaRef.deduceOpenCLAddressSpace(Var); @@ -4099,6 +4189,9 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, for (unsigned OldIdx = 0, NumOldParams = OldProtoLoc.getNumParams(); OldIdx != NumOldParams; ++OldIdx) { ParmVarDecl *OldParam = OldProtoLoc.getParam(OldIdx); + if (!OldParam) + return nullptr; + LocalInstantiationScope *Scope = SemaRef.CurrentInstantiationScope; Optional<unsigned> NumArgumentsInExpansion; @@ -4431,6 +4524,8 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, // into a template instantiation for this specific function template // specialization, which is not a SFINAE context, so that we diagnose any // further errors in the declaration itself. + // + // FIXME: This is a hack. typedef Sema::CodeSynthesisContext ActiveInstType; ActiveInstType &ActiveInst = SemaRef.CodeSynthesisContexts.back(); if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution || @@ -4440,6 +4535,8 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, assert(FunTmpl->getTemplatedDecl() == Tmpl && "Deduction from the wrong function template?"); (void) FunTmpl; + SemaRef.InstantiatingSpecializations.erase( + {ActiveInst.Entity->getCanonicalDecl(), ActiveInst.Kind}); atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef, ActiveInst); ActiveInst.Kind = ActiveInstType::TemplateInstantiation; ActiveInst.Entity = New; @@ -4569,27 +4666,6 @@ Sema::InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD, return cast_or_null<FunctionDecl>(SubstDecl(FD, FD->getParent(), MArgs)); } -/// In the MS ABI, we need to instantiate default arguments of dllexported -/// default constructors along with the constructor definition. This allows IR -/// gen to emit a constructor closure which calls the default constructor with -/// its default arguments. -static void InstantiateDefaultCtorDefaultArgs(Sema &S, - CXXConstructorDecl *Ctor) { - assert(S.Context.getTargetInfo().getCXXABI().isMicrosoft() && - Ctor->isDefaultConstructor()); - unsigned NumParams = Ctor->getNumParams(); - if (NumParams == 0) - return; - DLLExportAttr *Attr = Ctor->getAttr<DLLExportAttr>(); - if (!Attr) - return; - for (unsigned I = 0; I != NumParams; ++I) { - (void)S.CheckCXXDefaultArgExpr(Attr->getLocation(), Ctor, - Ctor->getParamDecl(I)); - S.DiscardCleanupsInEvaluationContext(); - } -} - /// Instantiate the definition of the given function from its /// template. /// @@ -4612,8 +4688,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, bool Recursive, bool DefinitionRequired, bool AtEndOfTU) { - if (Function->isInvalidDecl() || Function->isDefined() || - isa<CXXDeductionGuideDecl>(Function)) + if (Function->isInvalidDecl() || isa<CXXDeductionGuideDecl>(Function)) return; // Never instantiate an explicit specialization except if it is a class scope @@ -4623,6 +4698,20 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, if (TSK == TSK_ExplicitSpecialization) return; + // Don't instantiate a definition if we already have one. + const FunctionDecl *ExistingDefn = nullptr; + if (Function->isDefined(ExistingDefn, + /*CheckForPendingFriendDefinition=*/true)) { + if (ExistingDefn->isThisDeclarationADefinition()) + return; + + // If we're asked to instantiate a function whose body comes from an + // instantiated friend declaration, attach the instantiated body to the + // corresponding declaration of the function. + assert(ExistingDefn->isThisDeclarationInstantiatedFromAFriendDefinition()); + Function = const_cast<FunctionDecl*>(ExistingDefn); + } + // Find the function body that we'll be substituting. const FunctionDecl *PatternDecl = Function->getTemplateInstantiationPattern(); assert(PatternDecl && "instantiating a non-template"); @@ -4795,7 +4884,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, // default arguments. if (Context.getTargetInfo().getCXXABI().isMicrosoft() && Ctor->isDefaultConstructor()) { - InstantiateDefaultCtorDefaultArgs(*this, Ctor); + InstantiateDefaultCtorDefaultArgs(Ctor); } } @@ -4832,7 +4921,7 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation( const TemplateArgumentList &TemplateArgList, const TemplateArgumentListInfo &TemplateArgsInfo, SmallVectorImpl<TemplateArgument> &Converted, - SourceLocation PointOfInstantiation, void *InsertPos, + SourceLocation PointOfInstantiation, LateInstantiatedAttrVec *LateAttrs, LocalInstantiationScope *StartingScope) { if (FromVar->isInvalidDecl()) @@ -4871,7 +4960,7 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation( return cast_or_null<VarTemplateSpecializationDecl>( Instantiator.VisitVarTemplateSpecializationDecl( - VarTemplate, FromVar, InsertPos, TemplateArgsInfo, Converted)); + VarTemplate, FromVar, TemplateArgsInfo, Converted)); } /// Instantiates a variable template specialization by completing it @@ -5143,15 +5232,6 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, VarTemplateSpecializationDecl *VarSpec = dyn_cast<VarTemplateSpecializationDecl>(Var); if (VarSpec) { - // If this is a variable template specialization, make sure that it is - // non-dependent. - bool InstantiationDependent = false; - assert(!TemplateSpecializationType::anyDependentTemplateArguments( - VarSpec->getTemplateArgsInfo(), InstantiationDependent) && - "Only instantiate variable template specializations that are " - "not type-dependent"); - (void)InstantiationDependent; - // If this is a static data member template, there might be an // uninstantiated initializer on the declaration. If so, instantiate // it now. @@ -5303,8 +5383,8 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, TemplateDeclInstantiator Instantiator(*this, Var->getDeclContext(), TemplateArgs); Var = cast_or_null<VarDecl>(Instantiator.VisitVarTemplateSpecializationDecl( - VarSpec->getSpecializedTemplate(), Def, nullptr, - VarSpec->getTemplateArgsInfo(), VarSpec->getTemplateArgs().asArray())); + VarSpec->getSpecializedTemplate(), Def, VarSpec->getTemplateArgsInfo(), + VarSpec->getTemplateArgs().asArray(), VarSpec)); if (Var) { llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *> PatternPtr = @@ -5314,12 +5394,6 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, cast<VarTemplateSpecializationDecl>(Var)->setInstantiationOf( Partial, &VarSpec->getTemplateInstantiationArgs()); - // Merge the definition with the declaration. - LookupResult R(*this, Var->getDeclName(), Var->getLocation(), - LookupOrdinaryName, forRedeclarationInCurContext()); - R.addDecl(OldVar); - MergeVarDecl(Var, R); - // Attach the initializer. InstantiateVariableInitializer(Var, Def, TemplateArgs); } @@ -5972,16 +6046,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, return nullptr; DeclContext::lookup_result Found = ParentDC->lookup(Name); - if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(D)) { - VarTemplateDecl *Templ = cast_or_null<VarTemplateDecl>( - findInstantiationOf(Context, VTSD->getSpecializedTemplate(), - Found.begin(), Found.end())); - if (!Templ) - return nullptr; - Result = getVarTemplateSpecialization( - Templ, &VTSD->getTemplateArgsInfo(), NewNameInfo, SourceLocation()); - } else - Result = findInstantiationOf(Context, D, Found.begin(), Found.end()); + Result = findInstantiationOf(Context, D, Found.begin(), Found.end()); } else { // Since we don't have a name for the entity we're looking for, // our only option is to walk through all of the declarations to @@ -5999,7 +6064,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, if (!Result) { if (isa<UsingShadowDecl>(D)) { // UsingShadowDecls can instantiate to nothing because of using hiding. - } else if (Diags.hasUncompilableErrorOccurred()) { + } else if (hasUncompilableErrorOccurred()) { // We've already complained about some ill-formed code, so most likely // this declaration failed to instantiate. There's no point in // complaining further, since this is normal in invalid code. diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index 7b77d1cb482a..1951aec3d17d 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -368,8 +368,8 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc, Locations.push_back(Unexpanded[I].second); } - DiagnosticBuilder DB = Diag(Loc, diag::err_unexpanded_parameter_pack) - << (int)UPPC << (int)Names.size(); + auto DB = Diag(Loc, diag::err_unexpanded_parameter_pack) + << (int)UPPC << (int)Names.size(); for (size_t I = 0, E = std::min(Names.size(), (size_t)2); I != E; ++I) DB << Names[I]; @@ -408,6 +408,29 @@ bool Sema::DiagnoseUnexpandedParameterPack(Expr *E, return DiagnoseUnexpandedParameterPacks(E->getBeginLoc(), UPPC, Unexpanded); } +bool Sema::DiagnoseUnexpandedParameterPackInRequiresExpr(RequiresExpr *RE) { + if (!RE->containsUnexpandedParameterPack()) + return false; + + SmallVector<UnexpandedParameterPack, 2> Unexpanded; + CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(RE); + assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); + + // We only care about unexpanded references to the RequiresExpr's own + // parameter packs. + auto Parms = RE->getLocalParameters(); + llvm::SmallPtrSet<NamedDecl*, 8> ParmSet(Parms.begin(), Parms.end()); + SmallVector<UnexpandedParameterPack, 2> UnexpandedParms; + for (auto Parm : Unexpanded) + if (ParmSet.contains(Parm.first.dyn_cast<NamedDecl*>())) + UnexpandedParms.push_back(Parm); + if (UnexpandedParms.empty()) + return false; + + return DiagnoseUnexpandedParameterPacks(RE->getBeginLoc(), UPPC_Requirement, + UnexpandedParms); +} + bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS, UnexpandedParameterPackContext UPPC) { // C++0x [temp.variadic]p5: @@ -614,7 +637,8 @@ QualType Sema::CheckPackExpansion(QualType Pattern, SourceRange PatternRange, return QualType(); } - return Context.getPackExpansionType(Pattern, NumExpansions); + return Context.getPackExpansionType(Pattern, NumExpansions, + /*ExpectPackInType=*/false); } ExprResult Sema::ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc) { @@ -1071,7 +1095,7 @@ Sema::getTemplateArgumentPackExpansionPattern( case TemplateArgument::TemplateExpansion: Ellipsis = OrigLoc.getTemplateEllipsisLoc(); NumExpansions = Argument.getNumTemplateExpansions(); - return TemplateArgumentLoc(Argument.getPackExpansionPattern(), + return TemplateArgumentLoc(Context, Argument.getPackExpansionPattern(), OrigLoc.getTemplateQualifierLoc(), OrigLoc.getTemplateNameLoc()); @@ -1159,7 +1183,7 @@ static void CheckFoldOperand(Sema &S, Expr *E) { } } -ExprResult Sema::ActOnCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS, +ExprResult Sema::ActOnCXXFoldExpr(Scope *S, SourceLocation LParenLoc, Expr *LHS, tok::TokenKind Operator, SourceLocation EllipsisLoc, Expr *RHS, SourceLocation RParenLoc) { @@ -1201,18 +1225,37 @@ ExprResult Sema::ActOnCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS, } BinaryOperatorKind Opc = ConvertTokenKindToBinaryOpcode(Operator); - return BuildCXXFoldExpr(LParenLoc, LHS, Opc, EllipsisLoc, RHS, RParenLoc, + + // Perform first-phase name lookup now. + UnresolvedLookupExpr *ULE = nullptr; + { + UnresolvedSet<16> Functions; + LookupBinOp(S, EllipsisLoc, Opc, Functions); + if (!Functions.empty()) { + DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName( + BinaryOperator::getOverloadedOperator(Opc)); + ExprResult Callee = CreateUnresolvedLookupExpr( + /*NamingClass*/ nullptr, NestedNameSpecifierLoc(), + DeclarationNameInfo(OpName, EllipsisLoc), Functions); + if (Callee.isInvalid()) + return ExprError(); + ULE = cast<UnresolvedLookupExpr>(Callee.get()); + } + } + + return BuildCXXFoldExpr(ULE, LParenLoc, LHS, Opc, EllipsisLoc, RHS, RParenLoc, None); } -ExprResult Sema::BuildCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS, +ExprResult Sema::BuildCXXFoldExpr(UnresolvedLookupExpr *Callee, + SourceLocation LParenLoc, Expr *LHS, BinaryOperatorKind Operator, SourceLocation EllipsisLoc, Expr *RHS, SourceLocation RParenLoc, Optional<unsigned> NumExpansions) { - return new (Context) CXXFoldExpr(Context.DependentTy, LParenLoc, LHS, - Operator, EllipsisLoc, RHS, RParenLoc, - NumExpansions); + return new (Context) + CXXFoldExpr(Context.DependentTy, Callee, LParenLoc, LHS, Operator, + EllipsisLoc, RHS, RParenLoc, NumExpansions); } ExprResult Sema::BuildEmptyCXXFoldExpr(SourceLocation EllipsisLoc, diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index b8f7f1a58159..4178024d1264 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -37,6 +37,7 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/Support/ErrorHandling.h" +#include <bitset> using namespace clang; @@ -49,7 +50,7 @@ enum TypeDiagSelector { /// isOmittedBlockReturnType - Return true if this declarator is missing a /// return type because this is a omitted return type on a block literal. static bool isOmittedBlockReturnType(const Declarator &D) { - if (D.getContext() != DeclaratorContext::BlockLiteralContext || + if (D.getContext() != DeclaratorContext::BlockLiteral || D.getDeclSpec().hasTypeSpecifier()) return false; @@ -146,6 +147,7 @@ static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr, #define NULLABILITY_TYPE_ATTRS_CASELIST \ case ParsedAttr::AT_TypeNonNull: \ case ParsedAttr::AT_TypeNullable: \ + case ParsedAttr::AT_TypeNullableResult: \ case ParsedAttr::AT_TypeNullUnspecified namespace { @@ -1299,27 +1301,27 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { Result = Context.VoidTy; break; case DeclSpec::TST_char: - if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified) + if (DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified) Result = Context.CharTy; - else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed) + else if (DS.getTypeSpecSign() == TypeSpecifierSign::Signed) Result = Context.SignedCharTy; else { - assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned && + assert(DS.getTypeSpecSign() == TypeSpecifierSign::Unsigned && "Unknown TSS value"); Result = Context.UnsignedCharTy; } break; case DeclSpec::TST_wchar: - if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified) + if (DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified) Result = Context.WCharTy; - else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed) { + else if (DS.getTypeSpecSign() == TypeSpecifierSign::Signed) { S.Diag(DS.getTypeSpecSignLoc(), diag::ext_wchar_t_sign_spec) << DS.getSpecifierName(DS.getTypeSpecType(), Context.getPrintingPolicy()); Result = Context.getSignedWCharType(); } else { - assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned && - "Unknown TSS value"); + assert(DS.getTypeSpecSign() == TypeSpecifierSign::Unsigned && + "Unknown TSS value"); S.Diag(DS.getTypeSpecSignLoc(), diag::ext_wchar_t_sign_spec) << DS.getSpecifierName(DS.getTypeSpecType(), Context.getPrintingPolicy()); @@ -1327,19 +1329,19 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { } break; case DeclSpec::TST_char8: - assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified && - "Unknown TSS value"); - Result = Context.Char8Ty; + assert(DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified && + "Unknown TSS value"); + Result = Context.Char8Ty; break; case DeclSpec::TST_char16: - assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified && - "Unknown TSS value"); - Result = Context.Char16Ty; + assert(DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified && + "Unknown TSS value"); + Result = Context.Char16Ty; break; case DeclSpec::TST_char32: - assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified && - "Unknown TSS value"); - Result = Context.Char32Ty; + assert(DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified && + "Unknown TSS value"); + Result = Context.Char32Ty; break; case DeclSpec::TST_unspecified: // If this is a missing declspec in a block literal return context, then it @@ -1347,12 +1349,11 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // The declspec is always missing in a lambda expr context; it is either // specified with a trailing return type or inferred. if (S.getLangOpts().CPlusPlus14 && - declarator.getContext() == DeclaratorContext::LambdaExprContext) { + declarator.getContext() == DeclaratorContext::LambdaExpr) { // In C++1y, a lambda's implicit return type is 'auto'. Result = Context.getAutoDeductType(); break; - } else if (declarator.getContext() == - DeclaratorContext::LambdaExprContext || + } else if (declarator.getContext() == DeclaratorContext::LambdaExpr || checkOmittedBlockReturnType(S, declarator, Context.DependentTy)) { Result = Context.DependentTy; @@ -1401,12 +1402,18 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { LLVM_FALLTHROUGH; case DeclSpec::TST_int: { - if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) { + if (DS.getTypeSpecSign() != TypeSpecifierSign::Unsigned) { switch (DS.getTypeSpecWidth()) { - case DeclSpec::TSW_unspecified: Result = Context.IntTy; break; - case DeclSpec::TSW_short: Result = Context.ShortTy; break; - case DeclSpec::TSW_long: Result = Context.LongTy; break; - case DeclSpec::TSW_longlong: + case TypeSpecifierWidth::Unspecified: + Result = Context.IntTy; + break; + case TypeSpecifierWidth::Short: + Result = Context.ShortTy; + break; + case TypeSpecifierWidth::Long: + Result = Context.LongTy; + break; + case TypeSpecifierWidth::LongLong: Result = Context.LongLongTy; // 'long long' is a C99 or C++11 feature. @@ -1422,10 +1429,16 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { } } else { switch (DS.getTypeSpecWidth()) { - case DeclSpec::TSW_unspecified: Result = Context.UnsignedIntTy; break; - case DeclSpec::TSW_short: Result = Context.UnsignedShortTy; break; - case DeclSpec::TSW_long: Result = Context.UnsignedLongTy; break; - case DeclSpec::TSW_longlong: + case TypeSpecifierWidth::Unspecified: + Result = Context.UnsignedIntTy; + break; + case TypeSpecifierWidth::Short: + Result = Context.UnsignedShortTy; + break; + case TypeSpecifierWidth::Long: + Result = Context.UnsignedLongTy; + break; + case TypeSpecifierWidth::LongLong: Result = Context.UnsignedLongLongTy; // 'long long' is a C99 or C++11 feature. @@ -1446,8 +1459,9 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { if (!S.Context.getTargetInfo().hasExtIntType()) S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported) << "_ExtInt"; - Result = S.BuildExtIntType(DS.getTypeSpecSign() == TSS_unsigned, - DS.getRepAsExpr(), DS.getBeginLoc()); + Result = + S.BuildExtIntType(DS.getTypeSpecSign() == TypeSpecifierSign::Unsigned, + DS.getRepAsExpr(), DS.getBeginLoc()); if (Result.isNull()) { Result = Context.IntTy; declarator.setInvalidType(true); @@ -1456,20 +1470,20 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { } case DeclSpec::TST_accum: { switch (DS.getTypeSpecWidth()) { - case DeclSpec::TSW_short: - Result = Context.ShortAccumTy; - break; - case DeclSpec::TSW_unspecified: - Result = Context.AccumTy; - break; - case DeclSpec::TSW_long: - Result = Context.LongAccumTy; - break; - case DeclSpec::TSW_longlong: - llvm_unreachable("Unable to specify long long as _Accum width"); + case TypeSpecifierWidth::Short: + Result = Context.ShortAccumTy; + break; + case TypeSpecifierWidth::Unspecified: + Result = Context.AccumTy; + break; + case TypeSpecifierWidth::Long: + Result = Context.LongAccumTy; + break; + case TypeSpecifierWidth::LongLong: + llvm_unreachable("Unable to specify long long as _Accum width"); } - if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned) + if (DS.getTypeSpecSign() == TypeSpecifierSign::Unsigned) Result = Context.getCorrespondingUnsignedType(Result); if (DS.isTypeSpecSat()) @@ -1479,20 +1493,20 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { } case DeclSpec::TST_fract: { switch (DS.getTypeSpecWidth()) { - case DeclSpec::TSW_short: - Result = Context.ShortFractTy; - break; - case DeclSpec::TSW_unspecified: - Result = Context.FractTy; - break; - case DeclSpec::TSW_long: - Result = Context.LongFractTy; - break; - case DeclSpec::TSW_longlong: - llvm_unreachable("Unable to specify long long as _Fract width"); + case TypeSpecifierWidth::Short: + Result = Context.ShortFractTy; + break; + case TypeSpecifierWidth::Unspecified: + Result = Context.FractTy; + break; + case TypeSpecifierWidth::Long: + Result = Context.LongFractTy; + break; + case TypeSpecifierWidth::LongLong: + llvm_unreachable("Unable to specify long long as _Fract width"); } - if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned) + if (DS.getTypeSpecSign() == TypeSpecifierSign::Unsigned) Result = Context.getCorrespondingUnsignedType(Result); if (DS.isTypeSpecSat()) @@ -1502,10 +1516,11 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { } case DeclSpec::TST_int128: if (!S.Context.getTargetInfo().hasInt128Type() && + !S.getLangOpts().SYCLIsDevice && !(S.getLangOpts().OpenMP && S.getLangOpts().OpenMPIsDevice)) S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported) << "__int128"; - if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned) + if (DS.getTypeSpecSign() == TypeSpecifierSign::Unsigned) Result = Context.UnsignedInt128Ty; else Result = Context.Int128Ty; @@ -1529,7 +1544,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { break; case DeclSpec::TST_float: Result = Context.FloatTy; break; case DeclSpec::TST_double: - if (DS.getTypeSpecWidth() == DeclSpec::TSW_long) + if (DS.getTypeSpecWidth() == TypeSpecifierWidth::Long) Result = Context.LongDoubleTy; else Result = Context.DoubleTy; @@ -1542,7 +1557,8 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { << "__float128"; Result = Context.Float128Ty; break; - case DeclSpec::TST_bool: Result = Context.BoolTy; break; // _Bool or bool + case DeclSpec::TST_bool: + Result = Context.BoolTy; // _Bool or bool break; case DeclSpec::TST_decimal32: // _Decimal32 case DeclSpec::TST_decimal64: // _Decimal64 @@ -1567,8 +1583,10 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // If the type is deprecated or unavailable, diagnose it. S.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeNameLoc()); - assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 && - DS.getTypeSpecSign() == 0 && "No qualifiers on tag names!"); + assert(DS.getTypeSpecWidth() == TypeSpecifierWidth::Unspecified && + DS.getTypeSpecComplex() == 0 && + DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified && + "No qualifiers on tag names!"); // TypeQuals handled by caller. Result = Context.getTypeDeclType(D); @@ -1581,8 +1599,9 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { break; } case DeclSpec::TST_typename: { - assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 && - DS.getTypeSpecSign() == 0 && + assert(DS.getTypeSpecWidth() == TypeSpecifierWidth::Unspecified && + DS.getTypeSpecComplex() == 0 && + DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified && "Can't handle qualifiers on typedef names yet!"); Result = S.GetTypeFromParser(DS.getRepAsType()); if (Result.isNull()) { @@ -1739,7 +1758,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // Before we process any type attributes, synthesize a block literal // function declarator if necessary. - if (declarator.getContext() == DeclaratorContext::BlockLiteralContext) + if (declarator.getContext() == DeclaratorContext::BlockLiteral) maybeSynthesizeBlockSignature(state, Result); // Apply any type attributes from the decl spec. This may cause the @@ -2070,7 +2089,8 @@ QualType Sema::BuildPointerType(QualType T, return QualType(); } - if (T->isFunctionType() && getLangOpts().OpenCL) { + if (T->isFunctionType() && getLangOpts().OpenCL && + !getOpenCLOptions().isEnabled("__cl_clang_function_pointers")) { Diag(Loc, diag::err_opencl_function_pointer); return QualType(); } @@ -2194,7 +2214,8 @@ QualType Sema::BuildExtIntType(bool IsUnsigned, Expr *BitWidth, return Context.getDependentExtIntType(IsUnsigned, BitWidth); llvm::APSInt Bits(32); - ExprResult ICE = VerifyIntegerConstantExpression(BitWidth, &Bits); + ExprResult ICE = + VerifyIntegerConstantExpression(BitWidth, &Bits, /*FIXME*/ AllowFold); if (ICE.isInvalid()) return QualType(); @@ -2219,26 +2240,62 @@ QualType Sema::BuildExtIntType(bool IsUnsigned, Expr *BitWidth, return Context.getExtIntType(IsUnsigned, NumBits); } -/// Check whether the specified array size makes the array type a VLA. If so, -/// return true, if not, return the size of the array in SizeVal. -static bool isArraySizeVLA(Sema &S, Expr *ArraySize, llvm::APSInt &SizeVal) { +/// Check whether the specified array bound can be evaluated using the relevant +/// language rules. If so, returns the possibly-converted expression and sets +/// SizeVal to the size. If not, but the expression might be a VLA bound, +/// returns ExprResult(). Otherwise, produces a diagnostic and returns +/// ExprError(). +static ExprResult checkArraySize(Sema &S, Expr *&ArraySize, + llvm::APSInt &SizeVal, unsigned VLADiag, + bool VLAIsError) { + if (S.getLangOpts().CPlusPlus14 && + (VLAIsError || + !ArraySize->getType()->isIntegralOrUnscopedEnumerationType())) { + // C++14 [dcl.array]p1: + // The constant-expression shall be a converted constant expression of + // type std::size_t. + // + // Don't apply this rule if we might be forming a VLA: in that case, we + // allow non-constant expressions and constant-folding. We only need to use + // the converted constant expression rules (to properly convert the source) + // when the source expression is of class type. + return S.CheckConvertedConstantExpression( + ArraySize, S.Context.getSizeType(), SizeVal, Sema::CCEK_ArrayBound); + } + // If the size is an ICE, it certainly isn't a VLA. If we're in a GNU mode // (like gnu99, but not c99) accept any evaluatable value as an extension. class VLADiagnoser : public Sema::VerifyICEDiagnoser { public: - VLADiagnoser() : Sema::VerifyICEDiagnoser(true) {} + unsigned VLADiag; + bool VLAIsError; + bool IsVLA = false; + + VLADiagnoser(unsigned VLADiag, bool VLAIsError) + : VLADiag(VLADiag), VLAIsError(VLAIsError) {} - void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) override { + Sema::SemaDiagnosticBuilder diagnoseNotICEType(Sema &S, SourceLocation Loc, + QualType T) override { + return S.Diag(Loc, diag::err_array_size_non_int) << T; } - void diagnoseFold(Sema &S, SourceLocation Loc, SourceRange SR) override { - S.Diag(Loc, diag::ext_vla_folded_to_constant) << SR; + Sema::SemaDiagnosticBuilder diagnoseNotICE(Sema &S, + SourceLocation Loc) override { + IsVLA = !VLAIsError; + return S.Diag(Loc, VLADiag); } - } Diagnoser; - return S.VerifyIntegerConstantExpression(ArraySize, &SizeVal, Diagnoser, - S.LangOpts.GNUMode || - S.LangOpts.OpenCL).isInvalid(); + Sema::SemaDiagnosticBuilder diagnoseFold(Sema &S, + SourceLocation Loc) override { + return S.Diag(Loc, diag::ext_vla_folded_to_constant); + } + } Diagnoser(VLADiag, VLAIsError); + + ExprResult R = + S.VerifyIntegerConstantExpression(ArraySize, &SizeVal, Diagnoser); + if (Diagnoser.IsVLA) + return ExprResult(); + return R; } /// Build an array type. @@ -2350,68 +2407,95 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, return QualType(); } + // VLAs always produce at least a -Wvla diagnostic, sometimes an error. + unsigned VLADiag; + bool VLAIsError; + if (getLangOpts().OpenCL) { + // OpenCL v1.2 s6.9.d: variable length arrays are not supported. + VLADiag = diag::err_opencl_vla; + VLAIsError = true; + } else if (getLangOpts().C99) { + VLADiag = diag::warn_vla_used; + VLAIsError = false; + } else if (isSFINAEContext()) { + VLADiag = diag::err_vla_in_sfinae; + VLAIsError = true; + } else { + VLADiag = diag::ext_vla; + VLAIsError = false; + } + llvm::APSInt ConstVal(Context.getTypeSize(Context.getSizeType())); if (!ArraySize) { - if (ASM == ArrayType::Star) + if (ASM == ArrayType::Star) { + Diag(Loc, VLADiag); + if (VLAIsError) + return QualType(); + T = Context.getVariableArrayType(T, nullptr, ASM, Quals, Brackets); - else + } else { T = Context.getIncompleteArrayType(T, ASM, Quals); + } } else if (ArraySize->isTypeDependent() || ArraySize->isValueDependent()) { T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals, Brackets); - } else if ((!T->isDependentType() && !T->isIncompleteType() && - !T->isConstantSizeType()) || - isArraySizeVLA(*this, ArraySize, ConstVal)) { - // Even in C++11, don't allow contextual conversions in the array bound - // of a VLA. - if (getLangOpts().CPlusPlus11 && - !ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) { - Diag(ArraySize->getBeginLoc(), diag::err_array_size_non_int) - << ArraySize->getType() << ArraySize->getSourceRange(); + } else { + ExprResult R = + checkArraySize(*this, ArraySize, ConstVal, VLADiag, VLAIsError); + if (R.isInvalid()) return QualType(); - } - // C99: an array with an element type that has a non-constant-size is a VLA. - // C99: an array with a non-ICE size is a VLA. We accept any expression - // that we can fold to a non-zero positive value as an extension. - T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets); - } else { - // C99 6.7.5.2p1: If the expression is a constant expression, it shall - // have a value greater than zero. - if (ConstVal.isSigned() && ConstVal.isNegative()) { - if (Entity) - Diag(ArraySize->getBeginLoc(), diag::err_decl_negative_array_size) - << getPrintableNameForEntity(Entity) << ArraySize->getSourceRange(); - else - Diag(ArraySize->getBeginLoc(), diag::err_typecheck_negative_array_size) + if (!R.isUsable()) { + // C99: an array with a non-ICE size is a VLA. We accept any expression + // that we can fold to a non-zero positive value as a non-VLA as an + // extension. + T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets); + } else if (!T->isDependentType() && !T->isIncompleteType() && + !T->isConstantSizeType()) { + // C99: an array with an element type that has a non-constant-size is a + // VLA. + // FIXME: Add a note to explain why this isn't a VLA. + Diag(Loc, VLADiag); + if (VLAIsError) + return QualType(); + T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets); + } else { + // C99 6.7.5.2p1: If the expression is a constant expression, it shall + // have a value greater than zero. + // In C++, this follows from narrowing conversions being disallowed. + if (ConstVal.isSigned() && ConstVal.isNegative()) { + if (Entity) + Diag(ArraySize->getBeginLoc(), diag::err_decl_negative_array_size) + << getPrintableNameForEntity(Entity) + << ArraySize->getSourceRange(); + else + Diag(ArraySize->getBeginLoc(), + diag::err_typecheck_negative_array_size) + << ArraySize->getSourceRange(); + return QualType(); + } + if (ConstVal == 0) { + // GCC accepts zero sized static arrays. We allow them when + // we're not in a SFINAE context. + Diag(ArraySize->getBeginLoc(), + isSFINAEContext() ? diag::err_typecheck_zero_array_size + : diag::ext_typecheck_zero_array_size) << ArraySize->getSourceRange(); - return QualType(); - } - if (ConstVal == 0) { - // GCC accepts zero sized static arrays. We allow them when - // we're not in a SFINAE context. - Diag(ArraySize->getBeginLoc(), isSFINAEContext() - ? diag::err_typecheck_zero_array_size - : diag::ext_typecheck_zero_array_size) - << ArraySize->getSourceRange(); - } else if (!T->isDependentType() && !T->isVariablyModifiedType() && - !T->isIncompleteType() && !T->isUndeducedType()) { + } + // Is the array too large? - unsigned ActiveSizeBits - = ConstantArrayType::getNumAddressingBits(Context, T, ConstVal); + unsigned ActiveSizeBits = + (!T->isDependentType() && !T->isVariablyModifiedType() && + !T->isIncompleteType() && !T->isUndeducedType()) + ? ConstantArrayType::getNumAddressingBits(Context, T, ConstVal) + : ConstVal.getActiveBits(); if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) { Diag(ArraySize->getBeginLoc(), diag::err_array_too_large) << ConstVal.toString(10) << ArraySize->getSourceRange(); return QualType(); } - } - T = Context.getConstantArrayType(T, ConstVal, ArraySize, ASM, Quals); - } - - // OpenCL v1.2 s6.9.d: variable length arrays are not supported. - if (getLangOpts().OpenCL && T->isVariableArrayType()) { - Diag(Loc, diag::err_opencl_vla); - return QualType(); + T = Context.getConstantArrayType(T, ConstVal, ArraySize, ASM, Quals); + } } if (T->isVariableArrayType() && !Context.getTargetInfo().isVLASupported()) { @@ -2424,26 +2508,12 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, : CFT_InvalidTarget); } - // If this is not C99, extwarn about VLA's and C99 array size modifiers. - if (!getLangOpts().C99) { - if (T->isVariableArrayType()) { - // Prohibit the use of VLAs during template argument deduction. - if (isSFINAEContext()) { - Diag(Loc, diag::err_vla_in_sfinae); - return QualType(); - } - // Just extwarn about VLAs. - else - Diag(Loc, diag::ext_vla); - } else if (ASM != ArrayType::Normal || Quals != 0) - Diag(Loc, - getLangOpts().CPlusPlus? diag::err_c99_array_usage_cxx - : diag::ext_c99_array_usage) << ASM; - } - - if (T->isVariableArrayType()) { - // Warn about VLAs for -Wvla. - Diag(Loc, diag::warn_vla_used); + // If this is not C99, diagnose array size modifiers on non-VLAs. + if (!getLangOpts().C99 && !T->isVariableArrayType() && + (ASM != ArrayType::Normal || Quals != 0)) { + Diag(Loc, getLangOpts().CPlusPlus ? diag::err_c99_array_usage_cxx + : diag::ext_c99_array_usage) + << ASM; } // OpenCL v2.0 s6.12.5 - Arrays of blocks are not supported. @@ -2465,9 +2535,10 @@ QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr, SourceLocation AttrLoc) { // The base type must be integer (not Boolean or enumeration) or float, and // can't already be a vector. - if (!CurType->isDependentType() && - (!CurType->isBuiltinType() || CurType->isBooleanType() || - (!CurType->isIntegerType() && !CurType->isRealFloatingType()))) { + if ((!CurType->isDependentType() && + (!CurType->isBuiltinType() || CurType->isBooleanType() || + (!CurType->isIntegerType() && !CurType->isRealFloatingType()))) || + CurType->isArrayType()) { Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << CurType; return QualType(); } @@ -2476,8 +2547,8 @@ QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr, return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc, VectorType::GenericVector); - llvm::APSInt VecSize(32); - if (!SizeExpr->isIntegerConstantExpr(VecSize, Context)) { + Optional<llvm::APSInt> VecSize = SizeExpr->getIntegerConstantExpr(Context); + if (!VecSize) { Diag(AttrLoc, diag::err_attribute_argument_type) << "vector_size" << AANT_ArgumentIntegerConstant << SizeExpr->getSourceRange(); @@ -2489,13 +2560,13 @@ QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr, VectorType::GenericVector); // vecSize is specified in bytes - convert to bits. - if (!VecSize.isIntN(61)) { + if (!VecSize->isIntN(61)) { // Bit size will overflow uint64. Diag(AttrLoc, diag::err_attribute_size_too_large) << SizeExpr->getSourceRange() << "vector"; return QualType(); } - uint64_t VectorSizeBits = VecSize.getZExtValue() * 8; + uint64_t VectorSizeBits = VecSize->getZExtValue() * 8; unsigned TypeSize = static_cast<unsigned>(Context.getTypeSize(CurType)); if (VectorSizeBits == 0) { @@ -2540,22 +2611,22 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize, } if (!ArraySize->isTypeDependent() && !ArraySize->isValueDependent()) { - llvm::APSInt vecSize(32); - if (!ArraySize->isIntegerConstantExpr(vecSize, Context)) { + Optional<llvm::APSInt> vecSize = ArraySize->getIntegerConstantExpr(Context); + if (!vecSize) { Diag(AttrLoc, diag::err_attribute_argument_type) << "ext_vector_type" << AANT_ArgumentIntegerConstant << ArraySize->getSourceRange(); return QualType(); } - if (!vecSize.isIntN(32)) { + if (!vecSize->isIntN(32)) { Diag(AttrLoc, diag::err_attribute_size_too_large) << ArraySize->getSourceRange() << "vector"; return QualType(); } // Unlike gcc's vector_size attribute, the size is specified as the // number of elements, not the number of bytes. - unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue()); + unsigned vectorSize = static_cast<unsigned>(vecSize->getZExtValue()); if (vectorSize == 0) { Diag(AttrLoc, diag::err_attribute_zero_size) @@ -2586,18 +2657,15 @@ QualType Sema::BuildMatrixType(QualType ElementTy, Expr *NumRows, Expr *NumCols, return Context.getDependentSizedMatrixType(ElementTy, NumRows, NumCols, AttrLoc); - // Both row and column values can only be 20 bit wide currently. - llvm::APSInt ValueRows(32), ValueColumns(32); - - bool const RowsIsInteger = NumRows->isIntegerConstantExpr(ValueRows, Context); - bool const ColumnsIsInteger = - NumCols->isIntegerConstantExpr(ValueColumns, Context); + Optional<llvm::APSInt> ValueRows = NumRows->getIntegerConstantExpr(Context); + Optional<llvm::APSInt> ValueColumns = + NumCols->getIntegerConstantExpr(Context); auto const RowRange = NumRows->getSourceRange(); auto const ColRange = NumCols->getSourceRange(); // Both are row and column expressions are invalid. - if (!RowsIsInteger && !ColumnsIsInteger) { + if (!ValueRows && !ValueColumns) { Diag(AttrLoc, diag::err_attribute_argument_type) << "matrix_type" << AANT_ArgumentIntegerConstant << RowRange << ColRange; @@ -2605,22 +2673,22 @@ QualType Sema::BuildMatrixType(QualType ElementTy, Expr *NumRows, Expr *NumCols, } // Only the row expression is invalid. - if (!RowsIsInteger) { + if (!ValueRows) { Diag(AttrLoc, diag::err_attribute_argument_type) << "matrix_type" << AANT_ArgumentIntegerConstant << RowRange; return QualType(); } // Only the column expression is invalid. - if (!ColumnsIsInteger) { + if (!ValueColumns) { Diag(AttrLoc, diag::err_attribute_argument_type) << "matrix_type" << AANT_ArgumentIntegerConstant << ColRange; return QualType(); } // Check the matrix dimensions. - unsigned MatrixRows = static_cast<unsigned>(ValueRows.getZExtValue()); - unsigned MatrixColumns = static_cast<unsigned>(ValueColumns.getZExtValue()); + unsigned MatrixRows = static_cast<unsigned>(ValueRows->getZExtValue()); + unsigned MatrixColumns = static_cast<unsigned>(ValueColumns->getZExtValue()); if (MatrixRows == 0 && MatrixColumns == 0) { Diag(AttrLoc, diag::err_attribute_zero_size) << "matrix" << RowRange << ColRange; @@ -3034,12 +3102,12 @@ void Sema::diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals, static void diagnoseRedundantReturnTypeQualifiers(Sema &S, QualType RetTy, Declarator &D, unsigned FunctionChunkIndex) { - if (D.getTypeObject(FunctionChunkIndex).Fun.hasTrailingReturnType()) { - // FIXME: TypeSourceInfo doesn't preserve location information for - // qualifiers. + const DeclaratorChunk::FunctionTypeInfo &FTI = + D.getTypeObject(FunctionChunkIndex).Fun; + if (FTI.hasTrailingReturnType()) { S.diagnoseIgnoredQualifiers(diag::warn_qual_return_type, RetTy.getLocalCVRQualifiers(), - D.getIdentifierLoc()); + FTI.getTrailingReturnTypeLoc()); return; } @@ -3057,11 +3125,11 @@ static void diagnoseRedundantReturnTypeQualifiers(Sema &S, QualType RetTy, diag::warn_qual_return_type, PTI.TypeQuals, SourceLocation(), - SourceLocation::getFromRawEncoding(PTI.ConstQualLoc), - SourceLocation::getFromRawEncoding(PTI.VolatileQualLoc), - SourceLocation::getFromRawEncoding(PTI.RestrictQualLoc), - SourceLocation::getFromRawEncoding(PTI.AtomicQualLoc), - SourceLocation::getFromRawEncoding(PTI.UnalignedQualLoc)); + PTI.ConstQualLoc, + PTI.VolatileQualLoc, + PTI.RestrictQualLoc, + PTI.AtomicQualLoc, + PTI.UnalignedQualLoc); return; } @@ -3101,24 +3169,10 @@ static void diagnoseRedundantReturnTypeQualifiers(Sema &S, QualType RetTy, D.getDeclSpec().getUnalignedSpecLoc()); } -static void CopyTypeConstraintFromAutoType(Sema &SemaRef, const AutoType *Auto, - AutoTypeLoc AutoLoc, - TemplateTypeParmDecl *TP, - SourceLocation EllipsisLoc) { - - TemplateArgumentListInfo TAL(AutoLoc.getLAngleLoc(), AutoLoc.getRAngleLoc()); - for (unsigned Idx = 0; Idx < AutoLoc.getNumArgs(); ++Idx) - TAL.addArgument(AutoLoc.getArgLoc(Idx)); - - SemaRef.AttachTypeConstraint( - AutoLoc.getNestedNameSpecifierLoc(), AutoLoc.getConceptNameInfo(), - AutoLoc.getNamedConcept(), - AutoLoc.hasExplicitTemplateArgs() ? &TAL : nullptr, TP, EllipsisLoc); -} - -static QualType InventTemplateParameter( - TypeProcessingState &state, QualType T, TypeSourceInfo *TSI, AutoType *Auto, - InventedTemplateParameterInfo &Info) { +static std::pair<QualType, TypeSourceInfo *> +InventTemplateParameter(TypeProcessingState &state, QualType T, + TypeSourceInfo *TrailingTSI, AutoType *Auto, + InventedTemplateParameterInfo &Info) { Sema &S = state.getSema(); Declarator &D = state.getDeclarator(); @@ -3143,13 +3197,25 @@ static QualType InventTemplateParameter( IsParameterPack, /*HasTypeConstraint=*/Auto->isConstrained()); InventedTemplateParam->setImplicit(); Info.TemplateParams.push_back(InventedTemplateParam); - // Attach type constraints + + // Attach type constraints to the new parameter. if (Auto->isConstrained()) { - if (TSI) { - CopyTypeConstraintFromAutoType( - S, Auto, TSI->getTypeLoc().getContainedAutoTypeLoc(), - InventedTemplateParam, D.getEllipsisLoc()); + if (TrailingTSI) { + // The 'auto' appears in a trailing return type we've already built; + // extract its type constraints to attach to the template parameter. + AutoTypeLoc AutoLoc = TrailingTSI->getTypeLoc().getContainedAutoTypeLoc(); + TemplateArgumentListInfo TAL(AutoLoc.getLAngleLoc(), AutoLoc.getRAngleLoc()); + for (unsigned Idx = 0; Idx < AutoLoc.getNumArgs(); ++Idx) + TAL.addArgument(AutoLoc.getArgLoc(Idx)); + + S.AttachTypeConstraint(AutoLoc.getNestedNameSpecifierLoc(), + AutoLoc.getConceptNameInfo(), + AutoLoc.getNamedConcept(), + AutoLoc.hasExplicitTemplateArgs() ? &TAL : nullptr, + InventedTemplateParam, D.getEllipsisLoc()); } else { + // The 'auto' appears in the decl-specifiers; we've not finished forming + // TypeSourceInfo for it yet. TemplateIdAnnotation *TemplateId = D.getDeclSpec().getRepAsTemplateId(); TemplateArgumentListInfo TemplateArgsInfo; if (TemplateId->LAngleLoc.isValid()) { @@ -3167,15 +3233,16 @@ static QualType InventTemplateParameter( } } - // If TSI is nullptr, this is a constrained declspec auto and the type - // constraint will be attached later in TypeSpecLocFiller - // Replace the 'auto' in the function parameter with this invented // template type parameter. // FIXME: Retain some type sugar to indicate that this was written // as 'auto'? - return state.ReplaceAutoType( - T, QualType(InventedTemplateParam->getTypeForDecl(), 0)); + QualType Replacement(InventedTemplateParam->getTypeForDecl(), 0); + QualType NewT = state.ReplaceAutoType(T, Replacement); + TypeSourceInfo *NewTSI = + TrailingTSI ? S.ReplaceAutoTypeSourceInfo(TrailingTSI, Replacement) + : nullptr; + return {NewT, NewTSI}; } static TypeSourceInfo * @@ -3234,8 +3301,19 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, if (!D.getAttributes().empty()) distributeTypeAttrsFromDeclarator(state, T); + // Find the deduced type in this type. Look in the trailing return type if we + // have one, otherwise in the DeclSpec type. + // FIXME: The standard wording doesn't currently describe this. + DeducedType *Deduced = T->getContainedDeducedType(); + bool DeducedIsTrailingReturnType = false; + if (Deduced && isa<AutoType>(Deduced) && D.hasTrailingReturnType()) { + QualType T = SemaRef.GetTypeFromParser(D.getTrailingReturnType()); + Deduced = T.isNull() ? nullptr : T->getContainedDeducedType(); + DeducedIsTrailingReturnType = true; + } + // C++11 [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context. - if (DeducedType *Deduced = T->getContainedDeducedType()) { + if (Deduced) { AutoType *Auto = dyn_cast<AutoType>(Deduced); int Error = -1; @@ -3246,21 +3324,21 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, bool IsDeducedReturnType = false; switch (D.getContext()) { - case DeclaratorContext::LambdaExprContext: + case DeclaratorContext::LambdaExpr: // Declared return type of a lambda-declarator is implicit and is always // 'auto'. break; - case DeclaratorContext::ObjCParameterContext: - case DeclaratorContext::ObjCResultContext: + case DeclaratorContext::ObjCParameter: + case DeclaratorContext::ObjCResult: Error = 0; break; - case DeclaratorContext::RequiresExprContext: + case DeclaratorContext::RequiresExpr: Error = 22; break; - case DeclaratorContext::PrototypeContext: - case DeclaratorContext::LambdaExprParameterContext: { + case DeclaratorContext::Prototype: + case DeclaratorContext::LambdaExprParameter: { InventedTemplateParameterInfo *Info = nullptr; - if (D.getContext() == DeclaratorContext::PrototypeContext) { + if (D.getContext() == DeclaratorContext::Prototype) { // With concepts we allow 'auto' in function parameters. if (!SemaRef.getLangOpts().CPlusPlus20 || !Auto || Auto->getKeyword() != AutoTypeKeyword::Auto) { @@ -3269,10 +3347,6 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, } else if (!SemaRef.getCurScope()->isFunctionDeclarationScope()) { Error = 21; break; - } else if (D.hasTrailingReturnType()) { - // This might be OK, but we'll need to convert the trailing return - // type later. - break; } Info = &SemaRef.InventedParameterInfos.back(); @@ -3286,10 +3360,15 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, Info = SemaRef.getCurLambda(); assert(Info && "No LambdaScopeInfo on the stack!"); } - T = InventTemplateParameter(state, T, nullptr, Auto, *Info); + + // We'll deal with inventing template parameters for 'auto' in trailing + // return types when we pick up the trailing return type when processing + // the function chunk. + if (!DeducedIsTrailingReturnType) + T = InventTemplateParameter(state, T, nullptr, Auto, *Info).first; break; } - case DeclaratorContext::MemberContext: { + case DeclaratorContext::Member: { if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static || D.isFunctionDeclarator()) break; @@ -3309,20 +3388,21 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, Error = 20; // Friend type break; } - case DeclaratorContext::CXXCatchContext: - case DeclaratorContext::ObjCCatchContext: + case DeclaratorContext::CXXCatch: + case DeclaratorContext::ObjCCatch: Error = 7; // Exception declaration break; - case DeclaratorContext::TemplateParamContext: - if (isa<DeducedTemplateSpecializationType>(Deduced)) - Error = 19; // Template parameter + case DeclaratorContext::TemplateParam: + if (isa<DeducedTemplateSpecializationType>(Deduced) && + !SemaRef.getLangOpts().CPlusPlus20) + Error = 19; // Template parameter (until C++20) else if (!SemaRef.getLangOpts().CPlusPlus17) Error = 8; // Template parameter (until C++17) break; - case DeclaratorContext::BlockLiteralContext: + case DeclaratorContext::BlockLiteral: Error = 9; // Block literal break; - case DeclaratorContext::TemplateArgContext: + case DeclaratorContext::TemplateArg: // Within a template argument list, a deduced template specialization // type will be reinterpreted as a template template argument. if (isa<DeducedTemplateSpecializationType>(Deduced) && @@ -3330,47 +3410,47 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, D.getDeclSpec().getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier) break; LLVM_FALLTHROUGH; - case DeclaratorContext::TemplateTypeArgContext: + case DeclaratorContext::TemplateTypeArg: Error = 10; // Template type argument break; - case DeclaratorContext::AliasDeclContext: - case DeclaratorContext::AliasTemplateContext: + case DeclaratorContext::AliasDecl: + case DeclaratorContext::AliasTemplate: Error = 12; // Type alias break; - case DeclaratorContext::TrailingReturnContext: - case DeclaratorContext::TrailingReturnVarContext: + case DeclaratorContext::TrailingReturn: + case DeclaratorContext::TrailingReturnVar: if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType) Error = 13; // Function return type IsDeducedReturnType = true; break; - case DeclaratorContext::ConversionIdContext: + case DeclaratorContext::ConversionId: if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType) Error = 14; // conversion-type-id IsDeducedReturnType = true; break; - case DeclaratorContext::FunctionalCastContext: + case DeclaratorContext::FunctionalCast: if (isa<DeducedTemplateSpecializationType>(Deduced)) break; LLVM_FALLTHROUGH; - case DeclaratorContext::TypeNameContext: + case DeclaratorContext::TypeName: Error = 15; // Generic break; - case DeclaratorContext::FileContext: - case DeclaratorContext::BlockContext: - case DeclaratorContext::ForContext: - case DeclaratorContext::InitStmtContext: - case DeclaratorContext::ConditionContext: + case DeclaratorContext::File: + case DeclaratorContext::Block: + case DeclaratorContext::ForInit: + case DeclaratorContext::SelectionInit: + case DeclaratorContext::Condition: // FIXME: P0091R3 (erroneously) does not permit class template argument // deduction in conditions, for-init-statements, and other declarations // that are not simple-declarations. break; - case DeclaratorContext::CXXNewContext: + case DeclaratorContext::CXXNew: // FIXME: P0091R3 does not permit class template argument deduction here, // but we follow GCC and allow it anyway. if (!IsCXXAutoType && !isa<DeducedTemplateSpecializationType>(Deduced)) Error = 17; // 'new' type break; - case DeclaratorContext::KNRTypeListContext: + case DeclaratorContext::KNRTypeList: Error = 18; // K&R function parameter break; } @@ -3384,20 +3464,6 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, (!SemaRef.getLangOpts().CPlusPlus11 || !IsCXXAutoType)) Error = 13; - bool HaveTrailing = false; - - // C++11 [dcl.spec.auto]p2: 'auto' is always fine if the declarator - // contains a trailing return type. That is only legal at the outermost - // level. Check all declarator chunks (outermost first) anyway, to give - // better diagnostics. - // We don't support '__auto_type' with trailing return types. - // FIXME: Should we only do this for 'auto' and not 'decltype(auto)'? - if (SemaRef.getLangOpts().CPlusPlus11 && IsCXXAutoType && - D.hasTrailingReturnType()) { - HaveTrailing = true; - Error = -1; - } - SourceRange AutoRange = D.getDeclSpec().getTypeSpecTypeLoc(); if (D.getName().getKind() == UnqualifiedIdKind::IK_ConversionFunctionId) AutoRange = D.getName().getSourceRange(); @@ -3427,17 +3493,15 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, T = SemaRef.Context.IntTy; D.setInvalidType(true); - } else if (Auto && !HaveTrailing && - D.getContext() != DeclaratorContext::LambdaExprContext) { + } else if (Auto && D.getContext() != DeclaratorContext::LambdaExpr) { // If there was a trailing return type, we already got // warn_cxx98_compat_trailing_return_type in the parser. SemaRef.Diag(AutoRange.getBegin(), - D.getContext() == - DeclaratorContext::LambdaExprParameterContext + D.getContext() == DeclaratorContext::LambdaExprParameter ? diag::warn_cxx11_compat_generic_lambda - : IsDeducedReturnType - ? diag::warn_cxx11_compat_deduced_return_type - : diag::warn_cxx98_compat_auto_type_specifier) + : IsDeducedReturnType + ? diag::warn_cxx11_compat_deduced_return_type + : diag::warn_cxx98_compat_auto_type_specifier) << AutoRange; } } @@ -3448,50 +3512,50 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, // or enumeration in a type-specifier-seq. unsigned DiagID = 0; switch (D.getContext()) { - case DeclaratorContext::TrailingReturnContext: - case DeclaratorContext::TrailingReturnVarContext: + case DeclaratorContext::TrailingReturn: + case DeclaratorContext::TrailingReturnVar: // Class and enumeration definitions are syntactically not allowed in // trailing return types. llvm_unreachable("parser should not have allowed this"); break; - case DeclaratorContext::FileContext: - case DeclaratorContext::MemberContext: - case DeclaratorContext::BlockContext: - case DeclaratorContext::ForContext: - case DeclaratorContext::InitStmtContext: - case DeclaratorContext::BlockLiteralContext: - case DeclaratorContext::LambdaExprContext: + case DeclaratorContext::File: + case DeclaratorContext::Member: + case DeclaratorContext::Block: + case DeclaratorContext::ForInit: + case DeclaratorContext::SelectionInit: + case DeclaratorContext::BlockLiteral: + case DeclaratorContext::LambdaExpr: // C++11 [dcl.type]p3: // A type-specifier-seq shall not define a class or enumeration unless // it appears in the type-id of an alias-declaration (7.1.3) that is not // the declaration of a template-declaration. - case DeclaratorContext::AliasDeclContext: + case DeclaratorContext::AliasDecl: break; - case DeclaratorContext::AliasTemplateContext: + case DeclaratorContext::AliasTemplate: DiagID = diag::err_type_defined_in_alias_template; break; - case DeclaratorContext::TypeNameContext: - case DeclaratorContext::FunctionalCastContext: - case DeclaratorContext::ConversionIdContext: - case DeclaratorContext::TemplateParamContext: - case DeclaratorContext::CXXNewContext: - case DeclaratorContext::CXXCatchContext: - case DeclaratorContext::ObjCCatchContext: - case DeclaratorContext::TemplateArgContext: - case DeclaratorContext::TemplateTypeArgContext: + case DeclaratorContext::TypeName: + case DeclaratorContext::FunctionalCast: + case DeclaratorContext::ConversionId: + case DeclaratorContext::TemplateParam: + case DeclaratorContext::CXXNew: + case DeclaratorContext::CXXCatch: + case DeclaratorContext::ObjCCatch: + case DeclaratorContext::TemplateArg: + case DeclaratorContext::TemplateTypeArg: DiagID = diag::err_type_defined_in_type_specifier; break; - case DeclaratorContext::PrototypeContext: - case DeclaratorContext::LambdaExprParameterContext: - case DeclaratorContext::ObjCParameterContext: - case DeclaratorContext::ObjCResultContext: - case DeclaratorContext::KNRTypeListContext: - case DeclaratorContext::RequiresExprContext: + case DeclaratorContext::Prototype: + case DeclaratorContext::LambdaExprParameter: + case DeclaratorContext::ObjCParameter: + case DeclaratorContext::ObjCResult: + case DeclaratorContext::KNRTypeList: + case DeclaratorContext::RequiresExpr: // C++ [dcl.fct]p6: // Types shall not be defined in return or parameter types. DiagID = diag::err_type_defined_in_param_type; break; - case DeclaratorContext::ConditionContext: + case DeclaratorContext::Condition: // C++ 6.4p2: // The type-specifier-seq shall not contain typedef and shall not declare // a new class or enumeration. @@ -3532,15 +3596,14 @@ static void warnAboutAmbiguousFunction(Sema &S, Declarator &D, // Only warn if this declarator is declaring a function at block scope, and // doesn't have a storage class (such as 'extern') specified. if (!D.isFunctionDeclarator() || - D.getFunctionDefinitionKind() != FDK_Declaration || + D.getFunctionDefinitionKind() != FunctionDefinitionKind::Declaration || !S.CurContext->isFunctionOrMethod() || - D.getDeclSpec().getStorageClassSpec() - != DeclSpec::SCS_unspecified) + D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_unspecified) return; // Inside a condition, a direct initializer is not permitted. We allow one to // be parsed in order to give better diagnostics in condition parsing. - if (D.getContext() == DeclaratorContext::ConditionContext) + if (D.getContext() == DeclaratorContext::Condition) return; SourceRange ParenRange(DeclType.Loc, DeclType.EndLoc); @@ -3656,7 +3719,7 @@ static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) { case DeclaratorChunk::Function: // In a new-type-id, function chunks require parentheses. - if (D.getContext() == DeclaratorContext::CXXNewContext) + if (D.getContext() == DeclaratorContext::CXXNew) return; // FIXME: "A(f())" deserves a vexing-parse warning, not just a // redundant-parens warning, but we don't know whether the function @@ -3773,7 +3836,7 @@ static CallingConv getCCForDeclaratorChunk( // in a member pointer. IsCXXInstanceMethod = D.getTypeObject(I).Kind == DeclaratorChunk::MemberPointer; - } else if (D.getContext() == DeclaratorContext::LambdaExprContext) { + } else if (D.getContext() == DeclaratorContext::LambdaExpr) { // This can only be a call operator for a lambda, which is an instance // method. IsCXXInstanceMethod = true; @@ -3832,6 +3895,11 @@ IdentifierInfo *Sema::getNullabilityKeyword(NullabilityKind nullability) { Ident__Nullable = PP.getIdentifierInfo("_Nullable"); return Ident__Nullable; + case NullabilityKind::NullableResult: + if (!Ident__Nullable_result) + Ident__Nullable_result = PP.getIdentifierInfo("_Nullable_result"); + return Ident__Nullable_result; + case NullabilityKind::Unspecified: if (!Ident__Null_unspecified) Ident__Null_unspecified = PP.getIdentifierInfo("_Null_unspecified"); @@ -3854,6 +3922,7 @@ static bool hasNullabilityAttr(const ParsedAttributesView &attrs) { for (const ParsedAttr &AL : attrs) { if (AL.getKind() == ParsedAttr::AT_TypeNonNull || AL.getKind() == ParsedAttr::AT_TypeNullable || + AL.getKind() == ParsedAttr::AT_TypeNullableResult || AL.getKind() == ParsedAttr::AT_TypeNullUnspecified) return true; } @@ -3998,32 +4067,9 @@ classifyPointerDeclarator(Sema &S, QualType type, Declarator &declarator, if (auto recordType = type->getAs<RecordType>()) { RecordDecl *recordDecl = recordType->getDecl(); - bool isCFError = false; - if (S.CFError) { - // If we already know about CFError, test it directly. - isCFError = (S.CFError == recordDecl); - } else { - // Check whether this is CFError, which we identify based on its bridge - // to NSError. CFErrorRef used to be declared with "objc_bridge" but is - // now declared with "objc_bridge_mutable", so look for either one of - // the two attributes. - if (recordDecl->getTagKind() == TTK_Struct && numNormalPointers > 0) { - IdentifierInfo *bridgedType = nullptr; - if (auto bridgeAttr = recordDecl->getAttr<ObjCBridgeAttr>()) - bridgedType = bridgeAttr->getBridgedType(); - else if (auto bridgeAttr = - recordDecl->getAttr<ObjCBridgeMutableAttr>()) - bridgedType = bridgeAttr->getBridgedType(); - - if (bridgedType == S.getNSErrorIdent()) { - S.CFError = recordDecl; - isCFError = true; - } - } - } - // If this is CFErrorRef*, report it as such. - if (isCFError && numNormalPointers == 2 && numTypeSpecifierPointers < 2) { + if (numNormalPointers == 2 && numTypeSpecifierPointers < 2 && + S.isCFError(recordDecl)) { return PointerDeclaratorKind::CFErrorRefPointer; } break; @@ -4047,6 +4093,31 @@ classifyPointerDeclarator(Sema &S, QualType type, Declarator &declarator, } } +bool Sema::isCFError(RecordDecl *RD) { + // If we already know about CFError, test it directly. + if (CFError) + return CFError == RD; + + // Check whether this is CFError, which we identify based on its bridge to + // NSError. CFErrorRef used to be declared with "objc_bridge" but is now + // declared with "objc_bridge_mutable", so look for either one of the two + // attributes. + if (RD->getTagKind() == TTK_Struct) { + IdentifierInfo *bridgedType = nullptr; + if (auto bridgeAttr = RD->getAttr<ObjCBridgeAttr>()) + bridgedType = bridgeAttr->getBridgedType(); + else if (auto bridgeAttr = RD->getAttr<ObjCBridgeMutableAttr>()) + bridgedType = bridgeAttr->getBridgedType(); + + if (bridgedType == getNSErrorIdent()) { + CFError = RD; + return true; + } + } + + return false; +} + static FileID getNullabilityCompletenessCheckFileID(Sema &S, SourceLocation loc) { // If we're anywhere in a function, method, or closure context, don't perform @@ -4086,7 +4157,8 @@ static FileID getNullabilityCompletenessCheckFileID(Sema &S, /// Creates a fix-it to insert a C-style nullability keyword at \p pointerLoc, /// taking into account whitespace before and after. -static void fixItNullability(Sema &S, DiagnosticBuilder &Diag, +template <typename DiagBuilderT> +static void fixItNullability(Sema &S, DiagBuilderT &Diag, SourceLocation PointerLoc, NullabilityKind Nullability) { assert(PointerLoc.isValid()); @@ -4269,6 +4341,9 @@ static Attr *createNullabilityAttr(ASTContext &Ctx, ParsedAttr &Attr, case NullabilityKind::Nullable: return createSimpleAttr<TypeNullableAttr>(Ctx, Attr); + case NullabilityKind::NullableResult: + return createSimpleAttr<TypeNullableResultAttr>(Ctx, Attr); + case NullabilityKind::Unspecified: return createSimpleAttr<TypeNullUnspecifiedAttr>(Ctx, Attr); } @@ -4312,9 +4387,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // Does this declaration declare a typedef-name? bool IsTypedefName = - D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef || - D.getContext() == DeclaratorContext::AliasDeclContext || - D.getContext() == DeclaratorContext::AliasTemplateContext; + D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef || + D.getContext() == DeclaratorContext::AliasDecl || + D.getContext() == DeclaratorContext::AliasTemplate; // Does T refer to a function type with a cv-qualifier or a ref-qualifier? bool IsQualifiedFunction = T->isFunctionProtoType() && @@ -4443,15 +4518,15 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, } else { bool isFunctionOrMethod = false; switch (auto context = state.getDeclarator().getContext()) { - case DeclaratorContext::ObjCParameterContext: - case DeclaratorContext::ObjCResultContext: - case DeclaratorContext::PrototypeContext: - case DeclaratorContext::TrailingReturnContext: - case DeclaratorContext::TrailingReturnVarContext: + case DeclaratorContext::ObjCParameter: + case DeclaratorContext::ObjCResult: + case DeclaratorContext::Prototype: + case DeclaratorContext::TrailingReturn: + case DeclaratorContext::TrailingReturnVar: isFunctionOrMethod = true; LLVM_FALLTHROUGH; - case DeclaratorContext::MemberContext: + case DeclaratorContext::Member: if (state.getDeclarator().isObjCIvar() && !isFunctionOrMethod) { complainAboutMissingNullability = CAMN_No; break; @@ -4465,8 +4540,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, LLVM_FALLTHROUGH; - case DeclaratorContext::FileContext: - case DeclaratorContext::KNRTypeListContext: { + case DeclaratorContext::File: + case DeclaratorContext::KNRTypeList: { complainAboutMissingNullability = CAMN_Yes; // Nullability inference depends on the type and declarator. @@ -4482,9 +4557,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, if (inAssumeNonNullRegion) { complainAboutInferringWithinChunk = wrappingKind; inferNullability = NullabilityKind::NonNull; - inferNullabilityCS = - (context == DeclaratorContext::ObjCParameterContext || - context == DeclaratorContext::ObjCResultContext); + inferNullabilityCS = (context == DeclaratorContext::ObjCParameter || + context == DeclaratorContext::ObjCResult); } break; @@ -4520,28 +4594,28 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, break; } - case DeclaratorContext::ConversionIdContext: + case DeclaratorContext::ConversionId: complainAboutMissingNullability = CAMN_Yes; break; - case DeclaratorContext::AliasDeclContext: - case DeclaratorContext::AliasTemplateContext: - case DeclaratorContext::BlockContext: - case DeclaratorContext::BlockLiteralContext: - case DeclaratorContext::ConditionContext: - case DeclaratorContext::CXXCatchContext: - case DeclaratorContext::CXXNewContext: - case DeclaratorContext::ForContext: - case DeclaratorContext::InitStmtContext: - case DeclaratorContext::LambdaExprContext: - case DeclaratorContext::LambdaExprParameterContext: - case DeclaratorContext::ObjCCatchContext: - case DeclaratorContext::TemplateParamContext: - case DeclaratorContext::TemplateArgContext: - case DeclaratorContext::TemplateTypeArgContext: - case DeclaratorContext::TypeNameContext: - case DeclaratorContext::FunctionalCastContext: - case DeclaratorContext::RequiresExprContext: + case DeclaratorContext::AliasDecl: + case DeclaratorContext::AliasTemplate: + case DeclaratorContext::Block: + case DeclaratorContext::BlockLiteral: + case DeclaratorContext::Condition: + case DeclaratorContext::CXXCatch: + case DeclaratorContext::CXXNew: + case DeclaratorContext::ForInit: + case DeclaratorContext::SelectionInit: + case DeclaratorContext::LambdaExpr: + case DeclaratorContext::LambdaExprParameter: + case DeclaratorContext::ObjCCatch: + case DeclaratorContext::TemplateParam: + case DeclaratorContext::TemplateArg: + case DeclaratorContext::TemplateTypeArg: + case DeclaratorContext::TypeName: + case DeclaratorContext::FunctionalCast: + case DeclaratorContext::RequiresExpr: // Don't infer in these contexts. break; } @@ -4778,7 +4852,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // array type, ... if (ASM == ArrayType::Static || ATI.TypeQuals) { if (!(D.isPrototypeContext() || - D.getContext() == DeclaratorContext::KNRTypeListContext)) { + D.getContext() == DeclaratorContext::KNRTypeList)) { S.Diag(DeclType.Loc, diag::err_array_static_outside_prototype) << (ASM == ArrayType::Static ? "'static'" : "type qualifier"); // Remove the 'static' and the type qualifiers. @@ -4802,12 +4876,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, const AutoType *AT = T->getContainedAutoType(); // Allow arrays of auto if we are a generic lambda parameter. // i.e. [](auto (&array)[5]) { return array[0]; }; OK - if (AT && - D.getContext() != DeclaratorContext::LambdaExprParameterContext) { + if (AT && D.getContext() != DeclaratorContext::LambdaExprParameter) { // We've already diagnosed this for decltype(auto). if (!AT->isDecltypeAuto()) S.Diag(DeclType.Loc, diag::err_illegal_decl_array_of_auto) - << getPrintableNameForEntity(Name) << T; + << getPrintableNameForEntity(Name) << T; T = QualType(); break; } @@ -4866,7 +4939,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, << D.getSourceRange(); D.setInvalidType(true); } - } else if (D.getContext() != DeclaratorContext::LambdaExprContext && + } else if (D.getContext() != DeclaratorContext::LambdaExpr && (T.hasQualifiers() || !isa<AutoType>(T) || cast<AutoType>(T)->getKeyword() != AutoTypeKeyword::Auto || @@ -4881,12 +4954,20 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // An error occurred parsing the trailing return type. T = Context.IntTy; D.setInvalidType(true); - } else if (S.getLangOpts().CPlusPlus20) - // Handle cases like: `auto f() -> auto` or `auto f() -> C auto`. - if (AutoType *Auto = T->getContainedAutoType()) - if (S.getCurScope()->isFunctionDeclarationScope()) - T = InventTemplateParameter(state, T, TInfo, Auto, - S.InventedParameterInfos.back()); + } else if (AutoType *Auto = T->getContainedAutoType()) { + // If the trailing return type contains an `auto`, we may need to + // invent a template parameter for it, for cases like + // `auto f() -> C auto` or `[](auto (*p) -> auto) {}`. + InventedTemplateParameterInfo *InventedParamInfo = nullptr; + if (D.getContext() == DeclaratorContext::Prototype) + InventedParamInfo = &S.InventedParameterInfos.back(); + else if (D.getContext() == DeclaratorContext::LambdaExprParameter) + InventedParamInfo = S.getCurLambda(); + if (InventedParamInfo) { + std::tie(T, TInfo) = InventTemplateParameter( + state, T, TInfo, Auto, *InventedParamInfo); + } + } } else { // This function type is not the type of the entity being declared, // so checking the 'auto' is not the responsibility of this chunk. @@ -4902,7 +4983,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // Last processing chunk in block context means this function chunk // represents the block. if (chunkIndex == 0 && - D.getContext() == DeclaratorContext::BlockLiteralContext) + D.getContext() == DeclaratorContext::BlockLiteral) diagID = diag::err_block_returning_array_function; S.Diag(DeclType.Loc, diagID) << T->isFunctionType() << T; T = Context.IntTy; @@ -4938,6 +5019,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // (s6.9.e and s6.12.5 OpenCL v2.0) except for printf. // We also allow here any toolchain reserved identifiers. if (FTI.isVariadic && + !S.getOpenCLOptions().isEnabled("__cl_clang_variadic_functions") && !(D.getIdentifier() && ((D.getIdentifier()->getName() == "printf" && (LangOpts.OpenCLCPlusPlus || LangOpts.OpenCLVersion >= 120)) || @@ -4980,7 +5062,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, !(S.getLangOpts().CPlusPlus && (T->isDependentType() || T->isRecordType()))) { if (T->isVoidType() && !S.getLangOpts().CPlusPlus && - D.getFunctionDefinitionKind() == FDK_Definition) { + D.getFunctionDefinitionKind() == + FunctionDefinitionKind::Definition) { // [6.9.1/3] qualified void return is invalid on a C // function definition. Apparently ok on declarations and // in C++ though (!) @@ -5043,8 +5126,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, if (IsTypedefName && FTI.getExceptionSpecType() && !LangOpts.CPlusPlus17) S.Diag(FTI.getExceptionSpecLocBeg(), diag::err_exception_spec_in_typedef) - << (D.getContext() == DeclaratorContext::AliasDeclContext || - D.getContext() == DeclaratorContext::AliasTemplateContext); + << (D.getContext() == DeclaratorContext::AliasDecl || + D.getContext() == DeclaratorContext::AliasTemplate); // If we see "T var();" or "T var(T());" at block scope, it is probably // an attempt to initialize a variable, not a function declaration. @@ -5111,7 +5194,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // is an incomplete type (C99 6.2.5p19) and function decls cannot // have parameters of incomplete type. if (FTI.NumParams != 1 || FTI.isVariadic) { - S.Diag(DeclType.Loc, diag::err_void_only_param); + S.Diag(FTI.Params[i].IdentLoc, diag::err_void_only_param); ParamTy = Context.IntTy; Param->setType(ParamTy); } else if (FTI.Params[i].Ident) { @@ -5225,9 +5308,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, .getScopeRep() ->getKind() == NestedNameSpecifier::TypeSpec) || state.getDeclarator().getContext() == - DeclaratorContext::MemberContext || + DeclaratorContext::Member || state.getDeclarator().getContext() == - DeclaratorContext::LambdaExprContext; + DeclaratorContext::LambdaExpr; }; if (state.getSema().getLangOpts().OpenCLCPlusPlus && IsClassMember()) { @@ -5351,7 +5434,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // The empty list in a function declarator that is not part of a definition // of that function specifies that no information about the number or types // of the parameters is supplied. - if (!LangOpts.CPlusPlus && D.getFunctionDefinitionKind() == FDK_Declaration) { + if (!LangOpts.CPlusPlus && + D.getFunctionDefinitionKind() == FunctionDefinitionKind::Declaration) { bool IsBlock = false; for (const DeclaratorChunk &DeclType : D.type_objects()) { switch (DeclType.Kind) { @@ -5394,8 +5478,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, if (D.getName().getKind() == UnqualifiedIdKind::IK_DeductionGuideName) Kind = DeductionGuide; else if (!D.getCXXScopeSpec().isSet()) { - if ((D.getContext() == DeclaratorContext::MemberContext || - D.getContext() == DeclaratorContext::LambdaExprContext) && + if ((D.getContext() == DeclaratorContext::Member || + D.getContext() == DeclaratorContext::LambdaExpr) && !D.getDeclSpec().isFriendSpecified()) Kind = Member; } else { @@ -5423,9 +5507,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, if (IsQualifiedFunction && !(Kind == Member && D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) && - !IsTypedefName && - D.getContext() != DeclaratorContext::TemplateArgContext && - D.getContext() != DeclaratorContext::TemplateTypeArgContext) { + !IsTypedefName && D.getContext() != DeclaratorContext::TemplateArg && + D.getContext() != DeclaratorContext::TemplateTypeArg) { SourceLocation Loc = D.getBeginLoc(); SourceRange RemovalRange; unsigned I; @@ -5480,15 +5563,15 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // C++0x [dcl.constexpr]p9: // A constexpr specifier used in an object declaration declares the object // as const. - if (D.getDeclSpec().getConstexprSpecifier() == CSK_constexpr && + if (D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr && T->isObjectType()) T.addConst(); // C++2a [dcl.fct]p4: // A parameter with volatile-qualified type is deprecated if (T.isVolatileQualified() && S.getLangOpts().CPlusPlus20 && - (D.getContext() == DeclaratorContext::PrototypeContext || - D.getContext() == DeclaratorContext::LambdaExprParameterContext)) + (D.getContext() == DeclaratorContext::Prototype || + D.getContext() == DeclaratorContext::LambdaExprParameter)) S.Diag(D.getIdentifierLoc(), diag::warn_deprecated_volatile_param) << T; // If there was an ellipsis in the declarator, the declaration declares a @@ -5499,9 +5582,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // only be used in a parameter-declaration. Such a parameter-declaration // is a parameter pack (14.5.3). [...] switch (D.getContext()) { - case DeclaratorContext::PrototypeContext: - case DeclaratorContext::LambdaExprParameterContext: - case DeclaratorContext::RequiresExprContext: + case DeclaratorContext::Prototype: + case DeclaratorContext::LambdaExprParameter: + case DeclaratorContext::RequiresExpr: // C++0x [dcl.fct]p13: // [...] When it is part of a parameter-declaration-clause, the // parameter pack is a function parameter pack (14.5.3). The type T @@ -5518,10 +5601,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, << T << D.getSourceRange(); D.setEllipsisLoc(SourceLocation()); } else { - T = Context.getPackExpansionType(T, None); + T = Context.getPackExpansionType(T, None, /*ExpectPackInType=*/false); } break; - case DeclaratorContext::TemplateParamContext: + case DeclaratorContext::TemplateParam: // C++0x [temp.param]p15: // If a template-parameter is a [...] is a parameter-declaration that // declares a parameter pack (8.3.5), then the template-parameter is a @@ -5539,31 +5622,29 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, : diag::ext_variadic_templates); break; - case DeclaratorContext::FileContext: - case DeclaratorContext::KNRTypeListContext: - case DeclaratorContext::ObjCParameterContext: // FIXME: special diagnostic - // here? - case DeclaratorContext::ObjCResultContext: // FIXME: special diagnostic - // here? - case DeclaratorContext::TypeNameContext: - case DeclaratorContext::FunctionalCastContext: - case DeclaratorContext::CXXNewContext: - case DeclaratorContext::AliasDeclContext: - case DeclaratorContext::AliasTemplateContext: - case DeclaratorContext::MemberContext: - case DeclaratorContext::BlockContext: - case DeclaratorContext::ForContext: - case DeclaratorContext::InitStmtContext: - case DeclaratorContext::ConditionContext: - case DeclaratorContext::CXXCatchContext: - case DeclaratorContext::ObjCCatchContext: - case DeclaratorContext::BlockLiteralContext: - case DeclaratorContext::LambdaExprContext: - case DeclaratorContext::ConversionIdContext: - case DeclaratorContext::TrailingReturnContext: - case DeclaratorContext::TrailingReturnVarContext: - case DeclaratorContext::TemplateArgContext: - case DeclaratorContext::TemplateTypeArgContext: + case DeclaratorContext::File: + case DeclaratorContext::KNRTypeList: + case DeclaratorContext::ObjCParameter: // FIXME: special diagnostic here? + case DeclaratorContext::ObjCResult: // FIXME: special diagnostic here? + case DeclaratorContext::TypeName: + case DeclaratorContext::FunctionalCast: + case DeclaratorContext::CXXNew: + case DeclaratorContext::AliasDecl: + case DeclaratorContext::AliasTemplate: + case DeclaratorContext::Member: + case DeclaratorContext::Block: + case DeclaratorContext::ForInit: + case DeclaratorContext::SelectionInit: + case DeclaratorContext::Condition: + case DeclaratorContext::CXXCatch: + case DeclaratorContext::ObjCCatch: + case DeclaratorContext::BlockLiteral: + case DeclaratorContext::LambdaExpr: + case DeclaratorContext::ConversionId: + case DeclaratorContext::TrailingReturn: + case DeclaratorContext::TrailingReturnVar: + case DeclaratorContext::TemplateArg: + case DeclaratorContext::TemplateTypeArg: // FIXME: We may want to allow parameter packs in block-literal contexts // in the future. S.Diag(D.getEllipsisLoc(), @@ -5816,9 +5897,9 @@ namespace { // Set info for the written builtin specifiers. TL.getWrittenBuiltinSpecs() = DS.getWrittenBuiltinSpecs(); // Try to have a meaningful source location. - if (TL.getWrittenSignSpec() != TSS_unspecified) + if (TL.getWrittenSignSpec() != TypeSpecifierSign::Unspecified) TL.expandBuiltinRange(DS.getTypeSpecSignLoc()); - if (TL.getWrittenWidthSpec() != TSW_unspecified) + if (TL.getWrittenWidthSpec() != TypeSpecifierWidth::Unspecified) TL.expandBuiltinRange(DS.getTypeSpecWidthRange()); } } @@ -6005,7 +6086,7 @@ namespace { } // Finally fill in MemberPointerLocInfo fields. - TL.setStarLoc(SourceLocation::getFromRawEncoding(Chunk.Mem.StarLoc)); + TL.setStarLoc(Chunk.Mem.StarLoc); TL.setClassTInfo(ClsTInfo); } void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) { @@ -6054,6 +6135,17 @@ namespace { void VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc TL) { TL.setExpansionLoc(Chunk.Loc); } + void VisitVectorTypeLoc(VectorTypeLoc TL) { TL.setNameLoc(Chunk.Loc); } + void VisitDependentVectorTypeLoc(DependentVectorTypeLoc TL) { + TL.setNameLoc(Chunk.Loc); + } + void VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { + TL.setNameLoc(Chunk.Loc); + } + void + VisitDependentSizedExtVectorTypeLoc(DependentSizedExtVectorTypeLoc TL) { + TL.setNameLoc(Chunk.Loc); + } void VisitTypeLoc(TypeLoc TL) { llvm_unreachable("unsupported TypeLoc kind in declarator!"); @@ -6071,7 +6163,7 @@ static void fillAtomicQualLoc(AtomicTypeLoc ATL, const DeclaratorChunk &Chunk) { llvm_unreachable("cannot be _Atomic qualified"); case DeclaratorChunk::Pointer: - Loc = SourceLocation::getFromRawEncoding(Chunk.Ptr.AtomicQualLoc); + Loc = Chunk.Ptr.AtomicQualLoc; break; case DeclaratorChunk::BlockPointer: @@ -6224,9 +6316,9 @@ TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) { // to apply them to the actual parameter declaration. // Likewise, we don't want to do this for alias declarations, because // we are actually going to build a declaration from this eventually. - if (D.getContext() != DeclaratorContext::ObjCParameterContext && - D.getContext() != DeclaratorContext::AliasDeclContext && - D.getContext() != DeclaratorContext::AliasTemplateContext) + if (D.getContext() != DeclaratorContext::ObjCParameter && + D.getContext() != DeclaratorContext::AliasDecl && + D.getContext() != DeclaratorContext::AliasTemplate) checkUnusedDeclAttributes(D); if (getLangOpts().CPlusPlus) { @@ -6254,13 +6346,15 @@ static bool BuildAddressSpaceIndex(Sema &S, LangAS &ASIdx, const Expr *AddrSpace, SourceLocation AttrLoc) { if (!AddrSpace->isValueDependent()) { - llvm::APSInt addrSpace(32); - if (!AddrSpace->isIntegerConstantExpr(addrSpace, S.Context)) { + Optional<llvm::APSInt> OptAddrSpace = + AddrSpace->getIntegerConstantExpr(S.Context); + if (!OptAddrSpace) { S.Diag(AttrLoc, diag::err_attribute_argument_type) << "'address_space'" << AANT_ArgumentIntegerConstant << AddrSpace->getSourceRange(); return false; } + llvm::APSInt &addrSpace = *OptAddrSpace; // Bounds checking. if (addrSpace.isSigned()) { @@ -6353,25 +6447,7 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, return; } - Expr *ASArgExpr; - if (Attr.isArgIdent(0)) { - // Special case where the argument is a template id. - CXXScopeSpec SS; - SourceLocation TemplateKWLoc; - UnqualifiedId id; - id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc()); - - ExprResult AddrSpace = S.ActOnIdExpression( - S.getCurScope(), SS, TemplateKWLoc, id, /*HasTrailingLParen=*/false, - /*IsAddressOfOperand=*/false); - if (AddrSpace.isInvalid()) - return; - - ASArgExpr = static_cast<Expr *>(AddrSpace.get()); - } else { - ASArgExpr = static_cast<Expr *>(Attr.getArgAsExpr(0)); - } - + Expr *ASArgExpr = static_cast<Expr *>(Attr.getArgAsExpr(0)); LangAS ASIdx; if (!BuildAddressSpaceIndex(S, ASIdx, ASArgExpr, Attr.getLoc())) { Attr.setInvalid(); @@ -6858,32 +6934,32 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State, break; } - llvm::SmallSet<attr::Kind, 2> Attrs; + std::bitset<attr::LastAttr> Attrs; attr::Kind NewAttrKind = A->getKind(); QualType Desugared = Type; const AttributedType *AT = dyn_cast<AttributedType>(Type); while (AT) { - Attrs.insert(AT->getAttrKind()); + Attrs[AT->getAttrKind()] = true; Desugared = AT->getModifiedType(); AT = dyn_cast<AttributedType>(Desugared); } // You cannot specify duplicate type attributes, so if the attribute has // already been applied, flag it. - if (Attrs.count(NewAttrKind)) { + if (Attrs[NewAttrKind]) { S.Diag(PAttr.getLoc(), diag::warn_duplicate_attribute_exact) << PAttr; return true; } - Attrs.insert(NewAttrKind); + Attrs[NewAttrKind] = true; // You cannot have both __sptr and __uptr on the same type, nor can you // have __ptr32 and __ptr64. - if (Attrs.count(attr::Ptr32) && Attrs.count(attr::Ptr64)) { + if (Attrs[attr::Ptr32] && Attrs[attr::Ptr64]) { S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible) << "'__ptr32'" << "'__ptr64'"; return true; - } else if (Attrs.count(attr::SPtr) && Attrs.count(attr::UPtr)) { + } else if (Attrs[attr::SPtr] && Attrs[attr::UPtr]) { S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible) << "'__sptr'" << "'__uptr'"; @@ -6909,12 +6985,12 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State, LangAS ASIdx = LangAS::Default; uint64_t PtrWidth = S.Context.getTargetInfo().getPointerWidth(0); if (PtrWidth == 32) { - if (Attrs.count(attr::Ptr64)) + if (Attrs[attr::Ptr64]) ASIdx = LangAS::ptr64; - else if (Attrs.count(attr::UPtr)) + else if (Attrs[attr::UPtr]) ASIdx = LangAS::ptr32_uptr; - } else if (PtrWidth == 64 && Attrs.count(attr::Ptr32)) { - if (Attrs.count(attr::UPtr)) + } else if (PtrWidth == 64 && Attrs[attr::Ptr32]) { + if (Attrs[attr::UPtr]) ASIdx = LangAS::ptr32_uptr; else ASIdx = LangAS::ptr32_sptr; @@ -6937,6 +7013,9 @@ static NullabilityKind mapNullabilityAttrKind(ParsedAttr::Kind kind) { case ParsedAttr::AT_TypeNullable: return NullabilityKind::Nullable; + case ParsedAttr::AT_TypeNullableResult: + return NullabilityKind::NullableResult; + case ParsedAttr::AT_TypeNullUnspecified: return NullabilityKind::Unspecified; @@ -7574,25 +7653,7 @@ static void HandleVectorSizeAttr(QualType &CurType, const ParsedAttr &Attr, return; } - Expr *SizeExpr; - // Special case where the argument is a template id. - if (Attr.isArgIdent(0)) { - CXXScopeSpec SS; - SourceLocation TemplateKWLoc; - UnqualifiedId Id; - Id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc()); - - ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc, - Id, /*HasTrailingLParen=*/false, - /*IsAddressOfOperand=*/false); - - if (Size.isInvalid()) - return; - SizeExpr = Size.get(); - } else { - SizeExpr = Attr.getArgAsExpr(0); - } - + Expr *SizeExpr = Attr.getArgAsExpr(0); QualType T = S.BuildVectorType(CurType, SizeExpr, Attr.getLoc()); if (!T.isNull()) CurType = T; @@ -7611,28 +7672,8 @@ static void HandleExtVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr, return; } - Expr *sizeExpr; - - // Special case where the argument is a template id. - if (Attr.isArgIdent(0)) { - CXXScopeSpec SS; - SourceLocation TemplateKWLoc; - UnqualifiedId id; - id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc()); - - ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc, - id, /*HasTrailingLParen=*/false, - /*IsAddressOfOperand=*/false); - if (Size.isInvalid()) - return; - - sizeExpr = Size.get(); - } else { - sizeExpr = Attr.getArgAsExpr(0); - } - - // Create the vector type. - QualType T = S.BuildExtVectorType(CurType, sizeExpr, Attr.getLoc()); + Expr *SizeExpr = Attr.getArgAsExpr(0); + QualType T = S.BuildExtVectorType(CurType, SizeExpr, Attr.getLoc()); if (!T.isNull()) CurType = T; } @@ -7686,6 +7727,22 @@ static bool isPermittedNeonBaseType(QualType &Ty, BTy->getKind() == BuiltinType::BFloat16; } +static bool verifyValidIntegerConstantExpr(Sema &S, const ParsedAttr &Attr, + llvm::APSInt &Result) { + const auto *AttrExpr = Attr.getArgAsExpr(0); + if (!AttrExpr->isTypeDependent() && !AttrExpr->isValueDependent()) { + if (Optional<llvm::APSInt> Res = + AttrExpr->getIntegerConstantExpr(S.Context)) { + Result = *Res; + return true; + } + } + S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) + << Attr << AANT_ArgumentIntegerConstant << AttrExpr->getSourceRange(); + Attr.setInvalid(); + return false; +} + /// HandleNeonVectorTypeAttr - The "neon_vector_type" and /// "neon_polyvector_type" attributes are used to create vector types that /// are mangled according to ARM's ABI. Otherwise, these types are identical @@ -7699,7 +7756,8 @@ static void HandleNeonVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr, // not to need a separate attribute) if (!S.Context.getTargetInfo().hasFeature("neon") && !S.Context.getTargetInfo().hasFeature("mve")) { - S.Diag(Attr.getLoc(), diag::err_attribute_unsupported) << Attr; + S.Diag(Attr.getLoc(), diag::err_attribute_unsupported) + << Attr << "'neon' or 'mve'"; Attr.setInvalid(); return; } @@ -7711,16 +7769,10 @@ static void HandleNeonVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr, return; } // The number of elements must be an ICE. - Expr *numEltsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0)); llvm::APSInt numEltsInt(32); - if (numEltsExpr->isTypeDependent() || numEltsExpr->isValueDependent() || - !numEltsExpr->isIntegerConstantExpr(numEltsInt, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) - << Attr << AANT_ArgumentIntegerConstant - << numEltsExpr->getSourceRange(); - Attr.setInvalid(); + if (!verifyValidIntegerConstantExpr(S, Attr, numEltsInt)) return; - } + // Only certain element types are supported for Neon vectors. if (!isPermittedNeonBaseType(CurType, VecKind, S)) { S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType; @@ -7741,6 +7793,71 @@ static void HandleNeonVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr, CurType = S.Context.getVectorType(CurType, numElts, VecKind); } +/// HandleArmSveVectorBitsTypeAttr - The "arm_sve_vector_bits" attribute is +/// used to create fixed-length versions of sizeless SVE types defined by +/// the ACLE, such as svint32_t and svbool_t. +static void HandleArmSveVectorBitsTypeAttr(QualType &CurType, ParsedAttr &Attr, + Sema &S) { + // Target must have SVE. + if (!S.Context.getTargetInfo().hasFeature("sve")) { + S.Diag(Attr.getLoc(), diag::err_attribute_unsupported) << Attr << "'sve'"; + Attr.setInvalid(); + return; + } + + // Attribute is unsupported if '-msve-vector-bits=<bits>' isn't specified. + if (!S.getLangOpts().ArmSveVectorBits) { + S.Diag(Attr.getLoc(), diag::err_attribute_arm_feature_sve_bits_unsupported) + << Attr; + Attr.setInvalid(); + return; + } + + // Check the attribute arguments. + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) + << Attr << 1; + Attr.setInvalid(); + return; + } + + // The vector size must be an integer constant expression. + llvm::APSInt SveVectorSizeInBits(32); + if (!verifyValidIntegerConstantExpr(S, Attr, SveVectorSizeInBits)) + return; + + unsigned VecSize = static_cast<unsigned>(SveVectorSizeInBits.getZExtValue()); + + // The attribute vector size must match -msve-vector-bits. + if (VecSize != S.getLangOpts().ArmSveVectorBits) { + S.Diag(Attr.getLoc(), diag::err_attribute_bad_sve_vector_size) + << VecSize << S.getLangOpts().ArmSveVectorBits; + Attr.setInvalid(); + return; + } + + // Attribute can only be attached to a single SVE vector or predicate type. + if (!CurType->isVLSTBuiltinType()) { + S.Diag(Attr.getLoc(), diag::err_attribute_invalid_sve_type) + << Attr << CurType; + Attr.setInvalid(); + return; + } + + const auto *BT = CurType->castAs<BuiltinType>(); + + QualType EltType = CurType->getSveEltType(S.Context); + unsigned TypeSize = S.Context.getTypeSize(EltType); + VectorType::VectorKind VecKind = VectorType::SveFixedLengthDataVector; + if (BT->getKind() == BuiltinType::SveBool) { + // Predicates are represented as i8. + VecSize /= S.Context.getCharWidth() * S.Context.getCharWidth(); + VecKind = VectorType::SveFixedLengthPredicateVector; + } else + VecSize /= TypeSize; + CurType = S.Context.getVectorType(EltType, VecSize, VecKind); +} + static void HandleArmMveStrictPolymorphismAttr(TypeProcessingState &State, QualType &CurType, ParsedAttr &Attr) { @@ -7808,7 +7925,7 @@ static void HandleOpenCLAccessAttr(QualType &CurType, const ParsedAttr &Attr, diag::note_opencl_typedef_access_qualifier) << PrevAccessQual; } else if (CurType->isPipeType()) { if (Attr.getSemanticSpelling() == OpenCLAccessAttr::Keyword_write_only) { - QualType ElemType = CurType->getAs<PipeType>()->getElementType(); + QualType ElemType = CurType->castAs<PipeType>()->getElementType(); CurType = S.Context.getWritePipeType(ElemType); } } @@ -7828,49 +7945,8 @@ static void HandleMatrixTypeAttr(QualType &CurType, const ParsedAttr &Attr, return; } - Expr *RowsExpr = nullptr; - Expr *ColsExpr = nullptr; - - // TODO: Refactor parameter extraction into separate function - // Get the number of rows - if (Attr.isArgIdent(0)) { - CXXScopeSpec SS; - SourceLocation TemplateKeywordLoc; - UnqualifiedId id; - id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc()); - ExprResult Rows = S.ActOnIdExpression(S.getCurScope(), SS, - TemplateKeywordLoc, id, false, false); - - if (Rows.isInvalid()) - // TODO: maybe a good error message would be nice here - return; - RowsExpr = Rows.get(); - } else { - assert(Attr.isArgExpr(0) && - "Argument to should either be an identity or expression"); - RowsExpr = Attr.getArgAsExpr(0); - } - - // Get the number of columns - if (Attr.isArgIdent(1)) { - CXXScopeSpec SS; - SourceLocation TemplateKeywordLoc; - UnqualifiedId id; - id.setIdentifier(Attr.getArgAsIdent(1)->Ident, Attr.getLoc()); - ExprResult Columns = S.ActOnIdExpression( - S.getCurScope(), SS, TemplateKeywordLoc, id, false, false); - - if (Columns.isInvalid()) - // TODO: a good error message would be nice here - return; - RowsExpr = Columns.get(); - } else { - assert(Attr.isArgExpr(1) && - "Argument to should either be an identity or expression"); - ColsExpr = Attr.getArgAsExpr(1); - } - - // Create the matrix type. + Expr *RowsExpr = Attr.getArgAsExpr(0); + Expr *ColsExpr = Attr.getArgAsExpr(1); QualType T = S.BuildMatrixType(CurType, RowsExpr, ColsExpr, Attr.getLoc()); if (!T.isNull()) CurType = T; @@ -7894,6 +7970,8 @@ static bool isAddressSpaceKind(const ParsedAttr &attr) { return attrKind == ParsedAttr::AT_AddressSpace || attrKind == ParsedAttr::AT_OpenCLPrivateAddressSpace || attrKind == ParsedAttr::AT_OpenCLGlobalAddressSpace || + attrKind == ParsedAttr::AT_OpenCLGlobalDeviceAddressSpace || + attrKind == ParsedAttr::AT_OpenCLGlobalHostAddressSpace || attrKind == ParsedAttr::AT_OpenCLLocalAddressSpace || attrKind == ParsedAttr::AT_OpenCLConstantAddressSpace || attrKind == ParsedAttr::AT_OpenCLGenericAddressSpace; @@ -7961,7 +8039,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, if (attr.isCXX11Attribute() && TAL == TAL_DeclChunk) state.getSema().Diag(attr.getLoc(), diag::warn_unknown_attribute_ignored) - << attr; + << attr << attr.getRange(); break; case ParsedAttr::IgnoredAttribute: @@ -7974,6 +8052,8 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, break; case ParsedAttr::AT_OpenCLPrivateAddressSpace: case ParsedAttr::AT_OpenCLGlobalAddressSpace: + case ParsedAttr::AT_OpenCLGlobalDeviceAddressSpace: + case ParsedAttr::AT_OpenCLGlobalHostAddressSpace: case ParsedAttr::AT_OpenCLLocalAddressSpace: case ParsedAttr::AT_OpenCLConstantAddressSpace: case ParsedAttr::AT_OpenCLGenericAddressSpace: @@ -8004,6 +8084,10 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, VectorType::NeonPolyVector); attr.setUsedAsTypeAttr(); break; + case ParsedAttr::AT_ArmSveVectorBits: + HandleArmSveVectorBitsTypeAttr(type, attr, state.getSema()); + attr.setUsedAsTypeAttr(); + break; case ParsedAttr::AT_ArmMveStrictPolymorphism: { HandleArmMveStrictPolymorphismAttr(state, type, attr); attr.setUsedAsTypeAttr(); @@ -8192,6 +8276,20 @@ void Sema::completeExprArrayBound(Expr *E) { } } +QualType Sema::getCompletedType(Expr *E) { + // Incomplete array types may be completed by the initializer attached to + // their definitions. For static data members of class templates and for + // variable templates, we need to instantiate the definition to get this + // initializer and complete the type. + if (E->getType()->isIncompleteArrayType()) + completeExprArrayBound(E); + + // FIXME: Are there other cases which require instantiating something other + // than the type to complete the type of an expression? + + return E->getType(); +} + /// Ensure that the type of the given expression is complete. /// /// This routine checks whether the expression \p E has a complete type. If the @@ -8209,21 +8307,8 @@ void Sema::completeExprArrayBound(Expr *E) { /// otherwise. bool Sema::RequireCompleteExprType(Expr *E, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser) { - QualType T = E->getType(); - - // Incomplete array types may be completed by the initializer attached to - // their definitions. For static data members of class templates and for - // variable templates, we need to instantiate the definition to get this - // initializer and complete the type. - if (T->isIncompleteArrayType()) { - completeExprArrayBound(E); - T = E->getType(); - } - - // FIXME: Are there other cases which require instantiating something other - // than the type to complete the type of an expression? - - return RequireCompleteType(E->getExprLoc(), T, Kind, Diagnoser); + return RequireCompleteType(E->getExprLoc(), getCompletedType(E), Kind, + Diagnoser); } bool Sema::RequireCompleteExprType(Expr *E, unsigned DiagID) { @@ -8747,7 +8832,17 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) { // C++11 [dcl.type.simple]p4: // The type denoted by decltype(e) is defined as follows: - // + + // C++20: + // - if E is an unparenthesized id-expression naming a non-type + // template-parameter (13.2), decltype(E) is the type of the + // template-parameter after performing any necessary type deduction + // Note that this does not pick up the implicit 'const' for a template + // parameter object. This rule makes no difference before C++20 so we apply + // it unconditionally. + if (const auto *SNTTPE = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) + return SNTTPE->getParameterType(S.Context); + // - if e is an unparenthesized id-expression or an unparenthesized class // member access (5.2.5), decltype(e) is the type of the entity named // by e. If there is no such entity, or if e names a set of overloaded @@ -8756,6 +8851,8 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) { // We apply the same rules for Objective-C ivar and property references. if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { const ValueDecl *VD = DRE->getDecl(); + if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(VD)) + return TPO->getType().getUnqualifiedType(); return VD->getType(); } else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) { if (const ValueDecl *VD = ME->getMemberDecl()) @@ -8813,9 +8910,11 @@ QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc, assert(!E->hasPlaceholderType() && "unexpected placeholder"); if (AsUnevaluated && CodeSynthesisContexts.empty() && - E->HasSideEffects(Context, false)) { + !E->isInstantiationDependent() && E->HasSideEffects(Context, false)) { // The expression operand for decltype is in an unevaluated expression // context, so side effects could result in unintended consequences. + // Exclude instantiation-dependent expressions, because 'decltype' is often + // used to build SFINAE gadgets. Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context); } @@ -8842,7 +8941,7 @@ QualType Sema::BuildUnaryTransformType(QualType BaseType, return QualType(); } - EnumDecl *ED = BaseType->getAs<EnumType>()->getDecl(); + EnumDecl *ED = BaseType->castAs<EnumType>()->getDecl(); assert(ED && "EnumType has no EnumDecl"); DiagnoseUseOfDecl(ED, Loc); @@ -8880,11 +8979,8 @@ QualType Sema::BuildAtomicType(QualType T, SourceLocation Loc) { else if (!T.isTriviallyCopyableType(Context)) // Some other non-trivially-copyable type (probably a C++ class) DisallowedKind = 7; - else if (auto *ExtTy = T->getAs<ExtIntType>()) { - if (ExtTy->getNumBits() < 8) + else if (T->isExtIntType()) { DisallowedKind = 8; - else if (!llvm::isPowerOf2_32(ExtTy->getNumBits())) - DisallowedKind = 9; } if (DisallowedKind != -1) { diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index ae0e9f1119b4..0a596e50658b 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -28,6 +28,7 @@ #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtOpenMP.h" +#include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/OpenMPKinds.h" #include "clang/Sema/Designator.h" #include "clang/Sema/Lookup.h" @@ -730,10 +731,11 @@ public: #define ABSTRACT_STMT(Stmt) #include "clang/AST/StmtNodes.inc" -#define OMP_CLAUSE_CLASS(Enum, Str, Class) \ - LLVM_ATTRIBUTE_NOINLINE \ - OMPClause *Transform ## Class(Class *S); -#include "llvm/Frontend/OpenMP/OMPKinds.def" +#define GEN_CLANG_CLAUSE_CLASS +#define CLAUSE_CLASS(Enum, Str, Class) \ + LLVM_ATTRIBUTE_NOINLINE \ + OMPClause *Transform##Class(Class *S); +#include "llvm/Frontend/OpenMP/OMP.inc" /// Build a new qualified type given its unqualified type and type location. /// @@ -1304,7 +1306,7 @@ public: return SemaRef.ActOnLabelStmt(IdentLoc, L, ColonLoc, SubStmt); } - /// Build a new label statement. + /// Build a new attributed statement. /// /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. @@ -1319,19 +1321,23 @@ public: /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. StmtResult RebuildIfStmt(SourceLocation IfLoc, bool IsConstexpr, - Sema::ConditionResult Cond, Stmt *Init, Stmt *Then, + SourceLocation LParenLoc, Sema::ConditionResult Cond, + SourceLocation RParenLoc, Stmt *Init, Stmt *Then, SourceLocation ElseLoc, Stmt *Else) { - return getSema().ActOnIfStmt(IfLoc, IsConstexpr, Init, Cond, Then, - ElseLoc, Else); + return getSema().ActOnIfStmt(IfLoc, IsConstexpr, LParenLoc, Init, Cond, + RParenLoc, Then, ElseLoc, Else); } /// Start building a new switch statement. /// /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. - StmtResult RebuildSwitchStmtStart(SourceLocation SwitchLoc, Stmt *Init, - Sema::ConditionResult Cond) { - return getSema().ActOnStartOfSwitchStmt(SwitchLoc, Init, Cond); + StmtResult RebuildSwitchStmtStart(SourceLocation SwitchLoc, + SourceLocation LParenLoc, Stmt *Init, + Sema::ConditionResult Cond, + SourceLocation RParenLoc) { + return getSema().ActOnStartOfSwitchStmt(SwitchLoc, LParenLoc, Init, Cond, + RParenLoc); } /// Attach the body to the switch statement. @@ -2006,26 +2012,32 @@ public: /// /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. - OMPClause *RebuildOMPToClause(ArrayRef<Expr *> VarList, - CXXScopeSpec &MapperIdScopeSpec, - DeclarationNameInfo &MapperId, - const OMPVarListLocTy &Locs, - ArrayRef<Expr *> UnresolvedMappers) { - return getSema().ActOnOpenMPToClause(VarList, MapperIdScopeSpec, MapperId, - Locs, UnresolvedMappers); + OMPClause * + RebuildOMPToClause(ArrayRef<OpenMPMotionModifierKind> MotionModifiers, + ArrayRef<SourceLocation> MotionModifiersLoc, + CXXScopeSpec &MapperIdScopeSpec, + DeclarationNameInfo &MapperId, SourceLocation ColonLoc, + ArrayRef<Expr *> VarList, const OMPVarListLocTy &Locs, + ArrayRef<Expr *> UnresolvedMappers) { + return getSema().ActOnOpenMPToClause(MotionModifiers, MotionModifiersLoc, + MapperIdScopeSpec, MapperId, ColonLoc, + VarList, Locs, UnresolvedMappers); } /// Build a new OpenMP 'from' clause. /// /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. - OMPClause *RebuildOMPFromClause(ArrayRef<Expr *> VarList, - CXXScopeSpec &MapperIdScopeSpec, - DeclarationNameInfo &MapperId, - const OMPVarListLocTy &Locs, - ArrayRef<Expr *> UnresolvedMappers) { - return getSema().ActOnOpenMPFromClause(VarList, MapperIdScopeSpec, MapperId, - Locs, UnresolvedMappers); + OMPClause * + RebuildOMPFromClause(ArrayRef<OpenMPMotionModifierKind> MotionModifiers, + ArrayRef<SourceLocation> MotionModifiersLoc, + CXXScopeSpec &MapperIdScopeSpec, + DeclarationNameInfo &MapperId, SourceLocation ColonLoc, + ArrayRef<Expr *> VarList, const OMPVarListLocTy &Locs, + ArrayRef<Expr *> UnresolvedMappers) { + return getSema().ActOnOpenMPFromClause( + MotionModifiers, MotionModifiersLoc, MapperIdScopeSpec, MapperId, + ColonLoc, VarList, Locs, UnresolvedMappers); } /// Build a new OpenMP 'use_device_ptr' clause. @@ -3500,7 +3512,8 @@ public: // Build the CallExpr ExprResult TheCall = CallExpr::Create( SemaRef.Context, Callee, SubExprs, Builtin->getCallResultType(), - Expr::getValueKindForType(Builtin->getReturnType()), RParenLoc); + Expr::getValueKindForType(Builtin->getReturnType()), RParenLoc, + FPOptionsOverride()); // Type-check the __builtin_shufflevector expression. return SemaRef.SemaBuiltinShuffleVector(cast<CallExpr>(TheCall.get())); @@ -3534,12 +3547,12 @@ public: } case TemplateArgument::Template: - return TemplateArgumentLoc(TemplateArgument( - Pattern.getArgument().getAsTemplate(), - NumExpansions), - Pattern.getTemplateQualifierLoc(), - Pattern.getTemplateNameLoc(), - EllipsisLoc); + return TemplateArgumentLoc( + SemaRef.Context, + TemplateArgument(Pattern.getArgument().getAsTemplate(), + NumExpansions), + Pattern.getTemplateQualifierLoc(), Pattern.getTemplateNameLoc(), + EllipsisLoc); case TemplateArgument::Null: case TemplateArgument::Integral: @@ -3576,13 +3589,15 @@ public: /// /// By default, performs semantic analysis in order to build a new fold /// expression. - ExprResult RebuildCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS, + ExprResult RebuildCXXFoldExpr(UnresolvedLookupExpr *ULE, + SourceLocation LParenLoc, Expr *LHS, BinaryOperatorKind Operator, SourceLocation EllipsisLoc, Expr *RHS, SourceLocation RParenLoc, Optional<unsigned> NumExpansions) { - return getSema().BuildCXXFoldExpr(LParenLoc, LHS, Operator, EllipsisLoc, - RHS, RParenLoc, NumExpansions); + return getSema().BuildCXXFoldExpr(ULE, LParenLoc, LHS, Operator, + EllipsisLoc, RHS, RParenLoc, + NumExpansions); } /// Build an empty C++1z fold-expression with the given operator. @@ -3609,8 +3624,8 @@ public: } ExprResult RebuildRecoveryExpr(SourceLocation BeginLoc, SourceLocation EndLoc, - ArrayRef<Expr *> SubExprs) { - return getSema().CreateRecoveryExpr(BeginLoc, EndLoc, SubExprs); + ArrayRef<Expr *> SubExprs, QualType Type) { + return getSema().CreateRecoveryExpr(BeginLoc, EndLoc, SubExprs, Type); } private: @@ -3677,10 +3692,11 @@ OMPClause *TreeTransform<Derived>::TransformOMPClause(OMPClause *S) { switch (S->getClauseKind()) { default: break; // Transform individual clause nodes -#define OMP_CLAUSE_CLASS(Enum, Str, Class) \ +#define GEN_CLANG_CLAUSE_CLASS +#define CLAUSE_CLASS(Enum, Str, Class) \ case Enum: \ - return getDerived().Transform ## Class(cast<Class>(S)); -#include "llvm/Frontend/OpenMP/OMPKinds.def" + return getDerived().Transform##Class(cast<Class>(S)); +#include "llvm/Frontend/OpenMP/OMP.inc" } return S; @@ -4275,8 +4291,8 @@ bool TreeTransform<Derived>::TransformTemplateArgument( if (Template.isNull()) return true; - Output = TemplateArgumentLoc(TemplateArgument(Template), QualifierLoc, - Input.getTemplateNameLoc()); + Output = TemplateArgumentLoc(SemaRef.Context, TemplateArgument(Template), + QualifierLoc, Input.getTemplateNameLoc()); return false; } @@ -5162,7 +5178,7 @@ template <typename Derived> QualType TreeTransform<Derived>::TransformDependentVectorType( TypeLocBuilder &TLB, DependentVectorTypeLoc TL) { const DependentVectorType *T = TL.getTypePtr(); - QualType ElementType = getDerived().TransformType(T->getElementType()); + QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc()); if (ElementType.isNull()) return QualType(); @@ -5203,7 +5219,7 @@ QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType( const DependentSizedExtVectorType *T = TL.getTypePtr(); // FIXME: ext vector locs should be nested - QualType ElementType = getDerived().TransformType(T->getElementType()); + QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc()); if (ElementType.isNull()) return QualType(); @@ -5370,7 +5386,7 @@ template <typename Derived> QualType TreeTransform<Derived>::TransformVectorType(TypeLocBuilder &TLB, VectorTypeLoc TL) { const VectorType *T = TL.getTypePtr(); - QualType ElementType = getDerived().TransformType(T->getElementType()); + QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc()); if (ElementType.isNull()) return QualType(); @@ -5393,7 +5409,7 @@ template<typename Derived> QualType TreeTransform<Derived>::TransformExtVectorType(TypeLocBuilder &TLB, ExtVectorTypeLoc TL) { const VectorType *T = TL.getTypePtr(); - QualType ElementType = getDerived().TransformType(T->getElementType()); + QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc()); if (ElementType.isNull()) return QualType(); @@ -5465,6 +5481,7 @@ ParmVarDecl *TreeTransform<Derived>::TransformFunctionTypeParam( /* DefArg */ nullptr); newParm->setScopeInfo(OldParm->getFunctionScopeDepth(), OldParm->getFunctionScopeIndex() + indexAdjustment); + transformedLocalDecl(OldParm, {newParm}); return newParm; } @@ -7280,9 +7297,9 @@ TreeTransform<Derived>::TransformIfStmt(IfStmt *S) { Else.get() == S->getElse()) return S; - return getDerived().RebuildIfStmt(S->getIfLoc(), S->isConstexpr(), Cond, - Init.get(), Then.get(), S->getElseLoc(), - Else.get()); + return getDerived().RebuildIfStmt( + S->getIfLoc(), S->isConstexpr(), S->getLParenLoc(), Cond, + S->getRParenLoc(), Init.get(), Then.get(), S->getElseLoc(), Else.get()); } template<typename Derived> @@ -7301,8 +7318,9 @@ TreeTransform<Derived>::TransformSwitchStmt(SwitchStmt *S) { return StmtError(); // Rebuild the switch statement. - StmtResult Switch - = getDerived().RebuildSwitchStmtStart(S->getSwitchLoc(), Init.get(), Cond); + StmtResult Switch = + getDerived().RebuildSwitchStmtStart(S->getSwitchLoc(), S->getLParenLoc(), + Init.get(), Cond, S->getRParenLoc()); if (Switch.isInvalid()) return StmtError(); @@ -8323,7 +8341,14 @@ StmtResult TreeTransform<Derived>::TransformOMPExecutableDirective( StmtResult Body; { Sema::CompoundScopeRAII CompoundScope(getSema()); - Stmt *CS = D->getInnermostCapturedStmt()->getCapturedStmt(); + Stmt *CS; + if (D->getDirectiveKind() == OMPD_atomic || + D->getDirectiveKind() == OMPD_critical || + D->getDirectiveKind() == OMPD_section || + D->getDirectiveKind() == OMPD_master) + CS = D->getAssociatedStmt(); + else + CS = D->getInnermostCapturedStmt()->getCapturedStmt(); Body = getDerived().TransformStmt(CS); } AssociatedStmt = @@ -9737,8 +9762,9 @@ OMPClause *TreeTransform<Derived>::TransformOMPToClause(OMPToClause *C) { if (transformOMPMappableExprListClause<Derived, OMPToClause>( *this, C, Vars, MapperIdScopeSpec, MapperIdInfo, UnresolvedMappers)) return nullptr; - return getDerived().RebuildOMPToClause(Vars, MapperIdScopeSpec, MapperIdInfo, - Locs, UnresolvedMappers); + return getDerived().RebuildOMPToClause( + C->getMotionModifiers(), C->getMotionModifiersLoc(), MapperIdScopeSpec, + MapperIdInfo, C->getColonLoc(), Vars, Locs, UnresolvedMappers); } template <typename Derived> @@ -9752,7 +9778,8 @@ OMPClause *TreeTransform<Derived>::TransformOMPFromClause(OMPFromClause *C) { *this, C, Vars, MapperIdScopeSpec, MapperIdInfo, UnresolvedMappers)) return nullptr; return getDerived().RebuildOMPFromClause( - Vars, MapperIdScopeSpec, MapperIdInfo, Locs, UnresolvedMappers); + C->getMotionModifiers(), C->getMotionModifiersLoc(), MapperIdScopeSpec, + MapperIdInfo, C->getColonLoc(), Vars, Locs, UnresolvedMappers); } template <typename Derived> @@ -10198,7 +10225,7 @@ ExprResult TreeTransform<Derived>::TransformRecoveryExpr(RecoveryExpr *E) { if (!getDerived().AlwaysRebuild() && !Changed) return E; return getDerived().RebuildRecoveryExpr(E->getBeginLoc(), E->getEndLoc(), - Children); + Children, E->getType()); } template<typename Derived> @@ -10466,6 +10493,15 @@ TreeTransform<Derived>::TransformCallExpr(CallExpr *E) { // FIXME: Wrong source location information for the '('. SourceLocation FakeLParenLoc = ((Expr *)Callee.get())->getSourceRange().getBegin(); + + Sema::FPFeaturesStateRAII FPFeaturesState(getSema()); + if (E->hasStoredFPFeatures()) { + FPOptionsOverride NewOverrides = E->getFPFeatures(); + getSema().CurFPFeatures = + NewOverrides.applyOverrides(getSema().getLangOpts()); + getSema().FpPragmaStack.CurrentValue = NewOverrides; + } + return getDerived().RebuildCallExpr(Callee.get(), FakeLParenLoc, Args, E->getRParenLoc()); @@ -10580,7 +10616,7 @@ TreeTransform<Derived>::TransformBinaryOperator(BinaryOperator *E) { FPOptionsOverride NewOverrides(E->getFPFeatures(getSema().getLangOpts())); getSema().CurFPFeatures = NewOverrides.applyOverrides(getSema().getLangOpts()); - getSema().FpPragmaStack.CurrentValue = NewOverrides.getAsOpaqueInt(); + getSema().FpPragmaStack.CurrentValue = NewOverrides; return getDerived().RebuildBinaryOperator(E->getOperatorLoc(), E->getOpcode(), LHS.get(), RHS.get()); } @@ -10637,7 +10673,7 @@ TreeTransform<Derived>::TransformCompoundAssignOperator( FPOptionsOverride NewOverrides(E->getFPFeatures(getSema().getLangOpts())); getSema().CurFPFeatures = NewOverrides.applyOverrides(getSema().getLangOpts()); - getSema().FpPragmaStack.CurrentValue = NewOverrides.getAsOpaqueInt(); + getSema().FpPragmaStack.CurrentValue = NewOverrides; return getDerived().TransformBinaryOperator(E); } @@ -11115,7 +11151,7 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) { FPOptionsOverride NewOverrides(E->getFPFeatures()); getSema().CurFPFeatures = NewOverrides.applyOverrides(getSema().getLangOpts()); - getSema().FpPragmaStack.CurrentValue = NewOverrides.getAsOpaqueInt(); + getSema().FpPragmaStack.CurrentValue = NewOverrides; return getDerived().RebuildCXXOperatorCallExpr(E->getOperator(), E->getOperatorLoc(), @@ -12711,12 +12747,12 @@ TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr( bool ArgumentChanged = false; SmallVector<Expr*, 8> Args; - Args.reserve(E->arg_size()); + Args.reserve(E->getNumArgs()); { EnterExpressionEvaluationContext Context( getSema(), EnterExpressionEvaluationContext::InitList, E->isListInitialization()); - if (getDerived().TransformExprs(E->arg_begin(), E->arg_size(), true, Args, + if (getDerived().TransformExprs(E->arg_begin(), E->getNumArgs(), true, Args, &ArgumentChanged)) return ExprError(); } @@ -13110,6 +13146,14 @@ TreeTransform<Derived>::TransformMaterializeTemporaryExpr( template<typename Derived> ExprResult TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) { + UnresolvedLookupExpr *Callee = nullptr; + if (Expr *OldCallee = E->getCallee()) { + ExprResult CalleeResult = getDerived().TransformExpr(OldCallee); + if (CalleeResult.isInvalid()) + return ExprError(); + Callee = cast<UnresolvedLookupExpr>(CalleeResult.get()); + } + Expr *Pattern = E->getPattern(); SmallVector<UnexpandedParameterPack, 2> Unexpanded; @@ -13149,8 +13193,20 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) { return E; return getDerived().RebuildCXXFoldExpr( - E->getBeginLoc(), LHS.get(), E->getOperator(), E->getEllipsisLoc(), - RHS.get(), E->getEndLoc(), NumExpansions); + Callee, E->getBeginLoc(), LHS.get(), E->getOperator(), + E->getEllipsisLoc(), RHS.get(), E->getEndLoc(), NumExpansions); + } + + // Formally a fold expression expands to nested parenthesized expressions. + // Enforce this limit to avoid creating trees so deep we can't safely traverse + // them. + if (NumExpansions && SemaRef.getLangOpts().BracketDepth < NumExpansions) { + SemaRef.Diag(E->getEllipsisLoc(), + clang::diag::err_fold_expression_limit_exceeded) + << *NumExpansions << SemaRef.getLangOpts().BracketDepth + << E->getSourceRange(); + SemaRef.Diag(E->getEllipsisLoc(), diag::note_bracket_depth); + return ExprError(); } // The transform has determined that we should perform an elementwise @@ -13170,8 +13226,8 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) { return true; Result = getDerived().RebuildCXXFoldExpr( - E->getBeginLoc(), Out.get(), E->getOperator(), E->getEllipsisLoc(), - Result.get(), E->getEndLoc(), OrigNumExpansions); + Callee, E->getBeginLoc(), Out.get(), E->getOperator(), + E->getEllipsisLoc(), Result.get(), E->getEndLoc(), OrigNumExpansions); if (Result.isInvalid()) return true; } @@ -13186,16 +13242,21 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) { if (Out.get()->containsUnexpandedParameterPack()) { // We still have a pack; retain a pack expansion for this slice. Result = getDerived().RebuildCXXFoldExpr( - E->getBeginLoc(), LeftFold ? Result.get() : Out.get(), + Callee, E->getBeginLoc(), LeftFold ? Result.get() : Out.get(), E->getOperator(), E->getEllipsisLoc(), LeftFold ? Out.get() : Result.get(), E->getEndLoc(), OrigNumExpansions); } else if (Result.isUsable()) { // We've got down to a single element; build a binary operator. - Result = getDerived().RebuildBinaryOperator( - E->getEllipsisLoc(), E->getOperator(), - LeftFold ? Result.get() : Out.get(), - LeftFold ? Out.get() : Result.get()); + Expr *LHS = LeftFold ? Result.get() : Out.get(); + Expr *RHS = LeftFold ? Out.get() : Result.get(); + if (Callee) + Result = getDerived().RebuildCXXOperatorCallExpr( + BinaryOperator::getOverloadedOperator(E->getOperator()), + E->getEllipsisLoc(), Callee, LHS, RHS); + else + Result = getDerived().RebuildBinaryOperator(E->getEllipsisLoc(), + E->getOperator(), LHS, RHS); } else Result = Out; @@ -13213,8 +13274,8 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) { return true; Result = getDerived().RebuildCXXFoldExpr( - E->getBeginLoc(), Result.get(), E->getOperator(), E->getEllipsisLoc(), - Out.get(), E->getEndLoc(), OrigNumExpansions); + Callee, E->getBeginLoc(), Result.get(), E->getOperator(), + E->getEllipsisLoc(), Out.get(), E->getEndLoc(), OrigNumExpansions); if (Result.isInvalid()) return true; } diff --git a/clang/lib/Sema/UsedDeclVisitor.h b/clang/lib/Sema/UsedDeclVisitor.h index d207e07f451a..c33d30478e2a 100644 --- a/clang/lib/Sema/UsedDeclVisitor.h +++ b/clang/lib/Sema/UsedDeclVisitor.h @@ -67,10 +67,13 @@ public: void VisitCXXDeleteExpr(CXXDeleteExpr *E) { if (E->getOperatorDelete()) asImpl().visitUsedDecl(E->getBeginLoc(), E->getOperatorDelete()); - QualType Destroyed = S.Context.getBaseElementType(E->getDestroyedType()); - if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) { - CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl()); - asImpl().visitUsedDecl(E->getBeginLoc(), S.LookupDestructor(Record)); + QualType DestroyedOrNull = E->getDestroyedType(); + if (!DestroyedOrNull.isNull()) { + QualType Destroyed = S.Context.getBaseElementType(DestroyedOrNull); + if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) { + CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl()); + asImpl().visitUsedDecl(E->getBeginLoc(), S.LookupDestructor(Record)); + } } Inherited::VisitCXXDeleteExpr(E); |