diff options
Diffstat (limited to 'lib/Sema')
43 files changed, 10895 insertions, 7446 deletions
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index ed240f4ed292b..c818d40c77712 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -114,7 +114,7 @@ static void CheckUnreachable(Sema &S, AnalysisDeclContext &AC) { // // Note that this is also a performance optimization. Analyzing // headers many times can be expensive. - if (!S.getSourceManager().isInMainFile(AC.getDecl()->getLocStart())) + if (!S.getSourceManager().isInMainFile(AC.getDecl()->getBeginLoc())) return; UnreachableCodeHandler UC(S); @@ -252,7 +252,7 @@ static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD, // Emit diagnostic if a recursive function call is detected for all paths. if (checkForRecursiveFunctionCall(FD, cfg)) - S.Diag(Body->getLocStart(), diag::warn_infinite_recursive_function); + S.Diag(Body->getBeginLoc(), diag::warn_infinite_recursive_function); } //===----------------------------------------------------------------------===// @@ -651,7 +651,7 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, // Short circuit for compilation speed. if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn)) return; - SourceLocation LBrace = Body->getLocStart(), RBrace = Body->getLocEnd(); + SourceLocation LBrace = Body->getBeginLoc(), RBrace = Body->getEndLoc(); auto EmitDiag = [&](SourceLocation Loc, unsigned DiagID) { if (IsCoroutine) S.Diag(Loc, DiagID) << FSI->CoroutinePromise->getType(); @@ -748,10 +748,10 @@ static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) { return false; // Don't suggest a fixit inside macros. - if (VD->getLocEnd().isMacroID()) + if (VD->getEndLoc().isMacroID()) return false; - SourceLocation Loc = S.getLocForEndOfToken(VD->getLocEnd()); + SourceLocation Loc = S.getLocForEndOfToken(VD->getEndLoc()); // Suggest possible initialization (if any). std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc); @@ -771,19 +771,17 @@ static void CreateIfFixit(Sema &S, const Stmt *If, const Stmt *Then, if (CondVal) { // If condition is always true, remove all but the 'then'. Fixit1 = FixItHint::CreateRemoval( - CharSourceRange::getCharRange(If->getLocStart(), - Then->getLocStart())); + CharSourceRange::getCharRange(If->getBeginLoc(), Then->getBeginLoc())); if (Else) { - SourceLocation ElseKwLoc = S.getLocForEndOfToken(Then->getLocEnd()); - Fixit2 = FixItHint::CreateRemoval( - SourceRange(ElseKwLoc, Else->getLocEnd())); + SourceLocation ElseKwLoc = S.getLocForEndOfToken(Then->getEndLoc()); + Fixit2 = + FixItHint::CreateRemoval(SourceRange(ElseKwLoc, Else->getEndLoc())); } } else { // If condition is always false, remove all but the 'else'. if (Else) - Fixit1 = FixItHint::CreateRemoval( - CharSourceRange::getCharRange(If->getLocStart(), - Else->getLocStart())); + Fixit1 = FixItHint::CreateRemoval(CharSourceRange::getCharRange( + If->getBeginLoc(), Else->getBeginLoc())); else Fixit1 = FixItHint::CreateRemoval(If->getSourceRange()); } @@ -797,7 +795,7 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use, switch (Use.getKind()) { case UninitUse::Always: - S.Diag(Use.getUser()->getLocStart(), diag::warn_uninit_var) + S.Diag(Use.getUser()->getBeginLoc(), diag::warn_uninit_var) << VD->getDeclName() << IsCapturedByBlock << Use.getUser()->getSourceRange(); return; @@ -809,8 +807,8 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use, << (Use.getKind() == UninitUse::AfterDecl ? 4 : 5) << const_cast<DeclContext*>(VD->getLexicalDeclContext()) << VD->getSourceRange(); - S.Diag(Use.getUser()->getLocStart(), diag::note_uninit_var_use) - << IsCapturedByBlock << Use.getUser()->getSourceRange(); + S.Diag(Use.getUser()->getBeginLoc(), diag::note_uninit_var_use) + << IsCapturedByBlock << Use.getUser()->getSourceRange(); return; case UninitUse::Maybe: @@ -880,8 +878,8 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use, if ((BO->getOpcode() == BO_LAnd && I->Output) || (BO->getOpcode() == BO_LOr && !I->Output)) // true && y -> y, false || y -> y. - Fixit1 = FixItHint::CreateRemoval(SourceRange(BO->getLocStart(), - BO->getOperatorLoc())); + Fixit1 = FixItHint::CreateRemoval( + SourceRange(BO->getBeginLoc(), BO->getOperatorLoc())); else // false && y -> false, true || y -> true. Fixit1 = FixItHint::CreateReplacement(BO->getSourceRange(), FixitStr); @@ -943,8 +941,8 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use, S.Diag(Range.getBegin(), diag::warn_sometimes_uninit_var) << VD->getDeclName() << IsCapturedByBlock << DiagKind << Str << I->Output << Range; - S.Diag(User->getLocStart(), diag::note_uninit_var_use) - << IsCapturedByBlock << User->getSourceRange(); + S.Diag(User->getBeginLoc(), diag::note_uninit_var_use) + << IsCapturedByBlock << User->getSourceRange(); if (RemoveDiagKind != -1) S.Diag(Fixit1.RemoveRange.getBegin(), diag::note_uninit_fixit_remove_cond) << RemoveDiagKind << Str << I->Output << Fixit1 << Fixit2; @@ -953,7 +951,7 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use, } if (!Diagnosed) - S.Diag(Use.getUser()->getLocStart(), diag::warn_maybe_uninit_var) + S.Diag(Use.getUser()->getBeginLoc(), diag::warn_maybe_uninit_var) << VD->getDeclName() << IsCapturedByBlock << Use.getUser()->getSourceRange(); } @@ -985,9 +983,8 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, ContainsReference CR(S.Context, DRE); CR.Visit(Initializer); if (CR.doesContainReference()) { - S.Diag(DRE->getLocStart(), - diag::warn_uninit_self_reference_in_init) - << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange(); + S.Diag(DRE->getBeginLoc(), diag::warn_uninit_self_reference_in_init) + << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange(); return true; } } @@ -996,9 +993,9 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, } else { const BlockExpr *BE = cast<BlockExpr>(Use.getUser()); if (VD->getType()->isBlockPointerType() && !VD->hasAttr<BlocksAttr>()) - S.Diag(BE->getLocStart(), + S.Diag(BE->getBeginLoc(), diag::warn_uninit_byref_blockvar_captured_by_block) - << VD->getDeclName(); + << VD->getDeclName(); else DiagUninitUse(S, VD, Use, true); } @@ -1007,8 +1004,8 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, // the initializer of that declaration & we didn't already suggest // an initialization fixit. if (!SuggestInitializationFixit(S, VD)) - S.Diag(VD->getLocStart(), diag::note_var_declared_here) - << VD->getDeclName(); + S.Diag(VD->getBeginLoc(), diag::note_var_declared_here) + << VD->getDeclName(); return true; } @@ -1098,7 +1095,7 @@ namespace { // attribute in template instantiations as it may not be // unreachable in all instantiations of the template. if (!IsTemplateInstantiation) - S.Diag(AS->getLocStart(), + S.Diag(AS->getBeginLoc(), diag::warn_fallthrough_attr_unreachable); markFallthroughVisited(AS); ++AnnotatedCnt; @@ -1156,7 +1153,12 @@ namespace { bool TraverseDecl(Decl *D) { return true; } // We analyze lambda bodies separately. Skip them here. - bool TraverseLambdaBody(LambdaExpr *LE) { return true; } + bool TraverseLambdaExpr(LambdaExpr *LE) { + // Traverse the captures, but not the body. + for (const auto &C : zip(LE->captures(), LE->capture_inits())) + TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C)); + return true; + } private: @@ -1266,12 +1268,12 @@ static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, IsTemplateInstantiation)) continue; - S.Diag(Label->getLocStart(), - PerFunction ? diag::warn_unannotated_fallthrough_per_function - : diag::warn_unannotated_fallthrough); + S.Diag(Label->getBeginLoc(), + PerFunction ? diag::warn_unannotated_fallthrough_per_function + : diag::warn_unannotated_fallthrough); if (!AnnotatedCnt) { - SourceLocation L = Label->getLocStart(); + SourceLocation L = Label->getBeginLoc(); if (L.isMacroID()) continue; if (S.getLangOpts().CPlusPlus11) { @@ -1297,7 +1299,7 @@ static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, } for (const auto *F : FM.getFallthroughStmts()) - S.Diag(F->getLocStart(), diag::err_fallthrough_attr_invalid_placement); + S.Diag(F->getBeginLoc(), diag::err_fallthrough_attr_invalid_placement); } static bool isInLoop(const ASTContext &Ctx, const ParentMap &PM, @@ -1312,11 +1314,10 @@ static bool isInLoop(const ASTContext &Ctx, const ParentMap &PM, case Stmt::ObjCForCollectionStmtClass: return true; case Stmt::DoStmtClass: { - const Expr *Cond = cast<DoStmt>(S)->getCond(); - llvm::APSInt Val; - if (!Cond->EvaluateAsInt(Val, Ctx)) + Expr::EvalResult Result; + if (!cast<DoStmt>(S)->getCond()->EvaluateAsInt(Result, Ctx)) return true; - return Val.getBoolValue(); + return Result.Val.getInt().getBoolValue(); } default: break; @@ -1394,11 +1395,11 @@ static void diagnoseRepeatedUseOfWeak(Sema &S, // Sort by first use so that we emit the warnings in a deterministic order. SourceManager &SM = S.getSourceManager(); - llvm::sort(UsesByStmt.begin(), UsesByStmt.end(), + llvm::sort(UsesByStmt, [&SM](const StmtUsesPair &LHS, const StmtUsesPair &RHS) { - return SM.isBeforeInTranslationUnit(LHS.first->getLocStart(), - RHS.first->getLocStart()); - }); + return SM.isBeforeInTranslationUnit(LHS.first->getBeginLoc(), + RHS.first->getBeginLoc()); + }); // Classify the current code body for better warning text. // This enum should stay in sync with the cases in @@ -1467,15 +1468,15 @@ static void diagnoseRepeatedUseOfWeak(Sema &S, continue; // Show the first time the object was read. - S.Diag(FirstRead->getLocStart(), DiagKind) - << int(ObjectKind) << KeyProp << int(FunctionKind) - << FirstRead->getSourceRange(); + S.Diag(FirstRead->getBeginLoc(), DiagKind) + << int(ObjectKind) << KeyProp << int(FunctionKind) + << FirstRead->getSourceRange(); // Print all the other accesses as notes. for (const auto &Use : Uses) { if (Use.getUseExpr() == FirstRead) continue; - S.Diag(Use.getUseExpr()->getLocStart(), + S.Diag(Use.getUseExpr()->getBeginLoc(), diag::note_arc_weak_also_accessed_here) << Use.getUseExpr()->getSourceRange(); } @@ -1538,7 +1539,7 @@ public: // Prefer a more confident report over a less confident one. if (a.getKind() != b.getKind()) return a.getKind() > b.getKind(); - return a.getUser()->getLocStart() < b.getUser()->getLocStart(); + return a.getUser()->getBeginLoc() < b.getUser()->getBeginLoc(); }); for (const auto &U : *vec) { @@ -1605,7 +1606,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler { OptionalNotes getNotes() const { if (Verbose && CurrentFunction) { - PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(), + PartialDiagnosticAt FNote(CurrentFunction->getBody()->getBeginLoc(), S.PDiag(diag::note_thread_warning_in_fun) << CurrentFunction); return OptionalNotes(1, FNote); @@ -1616,7 +1617,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler { OptionalNotes getNotes(const PartialDiagnosticAt &Note) const { OptionalNotes ONS(1, Note); if (Verbose && CurrentFunction) { - PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(), + PartialDiagnosticAt FNote(CurrentFunction->getBody()->getBeginLoc(), S.PDiag(diag::note_thread_warning_in_fun) << CurrentFunction); ONS.push_back(std::move(FNote)); @@ -1630,7 +1631,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler { ONS.push_back(Note1); ONS.push_back(Note2); if (Verbose && CurrentFunction) { - PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(), + PartialDiagnosticAt FNote(CurrentFunction->getBody()->getBeginLoc(), S.PDiag(diag::note_thread_warning_in_fun) << CurrentFunction); ONS.push_back(std::move(FNote)); @@ -2068,11 +2069,11 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, } // Install the logical handler for -Wtautological-overlap-compare - std::unique_ptr<LogicalErrorHandler> LEH; + llvm::Optional<LogicalErrorHandler> LEH; if (!Diags.isIgnored(diag::warn_tautological_overlap_comparison, - D->getLocStart())) { - LEH.reset(new LogicalErrorHandler(S)); - AC.getCFGBuildOptions().Observer = LEH.get(); + D->getBeginLoc())) { + LEH.emplace(S); + AC.getCFGBuildOptions().Observer = &*LEH; } // Emit delayed diagnostics. @@ -2145,11 +2146,11 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, // Check for thread safety violations if (P.enableThreadSafetyAnalysis) { SourceLocation FL = AC.getDecl()->getLocation(); - SourceLocation FEL = AC.getDecl()->getLocEnd(); + SourceLocation FEL = AC.getDecl()->getEndLoc(); threadSafety::ThreadSafetyReporter Reporter(S, FL, FEL); - if (!Diags.isIgnored(diag::warn_thread_safety_beta, D->getLocStart())) + if (!Diags.isIgnored(diag::warn_thread_safety_beta, D->getBeginLoc())) Reporter.setIssueBetaWarnings(true); - if (!Diags.isIgnored(diag::warn_thread_safety_verbose, D->getLocStart())) + if (!Diags.isIgnored(diag::warn_thread_safety_verbose, D->getBeginLoc())) Reporter.setVerbose(true); threadSafety::runThreadSafetyAnalysis(AC, Reporter, @@ -2164,9 +2165,9 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, Analyzer.run(AC); } - if (!Diags.isIgnored(diag::warn_uninit_var, D->getLocStart()) || - !Diags.isIgnored(diag::warn_sometimes_uninit_var, D->getLocStart()) || - !Diags.isIgnored(diag::warn_maybe_uninit_var, D->getLocStart())) { + if (!Diags.isIgnored(diag::warn_uninit_var, D->getBeginLoc()) || + !Diags.isIgnored(diag::warn_sometimes_uninit_var, D->getBeginLoc()) || + !Diags.isIgnored(diag::warn_maybe_uninit_var, D->getBeginLoc())) { if (CFG *cfg = AC.getCFG()) { UninitValsDiagReporter reporter(S); UninitVariablesAnalysisStats stats; @@ -2189,29 +2190,29 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, } bool FallThroughDiagFull = - !Diags.isIgnored(diag::warn_unannotated_fallthrough, D->getLocStart()); + !Diags.isIgnored(diag::warn_unannotated_fallthrough, D->getBeginLoc()); bool FallThroughDiagPerFunction = !Diags.isIgnored( - diag::warn_unannotated_fallthrough_per_function, D->getLocStart()); + diag::warn_unannotated_fallthrough_per_function, D->getBeginLoc()); if (FallThroughDiagFull || FallThroughDiagPerFunction || fscope->HasFallthroughStmt) { DiagnoseSwitchLabelsFallthrough(S, AC, !FallThroughDiagFull); } if (S.getLangOpts().ObjCWeak && - !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, D->getLocStart())) + !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, D->getBeginLoc())) diagnoseRepeatedUseOfWeak(S, fscope, D, AC.getParentMap()); // Check for infinite self-recursion in functions if (!Diags.isIgnored(diag::warn_infinite_recursive_function, - D->getLocStart())) { + D->getBeginLoc())) { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { checkRecursiveFunction(S, FD, Body, AC); } } // Check for throw out of non-throwing function. - if (!Diags.isIgnored(diag::warn_throw_in_noexcept_func, D->getLocStart())) + if (!Diags.isIgnored(diag::warn_throw_in_noexcept_func, D->getBeginLoc())) if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) if (S.getLangOpts().CPlusPlus && isNoexcept(FD)) checkThrowInNonThrowingFunc(S, FD, AC); @@ -2219,7 +2220,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, // If none of the previous checks caused a CFG build, trigger one here // for -Wtautological-overlap-compare if (!Diags.isIgnored(diag::warn_tautological_overlap_comparison, - D->getLocStart())) { + D->getBeginLoc())) { AC.getCFG(); } diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt index 3d21d79f2b850..5f20af01fb7b0 100644 --- a/lib/Sema/CMakeLists.txt +++ b/lib/Sema/CMakeLists.txt @@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS if (MSVC) set_source_files_properties(SemaDeclAttr.cpp PROPERTIES COMPILE_FLAGS /bigobj) set_source_files_properties(SemaExpr.cpp PROPERTIES COMPILE_FLAGS /bigobj) + set_source_files_properties(SemaExprCXX.cpp PROPERTIES COMPILE_FLAGS /bigobj) set_source_files_properties(SemaTemplate.cpp PROPERTIES COMPILE_FLAGS /bigobj) endif() diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp index 8af54b993932f..92e65c4b819b1 100644 --- a/lib/Sema/CodeCompleteConsumer.cpp +++ b/lib/Sema/CodeCompleteConsumer.cpp @@ -20,8 +20,8 @@ #include "clang/AST/DeclarationName.h" #include "clang/AST/Type.h" #include "clang/Basic/IdentifierTable.h" -#include "clang/Sema/Sema.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Sema/Sema.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -29,6 +29,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> @@ -48,6 +49,8 @@ bool CodeCompletionContext::wantConstructorResults() const { case CCC_Expression: case CCC_ObjCMessageReceiver: case CCC_ParenthesizedExpression: + case CCC_Symbol: + case CCC_SymbolOrNewName: return true; case CCC_TopLevel: @@ -64,8 +67,7 @@ bool CodeCompletionContext::wantConstructorResults() const { case CCC_ObjCProtocolName: case CCC_Namespace: case CCC_Type: - case CCC_Name: - case CCC_PotentiallyQualifiedName: + case CCC_NewName: case CCC_MacroName: case CCC_MacroNameUse: case CCC_PreprocessorExpression: @@ -79,6 +81,7 @@ bool CodeCompletionContext::wantConstructorResults() const { case CCC_ObjCClassMessage: case CCC_ObjCInterfaceName: case CCC_ObjCCategoryName: + case CCC_IncludedFile: return false; } @@ -126,10 +129,12 @@ StringRef clang::getCompletionKindString(CodeCompletionContext::Kind Kind) { return "Namespace"; case CCKind::CCC_Type: return "Type"; - case CCKind::CCC_Name: - return "Name"; - case CCKind::CCC_PotentiallyQualifiedName: - return "PotentiallyQualifiedName"; + case CCKind::CCC_NewName: + return "NewName"; + case CCKind::CCC_Symbol: + return "Symbol"; + case CCKind::CCC_SymbolOrNewName: + return "SymbolOrNewName"; case CCKind::CCC_MacroName: return "MacroName"; case CCKind::CCC_MacroNameUse: @@ -154,6 +159,8 @@ StringRef clang::getCompletionKindString(CodeCompletionContext::Kind Kind) { return "ObjCInterfaceName"; case CCKind::CCC_ObjCCategoryName: return "ObjCCategoryName"; + case CCKind::CCC_IncludedFile: + return "IncludedFile"; case CCKind::CCC_Recovery: return "Recovery"; } @@ -265,23 +272,18 @@ CodeCompletionString::Chunk::CreateResultType(const char *ResultType) { return Chunk(CK_ResultType, ResultType); } -CodeCompletionString::Chunk -CodeCompletionString::Chunk::CreateCurrentParameter( - const char *CurrentParameter) { +CodeCompletionString::Chunk CodeCompletionString::Chunk::CreateCurrentParameter( + const char *CurrentParameter) { return Chunk(CK_CurrentParameter, CurrentParameter); } -CodeCompletionString::CodeCompletionString(const Chunk *Chunks, - unsigned NumChunks, - unsigned Priority, - CXAvailabilityKind Availability, - const char **Annotations, - unsigned NumAnnotations, - StringRef ParentName, - const char *BriefComment) - : NumChunks(NumChunks), NumAnnotations(NumAnnotations), - Priority(Priority), Availability(Availability), - ParentName(ParentName), BriefComment(BriefComment) { +CodeCompletionString::CodeCompletionString( + const Chunk *Chunks, unsigned NumChunks, unsigned Priority, + CXAvailabilityKind Availability, const char **Annotations, + unsigned NumAnnotations, StringRef ParentName, const char *BriefComment) + : NumChunks(NumChunks), NumAnnotations(NumAnnotations), Priority(Priority), + Availability(Availability), ParentName(ParentName), + BriefComment(BriefComment) { assert(NumChunks <= 0xffff); assert(NumAnnotations <= 0xffff); @@ -289,7 +291,8 @@ CodeCompletionString::CodeCompletionString(const Chunk *Chunks, for (unsigned I = 0; I != NumChunks; ++I) StoredChunks[I] = Chunks[I]; - const char **StoredAnnotations = reinterpret_cast<const char **>(StoredChunks + NumChunks); + const char **StoredAnnotations = + reinterpret_cast<const char **>(StoredChunks + NumChunks); for (unsigned I = 0; I != NumAnnotations; ++I) StoredAnnotations[I] = Annotations[I]; } @@ -300,7 +303,7 @@ unsigned CodeCompletionString::getAnnotationCount() const { const char *CodeCompletionString::getAnnotation(unsigned AnnotationNr) const { if (AnnotationNr < NumAnnotations) - return reinterpret_cast<const char * const*>(end())[AnnotationNr]; + return reinterpret_cast<const char *const *>(end())[AnnotationNr]; else return nullptr; } @@ -309,27 +312,33 @@ std::string CodeCompletionString::getAsString() const { std::string Result; llvm::raw_string_ostream OS(Result); - for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) { - switch (C->Kind) { - case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break; - case CK_Placeholder: OS << "<#" << C->Text << "#>"; break; - + for (const Chunk &C : *this) { + switch (C.Kind) { + case CK_Optional: + OS << "{#" << C.Optional->getAsString() << "#}"; + break; + case CK_Placeholder: + OS << "<#" << C.Text << "#>"; + break; case CK_Informative: case CK_ResultType: - OS << "[#" << C->Text << "#]"; + OS << "[#" << C.Text << "#]"; + break; + case CK_CurrentParameter: + OS << "<#" << C.Text << "#>"; + break; + default: + OS << C.Text; break; - - case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break; - default: OS << C->Text; break; } } return OS.str(); } const char *CodeCompletionString::getTypedText() const { - for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) - if (C->Kind == CK_TypedText) - return C->Text; + for (const Chunk &C : *this) + if (C.Kind == CK_TypedText) + return C.Text; return nullptr; } @@ -364,7 +373,7 @@ StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) { // Find the interesting names. SmallVector<const DeclContext *, 2> Contexts; while (DC && !DC->isFunctionOrMethod()) { - if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC)) { + if (const auto *ND = dyn_cast<NamedDecl>(DC)) { if (ND->getIdentifier()) Contexts.push_back(DC); } @@ -383,11 +392,11 @@ StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) { OS << "::"; } - const DeclContext *CurDC = Contexts[I-1]; - if (const ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(CurDC)) + const DeclContext *CurDC = Contexts[I - 1]; + if (const auto *CatImpl = dyn_cast<ObjCCategoryImplDecl>(CurDC)) CurDC = CatImpl->getCategoryDecl(); - if (const ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CurDC)) { + if (const auto *Cat = dyn_cast<ObjCCategoryDecl>(CurDC)) { const ObjCInterfaceDecl *Interface = Cat->getClassInterface(); if (!Interface) { // Assign an empty StringRef but with non-null data to distinguish @@ -413,11 +422,9 @@ CodeCompletionString *CodeCompletionBuilder::TakeString() { sizeof(CodeCompletionString) + sizeof(Chunk) * Chunks.size() + sizeof(const char *) * Annotations.size(), alignof(CodeCompletionString)); - CodeCompletionString *Result - = new (Mem) CodeCompletionString(Chunks.data(), Chunks.size(), - Priority, Availability, - Annotations.data(), Annotations.size(), - ParentName, BriefComment); + CodeCompletionString *Result = new (Mem) CodeCompletionString( + Chunks.data(), Chunks.size(), Priority, Availability, Annotations.data(), + Annotations.size(), ParentName, BriefComment); Chunks.clear(); return Result; } @@ -446,8 +453,8 @@ void CodeCompletionBuilder::AddResultTypeChunk(const char *ResultType) { Chunks.push_back(Chunk::CreateResultType(ResultType)); } -void -CodeCompletionBuilder::AddCurrentParameterChunk(const char *CurrentParameter) { +void CodeCompletionBuilder::AddCurrentParameterChunk( + const char *CurrentParameter) { Chunks.push_back(Chunk::CreateCurrentParameter(CurrentParameter)); } @@ -477,8 +484,7 @@ void CodeCompletionBuilder::addBriefComment(StringRef Comment) { //===----------------------------------------------------------------------===// // Code completion overload candidate implementation //===----------------------------------------------------------------------===// -FunctionDecl * -CodeCompleteConsumer::OverloadCandidate::getFunction() const { +FunctionDecl *CodeCompleteConsumer::OverloadCandidate::getFunction() const { if (getKind() == CK_Function) return Function; else if (getKind() == CK_FunctionTemplate) @@ -494,8 +500,9 @@ CodeCompleteConsumer::OverloadCandidate::getFunctionType() const { return Function->getType()->getAs<FunctionType>(); case CK_FunctionTemplate: - return FunctionTemplate->getTemplatedDecl()->getType() - ->getAs<FunctionType>(); + return FunctionTemplate->getTemplatedDecl() + ->getType() + ->getAs<FunctionType>(); case CK_FunctionType: return Type; @@ -510,46 +517,56 @@ CodeCompleteConsumer::OverloadCandidate::getFunctionType() const { CodeCompleteConsumer::~CodeCompleteConsumer() = default; -bool PrintingCodeCompleteConsumer::isResultFilteredOut(StringRef Filter, - CodeCompletionResult Result) { +bool PrintingCodeCompleteConsumer::isResultFilteredOut( + StringRef Filter, CodeCompletionResult Result) { switch (Result.Kind) { case CodeCompletionResult::RK_Declaration: return !(Result.Declaration->getIdentifier() && - Result.Declaration->getIdentifier()->getName().startswith(Filter)); + Result.Declaration->getIdentifier()->getName().startswith(Filter)); case CodeCompletionResult::RK_Keyword: return !StringRef(Result.Keyword).startswith(Filter); case CodeCompletionResult::RK_Macro: return !Result.Macro->getName().startswith(Filter); case CodeCompletionResult::RK_Pattern: - return !StringRef(Result.Pattern->getAsString()).startswith(Filter); + return !(Result.Pattern->getTypedText() && + StringRef(Result.Pattern->getTypedText()).startswith(Filter)); } llvm_unreachable("Unknown code completion result Kind."); } -void -PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, - CodeCompletionContext Context, - CodeCompletionResult *Results, - unsigned NumResults) { +void PrintingCodeCompleteConsumer::ProcessCodeCompleteResults( + Sema &SemaRef, CodeCompletionContext Context, CodeCompletionResult *Results, + unsigned NumResults) { std::stable_sort(Results, Results + NumResults); - StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter(); + if (!Context.getPreferredType().isNull()) + OS << "PREFERRED-TYPE: " << Context.getPreferredType().getAsString() + << "\n"; - // Print the results. + StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter(); + // Print the completions. for (unsigned I = 0; I != NumResults; ++I) { - if(!Filter.empty() && isResultFilteredOut(Filter, Results[I])) + if (!Filter.empty() && isResultFilteredOut(Filter, Results[I])) continue; OS << "COMPLETION: "; switch (Results[I].Kind) { case CodeCompletionResult::RK_Declaration: OS << *Results[I].Declaration; - if (Results[I].Hidden) - OS << " (Hidden)"; - if (CodeCompletionString *CCS - = Results[I].CreateCodeCompletionString(SemaRef, Context, - getAllocator(), - CCTUInfo, - includeBriefComments())) { + { + std::vector<std::string> Tags; + if (Results[I].Hidden) + Tags.push_back("Hidden"); + if (Results[I].InBaseClass) + Tags.push_back("InBase"); + if (Results[I].Availability == + CXAvailabilityKind::CXAvailability_NotAccessible) + Tags.push_back("Inaccessible"); + if (!Tags.empty()) + OS << " (" << llvm::join(Tags, ",") << ")"; + } + if (CodeCompletionString *CCS = Results[I].CreateCodeCompletionString( + SemaRef, Context, getAllocator(), CCTUInfo, + includeBriefComments())) { OS << " : " << CCS->getAsString(); if (const char *BriefComment = CCS->getBriefComment()) OS << " : " << BriefComment; @@ -581,19 +598,16 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, case CodeCompletionResult::RK_Macro: OS << Results[I].Macro->getName(); - if (CodeCompletionString *CCS - = Results[I].CreateCodeCompletionString(SemaRef, Context, - getAllocator(), - CCTUInfo, - includeBriefComments())) { + if (CodeCompletionString *CCS = Results[I].CreateCodeCompletionString( + SemaRef, Context, getAllocator(), CCTUInfo, + includeBriefComments())) { OS << " : " << CCS->getAsString(); } OS << '\n'; break; case CodeCompletionResult::RK_Pattern: - OS << "Pattern : " - << Results[I].Pattern->getAsString() << '\n'; + OS << "Pattern : " << Results[I].Pattern->getAsString() << '\n'; break; } } @@ -618,22 +632,29 @@ static std::string getOverloadAsString(const CodeCompletionString &CCS) { OS << "<#" << C.Text << "#>"; break; - default: OS << C.Text; break; + // FIXME: We can also print optional parameters of an overload. + case CodeCompletionString::CK_Optional: + break; + + default: + OS << C.Text; + break; } } return OS.str(); } -void -PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, - unsigned CurrentArg, - OverloadCandidate *Candidates, - unsigned NumCandidates) { +void PrintingCodeCompleteConsumer::ProcessOverloadCandidates( + Sema &SemaRef, unsigned CurrentArg, OverloadCandidate *Candidates, + unsigned NumCandidates, SourceLocation OpenParLoc) { + OS << "OPENING_PAREN_LOC: "; + OpenParLoc.print(OS, SemaRef.getSourceManager()); + OS << "\n"; + for (unsigned I = 0; I != NumCandidates; ++I) { - if (CodeCompletionString *CCS - = Candidates[I].CreateSignatureString(CurrentArg, SemaRef, - getAllocator(), CCTUInfo, - includeBriefComments())) { + if (CodeCompletionString *CCS = Candidates[I].CreateSignatureString( + CurrentArg, SemaRef, getAllocator(), CCTUInfo, + includeBriefComments())) { OS << "OVERLOAD: " << getOverloadAsString(*CCS) << "\n"; } } @@ -673,7 +694,7 @@ void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) { break; } - if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Declaration)) + if (const auto *Function = dyn_cast<FunctionDecl>(Declaration)) if (Function->isDeleted()) Availability = CXAvailability_NotAvailable; @@ -707,15 +728,15 @@ void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) { /// saved into Saved and the returned StringRef will refer to it. StringRef CodeCompletionResult::getOrderedName(std::string &Saved) const { switch (Kind) { - case RK_Keyword: - return Keyword; - case RK_Pattern: - return Pattern->getTypedText(); - case RK_Macro: - return Macro->getName(); - case RK_Declaration: - // Handle declarations below. - break; + case RK_Keyword: + return Keyword; + case RK_Pattern: + return Pattern->getTypedText(); + case RK_Macro: + return Macro->getName(); + case RK_Declaration: + // Handle declarations below. + break; } DeclarationName Name = Declaration->getDeclName(); @@ -725,8 +746,7 @@ StringRef CodeCompletionResult::getOrderedName(std::string &Saved) const { if (IdentifierInfo *Id = Name.getAsIdentifierInfo()) return Id->getName(); if (Name.isObjCZeroArgSelector()) - if (IdentifierInfo *Id - = Name.getObjCSelector().getIdentifierInfoForSlot(0)) + if (IdentifierInfo *Id = Name.getObjCSelector().getIdentifierInfoForSlot(0)) return Id->getName(); Saved = Name.getAsString(); @@ -743,9 +763,5 @@ bool clang::operator<(const CodeCompletionResult &X, return cmp < 0; // If case-insensitive comparison fails, try case-sensitive comparison. - cmp = XStr.compare(YStr); - if (cmp) - return cmp < 0; - - return false; + return XStr.compare(YStr) < 0; } diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp index b22eea2b3642a..8b002dac1343e 100644 --- a/lib/Sema/DeclSpec.cpp +++ b/lib/Sema/DeclSpec.cpp @@ -156,14 +156,8 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, unsigned NumParams, SourceLocation EllipsisLoc, SourceLocation RParenLoc, - unsigned TypeQuals, bool RefQualifierIsLvalueRef, SourceLocation RefQualifierLoc, - SourceLocation ConstQualifierLoc, - SourceLocation - VolatileQualifierLoc, - SourceLocation - RestrictQualifierLoc, SourceLocation MutableLoc, ExceptionSpecificationType ESpecType, @@ -178,8 +172,9 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, SourceLocation LocalRangeBegin, SourceLocation LocalRangeEnd, Declarator &TheDeclarator, - TypeResult TrailingReturnType) { - assert(!(TypeQuals & DeclSpec::TQ_atomic) && + TypeResult TrailingReturnType, + DeclSpec *MethodQualifiers) { + assert(!(MethodQualifiers && MethodQualifiers->getTypeQualifiers() & DeclSpec::TQ_atomic) && "function cannot have _Atomic qualifier"); DeclaratorChunk I; @@ -193,14 +188,10 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding(); I.Fun.RParenLoc = RParenLoc.getRawEncoding(); I.Fun.DeleteParams = false; - I.Fun.TypeQuals = TypeQuals; I.Fun.NumParams = NumParams; I.Fun.Params = nullptr; I.Fun.RefQualifierIsLValueRef = RefQualifierIsLvalueRef; I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding(); - I.Fun.ConstQualifierLoc = ConstQualifierLoc.getRawEncoding(); - I.Fun.VolatileQualifierLoc = VolatileQualifierLoc.getRawEncoding(); - I.Fun.RestrictQualifierLoc = RestrictQualifierLoc.getRawEncoding(); I.Fun.MutableLoc = MutableLoc.getRawEncoding(); I.Fun.ExceptionSpecType = ESpecType; I.Fun.ExceptionSpecLocBeg = ESpecRange.getBegin().getRawEncoding(); @@ -211,8 +202,21 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, I.Fun.HasTrailingReturnType = TrailingReturnType.isUsable() || TrailingReturnType.isInvalid(); I.Fun.TrailingReturnType = TrailingReturnType.get(); + I.Fun.MethodQualifiers = nullptr; + I.Fun.QualAttrFactory = nullptr; + + if (MethodQualifiers && (MethodQualifiers->getTypeQualifiers() || + MethodQualifiers->getAttributes().size())) { + auto &attrs = MethodQualifiers->getAttributes(); + I.Fun.MethodQualifiers = new DeclSpec(attrs.getPool().getFactory()); + MethodQualifiers->forEachCVRUQualifier( + [&](DeclSpec::TQ TypeQual, StringRef PrintName, SourceLocation SL) { + I.Fun.MethodQualifiers->SetTypeQual(TypeQual, SL); + }); + I.Fun.MethodQualifiers->getAttributes().takeAllFrom(attrs); + I.Fun.MethodQualifiers->getAttributePool().takeAllFrom(attrs.getPool()); + } - assert(I.Fun.TypeQuals == TypeQuals && "bitfield overflow"); assert(I.Fun.ExceptionSpecType == ESpecType && "bitfield overflow"); // new[] a parameter array if needed. @@ -403,6 +407,24 @@ bool Declarator::isCtorOrDtor() { (getName().getKind() == UnqualifiedIdKind::IK_DestructorName); } +void DeclSpec::forEachCVRUQualifier( + llvm::function_ref<void(TQ, StringRef, SourceLocation)> Handle) { + if (TypeQualifiers & TQ_const) + Handle(TQ_const, "const", TQ_constLoc); + if (TypeQualifiers & TQ_volatile) + Handle(TQ_volatile, "volatile", TQ_volatileLoc); + if (TypeQualifiers & TQ_restrict) + Handle(TQ_restrict, "restrict", TQ_restrictLoc); + if (TypeQualifiers & TQ_unaligned) + Handle(TQ_unaligned, "unaligned", TQ_unalignedLoc); +} + +void DeclSpec::forEachQualifier( + llvm::function_ref<void(TQ, StringRef, SourceLocation)> Handle) { + forEachCVRUQualifier(Handle); + // FIXME: Add code below to iterate through the attributes and call Handle. +} + bool DeclSpec::hasTagDefinition() const { if (!TypeSpecOwned) return false; @@ -438,7 +460,7 @@ template <class T> static bool BadSpecifier(T TNew, T TPrev, if (TNew != TPrev) DiagID = diag::err_invalid_decl_spec_combination; else - DiagID = IsExtension ? diag::ext_duplicate_declspec : + DiagID = IsExtension ? diag::ext_warn_duplicate_declspec : diag::warn_duplicate_declspec; return true; } @@ -566,14 +588,16 @@ bool DeclSpec::SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc, // these storage-class specifiers. // OpenCL v1.2 s6.8 changes this to "The auto and register storage-class // specifiers are not supported." + // OpenCL C++ v1.0 s2.9 restricts register. if (S.getLangOpts().OpenCL && !S.getOpenCLOptions().isEnabled("cl_clang_storage_class_specifiers")) { switch (SC) { case SCS_extern: case SCS_private_extern: case SCS_static: - if (S.getLangOpts().OpenCLVersion < 120) { - DiagID = diag::err_opencl_unknown_type_specifier; + if (S.getLangOpts().OpenCLVersion < 120 && + !S.getLangOpts().OpenCLCPlusPlus) { + DiagID = diag::err_opencl_unknown_type_specifier; PrevSpec = getSpecifierName(SC); return true; } @@ -860,6 +884,11 @@ bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec, IsExtension = false; return BadSpecifier(T, T, PrevSpec, DiagID, IsExtension); } + + return SetTypeQual(T, Loc); +} + +bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc) { TypeQualifiers |= T; switch (T) { @@ -967,7 +996,7 @@ bool DeclSpec::setModulePrivateSpec(SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID) { if (isModulePrivateSpecified()) { PrevSpec = "__module_private__"; - DiagID = diag::ext_duplicate_declspec; + DiagID = diag::ext_warn_duplicate_declspec; return true; } diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp index dba56931d49c3..b439f7255728d 100644 --- a/lib/Sema/IdentifierResolver.cpp +++ b/lib/Sema/IdentifierResolver.cpp @@ -147,7 +147,7 @@ void IdentifierResolver::AddDecl(NamedDecl *D) { if (IdentifierInfo *II = Name.getAsIdentifierInfo()) updatingIdentifier(*II); - void *Ptr = Name.getFETokenInfo<void>(); + void *Ptr = Name.getFETokenInfo(); if (!Ptr) { Name.setFETokenInfo(D); @@ -172,7 +172,7 @@ void IdentifierResolver::InsertDeclAfter(iterator Pos, NamedDecl *D) { if (IdentifierInfo *II = Name.getAsIdentifierInfo()) updatingIdentifier(*II); - void *Ptr = Name.getFETokenInfo<void>(); + void *Ptr = Name.getFETokenInfo(); if (!Ptr) { AddDecl(D); @@ -213,7 +213,7 @@ void IdentifierResolver::RemoveDecl(NamedDecl *D) { if (IdentifierInfo *II = Name.getAsIdentifierInfo()) updatingIdentifier(*II); - void *Ptr = Name.getFETokenInfo<void>(); + void *Ptr = Name.getFETokenInfo(); assert(Ptr && "Didn't find this decl on its identifier's chain!"); @@ -232,7 +232,7 @@ IdentifierResolver::begin(DeclarationName Name) { if (IdentifierInfo *II = Name.getAsIdentifierInfo()) readingIdentifier(*II); - void *Ptr = Name.getFETokenInfo<void>(); + void *Ptr = Name.getFETokenInfo(); if (!Ptr) return end(); if (isDeclPtr(Ptr)) @@ -304,7 +304,7 @@ bool IdentifierResolver::tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name){ if (IdentifierInfo *II = Name.getAsIdentifierInfo()) readingIdentifier(*II); - void *Ptr = Name.getFETokenInfo<void>(); + void *Ptr = Name.getFETokenInfo(); if (!Ptr) { Name.setFETokenInfo(D); @@ -397,7 +397,7 @@ void IdentifierResolver::updatingIdentifier(IdentifierInfo &II) { /// It creates a new IdDeclInfo if one was not created before for this id. IdentifierResolver::IdDeclInfo & IdentifierResolver::IdDeclInfoMap::operator[](DeclarationName Name) { - void *Ptr = Name.getFETokenInfo<void>(); + void *Ptr = Name.getFETokenInfo(); if (Ptr) return *toIdDeclInfo(Ptr); @@ -415,7 +415,7 @@ IdentifierResolver::IdDeclInfoMap::operator[](DeclarationName Name) { void IdentifierResolver::iterator::incrementSlowCase() { NamedDecl *D = **this; - void *InfoPtr = D->getDeclName().getFETokenInfo<void>(); + void *InfoPtr = D->getDeclName().getFETokenInfo(); assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?"); IdDeclInfo *Info = toIdDeclInfo(InfoPtr); diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp index 58a7862370cc0..a7495e8e04825 100644 --- a/lib/Sema/JumpDiagnostics.cpp +++ b/lib/Sema/JumpDiagnostics.cpp @@ -299,7 +299,7 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, auto *CS = cast<ObjCForCollectionStmt>(S); unsigned Diag = diag::note_protected_by_objc_fast_enumeration; unsigned NewParentScope = Scopes.size(); - Scopes.push_back(GotoScope(ParentScope, Diag, 0, S->getLocStart())); + Scopes.push_back(GotoScope(ParentScope, Diag, 0, S->getBeginLoc())); BuildScopeInformation(CS->getBody(), NewParentScope); return; } @@ -353,16 +353,16 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, // Cannot jump into the middle of the condition. unsigned NewParentScope = Scopes.size(); - Scopes.push_back(GotoScope(ParentScope, Diag, 0, IS->getLocStart())); + Scopes.push_back(GotoScope(ParentScope, Diag, 0, IS->getBeginLoc())); BuildScopeInformation(IS->getCond(), NewParentScope); // Jumps into either arm of an 'if constexpr' are not allowed. NewParentScope = Scopes.size(); - Scopes.push_back(GotoScope(ParentScope, Diag, 0, IS->getLocStart())); + Scopes.push_back(GotoScope(ParentScope, Diag, 0, IS->getBeginLoc())); BuildScopeInformation(IS->getThen(), NewParentScope); if (Stmt *Else = IS->getElse()) { NewParentScope = Scopes.size(); - Scopes.push_back(GotoScope(ParentScope, Diag, 0, IS->getLocStart())); + Scopes.push_back(GotoScope(ParentScope, Diag, 0, IS->getBeginLoc())); BuildScopeInformation(Else, NewParentScope); } return; @@ -619,11 +619,11 @@ void JumpScopeChecker::VerifyJumps() { continue; SourceLocation Loc; if (CaseStmt *CS = dyn_cast<CaseStmt>(SC)) - Loc = CS->getLocStart(); + Loc = CS->getBeginLoc(); else if (DefaultStmt *DS = dyn_cast<DefaultStmt>(SC)) - Loc = DS->getLocStart(); + Loc = DS->getBeginLoc(); else - Loc = SC->getLocStart(); + Loc = SC->getBeginLoc(); CheckJump(SS, SC, Loc, diag::err_switch_into_protected_scope, 0, diag::warn_cxx98_compat_switch_into_protected_scope); } @@ -863,7 +863,7 @@ void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc, // less nested scope. Check if it crosses a __finally along the way. for (unsigned I = FromScope; I > ToScope; I = Scopes[I].ParentScope) { if (Scopes[I].InDiag == diag::note_protected_by_seh_finally) { - S.Diag(From->getLocStart(), diag::warn_jump_out_of_seh_finally); + S.Diag(From->getBeginLoc(), diag::warn_jump_out_of_seh_finally); break; } } diff --git a/lib/Sema/ParsedAttr.cpp b/lib/Sema/ParsedAttr.cpp index 6509df9985efd..59e5aab677a9e 100644 --- a/lib/Sema/ParsedAttr.cpp +++ b/lib/Sema/ParsedAttr.cpp @@ -41,8 +41,12 @@ size_t ParsedAttr::allocated_size() const { else if (IsProperty) return AttributeFactory::PropertyAllocSize; else if (HasParsedType) - return sizeof(ParsedAttr) + sizeof(void *); - return (sizeof(ParsedAttr) + NumArgs * sizeof(ArgsUnion)); + return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, + detail::TypeTagForDatatypeData, ParsedType, + detail::PropertyData>(0, 0, 0, 1, 0); + return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, + detail::TypeTagForDatatypeData, ParsedType, + detail::PropertyData>(NumArgs, 0, 0, 0, 0); } AttributeFactory::AttributeFactory() { @@ -78,7 +82,7 @@ void AttributeFactory::deallocate(ParsedAttr *Attr) { if (freeListIndex >= FreeLists.size()) FreeLists.resize(freeListIndex + 1); -#if !NDEBUG +#ifndef NDEBUG // In debug mode, zero out the attribute to help find memory overwriting. memset(Attr, 0, size); #endif @@ -99,15 +103,31 @@ void AttributePool::takePool(AttributePool &pool) { #include "clang/Sema/AttrParsedAttrKinds.inc" -static StringRef normalizeAttrName(StringRef AttrName, StringRef ScopeName, +static StringRef normalizeAttrScopeName(StringRef ScopeName, + ParsedAttr::Syntax SyntaxUsed) { + // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name + // to be "clang". + if (SyntaxUsed == ParsedAttr::AS_CXX11 || + SyntaxUsed == ParsedAttr::AS_C2x) { + if (ScopeName == "__gnu__") + ScopeName = "gnu"; + else if (ScopeName == "_Clang") + ScopeName = "clang"; + } + return ScopeName; +} + +static StringRef normalizeAttrName(StringRef AttrName, + StringRef NormalizedScopeName, ParsedAttr::Syntax SyntaxUsed) { // Normalize the attribute name, __foo__ becomes foo. This is only allowable - // for GNU attributes. - bool IsGNU = SyntaxUsed == ParsedAttr::AS_GNU || - ((SyntaxUsed == ParsedAttr::AS_CXX11 || - SyntaxUsed == ParsedAttr::AS_C2x) && - ScopeName == "gnu"); - if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") && + // for GNU attributes, and attributes using the double square bracket syntax. + bool ShouldNormalize = + SyntaxUsed == ParsedAttr::AS_GNU || + ((SyntaxUsed == ParsedAttr::AS_CXX11 || + SyntaxUsed == ParsedAttr::AS_C2x) && + (NormalizedScopeName == "gnu" || NormalizedScopeName == "clang")); + if (ShouldNormalize && AttrName.size() >= 4 && AttrName.startswith("__") && AttrName.endswith("__")) AttrName = AttrName.slice(2, AttrName.size() - 2); @@ -121,7 +141,7 @@ ParsedAttr::Kind ParsedAttr::getKind(const IdentifierInfo *Name, SmallString<64> FullName; if (ScopeName) - FullName += ScopeName->getName(); + FullName += normalizeAttrScopeName(ScopeName->getName(), SyntaxUsed); AttrName = normalizeAttrName(AttrName, FullName, SyntaxUsed); @@ -137,9 +157,10 @@ ParsedAttr::Kind ParsedAttr::getKind(const IdentifierInfo *Name, unsigned ParsedAttr::getAttributeSpellingListIndex() const { // Both variables will be used in tablegen generated // attribute spell list index matching code. - StringRef Scope = ScopeName ? ScopeName->getName() : ""; - StringRef Name = normalizeAttrName(AttrName->getName(), Scope, - (ParsedAttr::Syntax)SyntaxUsed); + auto Syntax = static_cast<ParsedAttr::Syntax>(SyntaxUsed); + StringRef Scope = + ScopeName ? normalizeAttrScopeName(ScopeName->getName(), Syntax) : ""; + StringRef Name = normalizeAttrName(AttrName->getName(), Scope, Syntax); #include "clang/Sema/AttrSpellingListIndex.inc" diff --git a/lib/Sema/ScopeInfo.cpp b/lib/Sema/ScopeInfo.cpp index 62a83ccb70aad..bd8db6f4ed91c 100644 --- a/lib/Sema/ScopeInfo.cpp +++ b/lib/Sema/ScopeInfo.cpp @@ -54,6 +54,8 @@ void FunctionScopeInfo::Clear() { PossiblyUnreachableDiags.clear(); WeakObjectUses.clear(); ModifiedNonNullParams.clear(); + Blocks.clear(); + ByrefBlockVars.clear(); } static const NamedDecl *getBestPropertyDecl(const ObjCPropertyRefExpr *PropE) { diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 49f3decc11517..9fa39968625a6 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -152,7 +152,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, for (unsigned I = 0; I != NSAPI::NumNSNumberLiteralMethods; ++I) NSNumberLiteralMethods[I] = nullptr; - if (getLangOpts().ObjC1) + if (getLangOpts().ObjC) NSAPIObj.reset(new NSAPI(Context)); if (getLangOpts().CPlusPlus) @@ -167,7 +167,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, PreallocatedFunctionScope.reset(new FunctionScopeInfo(Diags)); - // Initilization of data sharing attributes stack for OpenMP + // Initialization of data sharing attributes stack for OpenMP InitDataSharingAttributesStack(); std::unique_ptr<sema::SemaPPCallbacks> Callbacks = @@ -214,7 +214,7 @@ void Sema::Initialize() { // Initialize predefined Objective-C types: - if (getLangOpts().ObjC1) { + if (getLangOpts().ObjC) { // If 'SEL' does not yet refer to any declarations, make it refer to the // predefined 'SEL'. DeclarationName SEL = &Context.Idents.get("SEL"); @@ -320,6 +320,10 @@ void Sema::Initialize() { #define GENERIC_IMAGE_TYPE_EXT(Type, Id, Ext) \ setOpenCLExtensionForType(Context.Id, Ext); #include "clang/Basic/OpenCLImageTypes.def" +#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ + addImplicitTypedef(#ExtType, Context.Id##Ty); \ + setOpenCLExtensionForType(Context.Id##Ty, #Ext); +#include "clang/Basic/OpenCLExtensionTypes.def" }; if (Context.getTargetInfo().hasBuiltinMSVaList()) { @@ -441,7 +445,7 @@ void Sema::diagnoseNullableToNonnullConversion(QualType DstType, void Sema::diagnoseZeroToNullptrConversion(CastKind Kind, const Expr* E) { if (Diags.isIgnored(diag::warn_zero_as_null_pointer_constant, - E->getLocStart())) + E->getBeginLoc())) return; // nullptr only exists from C++11 on, so don't warn on its absence earlier. if (!getLangOpts().CPlusPlus11) @@ -454,13 +458,13 @@ void Sema::diagnoseZeroToNullptrConversion(CastKind Kind, const Expr* E) { // If it is a macro from system header, and if the macro name is not "NULL", // do not warn. - SourceLocation MaybeMacroLoc = E->getLocStart(); + SourceLocation MaybeMacroLoc = E->getBeginLoc(); if (Diags.getSuppressSystemWarnings() && SourceMgr.isInSystemMacro(MaybeMacroLoc) && !findMacroSpelling(MaybeMacroLoc, "NULL")) return; - Diag(E->getLocStart(), diag::warn_zero_as_null_pointer_constant) + Diag(E->getBeginLoc(), diag::warn_zero_as_null_pointer_constant) << FixItHint::CreateReplacement(E->getSourceRange(), "nullptr"); } @@ -488,7 +492,7 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, assert((VK == VK_RValue || !E->isRValue()) && "can't cast rvalue to lvalue"); #endif - diagnoseNullableToNonnullConversion(Ty, E->getType(), E->getLocStart()); + diagnoseNullableToNonnullConversion(Ty, E->getType(), E->getBeginLoc()); diagnoseZeroToNullptrConversion(Kind, E); QualType ExprTy = Context.getCanonicalType(E->getType()); @@ -533,6 +537,7 @@ CastKind Sema::ScalarTypeToBooleanCastKind(QualType ScalarTy) { case Type::STK_Floating: return CK_FloatingToBoolean; case Type::STK_IntegralComplex: return CK_IntegralComplexToBoolean; case Type::STK_FloatingComplex: return CK_FloatingComplexToBoolean; + case Type::STK_FixedPoint: return CK_FixedPointToBoolean; } llvm_unreachable("unknown scalar type kind"); } @@ -644,7 +649,8 @@ void Sema::getUndefinedButUsed( continue; if (FD->isExternallyVisible() && !isExternalWithNoLinkageType(FD) && - !FD->getMostRecentDecl()->isInlined()) + !FD->getMostRecentDecl()->isInlined() && + !FD->hasAttr<ExcludeFromExplicitInstantiationAttr>()) continue; if (FD->getBuiltinID()) continue; @@ -654,7 +660,8 @@ void Sema::getUndefinedButUsed( continue; if (VD->isExternallyVisible() && !isExternalWithNoLinkageType(VD) && - !VD->getMostRecentDecl()->isInline()) + !VD->getMostRecentDecl()->isInline() && + !VD->hasAttr<ExcludeFromExplicitInstantiationAttr>()) continue; // Skip VarDecls that lack formal definitions but which we know are in @@ -827,7 +834,9 @@ void Sema::emitAndClearUnusedLocalTypedefWarnings() { /// is parsed. Note that the ASTContext may have already injected some /// declarations. void Sema::ActOnStartOfTranslationUnit() { - if (getLangOpts().ModulesTS) { + if (getLangOpts().ModulesTS && + (getLangOpts().getCompilingModule() == LangOptions::CMK_ModuleInterface || + getLangOpts().getCompilingModule() == LangOptions::CMK_None)) { SourceLocation StartOfTU = SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()); @@ -922,10 +931,9 @@ void Sema::ActOnEndOfTranslationUnit() { // All delayed member exception specs should be checked or we end up accepting // incompatible declarations. - // FIXME: This is wrong for TUKind == TU_Prefix. In that case, we need to - // write out the lists to the AST file (if any). + assert(DelayedOverridingExceptionSpecChecks.empty()); + assert(DelayedEquivalentExceptionSpecChecks.empty()); assert(DelayedDefaultedMemberExceptionSpecs.empty()); - assert(DelayedExceptionSpecChecks.empty()); // All dllexport classes should have been processed already. assert(DelayedDllExportClasses.empty()); @@ -978,7 +986,8 @@ void Sema::ActOnEndOfTranslationUnit() { // module declaration by now. if (getLangOpts().getCompilingModule() == LangOptions::CMK_ModuleInterface && - ModuleScopes.back().Module->Kind != Module::ModuleInterfaceUnit) { + (ModuleScopes.empty() || + ModuleScopes.back().Module->Kind != Module::ModuleInterfaceUnit)) { // FIXME: Make a better guess as to where to put the module declaration. Diag(getSourceManager().getLocForStartOfFile( getSourceManager().getMainFileID()), @@ -1399,9 +1408,69 @@ void Sema::RecordParsingTemplateParameterDepth(unsigned Depth) { "Remove assertion if intentionally called in a non-lambda context."); } +// Check that the type of the VarDecl has an accessible copy constructor and +// resolve its destructor's exception spefication. +static void checkEscapingByref(VarDecl *VD, Sema &S) { + QualType T = VD->getType(); + EnterExpressionEvaluationContext scope( + S, Sema::ExpressionEvaluationContext::PotentiallyEvaluated); + SourceLocation Loc = VD->getLocation(); + Expr *VarRef = + new (S.Context) DeclRefExpr(S.Context, VD, false, T, VK_LValue, Loc); + ExprResult Result = S.PerformMoveOrCopyInitialization( + InitializedEntity::InitializeBlock(Loc, T, false), VD, VD->getType(), + VarRef, /*AllowNRVO=*/true); + if (!Result.isInvalid()) { + Result = S.MaybeCreateExprWithCleanups(Result); + Expr *Init = Result.getAs<Expr>(); + S.Context.setBlockVarCopyInit(VD, Init, S.canThrow(Init)); + } + + // The destructor's exception spefication is needed when IRGen generates + // block copy/destroy functions. Resolve it here. + if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + if (CXXDestructorDecl *DD = RD->getDestructor()) { + auto *FPT = DD->getType()->getAs<FunctionProtoType>(); + S.ResolveExceptionSpec(Loc, FPT); + } +} + +static void markEscapingByrefs(const FunctionScopeInfo &FSI, Sema &S) { + // Set the EscapingByref flag of __block variables captured by + // escaping blocks. + for (const BlockDecl *BD : FSI.Blocks) { + if (BD->doesNotEscape()) + continue; + for (const BlockDecl::Capture &BC : BD->captures()) { + VarDecl *VD = BC.getVariable(); + if (VD->hasAttr<BlocksAttr>()) + VD->setEscapingByref(); + } + } + + for (VarDecl *VD : FSI.ByrefBlockVars) { + // __block variables might require us to capture a copy-initializer. + if (!VD->isEscapingByref()) + continue; + // It's currently invalid to ever have a __block variable with an + // array type; should we diagnose that here? + // Regardless, we don't want to ignore array nesting when + // constructing this copy. + if (VD->getType()->isStructureOrClassType()) + checkEscapingByref(VD, S); + } +} + void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP, const Decl *D, const BlockExpr *blkExpr) { assert(!FunctionScopes.empty() && "mismatched push/pop!"); + + // This function shouldn't be called after popping the current function scope. + // markEscapingByrefs calls PerformMoveOrCopyInitialization, which can call + // PushFunctionScope, which can cause clearing out PreallocatedFunctionScope + // when FunctionScopes is empty. + markEscapingByrefs(*FunctionScopes.back(), *this); + FunctionScopeInfo *Scope = FunctionScopes.pop_back_val(); if (LangOpts.OpenMP) @@ -1851,6 +1920,34 @@ void Sema::setCurrentOpenCLExtensionForDecl(Decl *D) { setOpenCLExtensionForDecl(D, CurrOpenCLExtension); } +std::string Sema::getOpenCLExtensionsFromDeclExtMap(FunctionDecl *FD) { + if (!OpenCLDeclExtMap.empty()) + return getOpenCLExtensionsFromExtMap(FD, OpenCLDeclExtMap); + + return ""; +} + +std::string Sema::getOpenCLExtensionsFromTypeExtMap(FunctionType *FT) { + if (!OpenCLTypeExtMap.empty()) + return getOpenCLExtensionsFromExtMap(FT, OpenCLTypeExtMap); + + return ""; +} + +template <typename T, typename MapT> +std::string Sema::getOpenCLExtensionsFromExtMap(T *FDT, MapT &Map) { + std::string ExtensionNames = ""; + auto Loc = Map.find(FDT); + + for (auto const& I : Loc->second) { + ExtensionNames += I; + ExtensionNames += " "; + } + ExtensionNames.pop_back(); + + return ExtensionNames; +} + bool Sema::isOpenCLDisabledDecl(Decl *FD) { auto Loc = OpenCLDeclExtMap.find(FD); if (Loc == OpenCLDeclExtMap.end()) @@ -1889,6 +1986,14 @@ bool Sema::checkOpenCLDisabledTypeDeclSpec(const DeclSpec &DS, QualType QT) { if (auto TagT = dyn_cast<TagType>(QT.getCanonicalType().getTypePtr())) Decl = TagT->getDecl(); auto Loc = DS.getTypeSpecTypeLoc(); + + // Check extensions for vector types. + // e.g. double4 is not allowed when cl_khr_fp64 is absent. + if (QT->isExtVectorType()) { + auto TypePtr = QT->castAs<ExtVectorType>()->getElementType().getTypePtr(); + return checkOpenCLDisabledTypeOrDecl(TypePtr, Loc, QT, OpenCLTypeExtMap); + } + if (checkOpenCLDisabledTypeOrDecl(Decl, Loc, QT, OpenCLDeclExtMap)) return true; @@ -1899,6 +2004,6 @@ bool Sema::checkOpenCLDisabledTypeDeclSpec(const DeclSpec &DS, QualType QT) { bool Sema::checkOpenCLDisabledDecl(const NamedDecl &D, const Expr &E) { IdentifierInfo *FnName = D.getIdentifier(); - return checkOpenCLDisabledTypeOrDecl(&D, E.getLocStart(), FnName, + return checkOpenCLDisabledTypeOrDecl(&D, E.getBeginLoc(), FnName, OpenCLDeclExtMap, 1, D.getSourceRange()); } diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp index e06792cae78ba..69084589efeac 100644 --- a/lib/Sema/SemaAccess.cpp +++ b/lib/Sema/SemaAccess.cpp @@ -1728,6 +1728,22 @@ Sema::AccessResult Sema::CheckMemberAccess(SourceLocation UseLoc, return CheckAccess(*this, UseLoc, Entity); } +/// Checks implicit access to a member in a structured binding. +Sema::AccessResult +Sema::CheckStructuredBindingMemberAccess(SourceLocation UseLoc, + CXXRecordDecl *DecomposedClass, + DeclAccessPair Field) { + if (!getLangOpts().AccessControl || + Field.getAccess() == AS_public) + return AR_accessible; + + AccessTarget Entity(Context, AccessTarget::Member, DecomposedClass, Field, + Context.getRecordType(DecomposedClass)); + Entity.setDiag(diag::err_decomp_decl_inaccessible_field); + + return CheckAccess(*this, UseLoc, Entity); +} + /// Checks access to an overloaded member operator, including /// conversion operators. Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc, @@ -1861,22 +1877,31 @@ void Sema::CheckLookupAccess(const LookupResult &R) { /// specifiers into account, but no member access expressions and such. /// /// \param Target the declaration to check if it can be accessed -/// \param Ctx the class/context from which to start the search +/// \param NamingClass the class in which the lookup was started. +/// \param BaseType type of the left side of member access expression. +/// \p BaseType and \p NamingClass are used for C++ access control. +/// Depending on the lookup case, they should be set to the following: +/// - lhs.target (member access without a qualifier): +/// \p BaseType and \p NamingClass are both the type of 'lhs'. +/// - lhs.X::target (member access with a qualifier): +/// BaseType is the type of 'lhs', NamingClass is 'X' +/// - X::target (qualified lookup without member access): +/// BaseType is null, NamingClass is 'X'. +/// - target (unqualified lookup). +/// BaseType is null, NamingClass is the parent class of 'target'. /// \return true if the Target is accessible from the Class, false otherwise. -bool Sema::IsSimplyAccessible(NamedDecl *Target, DeclContext *Ctx) { - if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx)) { - if (!Target->isCXXClassMember()) - return true; - - if (Target->getAccess() == AS_public) - return true; - QualType qType = Class->getTypeForDecl()->getCanonicalTypeInternal(); +bool Sema::IsSimplyAccessible(NamedDecl *Target, CXXRecordDecl *NamingClass, + QualType BaseType) { + // Perform the C++ accessibility checks first. + if (Target->isCXXClassMember() && NamingClass) { + if (!getLangOpts().CPlusPlus) + return false; // The unprivileged access is AS_none as we don't know how the member was // accessed, which is described by the access in DeclAccessPair. // `IsAccessible` will examine the actual access of Target (i.e. // Decl->getAccess()) when calculating the access. - AccessTarget Entity(Context, AccessedEntity::Member, Class, - DeclAccessPair::make(Target, AS_none), qType); + AccessTarget Entity(Context, AccessedEntity::Member, NamingClass, + DeclAccessPair::make(Target, AS_none), BaseType); EffectiveContext EC(CurContext); return ::IsAccessible(*this, EC, Entity) != ::AR_inaccessible; } diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp index 1a8a000753062..2bc1b769f77a1 100644 --- a/lib/Sema/SemaAttr.cpp +++ b/lib/Sema/SemaAttr.cpp @@ -405,7 +405,7 @@ void Sema::ActOnPragmaMSSeg(SourceLocation PragmaLocation, Diag(PragmaLocation, diag::warn_pragma_pop_failed) << PragmaName << "stack empty"; if (SegmentName && - !checkSectionName(SegmentName->getLocStart(), SegmentName->getString())) + !checkSectionName(SegmentName->getBeginLoc(), SegmentName->getString())) return; Stack->Act(PragmaLocation, Action, StackSlotLabel, SegmentName); } @@ -520,9 +520,9 @@ attrMatcherRuleListToString(ArrayRef<attr::SubjectMatchRule> Rules) { } // end anonymous namespace -void Sema::ActOnPragmaAttributePush(ParsedAttr &Attribute, - SourceLocation PragmaLoc, - attr::ParsedSubjectMatchRuleSet Rules) { +void Sema::ActOnPragmaAttributeAttribute( + ParsedAttr &Attribute, SourceLocation PragmaLoc, + attr::ParsedSubjectMatchRuleSet Rules) { SmallVector<attr::SubjectMatchRule, 4> SubjectMatchRules; // Gather the subject match rules that are supported by the attribute. SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> @@ -622,54 +622,88 @@ void Sema::ActOnPragmaAttributePush(ParsedAttr &Attribute, Diagnostic << attrMatcherRuleListToString(ExtraRules); } - PragmaAttributeStack.push_back( + if (PragmaAttributeStack.empty()) { + Diag(PragmaLoc, diag::err_pragma_attr_attr_no_push); + return; + } + + PragmaAttributeStack.back().Entries.push_back( {PragmaLoc, &Attribute, std::move(SubjectMatchRules), /*IsUsed=*/false}); } -void Sema::ActOnPragmaAttributePop(SourceLocation PragmaLoc) { +void Sema::ActOnPragmaAttributeEmptyPush(SourceLocation PragmaLoc, + const IdentifierInfo *Namespace) { + PragmaAttributeStack.emplace_back(); + PragmaAttributeStack.back().Loc = PragmaLoc; + PragmaAttributeStack.back().Namespace = Namespace; +} + +void Sema::ActOnPragmaAttributePop(SourceLocation PragmaLoc, + const IdentifierInfo *Namespace) { if (PragmaAttributeStack.empty()) { - Diag(PragmaLoc, diag::err_pragma_attribute_stack_mismatch); + Diag(PragmaLoc, diag::err_pragma_attribute_stack_mismatch) << 1; return; } - const PragmaAttributeEntry &Entry = PragmaAttributeStack.back(); - if (!Entry.IsUsed) { - assert(Entry.Attribute && "Expected an attribute"); - Diag(Entry.Attribute->getLoc(), diag::warn_pragma_attribute_unused) - << Entry.Attribute->getName(); - Diag(PragmaLoc, diag::note_pragma_attribute_region_ends_here); + + // Dig back through the stack trying to find the most recently pushed group + // that in Namespace. Note that this works fine if no namespace is present, + // think of push/pops without namespaces as having an implicit "nullptr" + // namespace. + for (size_t Index = PragmaAttributeStack.size(); Index;) { + --Index; + if (PragmaAttributeStack[Index].Namespace == Namespace) { + for (const PragmaAttributeEntry &Entry : + PragmaAttributeStack[Index].Entries) { + if (!Entry.IsUsed) { + assert(Entry.Attribute && "Expected an attribute"); + Diag(Entry.Attribute->getLoc(), diag::warn_pragma_attribute_unused) + << *Entry.Attribute; + Diag(PragmaLoc, diag::note_pragma_attribute_region_ends_here); + } + } + PragmaAttributeStack.erase(PragmaAttributeStack.begin() + Index); + return; + } } - PragmaAttributeStack.pop_back(); + + if (Namespace) + Diag(PragmaLoc, diag::err_pragma_attribute_stack_mismatch) + << 0 << Namespace->getName(); + else + Diag(PragmaLoc, diag::err_pragma_attribute_stack_mismatch) << 1; } void Sema::AddPragmaAttributes(Scope *S, Decl *D) { if (PragmaAttributeStack.empty()) return; - for (auto &Entry : PragmaAttributeStack) { - ParsedAttr *Attribute = Entry.Attribute; - assert(Attribute && "Expected an attribute"); - - // Ensure that the attribute can be applied to the given declaration. - bool Applies = false; - for (const auto &Rule : Entry.MatchRules) { - if (Attribute->appliesToDecl(D, Rule)) { - Applies = true; - break; + for (auto &Group : PragmaAttributeStack) { + for (auto &Entry : Group.Entries) { + ParsedAttr *Attribute = Entry.Attribute; + assert(Attribute && "Expected an attribute"); + + // Ensure that the attribute can be applied to the given declaration. + bool Applies = false; + for (const auto &Rule : Entry.MatchRules) { + if (Attribute->appliesToDecl(D, Rule)) { + Applies = true; + break; + } } + if (!Applies) + continue; + Entry.IsUsed = true; + PragmaAttributeCurrentTargetDecl = D; + ParsedAttributesView Attrs; + Attrs.addAtEnd(Attribute); + ProcessDeclAttributeList(S, D, Attrs); + PragmaAttributeCurrentTargetDecl = nullptr; } - if (!Applies) - continue; - Entry.IsUsed = true; - PragmaAttributeCurrentTargetDecl = D; - ParsedAttributesView Attrs; - Attrs.addAtStart(Attribute); - ProcessDeclAttributeList(S, D, Attrs); - PragmaAttributeCurrentTargetDecl = nullptr; } } void Sema::PrintPragmaAttributeInstantiationPoint() { assert(PragmaAttributeCurrentTargetDecl && "Expected an active declaration"); - Diags.Report(PragmaAttributeCurrentTargetDecl->getLocStart(), + Diags.Report(PragmaAttributeCurrentTargetDecl->getBeginLoc(), diag::note_pragma_attribute_applied_decl_here); } @@ -773,6 +807,18 @@ void Sema::ActOnPragmaFPContract(LangOptions::FPContractModeKind FPC) { } } +void Sema::ActOnPragmaFEnvAccess(LangOptions::FEnvAccessModeKind FPC) { + switch (FPC) { + case LangOptions::FEA_On: + FPFeatures.setAllowFEnvAccess(); + break; + case LangOptions::FEA_Off: + FPFeatures.setDisallowFEnvAccess(); + break; + } +} + + void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr, SourceLocation Loc) { // Visibility calculations will consider the namespace's visibility. diff --git a/lib/Sema/SemaCUDA.cpp b/lib/Sema/SemaCUDA.cpp index 13dd8d936fd2f..ffc7288985846 100644 --- a/lib/Sema/SemaCUDA.cpp +++ b/lib/Sema/SemaCUDA.cpp @@ -48,7 +48,7 @@ ExprResult Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc, QualType ConfigQTy = ConfigDecl->getType(); DeclRefExpr *ConfigDR = new (Context) - DeclRefExpr(ConfigDecl, false, ConfigQTy, VK_LValue, LLLLoc); + DeclRefExpr(Context, ConfigDecl, false, ConfigQTy, VK_LValue, LLLLoc); MarkFunctionReferenced(LLLLoc, ConfigDecl); return ActOnCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc, nullptr, diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 4e39d0675471e..2354ffe7fbccd 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -209,11 +209,13 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS, if (!tag || tag->isDependentContext()) return false; + // Grab the tag definition, if there is one. + QualType type = Context.getTypeDeclType(tag); + tag = type->getAsTagDecl(); + // If we're currently defining this type, then lookup into the // type is okay: don't complain that it isn't complete yet. - QualType type = Context.getTypeDeclType(tag); - const TagType *tagType = type->getAs<TagType>(); - if (tagType && tagType->isBeingDefined()) + if (tag->isBeingDefined()) return false; SourceLocation loc = SS.getLastQualifierNameLoc(); @@ -229,13 +231,13 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS, // Fixed enum types are complete, but they aren't valid as scopes // until we see a definition, so awkwardly pull out this special // case. - const EnumType *enumType = dyn_cast_or_null<EnumType>(tagType); - if (!enumType) + auto *EnumD = dyn_cast<EnumDecl>(tag); + if (!EnumD) return false; - if (enumType->getDecl()->isCompleteDefinition()) { + if (EnumD->isCompleteDefinition()) { // If we know about the definition but it is not visible, complain. NamedDecl *SuggestedDef = nullptr; - if (!hasVisibleDefinition(enumType->getDecl(), &SuggestedDef, + if (!hasVisibleDefinition(EnumD, &SuggestedDef, /*OnlyNeedComplete*/false)) { // If the user is going to see an error here, recover by making the // definition visible. @@ -249,11 +251,11 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS, // Try to instantiate the definition, if this is a specialization of an // enumeration temploid. - EnumDecl *ED = enumType->getDecl(); - if (EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) { - MemberSpecializationInfo *MSI = ED->getMemberSpecializationInfo(); + if (EnumDecl *Pattern = EnumD->getInstantiatedFromMemberEnum()) { + MemberSpecializationInfo *MSI = EnumD->getMemberSpecializationInfo(); if (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) { - if (InstantiateEnum(loc, ED, Pattern, getTemplateInstantiationArgs(ED), + if (InstantiateEnum(loc, EnumD, Pattern, + getTemplateInstantiationArgs(EnumD), TSK_ImplicitInstantiation)) { SS.SetInvalid(SS.getRange()); return true; diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index 57aac80f5ad2e..0b4645e11c341 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -131,6 +131,9 @@ namespace { return PlaceholderKind == K; } + // Language specific cast restrictions for address spaces. + void checkAddressSpaceCast(QualType SrcType, QualType DestType); + void checkCastAlign() { Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange); } @@ -561,7 +564,7 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType, Qualifiers *CastAwayQualifiers = nullptr) { // If the only checking we care about is for Objective-C lifetime qualifiers, // and we're not in ObjC mode, there's nothing to check. - if (!CheckCVR && CheckObjCLifetime && !Self.Context.getLangOpts().ObjC1) + if (!CheckCVR && CheckObjCLifetime && !Self.Context.getLangOpts().ObjC) return CastAwayConstnessKind::CACK_None; if (!DestType->isReferenceType()) { @@ -1044,6 +1047,17 @@ void CastOperation::CheckStaticCast() { } } +static bool IsAddressSpaceConversion(QualType SrcType, QualType DestType) { + auto *SrcPtrType = SrcType->getAs<PointerType>(); + if (!SrcPtrType) + return false; + auto *DestPtrType = DestType->getAs<PointerType>(); + if (!DestPtrType) + return false; + return SrcPtrType->getPointeeType().getAddressSpace() != + DestPtrType->getPointeeType().getAddressSpace(); +} + /// TryStaticCast - Check if a static cast can be performed, and do so if /// possible. If @p CStyle, ignore access restrictions on hierarchy casting /// and casting away constness. @@ -1185,7 +1199,9 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, return TC_Failed; } } - Kind = CK_BitCast; + Kind = IsAddressSpaceConversion(SrcType, DestType) + ? CK_AddressSpaceConversion + : CK_BitCast; return TC_Success; } @@ -1264,7 +1280,7 @@ TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, } Sema::ReferenceCompareResult RefResult = Self.CompareReferenceRelationship( - SrcExpr->getLocStart(), ToType, FromType, DerivedToBase, ObjCConversion, + SrcExpr->getBeginLoc(), ToType, FromType, DerivedToBase, ObjCConversion, ObjCLifetimeConversion); if (RefResult != Sema::Ref_Compatible) { if (CStyle || RefResult == Sema::Ref_Incompatible) @@ -1281,7 +1297,7 @@ TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, Kind = CK_DerivedToBase; CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, /*DetectVirtual=*/true); - if (!Self.IsDerivedFrom(SrcExpr->getLocStart(), SrcExpr->getType(), + if (!Self.IsDerivedFrom(SrcExpr->getBeginLoc(), SrcExpr->getType(), R->getPointeeType(), Paths)) return TC_NotApplicable; @@ -1964,12 +1980,6 @@ static bool fixOverloadedReinterpretCastExpr(Sema &Self, QualType DestType, return Result.isUsable(); } -static bool IsAddressSpaceConversion(QualType SrcType, QualType DestType) { - return SrcType->isPointerType() && DestType->isPointerType() && - SrcType->getAs<PointerType>()->getPointeeType().getAddressSpace() != - DestType->getAs<PointerType>()->getPointeeType().getAddressSpace(); -} - static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, bool CStyle, SourceRange OpRange, @@ -2269,6 +2279,27 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, return SuccessResult; } +void CastOperation::checkAddressSpaceCast(QualType SrcType, QualType DestType) { + // In OpenCL only conversions between pointers to objects in overlapping + // addr spaces are allowed. v2.0 s6.5.5 - Generic addr space overlaps + // with any named one, except for constant. + if (Self.getLangOpts().OpenCL) { + auto SrcPtrType = SrcType->getAs<PointerType>(); + if (!SrcPtrType) + return; + auto DestPtrType = DestType->getAs<PointerType>(); + if (!DestPtrType) + return; + if (!DestPtrType->isAddressSpaceOverlapping(*SrcPtrType)) { + Self.Diag(OpRange.getBegin(), + diag::err_typecheck_incompatible_address_space) + << SrcType << DestType << Sema::AA_Casting + << SrcExpr.get()->getSourceRange(); + SrcExpr = ExprError(); + } + } +} + void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle, bool ListInitialization) { assert(Self.getLangOpts().CPlusPlus); @@ -2396,6 +2427,8 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle, } } + checkAddressSpaceCast(SrcExpr.get()->getType(), DestType); + if (isValidCast(tcr)) { if (Kind == CK_BitCast) checkCastAlign(); @@ -2482,20 +2515,9 @@ void CastOperation::CheckCStyleCast() { assert(!SrcType->isPlaceholderType()); - // OpenCL v1 s6.5: Casting a pointer to address space A to a pointer to - // address space B is illegal. - if (Self.getLangOpts().OpenCL && DestType->isPointerType() && - SrcType->isPointerType()) { - const PointerType *DestPtr = DestType->getAs<PointerType>(); - if (!DestPtr->isAddressSpaceOverlapping(*SrcType->getAs<PointerType>())) { - Self.Diag(OpRange.getBegin(), - diag::err_typecheck_incompatible_address_space) - << SrcType << DestType << Sema::AA_Casting - << SrcExpr.get()->getSourceRange(); - SrcExpr = ExprError(); - return; - } - } + checkAddressSpaceCast(SrcType, DestType); + if (SrcExpr.isInvalid()) + return; if (Self.RequireCompleteType(OpRange.getBegin(), DestType, diag::err_typecheck_cast_to_incomplete)) { @@ -2532,10 +2554,11 @@ void CastOperation::CheckCStyleCast() { // OpenCL v2.0 s6.13.10 - Allow casts from '0' to event_t type. if (Self.getLangOpts().OpenCL && DestType->isEventT()) { - llvm::APSInt CastInt; - if (SrcExpr.get()->EvaluateAsInt(CastInt, Self.Context)) { + Expr::EvalResult Result; + if (SrcExpr.get()->EvaluateAsInt(Result, Self.Context)) { + llvm::APSInt CastInt = Result.Val.getInt(); if (0 == CastInt) { - Kind = CK_ZeroToOCLEvent; + Kind = CK_ZeroToOCLOpaqueType; return; } Self.Diag(OpRange.getBegin(), @@ -2612,9 +2635,9 @@ void CastOperation::CheckCStyleCast() { } else if (!SrcType->isArithmeticType()) { if (!DestType->isIntegralType(Self.Context) && DestType->isArithmeticType()) { - Self.Diag(SrcExpr.get()->getLocStart(), - diag::err_cast_pointer_to_non_pointer_int) - << DestType << SrcExpr.get()->getSourceRange(); + Self.Diag(SrcExpr.get()->getBeginLoc(), + diag::err_cast_pointer_to_non_pointer_int) + << DestType << SrcExpr.get()->getSourceRange(); SrcExpr = ExprError(); return; } @@ -2623,8 +2646,8 @@ void CastOperation::CheckCStyleCast() { if (Self.getLangOpts().OpenCL && !Self.getOpenCLOptions().isEnabled("cl_khr_fp16")) { if (DestType->isHalfType()) { - Self.Diag(SrcExpr.get()->getLocStart(), diag::err_opencl_cast_to_half) - << DestType << SrcExpr.get()->getSourceRange(); + Self.Diag(SrcExpr.get()->getBeginLoc(), diag::err_opencl_cast_to_half) + << DestType << SrcExpr.get()->getSourceRange(); SrcExpr = ExprError(); return; } @@ -2644,18 +2667,18 @@ void CastOperation::CheckCStyleCast() { if (CastPtr->getPointeeType()->isObjCLifetimeType() && ExprPtr->getPointeeType()->isObjCLifetimeType() && !CastQuals.compatiblyIncludesObjCLifetime(ExprQuals)) { - Self.Diag(SrcExpr.get()->getLocStart(), + Self.Diag(SrcExpr.get()->getBeginLoc(), diag::err_typecheck_incompatible_ownership) - << SrcType << DestType << Sema::AA_Casting - << SrcExpr.get()->getSourceRange(); + << SrcType << DestType << Sema::AA_Casting + << SrcExpr.get()->getSourceRange(); return; } } } else if (!Self.CheckObjCARCUnavailableWeakConversion(DestType, SrcType)) { - Self.Diag(SrcExpr.get()->getLocStart(), + Self.Diag(SrcExpr.get()->getBeginLoc(), diag::err_arc_convesion_of_weak_unavailable) - << 1 << SrcType << DestType << SrcExpr.get()->getSourceRange(); + << 1 << SrcType << DestType << SrcExpr.get()->getSourceRange(); SrcExpr = ExprError(); return; } @@ -2703,10 +2726,10 @@ static void DiagnoseCastQual(Sema &Self, const ExprResult &SrcExpr, } // This is a variant of int **x; const int **y = (const int **)x; if (qualifiers == -1) - Self.Diag(SrcExpr.get()->getLocStart(), diag::warn_cast_qual2) + Self.Diag(SrcExpr.get()->getBeginLoc(), diag::warn_cast_qual2) << SrcType << DestType; else - Self.Diag(SrcExpr.get()->getLocStart(), diag::warn_cast_qual) + Self.Diag(SrcExpr.get()->getBeginLoc(), diag::warn_cast_qual) << TheOffendingSrcType << TheOffendingDestType << qualifiers; } @@ -2716,7 +2739,7 @@ ExprResult Sema::BuildCStyleCastExpr(SourceLocation LPLoc, Expr *CastExpr) { CastOperation Op(*this, CastTypeInfo->getType(), CastExpr); Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange(); - Op.OpRange = SourceRange(LPLoc, CastExpr->getLocEnd()); + Op.OpRange = SourceRange(LPLoc, CastExpr->getEndLoc()); if (getLangOpts().CPlusPlus) { Op.CheckCXXCStyleCast(/*FunctionalStyle=*/ false, @@ -2744,7 +2767,7 @@ ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo, assert(LPLoc.isValid() && "List-initialization shouldn't get here."); CastOperation Op(*this, Type, CastExpr); Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange(); - Op.OpRange = SourceRange(Op.DestRange.getBegin(), CastExpr->getLocEnd()); + Op.OpRange = SourceRange(Op.DestRange.getBegin(), CastExpr->getEndLoc()); Op.CheckCXXCStyleCast(/*FunctionalStyle=*/true, /*ListInit=*/false); if (Op.SrcExpr.isInvalid()) diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 93dbeab5b0344..8dc1fdb76988d 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -27,6 +27,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" +#include "clang/AST/FormatString.h" #include "clang/AST/NSAPI.h" #include "clang/AST/NonTrivialTypeVisitor.h" #include "clang/AST/OperationKinds.h" @@ -35,7 +36,6 @@ #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/UnresolvedSet.h" -#include "clang/Analysis/Analyses/FormatString.h" #include "clang/Basic/AddressSpaces.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/Diagnostic.h" @@ -112,13 +112,13 @@ static bool checkArgCount(Sema &S, CallExpr *call, unsigned desiredArgCount) { if (argCount == desiredArgCount) return false; if (argCount < desiredArgCount) - return S.Diag(call->getLocEnd(), diag::err_typecheck_call_too_few_args) - << 0 /*function call*/ << desiredArgCount << argCount - << call->getSourceRange(); + return S.Diag(call->getEndLoc(), diag::err_typecheck_call_too_few_args) + << 0 /*function call*/ << desiredArgCount << argCount + << call->getSourceRange(); // Highlight all the excess arguments. - SourceRange range(call->getArg(desiredArgCount)->getLocStart(), - call->getArg(argCount - 1)->getLocEnd()); + SourceRange range(call->getArg(desiredArgCount)->getBeginLoc(), + call->getArg(argCount - 1)->getEndLoc()); return S.Diag(range.getBegin(), diag::err_typecheck_call_too_many_args) << 0 /*function call*/ << desiredArgCount << argCount @@ -135,8 +135,8 @@ static bool SemaBuiltinAnnotation(Sema &S, CallExpr *TheCall) { Expr *ValArg = TheCall->getArg(0); QualType Ty = ValArg->getType(); if (!Ty->isIntegerType()) { - S.Diag(ValArg->getLocStart(), diag::err_builtin_annotation_first_arg) - << ValArg->getSourceRange(); + S.Diag(ValArg->getBeginLoc(), diag::err_builtin_annotation_first_arg) + << ValArg->getSourceRange(); return true; } @@ -144,8 +144,8 @@ static bool SemaBuiltinAnnotation(Sema &S, CallExpr *TheCall) { Expr *StrArg = TheCall->getArg(1)->IgnoreParenCasts(); StringLiteral *Literal = dyn_cast<StringLiteral>(StrArg); if (!Literal || !Literal->isAscii()) { - S.Diag(StrArg->getLocStart(), diag::err_builtin_annotation_second_arg) - << StrArg->getSourceRange(); + S.Diag(StrArg->getBeginLoc(), diag::err_builtin_annotation_second_arg) + << StrArg->getSourceRange(); return true; } @@ -156,7 +156,7 @@ static bool SemaBuiltinAnnotation(Sema &S, CallExpr *TheCall) { static bool SemaBuiltinMSVCAnnotation(Sema &S, CallExpr *TheCall) { // We need at least one argument. if (TheCall->getNumArgs() < 1) { - S.Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least) + S.Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args_at_least) << 0 << 1 << TheCall->getNumArgs() << TheCall->getCallee()->getSourceRange(); return true; @@ -166,7 +166,7 @@ static bool SemaBuiltinMSVCAnnotation(Sema &S, CallExpr *TheCall) { for (Expr *Arg : TheCall->arguments()) { auto *Literal = dyn_cast<StringLiteral>(Arg->IgnoreParenCasts()); if (!Literal || !Literal->isWide()) { - S.Diag(Arg->getLocStart(), diag::err_msvc_annotation_wide_str) + S.Diag(Arg->getBeginLoc(), diag::err_msvc_annotation_wide_str) << Arg->getSourceRange(); return true; } @@ -182,7 +182,7 @@ static bool SemaBuiltinAddressof(Sema &S, CallExpr *TheCall) { return true; ExprResult Arg(TheCall->getArg(0)); - QualType ResultType = S.CheckAddressOfOperand(Arg, TheCall->getLocStart()); + QualType ResultType = S.CheckAddressOfOperand(Arg, TheCall->getBeginLoc()); if (ResultType.isNull()) return true; @@ -200,7 +200,7 @@ static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall) { ExprResult Arg = TheCall->getArg(I); QualType Ty = Arg.get()->getType(); if (!Ty->isIntegerType()) { - S.Diag(Arg.get()->getLocStart(), diag::err_overflow_builtin_must_be_int) + S.Diag(Arg.get()->getBeginLoc(), diag::err_overflow_builtin_must_be_int) << Ty << Arg.get()->getSourceRange(); return true; } @@ -221,7 +221,7 @@ static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall) { const auto *PtrTy = Ty->getAs<PointerType>(); if (!(PtrTy && PtrTy->getPointeeType()->isIntegerType() && !PtrTy->getPointeeType().isConstQualified())) { - S.Diag(Arg.get()->getLocStart(), + S.Diag(Arg.get()->getBeginLoc(), diag::err_overflow_builtin_must_be_ptr_int) << Ty << Arg.get()->getSourceRange(); return true; @@ -238,7 +238,8 @@ static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall) { static void SemaBuiltinMemChkCall(Sema &S, FunctionDecl *FDecl, CallExpr *TheCall, unsigned SizeIdx, - unsigned DstSizeIdx) { + unsigned DstSizeIdx, + StringRef LikelyMacroName) { if (TheCall->getNumArgs() <= SizeIdx || TheCall->getNumArgs() <= DstSizeIdx) return; @@ -246,29 +247,41 @@ static void SemaBuiltinMemChkCall(Sema &S, FunctionDecl *FDecl, const Expr *SizeArg = TheCall->getArg(SizeIdx); const Expr *DstSizeArg = TheCall->getArg(DstSizeIdx); - llvm::APSInt Size, DstSize; + Expr::EvalResult SizeResult, DstSizeResult; // find out if both sizes are known at compile time - if (!SizeArg->EvaluateAsInt(Size, S.Context) || - !DstSizeArg->EvaluateAsInt(DstSize, S.Context)) + if (!SizeArg->EvaluateAsInt(SizeResult, S.Context) || + !DstSizeArg->EvaluateAsInt(DstSizeResult, S.Context)) return; + llvm::APSInt Size = SizeResult.Val.getInt(); + llvm::APSInt DstSize = DstSizeResult.Val.getInt(); + if (Size.ule(DstSize)) return; - // confirmed overflow so generate the diagnostic. - IdentifierInfo *FnName = FDecl->getIdentifier(); - SourceLocation SL = TheCall->getLocStart(); - SourceRange SR = TheCall->getSourceRange(); + // Confirmed overflow, so generate the diagnostic. + StringRef FunctionName = FDecl->getName(); + SourceLocation SL = TheCall->getBeginLoc(); + SourceManager &SM = S.getSourceManager(); + // If we're in an expansion of a macro whose name corresponds to this builtin, + // use the simple macro name and location. + if (SL.isMacroID() && Lexer::getImmediateMacroName(SL, SM, S.getLangOpts()) == + LikelyMacroName) { + FunctionName = LikelyMacroName; + SL = SM.getImmediateMacroCallerLoc(SL); + } - S.Diag(SL, diag::warn_memcpy_chk_overflow) << SR << FnName; + S.Diag(SL, diag::warn_memcpy_chk_overflow) + << FunctionName << DstSize.toString(/*Radix=*/10) + << Size.toString(/*Radix=*/10); } static bool SemaBuiltinCallWithStaticChain(Sema &S, CallExpr *BuiltinCall) { if (checkArgCount(S, BuiltinCall, 2)) return true; - SourceLocation BuiltinLoc = BuiltinCall->getLocStart(); + SourceLocation BuiltinLoc = BuiltinCall->getBeginLoc(); Expr *Builtin = BuiltinCall->getCallee()->IgnoreImpCasts(); Expr *Call = BuiltinCall->getArg(0); Expr *Chain = BuiltinCall->getArg(1); @@ -375,9 +388,9 @@ static bool checkOpenCLBlockArgs(Sema &S, Expr *BlockArg) { SourceLocation ErrorLoc; if (isa<BlockExpr>(BlockArg)) { BlockDecl *BD = cast<BlockExpr>(BlockArg)->getBlockDecl(); - ErrorLoc = BD->getParamDecl(ArgCounter)->getLocStart(); + ErrorLoc = BD->getParamDecl(ArgCounter)->getBeginLoc(); } else if (isa<DeclRefExpr>(BlockArg)) { - ErrorLoc = cast<DeclRefExpr>(BlockArg)->getLocStart(); + ErrorLoc = cast<DeclRefExpr>(BlockArg)->getBeginLoc(); } S.Diag(ErrorLoc, diag::err_opencl_enqueue_kernel_blocks_non_local_void_args); @@ -390,8 +403,8 @@ static bool checkOpenCLBlockArgs(Sema &S, Expr *BlockArg) { static bool checkOpenCLSubgroupExt(Sema &S, CallExpr *Call) { if (!S.getOpenCLOptions().isEnabled("cl_khr_subgroups")) { - S.Diag(Call->getLocStart(), diag::err_opencl_requires_extension) - << 1 << Call->getDirectCallee() << "cl_khr_subgroups"; + S.Diag(Call->getBeginLoc(), diag::err_opencl_requires_extension) + << 1 << Call->getDirectCallee() << "cl_khr_subgroups"; return true; } return false; @@ -407,16 +420,14 @@ static bool SemaOpenCLBuiltinNDRangeAndBlock(Sema &S, CallExpr *TheCall) { // First argument is an ndrange_t type. Expr *NDRangeArg = TheCall->getArg(0); if (NDRangeArg->getType().getUnqualifiedType().getAsString() != "ndrange_t") { - S.Diag(NDRangeArg->getLocStart(), - diag::err_opencl_builtin_expected_type) + S.Diag(NDRangeArg->getBeginLoc(), diag::err_opencl_builtin_expected_type) << TheCall->getDirectCallee() << "'ndrange_t'"; return true; } Expr *BlockArg = TheCall->getArg(1); if (!isBlockPointer(BlockArg)) { - S.Diag(BlockArg->getLocStart(), - diag::err_opencl_builtin_expected_type) + S.Diag(BlockArg->getBeginLoc(), diag::err_opencl_builtin_expected_type) << TheCall->getDirectCallee() << "block"; return true; } @@ -432,8 +443,7 @@ static bool SemaOpenCLBuiltinKernelWorkGroupSize(Sema &S, CallExpr *TheCall) { Expr *BlockArg = TheCall->getArg(0); if (!isBlockPointer(BlockArg)) { - S.Diag(BlockArg->getLocStart(), - diag::err_opencl_builtin_expected_type) + S.Diag(BlockArg->getBeginLoc(), diag::err_opencl_builtin_expected_type) << TheCall->getDirectCallee() << "block"; return true; } @@ -467,7 +477,7 @@ static bool checkOpenCLEnqueueVariadicArgs(Sema &S, CallExpr *TheCall, // For each argument passed to the block, a corresponding uint needs to // be passed to describe the size of the local memory. if (TotalNumArgs != NumBlockParams + NumNonVarArgs) { - S.Diag(TheCall->getLocStart(), + S.Diag(TheCall->getBeginLoc(), diag::err_opencl_enqueue_kernel_local_size_args); return true; } @@ -507,7 +517,7 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) { unsigned NumArgs = TheCall->getNumArgs(); if (NumArgs < 4) { - S.Diag(TheCall->getLocStart(), diag::err_typecheck_call_too_few_args); + S.Diag(TheCall->getBeginLoc(), diag::err_typecheck_call_too_few_args); return true; } @@ -518,7 +528,7 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) { // First argument always needs to be a queue_t type. if (!Arg0->getType()->isQueueT()) { - S.Diag(TheCall->getArg(0)->getLocStart(), + S.Diag(TheCall->getArg(0)->getBeginLoc(), diag::err_opencl_builtin_expected_type) << TheCall->getDirectCallee() << S.Context.OCLQueueTy; return true; @@ -526,7 +536,7 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) { // Second argument always needs to be a kernel_enqueue_flags_t enum value. if (!Arg1->getType()->isIntegerType()) { - S.Diag(TheCall->getArg(1)->getLocStart(), + S.Diag(TheCall->getArg(1)->getBeginLoc(), diag::err_opencl_builtin_expected_type) << TheCall->getDirectCallee() << "'kernel_enqueue_flags_t' (i.e. uint)"; return true; @@ -534,7 +544,7 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) { // Third argument is always an ndrange_t type. if (Arg2->getType().getUnqualifiedType().getAsString() != "ndrange_t") { - S.Diag(TheCall->getArg(2)->getLocStart(), + S.Diag(TheCall->getArg(2)->getBeginLoc(), diag::err_opencl_builtin_expected_type) << TheCall->getDirectCallee() << "'ndrange_t'"; return true; @@ -545,7 +555,7 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) { if (NumArgs == 4) { // check that the last argument is the right block type. if (!isBlockPointer(Arg3)) { - S.Diag(Arg3->getLocStart(), diag::err_opencl_builtin_expected_type) + S.Diag(Arg3->getBeginLoc(), diag::err_opencl_builtin_expected_type) << TheCall->getDirectCallee() << "block"; return true; } @@ -553,7 +563,7 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) { const BlockPointerType *BPT = cast<BlockPointerType>(Arg3->getType().getCanonicalType()); if (BPT->getPointeeType()->getAs<FunctionProtoType>()->getNumParams() > 0) { - S.Diag(Arg3->getLocStart(), + S.Diag(Arg3->getBeginLoc(), diag::err_opencl_enqueue_kernel_blocks_no_args); return true; } @@ -568,7 +578,7 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) { // check common block argument. Expr *Arg6 = TheCall->getArg(6); if (!isBlockPointer(Arg6)) { - S.Diag(Arg6->getLocStart(), diag::err_opencl_builtin_expected_type) + S.Diag(Arg6->getBeginLoc(), diag::err_opencl_builtin_expected_type) << TheCall->getDirectCallee() << "block"; return true; } @@ -577,7 +587,7 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) { // Forth argument has to be any integer type. if (!Arg3->getType()->isIntegerType()) { - S.Diag(TheCall->getArg(3)->getLocStart(), + S.Diag(TheCall->getArg(3)->getBeginLoc(), diag::err_opencl_builtin_expected_type) << TheCall->getDirectCallee() << "integer"; return true; @@ -590,7 +600,7 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) { if (!Arg4->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull) && !Arg4->getType()->getPointeeOrArrayElementType()->isClkEventT()) { - S.Diag(TheCall->getArg(4)->getLocStart(), + S.Diag(TheCall->getArg(4)->getBeginLoc(), diag::err_opencl_builtin_expected_type) << TheCall->getDirectCallee() << S.Context.getPointerType(S.Context.OCLClkEventTy); @@ -602,7 +612,7 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) { Expr::NPC_ValueDependentIsNotNull) && !(Arg5->getType()->isPointerType() && Arg5->getType()->getPointeeType()->isClkEventT())) { - S.Diag(TheCall->getArg(5)->getLocStart(), + S.Diag(TheCall->getArg(5)->getBeginLoc(), diag::err_opencl_builtin_expected_type) << TheCall->getDirectCallee() << S.Context.getPointerType(S.Context.OCLClkEventTy); @@ -616,7 +626,7 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) { } // None of the specific case has been detected, give generic error - S.Diag(TheCall->getLocStart(), + S.Diag(TheCall->getBeginLoc(), diag::err_opencl_enqueue_kernel_incorrect_args); return true; } @@ -631,7 +641,7 @@ static bool checkOpenCLPipeArg(Sema &S, CallExpr *Call) { const Expr *Arg0 = Call->getArg(0); // First argument type should always be pipe. if (!Arg0->getType()->isPipeType()) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_first_arg) + S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_first_arg) << Call->getDirectCallee() << Arg0->getSourceRange(); return true; } @@ -650,7 +660,7 @@ static bool checkOpenCLPipeArg(Sema &S, CallExpr *Call) { case Builtin::BIwork_group_commit_read_pipe: case Builtin::BIsub_group_commit_read_pipe: if (!(!AccessQual || AccessQual->isReadOnly())) { - S.Diag(Arg0->getLocStart(), + S.Diag(Arg0->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_access_modifier) << "read_only" << Arg0->getSourceRange(); return true; @@ -664,7 +674,7 @@ static bool checkOpenCLPipeArg(Sema &S, CallExpr *Call) { case Builtin::BIwork_group_commit_write_pipe: case Builtin::BIsub_group_commit_write_pipe: if (!(AccessQual && AccessQual->isWriteOnly())) { - S.Diag(Arg0->getLocStart(), + S.Diag(Arg0->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_access_modifier) << "write_only" << Arg0->getSourceRange(); return true; @@ -688,7 +698,7 @@ static bool checkOpenCLPipePacketType(Sema &S, CallExpr *Call, unsigned Idx) { if (!ArgTy || !S.Context.hasSameType( EltTy, ArgTy->getPointeeType()->getCanonicalTypeInternal())) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) + S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg) << Call->getDirectCallee() << S.Context.getPointerType(EltTy) << ArgIdx->getType() << ArgIdx->getSourceRange(); return true; @@ -721,7 +731,7 @@ static bool SemaBuiltinRWPipe(Sema &S, CallExpr *Call) { // read/write_pipe(pipe T, reserve_id_t, uint, T*). // Check reserve_id_t. if (!Call->getArg(1)->getType()->isReserveIDT()) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) + S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg) << Call->getDirectCallee() << S.Context.OCLReserveIDTy << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange(); return true; @@ -731,7 +741,7 @@ static bool SemaBuiltinRWPipe(Sema &S, CallExpr *Call) { const Expr *Arg2 = Call->getArg(2); if (!Arg2->getType()->isIntegerType() && !Arg2->getType()->isUnsignedIntegerType()) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) + S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg) << Call->getDirectCallee() << S.Context.UnsignedIntTy << Arg2->getType() << Arg2->getSourceRange(); return true; @@ -742,7 +752,7 @@ static bool SemaBuiltinRWPipe(Sema &S, CallExpr *Call) { return true; } break; default: - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_arg_num) + S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_arg_num) << Call->getDirectCallee() << Call->getSourceRange(); return true; } @@ -765,7 +775,7 @@ static bool SemaBuiltinReserveRWPipe(Sema &S, CallExpr *Call) { // Check the reserve size. if (!Call->getArg(1)->getType()->isIntegerType() && !Call->getArg(1)->getType()->isUnsignedIntegerType()) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) + S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg) << Call->getDirectCallee() << S.Context.UnsignedIntTy << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange(); return true; @@ -793,7 +803,7 @@ static bool SemaBuiltinCommitRWPipe(Sema &S, CallExpr *Call) { // Check reserve_id_t. if (!Call->getArg(1)->getType()->isReserveIDT()) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) + S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg) << Call->getDirectCallee() << S.Context.OCLReserveIDTy << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange(); return true; @@ -812,7 +822,7 @@ static bool SemaBuiltinPipePackets(Sema &S, CallExpr *Call) { return true; if (!Call->getArg(0)->getType()->isPipeType()) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_first_arg) + S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_first_arg) << Call->getDirectCallee() << Call->getArg(0)->getSourceRange(); return true; } @@ -829,7 +839,7 @@ static bool SemaBuiltinPipePackets(Sema &S, CallExpr *Call) { static bool SemaOpenCLBuiltinToAddr(Sema &S, unsigned BuiltinID, CallExpr *Call) { if (Call->getNumArgs() != 1) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_to_addr_arg_num) + S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_to_addr_arg_num) << Call->getDirectCallee() << Call->getSourceRange(); return true; } @@ -837,11 +847,18 @@ static bool SemaOpenCLBuiltinToAddr(Sema &S, unsigned BuiltinID, auto RT = Call->getArg(0)->getType(); if (!RT->isPointerType() || RT->getPointeeType() .getAddressSpace() == LangAS::opencl_constant) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_to_addr_invalid_arg) + S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_to_addr_invalid_arg) << Call->getArg(0) << Call->getDirectCallee() << Call->getSourceRange(); return true; } + if (RT->getPointeeType().getAddressSpace() != LangAS::opencl_generic) { + S.Diag(Call->getArg(0)->getBeginLoc(), + diag::warn_opencl_generic_address_space_arg) + << Call->getDirectCallee()->getNameInfo().getAsString() + << Call->getArg(0)->getSourceRange(); + } + RT = RT->getPointeeType(); auto Qual = RT.getQualifiers(); switch (BuiltinID) { @@ -863,6 +880,66 @@ static bool SemaOpenCLBuiltinToAddr(Sema &S, unsigned BuiltinID, return false; } +static ExprResult SemaBuiltinLaunder(Sema &S, CallExpr *TheCall) { + if (checkArgCount(S, TheCall, 1)) + return ExprError(); + + // Compute __builtin_launder's parameter type from the argument. + // The parameter type is: + // * The type of the argument if it's not an array or function type, + // Otherwise, + // * The decayed argument type. + QualType ParamTy = [&]() { + QualType ArgTy = TheCall->getArg(0)->getType(); + if (const ArrayType *Ty = ArgTy->getAsArrayTypeUnsafe()) + return S.Context.getPointerType(Ty->getElementType()); + if (ArgTy->isFunctionType()) { + return S.Context.getPointerType(ArgTy); + } + return ArgTy; + }(); + + TheCall->setType(ParamTy); + + auto DiagSelect = [&]() -> llvm::Optional<unsigned> { + if (!ParamTy->isPointerType()) + return 0; + if (ParamTy->isFunctionPointerType()) + return 1; + if (ParamTy->isVoidPointerType()) + return 2; + return llvm::Optional<unsigned>{}; + }(); + if (DiagSelect.hasValue()) { + S.Diag(TheCall->getBeginLoc(), diag::err_builtin_launder_invalid_arg) + << DiagSelect.getValue() << TheCall->getSourceRange(); + return ExprError(); + } + + // We either have an incomplete class type, or we have a class template + // whose instantiation has not been forced. Example: + // + // template <class T> struct Foo { T value; }; + // Foo<int> *p = nullptr; + // auto *d = __builtin_launder(p); + if (S.RequireCompleteType(TheCall->getBeginLoc(), ParamTy->getPointeeType(), + diag::err_incomplete_type)) + return ExprError(); + + assert(ParamTy->getPointeeType()->isObjectType() && + "Unhandled non-object pointer case"); + + InitializedEntity Entity = + InitializedEntity::InitializeParameter(S.Context, ParamTy, false); + ExprResult Arg = + S.PerformCopyInitialization(Entity, SourceLocation(), TheCall->getArg(0)); + if (Arg.isInvalid()) + return ExprError(); + TheCall->setArg(0, Arg.get()); + + return TheCall; +} + // Emit an error and return true if the current architecture is not in the list // of supported architectures. static bool @@ -872,7 +949,7 @@ CheckBuiltinTargetSupport(Sema &S, unsigned BuiltinID, CallExpr *TheCall, S.getASTContext().getTargetInfo().getTriple().getArch(); if (llvm::is_contained(SupportedArchs, CurArch)) return false; - S.Diag(TheCall->getLocStart(), diag::err_builtin_target_unsupported) + S.Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported) << TheCall->getSourceRange(); return true; } @@ -915,6 +992,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, break; case Builtin::BI__va_start: { switch (Context.getTargetInfo().getTriple().getArch()) { + case llvm::Triple::aarch64: case llvm::Triple::arm: case llvm::Triple::thumb: if (SemaBuiltinVAStartARMMicrosoft(TheCall)) @@ -1024,6 +1102,8 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, if (checkArgCount(*this, TheCall, 1)) return true; TheCall->setType(Context.IntTy); break; + case Builtin::BI__builtin_launder: + return SemaBuiltinLaunder(*this, TheCall); case Builtin::BI__sync_fetch_and_add: case Builtin::BI__sync_fetch_and_add_1: case Builtin::BI__sync_fetch_and_add_2: @@ -1127,6 +1207,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, case Builtin::BI__sync_swap_8: case Builtin::BI__sync_swap_16: return SemaBuiltinAtomicOverloaded(TheCallResult); + case Builtin::BI__sync_synchronize: + Diag(TheCall->getBeginLoc(), diag::warn_atomic_implicit_seq_cst) + << TheCall->getCallee()->getSourceRange(); + break; case Builtin::BI__builtin_nontemporal_load: case Builtin::BI__builtin_nontemporal_store: return SemaBuiltinNontemporalOverloaded(TheCallResult); @@ -1171,7 +1255,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, const QualType PtrArgType = PtrArg->getType(); if (!PtrArgType->isPointerType() || !PtrArgType->getPointeeType()->isRecordType()) { - Diag(PtrArg->getLocStart(), diag::err_typecheck_convert_incompatible) + Diag(PtrArg->getBeginLoc(), diag::err_typecheck_convert_incompatible) << PtrArgType << "structure pointer" << 1 << 0 << 3 << 1 << PtrArgType << "structure pointer"; return ExprError(); @@ -1181,9 +1265,9 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, const Expr *FnPtrArg = TheCall->getArg(1)->IgnoreImpCasts(); const QualType FnPtrArgType = FnPtrArg->getType(); if (!FnPtrArgType->isPointerType()) { - Diag(FnPtrArg->getLocStart(), diag::err_typecheck_convert_incompatible) - << FnPtrArgType << "'int (*)(const char *, ...)'" << 1 << 0 << 3 - << 2 << FnPtrArgType << "'int (*)(const char *, ...)'"; + Diag(FnPtrArg->getBeginLoc(), diag::err_typecheck_convert_incompatible) + << FnPtrArgType << "'int (*)(const char *, ...)'" << 1 << 0 << 3 << 2 + << FnPtrArgType << "'int (*)(const char *, ...)'"; return ExprError(); } @@ -1191,15 +1275,15 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, FnPtrArgType->getPointeeType()->getAs<FunctionType>(); if (!FuncType) { - Diag(FnPtrArg->getLocStart(), diag::err_typecheck_convert_incompatible) - << FnPtrArgType << "'int (*)(const char *, ...)'" << 1 << 0 << 3 - << 2 << FnPtrArgType << "'int (*)(const char *, ...)'"; + Diag(FnPtrArg->getBeginLoc(), diag::err_typecheck_convert_incompatible) + << FnPtrArgType << "'int (*)(const char *, ...)'" << 1 << 0 << 3 << 2 + << FnPtrArgType << "'int (*)(const char *, ...)'"; return ExprError(); } if (const auto *FT = dyn_cast<FunctionProtoType>(FuncType)) { if (!FT->getNumParams()) { - Diag(FnPtrArg->getLocStart(), diag::err_typecheck_convert_incompatible) + Diag(FnPtrArg->getBeginLoc(), diag::err_typecheck_convert_incompatible) << FnPtrArgType << "'int (*)(const char *, ...)'" << 1 << 0 << 3 << 2 << FnPtrArgType << "'int (*)(const char *, ...)'"; return ExprError(); @@ -1208,7 +1292,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, if (!FT->isVariadic() || FT->getReturnType() != Context.IntTy || !PT->isPointerType() || !PT->getPointeeType()->isCharType() || !PT->getPointeeType().isConstQualified()) { - Diag(FnPtrArg->getLocStart(), diag::err_typecheck_convert_incompatible) + Diag(FnPtrArg->getBeginLoc(), diag::err_typecheck_convert_incompatible) << FnPtrArgType << "'int (*)(const char *, ...)'" << 1 << 0 << 3 << 2 << FnPtrArgType << "'int (*)(const char *, ...)'"; return ExprError(); @@ -1222,21 +1306,37 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, // check secure string manipulation functions where overflows // are detectable at compile time case Builtin::BI__builtin___memcpy_chk: + SemaBuiltinMemChkCall(*this, FDecl, TheCall, 2, 3, "memcpy"); + break; case Builtin::BI__builtin___memmove_chk: + SemaBuiltinMemChkCall(*this, FDecl, TheCall, 2, 3, "memmove"); + break; case Builtin::BI__builtin___memset_chk: + SemaBuiltinMemChkCall(*this, FDecl, TheCall, 2, 3, "memset"); + break; case Builtin::BI__builtin___strlcat_chk: + SemaBuiltinMemChkCall(*this, FDecl, TheCall, 2, 3, "strlcat"); + break; case Builtin::BI__builtin___strlcpy_chk: + SemaBuiltinMemChkCall(*this, FDecl, TheCall, 2, 3, "strlcpy"); + break; case Builtin::BI__builtin___strncat_chk: + SemaBuiltinMemChkCall(*this, FDecl, TheCall, 2, 3, "strncat"); + break; case Builtin::BI__builtin___strncpy_chk: + SemaBuiltinMemChkCall(*this, FDecl, TheCall, 2, 3, "strncpy"); + break; case Builtin::BI__builtin___stpncpy_chk: - SemaBuiltinMemChkCall(*this, FDecl, TheCall, 2, 3); + SemaBuiltinMemChkCall(*this, FDecl, TheCall, 2, 3, "stpncpy"); break; case Builtin::BI__builtin___memccpy_chk: - SemaBuiltinMemChkCall(*this, FDecl, TheCall, 3, 4); + SemaBuiltinMemChkCall(*this, FDecl, TheCall, 3, 4, "memccpy"); break; case Builtin::BI__builtin___snprintf_chk: + SemaBuiltinMemChkCall(*this, FDecl, TheCall, 1, 3, "snprintf"); + break; case Builtin::BI__builtin___vsnprintf_chk: - SemaBuiltinMemChkCall(*this, FDecl, TheCall, 1, 3); + SemaBuiltinMemChkCall(*this, FDecl, TheCall, 1, 3, "vsnprintf"); break; case Builtin::BI__builtin_call_with_static_chain: if (SemaBuiltinCallWithStaticChain(*this, TheCall)) @@ -1259,7 +1359,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, return ExprError(); if (CheckCXXThrowOperand( - TheCall->getLocStart(), + TheCall->getBeginLoc(), Context.getExceptionObjectType(FDecl->getParamDecl(0)->getType()), TheCall)) return ExprError(); @@ -1273,7 +1373,6 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, // check for the argument. if (SemaBuiltinRWPipe(*this, TheCall)) return ExprError(); - TheCall->setType(Context.IntTy); break; case Builtin::BIreserve_read_pipe: case Builtin::BIreserve_write_pipe: @@ -1305,7 +1404,6 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, case Builtin::BIget_pipe_max_packets: if (SemaBuiltinPipePackets(*this, TheCall)) return ExprError(); - TheCall->setType(Context.UnsignedIntTy); break; case Builtin::BIto_global: case Builtin::BIto_local: @@ -1477,8 +1575,8 @@ bool Sema::CheckNeonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { TV = Result.getLimitedValue(64); if ((TV > 63) || (mask & (1ULL << TV)) == 0) - return Diag(TheCall->getLocStart(), diag::err_invalid_neon_type_code) - << TheCall->getArg(ImmArg)->getSourceRange(); + return Diag(TheCall->getBeginLoc(), diag::err_invalid_neon_type_code) + << TheCall->getArg(ImmArg)->getSourceRange(); } if (PtrArgNum >= 0) { @@ -1503,7 +1601,7 @@ bool Sema::CheckNeonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS); if (RHS.isInvalid()) return true; - if (DiagnoseAssignmentResult(ConvTy, Arg->getLocStart(), LHSTy, RHSTy, + if (DiagnoseAssignmentResult(ConvTy, Arg->getBeginLoc(), LHSTy, RHSTy, RHS.get(), AA_Assigning)) return true; } @@ -1557,8 +1655,8 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall, const PointerType *pointerType = PointerArg->getType()->getAs<PointerType>(); if (!pointerType) { - Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer) - << PointerArg->getType() << PointerArg->getSourceRange(); + Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer) + << PointerArg->getType() << PointerArg->getSourceRange(); return true; } @@ -1574,10 +1672,9 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall, CastKind CastNeeded = CK_NoOp; if (!AddrType.isAtLeastAsQualifiedAs(ValType)) { CastNeeded = CK_BitCast; - Diag(DRE->getLocStart(), diag::ext_typecheck_convert_discards_qualifiers) - << PointerArg->getType() - << Context.getPointerType(AddrType) - << AA_Passing << PointerArg->getSourceRange(); + Diag(DRE->getBeginLoc(), diag::ext_typecheck_convert_discards_qualifiers) + << PointerArg->getType() << Context.getPointerType(AddrType) + << AA_Passing << PointerArg->getSourceRange(); } // Finally, do the cast and replace the argument with the corrected version. @@ -1592,16 +1689,16 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall, // In general, we allow ints, floats and pointers to be loaded and stored. if (!ValType->isIntegerType() && !ValType->isAnyPointerType() && !ValType->isBlockPointerType() && !ValType->isFloatingType()) { - Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer_intfltptr) - << PointerArg->getType() << PointerArg->getSourceRange(); + Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intfltptr) + << PointerArg->getType() << PointerArg->getSourceRange(); return true; } // But ARM doesn't have instructions to deal with 128-bit versions. if (Context.getTypeSize(ValType) > MaxWidth) { assert(MaxWidth == 64 && "Diagnostic unexpectedly inaccurate"); - Diag(DRE->getLocStart(), diag::err_atomic_exclusive_builtin_pointer_size) - << PointerArg->getType() << PointerArg->getSourceRange(); + Diag(DRE->getBeginLoc(), diag::err_atomic_exclusive_builtin_pointer_size) + << PointerArg->getType() << PointerArg->getSourceRange(); return true; } @@ -1614,8 +1711,8 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall, case Qualifiers::OCL_Weak: case Qualifiers::OCL_Strong: case Qualifiers::OCL_Autoreleasing: - Diag(DRE->getLocStart(), diag::err_arc_atomic_ownership) - << ValType << PointerArg->getSourceRange(); + Diag(DRE->getBeginLoc(), diag::err_arc_atomic_ownership) + << ValType << PointerArg->getSourceRange(); return true; } @@ -1715,6 +1812,16 @@ bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, BuiltinID == AArch64::BI__builtin_arm_wsrp) return SemaBuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true); + // Only check the valid encoding range. Any constant in this range would be + // converted to a register of the form S1_2_C3_C4_5. Let the hardware throw + // an exception for incorrect registers. This matches MSVC behavior. + if (BuiltinID == AArch64::BI_ReadStatusReg || + BuiltinID == AArch64::BI_WriteStatusReg) + return SemaBuiltinConstantArgRange(TheCall, 0, 0, 0x7fff); + + if (BuiltinID == AArch64::BI__getReg) + return SemaBuiltinConstantArgRange(TheCall, 0, 0, 31); + if (CheckNeonBuiltinFunctionCall(BuiltinID, TheCall)) return true; @@ -1732,783 +1839,820 @@ bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, } bool Sema::CheckHexagonBuiltinCpu(unsigned BuiltinID, CallExpr *TheCall) { - static const std::map<unsigned, std::vector<StringRef>> ValidCPU = { - { Hexagon::BI__builtin_HEXAGON_A6_vcmpbeq_notany, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_A6_vminub_RdP, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_M6_vabsdiffb, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_M6_vabsdiffub, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_and, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_nac, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_or, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_xacc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_and, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_nac, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_or, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_xacc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_S6_vsplatrbp, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_S6_vtrunehb_ppp, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_S6_vtrunohb_ppp, {"v62", "v65"} }, + struct BuiltinAndString { + unsigned BuiltinID; + const char *Str; }; - static const std::map<unsigned, std::vector<StringRef>> ValidHVX = { - { Hexagon::BI__builtin_HEXAGON_V6_extractw, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_extractw_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_hi, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_hi_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_lo, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_lo_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_lvsplatb, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_lvsplatb_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_lvsplath, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_lvsplath_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_lvsplatw, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_lvsplatw_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_pred_and, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_pred_and_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_pred_and_n, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_pred_and_n_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_pred_not, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_pred_not_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_pred_or, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_pred_or_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_pred_or_n, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_pred_or_n_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2v2, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2v2_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_pred_xor, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_pred_xor_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_shuffeqh, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_shuffeqh_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_shuffeqw, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_shuffeqw_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vabsb, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vabsb_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vabsb_sat, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vabsb_sat_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffub, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffub_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffuh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffuh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffw, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffw_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vabsh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vabsh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vabsh_sat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vabsh_sat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vabsw, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vabsw_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vabsw_sat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vabsw_sat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddb, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddb_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddb_dv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddb_dv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat_dv, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat_dv_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddcarry, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddcarry_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddclbh, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddclbh_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddclbw, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddclbw_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddh_dv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddh_dv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat_dv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat_dv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddhw, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddhw_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddhw_acc, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddhw_acc_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddubh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddubh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddubh_acc, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddubh_acc_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat_dv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat_dv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddububb_sat, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddububb_sat_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat_dv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat_dv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vadduhw, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vadduhw_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vadduhw_acc, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vadduhw_acc_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat_dv, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat_dv_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddw, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddw_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddw_dv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddw_dv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat_dv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat_dv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_valignb, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_valignb_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_valignbi, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_valignbi_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vand, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vand_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt_acc, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt_acc_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vandqrt, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vandqrt_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vandqrt_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vandqrt_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vandvnqv, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vandvnqv_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vandvqv, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vandvqv_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vandvrt, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vandvrt_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vandvrt_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vandvrt_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaslh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaslh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaslh_acc, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaslh_acc_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaslhv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaslhv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaslw, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaslw_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaslw_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaslw_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaslwv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vaslwv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrh_acc, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrh_acc_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrhbrndsat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrhbrndsat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrhbsat, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrhbsat_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrhubrndsat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrhubrndsat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrhubsat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrhubsat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrhv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrhv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasruhubrndsat, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasruhubrndsat_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasruhubsat, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasruhubsat_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhrndsat, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhrndsat_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhsat, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhsat_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrw, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrw_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrw_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrw_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrwh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrwh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrwhrndsat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrwhrndsat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrwhsat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrwhsat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhrndsat, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhrndsat_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhsat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhsat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrwv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vasrwv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vassign, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vassign_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vassignp, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vassignp_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vavgb, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vavgb_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vavgbrnd, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vavgbrnd_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vavgh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vavgh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vavghrnd, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vavghrnd_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vavgub, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vavgub_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vavgubrnd, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vavgubrnd_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vavguh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vavguh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vavguhrnd, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vavguhrnd_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vavguw, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vavguw_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vavguwrnd, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vavguwrnd_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vavgw, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vavgw_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vavgwrnd, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vavgwrnd_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vcl0h, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vcl0h_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vcl0w, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vcl0w_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vcombine, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vcombine_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vd0, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vd0_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdd0, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdd0_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdealb, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdealb_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdealb4w, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdealb4w_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdealh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdealh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdealvdd, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdealvdd_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdelta, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdelta_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_veqb, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_veqb_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_veqb_and, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_veqb_and_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_veqb_or, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_veqb_or_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_veqb_xor, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_veqb_xor_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_veqh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_veqh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_veqh_and, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_veqh_and_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_veqh_or, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_veqh_or_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_veqh_xor, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_veqh_xor_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_veqw, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_veqw_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_veqw_and, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_veqw_and_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_veqw_or, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_veqw_or_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_veqw_xor, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_veqw_xor_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtb, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtb_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtb_and, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtb_and_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtb_or, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtb_or_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtb_xor, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtb_xor_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgth, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgth_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgth_and, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgth_and_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgth_or, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgth_or_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgth_xor, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgth_xor_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtub, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtub_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtub_and, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtub_and_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtub_or, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtub_or_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtub_xor, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtub_xor_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtuh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_and, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_and_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_or, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_or_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_xor, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_xor_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtuw, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_and, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_and_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_or, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_or_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_xor, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_xor_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtw, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtw_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtw_and, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtw_and_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtw_or, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtw_or_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtw_xor, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vgtw_xor_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vinsertwr, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vinsertwr_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlalignb, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlalignb_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlalignbi, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlalignbi_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlsrb, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlsrb_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlsrh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlsrh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlsrhv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlsrhv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlsrw, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlsrw_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlsrwv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlsrwv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlut4, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlut4_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlutvvbi, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlutvvbi_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_nm, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_nm_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracci, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracci_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlutvwhi, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlutvwhi_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_nm, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_nm_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracci, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracci_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmaxb, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmaxb_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmaxh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmaxh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmaxub, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmaxub_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmaxuh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmaxuh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmaxw, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmaxw_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vminb, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vminb_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vminh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vminh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vminub, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vminub_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vminuh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vminuh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vminw, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vminw_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpabus, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpabus_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpabus_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpabus_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpabusv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpabusv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu_acc, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu_acc_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpabuuv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpabuuv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpahb, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpahb_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpahb_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpahb_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpahhsat, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpahhsat_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb_acc, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb_acc_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpauhuhsat, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpauhuhsat_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpsuhuhsat, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpsuhuhsat_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpybus, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpybus_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpybus_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpybus_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpybv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpybv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpybv_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpybv_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh_64, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh_64_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyh_acc, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyh_acc_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsat_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsat_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsrs, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsrs_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyhss, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyhss_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyhvsrs, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyhvsrs_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyieoh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyieoh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewh_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewh_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewuh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewuh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewuh_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewuh_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyih, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyih_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyih_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyih_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyihb, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyihb_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyihb_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyihb_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyiowh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyiowh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwb, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwb_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwb_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwb_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwh_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwh_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwub, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwub_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwub_acc, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwub_acc_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_64_acc, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_64_acc_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_rnd, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_rnd_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_rnd_sacc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_rnd_sacc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_sacc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_sacc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyub, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyub_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyub_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyub_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyubv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyubv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyubv_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyubv_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyuh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyuh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyuh_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyuh_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhe, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhe_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhe_acc, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhe_acc_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhv_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhv_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmux, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vmux_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vnavgb, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vnavgb_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vnavgh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vnavgh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vnavgub, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vnavgub_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vnavgw, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vnavgw_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vnormamth, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vnormamth_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vnormamtw, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vnormamtw_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vnot, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vnot_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vor, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vor_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vpackeb, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vpackeb_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vpackeh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vpackeh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vpackhb_sat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vpackhb_sat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vpackhub_sat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vpackhub_sat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vpackob, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vpackob_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vpackoh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vpackoh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vpackwh_sat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vpackwh_sat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vpackwuh_sat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vpackwuh_sat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vpopcounth, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vpopcounth_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vprefixqb, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vprefixqb_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vprefixqh, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vprefixqh_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vprefixqw, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vprefixqw_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrdelta, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrdelta_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpybub_rtt, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpybub_rtt_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpybub_rtt_acc, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpybub_rtt_acc_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpybus, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpybus_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpybus_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpybus_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusv_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusv_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpybv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpybv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpybv_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpybv_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_rtt, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_rtt_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_rtt_acc, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_rtt_acc_128B, {"v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubv_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubv_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vror, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vror_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vroundhb, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vroundhb_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vroundhub, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vroundhub_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrounduhub, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrounduhub_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrounduwuh, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrounduwuh_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vroundwh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vroundwh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vroundwuh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vroundwuh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsathub, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsathub_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsatuwuh, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsatuwuh_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsatwh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsatwh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsb, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsb_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vshufeh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vshufeh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vshuffb, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vshuffb_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vshuffeb, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vshuffeb_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vshuffh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vshuffh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vshuffob, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vshuffob_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vshuffvdd, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vshuffvdd_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vshufoeb, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vshufoeb_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vshufoeh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vshufoeh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vshufoh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vshufoh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubb, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubb_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubb_dv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubb_dv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubbsat, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubbsat_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubbsat_dv, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubbsat_dv_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubcarry, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubcarry_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubh_dv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubh_dv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubhsat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubhsat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubhsat_dv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubhsat_dv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubhw, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubhw_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsububh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsububh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsububsat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsububsat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsububsat_dv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsububsat_dv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubububb_sat, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubububb_sat_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubuhsat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubuhsat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubuhsat_dv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubuhsat_dv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubuhw, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubuhw_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubuwsat, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubuwsat_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubuwsat_dv, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubuwsat_dv_128B, {"v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubw, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubw_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubw_dv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubw_dv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubwsat, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubwsat_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubwsat_dv, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vsubwsat_dv_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vswap, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vswap_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vtmpyb, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vtmpyb_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vtmpyb_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vtmpyb_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vtmpybus, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vtmpybus_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vtmpybus_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vtmpybus_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vtmpyhb, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vtmpyhb_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vtmpyhb_acc, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vtmpyhb_acc_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vunpackb, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vunpackb_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vunpackh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vunpackh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vunpackob, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vunpackob_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vunpackoh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vunpackoh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vunpackub, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vunpackub_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vunpackuh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vunpackuh_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vxor, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vxor_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vzb, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vzb_128B, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vzh, {"v60", "v62", "v65"} }, - { Hexagon::BI__builtin_HEXAGON_V6_vzh_128B, {"v60", "v62", "v65"} }, + static BuiltinAndString ValidCPU[] = { + { Hexagon::BI__builtin_HEXAGON_A6_vcmpbeq_notany, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_A6_vminub_RdP, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_F2_dfadd, "v66" }, + { Hexagon::BI__builtin_HEXAGON_F2_dfsub, "v66" }, + { Hexagon::BI__builtin_HEXAGON_M2_mnaci, "v66" }, + { Hexagon::BI__builtin_HEXAGON_M6_vabsdiffb, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_M6_vabsdiffub, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_S2_mask, "v66" }, + { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_and, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_nac, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_or, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_xacc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_and, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_nac, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_or, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_xacc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_S6_vsplatrbp, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_S6_vtrunehb_ppp, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_S6_vtrunohb_ppp, "v62,v65,v66" }, + }; + + static BuiltinAndString ValidHVX[] = { + { Hexagon::BI__builtin_HEXAGON_V6_hi, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_hi_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_lo, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_lo_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_extractw, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_extractw_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_lvsplatb, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_lvsplatb_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_lvsplath, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_lvsplath_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_lvsplatw, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_lvsplatw_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_and, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_and_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_and_n, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_and_n_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_not, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_not_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_or, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_or_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_or_n, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_or_n_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2v2, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2v2_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_xor, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_xor_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_shuffeqh, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_shuffeqh_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_shuffeqw, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_shuffeqw_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsb, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsb_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsb_sat, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsb_sat_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffub, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffub_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffuh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffuh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffw, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffw_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsh_sat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsh_sat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsw, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsw_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsw_sat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsw_sat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddb, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddb_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddb_dv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddb_dv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat_dv, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat_dv_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddcarry, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddcarry_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddcarrysat, "v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddcarrysat_128B, "v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddclbh, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddclbh_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddclbw, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddclbw_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddh_dv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddh_dv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat_dv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat_dv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddhw, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddhw_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddhw_acc, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddhw_acc_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddubh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddubh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddubh_acc, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddubh_acc_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat_dv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat_dv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddububb_sat, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddububb_sat_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat_dv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat_dv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vadduhw, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vadduhw_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vadduhw_acc, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vadduhw_acc_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat_dv, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat_dv_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddw, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddw_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddw_dv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddw_dv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat_dv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat_dv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_valignb, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_valignb_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_valignbi, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_valignbi_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vand, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vand_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt_acc, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt_acc_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vandqrt, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vandqrt_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vandqrt_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vandqrt_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vandvnqv, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vandvnqv_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vandvqv, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vandvqv_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vandvrt, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vandvrt_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vandvrt_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vandvrt_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaslh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaslh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaslh_acc, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaslh_acc_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaslhv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaslhv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaslw, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaslw_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaslw_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaslw_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaslwv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vaslwv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrh_acc, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrh_acc_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrhbrndsat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrhbrndsat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrhbsat, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrhbsat_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrhubrndsat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrhubrndsat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrhubsat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrhubsat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrhv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrhv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasr_into, "v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasr_into_128B, "v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasruhubrndsat, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasruhubrndsat_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasruhubsat, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasruhubsat_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhrndsat, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhrndsat_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhsat, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhsat_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrw, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrw_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrw_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrw_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrwh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrwh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrwhrndsat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrwhrndsat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrwhsat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrwhsat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhrndsat, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhrndsat_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhsat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhsat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrwv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrwv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vassign, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vassign_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vassignp, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vassignp_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgb, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgb_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgbrnd, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgbrnd_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vavghrnd, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vavghrnd_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgub, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgub_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgubrnd, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgubrnd_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vavguh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vavguh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vavguhrnd, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vavguhrnd_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vavguw, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vavguw_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vavguwrnd, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vavguwrnd_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgw, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgw_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgwrnd, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgwrnd_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vcl0h, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vcl0h_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vcl0w, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vcl0w_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vcombine, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vcombine_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vd0, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vd0_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdd0, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdd0_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdealb, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdealb_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdealb4w, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdealb4w_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdealh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdealh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdealvdd, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdealvdd_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdelta, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdelta_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_veqb, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_veqb_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_veqb_and, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_veqb_and_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_veqb_or, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_veqb_or_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_veqb_xor, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_veqb_xor_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_veqh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_veqh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_veqh_and, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_veqh_and_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_veqh_or, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_veqh_or_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_veqh_xor, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_veqh_xor_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_veqw, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_veqw_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_veqw_and, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_veqw_and_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_veqw_or, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_veqw_or_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_veqw_xor, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_veqw_xor_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtb, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtb_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtb_and, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtb_and_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtb_or, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtb_or_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtb_xor, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtb_xor_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgth, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgth_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgth_and, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgth_and_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgth_or, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgth_or_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgth_xor, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgth_xor_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtub, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtub_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtub_and, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtub_and_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtub_or, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtub_or_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtub_xor, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtub_xor_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_and, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_and_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_or, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_or_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_xor, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_xor_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuw, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_and, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_and_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_or, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_or_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_xor, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_xor_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtw, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtw_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtw_and, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtw_and_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtw_or, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtw_or_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtw_xor, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtw_xor_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vinsertwr, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vinsertwr_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlalignb, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlalignb_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlalignbi, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlalignbi_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlsrb, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlsrb_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlsrh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlsrh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlsrhv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlsrhv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlsrw, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlsrw_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlsrwv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlsrwv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlut4, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlut4_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvvbi, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvvbi_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_nm, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_nm_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracci, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracci_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvwhi, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvwhi_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_nm, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_nm_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracci, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracci_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmaxb, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmaxb_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmaxh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmaxh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmaxub, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmaxub_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmaxuh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmaxuh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmaxw, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmaxw_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vminb, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vminb_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vminh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vminh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vminub, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vminub_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vminuh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vminuh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vminw, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vminw_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpabus, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpabus_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpabus_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpabus_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpabusv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpabusv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu_acc, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu_acc_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpabuuv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpabuuv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpahb, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpahb_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpahb_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpahb_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpahhsat, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpahhsat_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb_acc, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb_acc_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpauhuhsat, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpauhuhsat_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpsuhuhsat, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpsuhuhsat_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpybus, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpybus_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpybus_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpybus_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpybv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpybv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpybv_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpybv_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh_64, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh_64_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyh_acc, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyh_acc_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsat_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsat_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsrs, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsrs_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhss, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhss_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhvsrs, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhvsrs_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyieoh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyieoh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewh_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewh_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewuh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewuh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewuh_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewuh_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyih, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyih_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyih_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyih_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyihb, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyihb_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyihb_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyihb_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiowh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiowh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwb, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwb_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwb_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwb_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwh_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwh_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwub, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwub_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwub_acc, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwub_acc_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_64_acc, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_64_acc_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_rnd, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_rnd_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_rnd_sacc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_rnd_sacc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_sacc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_sacc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyub, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyub_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyub_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyub_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyubv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyubv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyubv_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyubv_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyuh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyuh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyuh_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyuh_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhe, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhe_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhe_acc, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhe_acc_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhv_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhv_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmux, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vmux_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vnavgb, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vnavgb_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vnavgh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vnavgh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vnavgub, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vnavgub_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vnavgw, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vnavgw_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vnormamth, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vnormamth_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vnormamtw, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vnormamtw_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vnot, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vnot_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vor, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vor_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackeb, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackeb_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackeh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackeh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackhb_sat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackhb_sat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackhub_sat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackhub_sat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackob, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackob_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackoh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackoh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackwh_sat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackwh_sat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackwuh_sat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackwuh_sat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vpopcounth, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vpopcounth_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vprefixqb, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vprefixqb_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vprefixqh, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vprefixqh_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vprefixqw, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vprefixqw_128B, "v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrdelta, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrdelta_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybub_rtt, "v65" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybub_rtt_128B, "v65" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybub_rtt_acc, "v65" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybub_rtt_acc_128B, "v65" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybus, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybus_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybus_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybus_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusv_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusv_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybv_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybv_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_rtt, "v65" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_rtt_128B, "v65" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_rtt_acc, "v65" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_rtt_acc_128B, "v65" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubv_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubv_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vror, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vror_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrotr, "v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrotr_128B, "v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vroundhb, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vroundhb_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vroundhub, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vroundhub_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrounduhub, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrounduhub_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrounduwuh, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrounduwuh_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vroundwh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vroundwh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vroundwuh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vroundwuh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsatdw, "v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsatdw_128B, "v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsathub, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsathub_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsatuwuh, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsatuwuh_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsatwh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsatwh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsb, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsb_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vshufeh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vshufeh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vshuffb, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vshuffb_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vshuffeb, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vshuffeb_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vshuffh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vshuffh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vshuffob, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vshuffob_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vshuffvdd, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vshuffvdd_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vshufoeb, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vshufoeb_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vshufoeh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vshufoeh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vshufoh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vshufoh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubb, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubb_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubb_dv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubb_dv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubbsat, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubbsat_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubbsat_dv, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubbsat_dv_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubcarry, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubcarry_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubh_dv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubh_dv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubhsat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubhsat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubhsat_dv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubhsat_dv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubhw, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubhw_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsububh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsububh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsububsat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsububsat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsububsat_dv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsububsat_dv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubububb_sat, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubububb_sat_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubuhsat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubuhsat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubuhsat_dv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubuhsat_dv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubuhw, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubuhw_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubuwsat, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubuwsat_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubuwsat_dv, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubuwsat_dv_128B, "v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubw, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubw_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubw_dv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubw_dv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubwsat, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubwsat_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubwsat_dv, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubwsat_dv_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vswap, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vswap_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vtmpyb, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vtmpyb_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vtmpyb_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vtmpyb_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vtmpybus, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vtmpybus_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vtmpybus_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vtmpybus_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vtmpyhb, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vtmpyhb_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vtmpyhb_acc, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vtmpyhb_acc_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vunpackb, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vunpackb_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vunpackh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vunpackh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vunpackob, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vunpackob_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vunpackoh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vunpackoh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vunpackub, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vunpackub_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vunpackuh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vunpackuh_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vxor, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vxor_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vzb, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vzb_128B, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vzh, "v60,v62,v65,v66" }, + { Hexagon::BI__builtin_HEXAGON_V6_vzh_128B, "v60,v62,v65,v66" }, + }; + + // Sort the tables on first execution so we can binary search them. + auto SortCmp = [](const BuiltinAndString &LHS, const BuiltinAndString &RHS) { + return LHS.BuiltinID < RHS.BuiltinID; + }; + static const bool SortOnce = + (llvm::sort(ValidCPU, SortCmp), + llvm::sort(ValidHVX, SortCmp), true); + (void)SortOnce; + auto LowerBoundCmp = [](const BuiltinAndString &BI, unsigned BuiltinID) { + return BI.BuiltinID < BuiltinID; }; const TargetInfo &TI = Context.getTargetInfo(); - auto FC = ValidCPU.find(BuiltinID); - if (FC != ValidCPU.end()) { + const BuiltinAndString *FC = + std::lower_bound(std::begin(ValidCPU), std::end(ValidCPU), BuiltinID, + LowerBoundCmp); + if (FC != std::end(ValidCPU) && FC->BuiltinID == BuiltinID) { const TargetOptions &Opts = TI.getTargetOpts(); StringRef CPU = Opts.CPU; if (!CPU.empty()) { assert(CPU.startswith("hexagon") && "Unexpected CPU name"); CPU.consume_front("hexagon"); - if (llvm::none_of(FC->second, [CPU](StringRef S) { return S == CPU; })) - return Diag(TheCall->getLocStart(), + SmallVector<StringRef, 3> CPUs; + StringRef(FC->Str).split(CPUs, ','); + if (llvm::none_of(CPUs, [CPU](StringRef S) { return S == CPU; })) + return Diag(TheCall->getBeginLoc(), diag::err_hexagon_builtin_unsupported_cpu); } } - auto FH = ValidHVX.find(BuiltinID); - if (FH != ValidHVX.end()) { + const BuiltinAndString *FH = + std::lower_bound(std::begin(ValidHVX), std::end(ValidHVX), BuiltinID, + LowerBoundCmp); + if (FH != std::end(ValidHVX) && FH->BuiltinID == BuiltinID) { if (!TI.hasFeature("hvx")) - return Diag(TheCall->getLocStart(), + return Diag(TheCall->getBeginLoc(), diag::err_hexagon_builtin_requires_hvx); - bool IsValid = llvm::any_of(FH->second, + SmallVector<StringRef, 3> HVXs; + StringRef(FH->Str).split(HVXs, ','); + bool IsValid = llvm::any_of(HVXs, [&TI] (StringRef V) { std::string F = "hvx" + V.str(); return TI.hasFeature(F); }); if (!IsValid) - return Diag(TheCall->getLocStart(), + return Diag(TheCall->getBeginLoc(), diag::err_hexagon_builtin_unsupported_hvx); } @@ -2517,15 +2661,17 @@ bool Sema::CheckHexagonBuiltinCpu(unsigned BuiltinID, CallExpr *TheCall) { bool Sema::CheckHexagonBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall) { struct ArgInfo { - ArgInfo(unsigned O, bool S, unsigned W, unsigned A) - : OpNum(O), IsSigned(S), BitWidth(W), Align(A) {} - unsigned OpNum = 0; - bool IsSigned = false; - unsigned BitWidth = 0; - unsigned Align = 0; + uint8_t OpNum; + bool IsSigned; + uint8_t BitWidth; + uint8_t Align; + }; + struct BuiltinInfo { + unsigned BuiltinID; + ArgInfo Infos[2]; }; - static const std::map<unsigned, std::vector<ArgInfo>> Infos = { + static BuiltinInfo Infos[] = { { Hexagon::BI__builtin_circ_ldd, {{ 3, true, 4, 3 }} }, { Hexagon::BI__builtin_circ_ldw, {{ 3, true, 4, 2 }} }, { Hexagon::BI__builtin_circ_ldh, {{ 3, true, 4, 1 }} }, @@ -2711,15 +2857,33 @@ bool Sema::CheckHexagonBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall) { {{ 3, false, 1, 0 }} }, }; - auto F = Infos.find(BuiltinID); - if (F == Infos.end()) + // Use a dynamically initialized static to sort the table exactly once on + // first run. + static const bool SortOnce = + (llvm::sort(Infos, + [](const BuiltinInfo &LHS, const BuiltinInfo &RHS) { + return LHS.BuiltinID < RHS.BuiltinID; + }), + true); + (void)SortOnce; + + const BuiltinInfo *F = + std::lower_bound(std::begin(Infos), std::end(Infos), BuiltinID, + [](const BuiltinInfo &BI, unsigned BuiltinID) { + return BI.BuiltinID < BuiltinID; + }); + if (F == std::end(Infos) || F->BuiltinID != BuiltinID) return false; bool Error = false; - for (const ArgInfo &A : F->second) { - int32_t Min = A.IsSigned ? -(1 << (A.BitWidth-1)) : 0; - int32_t Max = (1 << (A.IsSigned ? A.BitWidth-1 : A.BitWidth)) - 1; + for (const ArgInfo &A : F->Infos) { + // Ignore empty ArgInfo elements. + if (A.BitWidth == 0) + continue; + + int32_t Min = A.IsSigned ? -(1 << (A.BitWidth - 1)) : 0; + int32_t Max = (1 << (A.IsSigned ? A.BitWidth - 1 : A.BitWidth)) - 1; if (!A.Align) { Error |= SemaBuiltinConstantArgRange(TheCall, A.OpNum, Min, Max); } else { @@ -2760,7 +2924,7 @@ bool Sema::CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case Mips::BI__builtin_mips_precr_sra_ph_w: i = 2; l = 0; u = 31; break; case Mips::BI__builtin_mips_precr_sra_r_ph_w: i = 2; l = 0; u = 31; break; case Mips::BI__builtin_mips_prepend: i = 2; l = 0; u = 31; break; - // MSA instrinsics. Instructions (which the intrinsics maps to) which use the + // MSA intrinsics. Instructions (which the intrinsics maps to) which use the // df/m field. // These intrinsics take an unsigned 3 bit immediate. case Mips::BI__builtin_msa_bclri_b: @@ -2903,14 +3067,14 @@ bool Sema::CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case Mips::BI__builtin_msa_ldi_h: case Mips::BI__builtin_msa_ldi_w: case Mips::BI__builtin_msa_ldi_d: i = 0; l = -512; u = 511; break; - case Mips::BI__builtin_msa_ld_b: i = 1; l = -512; u = 511; m = 16; break; - case Mips::BI__builtin_msa_ld_h: i = 1; l = -1024; u = 1022; m = 16; break; - case Mips::BI__builtin_msa_ld_w: i = 1; l = -2048; u = 2044; m = 16; break; - case Mips::BI__builtin_msa_ld_d: i = 1; l = -4096; u = 4088; m = 16; break; - case Mips::BI__builtin_msa_st_b: i = 2; l = -512; u = 511; m = 16; break; - case Mips::BI__builtin_msa_st_h: i = 2; l = -1024; u = 1022; m = 16; break; - case Mips::BI__builtin_msa_st_w: i = 2; l = -2048; u = 2044; m = 16; break; - case Mips::BI__builtin_msa_st_d: i = 2; l = -4096; u = 4088; m = 16; break; + case Mips::BI__builtin_msa_ld_b: i = 1; l = -512; u = 511; m = 1; break; + case Mips::BI__builtin_msa_ld_h: i = 1; l = -1024; u = 1022; m = 2; break; + case Mips::BI__builtin_msa_ld_w: i = 1; l = -2048; u = 2044; m = 4; break; + case Mips::BI__builtin_msa_ld_d: i = 1; l = -4096; u = 4088; m = 8; break; + case Mips::BI__builtin_msa_st_b: i = 2; l = -512; u = 511; m = 1; break; + case Mips::BI__builtin_msa_st_h: i = 2; l = -1024; u = 1022; m = 2; break; + case Mips::BI__builtin_msa_st_w: i = 2; l = -2048; u = 2044; m = 4; break; + case Mips::BI__builtin_msa_st_d: i = 2; l = -4096; u = 4088; m = 8; break; } if (!m) @@ -2935,15 +3099,22 @@ bool Sema::CheckPPCBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { BuiltinID == PPC::BI__builtin_divdeu; if (Is64BitBltin && !IsTarget64Bit) - return Diag(TheCall->getLocStart(), diag::err_64_bit_builtin_32_bit_tgt) - << TheCall->getSourceRange(); + return Diag(TheCall->getBeginLoc(), diag::err_64_bit_builtin_32_bit_tgt) + << TheCall->getSourceRange(); if ((IsBltinExtDiv && !Context.getTargetInfo().hasFeature("extdiv")) || (BuiltinID == PPC::BI__builtin_bpermd && !Context.getTargetInfo().hasFeature("bpermd"))) - return Diag(TheCall->getLocStart(), diag::err_ppc_builtin_only_on_pwr7) + return Diag(TheCall->getBeginLoc(), diag::err_ppc_builtin_only_on_pwr7) << TheCall->getSourceRange(); + auto SemaVSXCheck = [&](CallExpr *TheCall) -> bool { + if (!Context.getTargetInfo().hasFeature("vsx")) + return Diag(TheCall->getBeginLoc(), diag::err_ppc_builtin_only_on_pwr7) + << TheCall->getSourceRange(); + return false; + }; + switch (BuiltinID) { default: return false; case PPC::BI__builtin_altivec_crypto_vshasigmaw: @@ -2962,6 +3133,11 @@ bool Sema::CheckPPCBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case PPC::BI__builtin_vsx_xxpermdi: case PPC::BI__builtin_vsx_xxsldwi: return SemaBuiltinVSX(TheCall); + case PPC::BI__builtin_unpack_vector_int128: + return SemaVSXCheck(TheCall) || + SemaBuiltinConstantArgRange(TheCall, 1, 0, 1); + case PPC::BI__builtin_pack_vector_int128: + return SemaVSXCheck(TheCall); } return SemaBuiltinConstantArgRange(TheCall, i, l, u); } @@ -2973,7 +3149,7 @@ bool Sema::CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, llvm::APSInt AbortCode(32); if (Arg->isIntegerConstantExpr(AbortCode, Context) && AbortCode.getSExtValue() >= 0 && AbortCode.getSExtValue() < 256) - return Diag(Arg->getLocStart(), diag::err_systemz_invalid_tabort_code) + return Diag(Arg->getBeginLoc(), diag::err_systemz_invalid_tabort_code) << Arg->getSourceRange(); } @@ -3037,14 +3213,14 @@ static bool SemaBuiltinCpuSupports(Sema &S, CallExpr *TheCall) { // Check if the argument is a string literal. if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts())) - return S.Diag(TheCall->getLocStart(), diag::err_expr_not_string_literal) + return S.Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal) << Arg->getSourceRange(); // Check the contents of the string. StringRef Feature = cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString(); if (!S.Context.getTargetInfo().validateCpuSupports(Feature)) - return S.Diag(TheCall->getLocStart(), diag::err_invalid_cpu_supports) + return S.Diag(TheCall->getBeginLoc(), diag::err_invalid_cpu_supports) << Arg->getSourceRange(); return false; } @@ -3057,14 +3233,14 @@ static bool SemaBuiltinCpuIs(Sema &S, CallExpr *TheCall) { // Check if the argument is a string literal. if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts())) - return S.Diag(TheCall->getLocStart(), diag::err_expr_not_string_literal) + return S.Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal) << Arg->getSourceRange(); // Check the contents of the string. StringRef Feature = cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString(); if (!S.Context.getTargetInfo().validateCpuIs(Feature)) - return S.Diag(TheCall->getLocStart(), diag::err_invalid_cpu_is) + return S.Diag(TheCall->getBeginLoc(), diag::err_invalid_cpu_is) << Arg->getSourceRange(); return false; } @@ -3267,8 +3443,8 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) { (HasRC && Result.getZExtValue() >= 8 && Result.getZExtValue() <= 11)) return false; - return Diag(TheCall->getLocStart(), diag::err_x86_builtin_invalid_rounding) - << Arg->getSourceRange(); + return Diag(TheCall->getBeginLoc(), diag::err_x86_builtin_invalid_rounding) + << Arg->getSourceRange(); } // Check if the gather/scatter scale is legal. @@ -3370,8 +3546,8 @@ bool Sema::CheckX86BuiltinGatherScatterScale(unsigned BuiltinID, if (Result == 1 || Result == 2 || Result == 4 || Result == 8) return false; - return Diag(TheCall->getLocStart(), diag::err_x86_builtin_invalid_scale) - << Arg->getSourceRange(); + return Diag(TheCall->getBeginLoc(), diag::err_x86_builtin_invalid_scale) + << Arg->getSourceRange(); } static bool isX86_32Builtin(unsigned BuiltinID) { @@ -3395,7 +3571,7 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { // Check for 32-bit only builtins on a 64-bit target. const llvm::Triple &TT = Context.getTargetInfo().getTriple(); if (TT.getArch() != llvm::Triple::x86 && isX86_32Builtin(BuiltinID)) - return Diag(TheCall->getCallee()->getLocStart(), + return Diag(TheCall->getCallee()->getBeginLoc(), diag::err_32_bit_builtin_64_bit_tgt); // If the intrinsic has rounding or SAE make sure its valid. @@ -3630,6 +3806,14 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_psrldqi128_byteshift: case X86::BI__builtin_ia32_psrldqi256_byteshift: case X86::BI__builtin_ia32_psrldqi512_byteshift: + case X86::BI__builtin_ia32_kshiftliqi: + case X86::BI__builtin_ia32_kshiftlihi: + case X86::BI__builtin_ia32_kshiftlisi: + case X86::BI__builtin_ia32_kshiftlidi: + case X86::BI__builtin_ia32_kshiftriqi: + case X86::BI__builtin_ia32_kshiftrihi: + case X86::BI__builtin_ia32_kshiftrisi: + case X86::BI__builtin_ia32_kshiftridi: i = 1; l = 0; u = 255; break; case X86::BI__builtin_ia32_vperm2f128_pd256: @@ -4056,7 +4240,7 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, CheckAbsoluteValueFunction(TheCall, FDecl); CheckMaxUnsignedZero(TheCall, FDecl); - if (getLangOpts().ObjC1) + if (getLangOpts().ObjC) DiagnoseCStringFormatDirectiveInCFAPI(*this, FDecl, Args, NumArgs); unsigned CMId = FDecl->getMemoryFunctionKind(); @@ -4312,15 +4496,15 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, ++AdjustedNumArgs; // Check we have the right number of arguments. if (TheCall->getNumArgs() < AdjustedNumArgs) { - Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) - << 0 << AdjustedNumArgs << TheCall->getNumArgs() - << TheCall->getCallee()->getSourceRange(); + Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args) + << 0 << AdjustedNumArgs << TheCall->getNumArgs() + << TheCall->getCallee()->getSourceRange(); return ExprError(); } else if (TheCall->getNumArgs() > AdjustedNumArgs) { - Diag(TheCall->getArg(AdjustedNumArgs)->getLocStart(), + Diag(TheCall->getArg(AdjustedNumArgs)->getBeginLoc(), diag::err_typecheck_call_too_many_args) - << 0 << AdjustedNumArgs << TheCall->getNumArgs() - << TheCall->getCallee()->getSourceRange(); + << 0 << AdjustedNumArgs << TheCall->getNumArgs() + << TheCall->getCallee()->getSourceRange(); return ExprError(); } @@ -4333,8 +4517,8 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, Ptr = ConvertedPtr.get(); const PointerType *pointerType = Ptr->getType()->getAs<PointerType>(); if (!pointerType) { - Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer) - << Ptr->getType() << Ptr->getSourceRange(); + Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer) + << Ptr->getType() << Ptr->getSourceRange(); return ExprError(); } @@ -4343,13 +4527,13 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, QualType ValType = AtomTy; // 'C' if (IsC11) { if (!AtomTy->isAtomicType()) { - Diag(DRE->getLocStart(), diag::err_atomic_op_needs_atomic) - << Ptr->getType() << Ptr->getSourceRange(); + Diag(DRE->getBeginLoc(), diag::err_atomic_op_needs_atomic) + << Ptr->getType() << Ptr->getSourceRange(); return ExprError(); } - if (AtomTy.isConstQualified() || + if ((Form != Load && Form != LoadCopy && AtomTy.isConstQualified()) || AtomTy.getAddressSpace() == LangAS::opencl_constant) { - Diag(DRE->getLocStart(), diag::err_atomic_op_needs_non_const_atomic) + Diag(DRE->getBeginLoc(), diag::err_atomic_op_needs_non_const_atomic) << (AtomTy.isConstQualified() ? 0 : 1) << Ptr->getType() << Ptr->getSourceRange(); return ExprError(); @@ -4357,8 +4541,8 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, ValType = AtomTy->getAs<AtomicType>()->getValueType(); } else if (Form != Load && Form != LoadCopy) { if (ValType.isConstQualified()) { - Diag(DRE->getLocStart(), diag::err_atomic_op_needs_non_const_pointer) - << Ptr->getType() << Ptr->getSourceRange(); + Diag(DRE->getBeginLoc(), diag::err_atomic_op_needs_non_const_pointer) + << Ptr->getType() << Ptr->getSourceRange(); return ExprError(); } } @@ -4368,33 +4552,33 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, // gcc does not enforce these rules for GNU atomics, but we do so for sanity. if (IsAddSub && !ValType->isIntegerType() && !ValType->isPointerType()) { - Diag(DRE->getLocStart(), diag::err_atomic_op_needs_atomic_int_or_ptr) - << IsC11 << Ptr->getType() << Ptr->getSourceRange(); + Diag(DRE->getBeginLoc(), diag::err_atomic_op_needs_atomic_int_or_ptr) + << IsC11 << Ptr->getType() << Ptr->getSourceRange(); return ExprError(); } if (IsMinMax) { const BuiltinType *BT = ValType->getAs<BuiltinType>(); if (!BT || (BT->getKind() != BuiltinType::Int && BT->getKind() != BuiltinType::UInt)) { - Diag(DRE->getLocStart(), diag::err_atomic_op_needs_int32_or_ptr); + Diag(DRE->getBeginLoc(), diag::err_atomic_op_needs_int32_or_ptr); return ExprError(); } } if (!IsAddSub && !IsMinMax && !ValType->isIntegerType()) { - Diag(DRE->getLocStart(), diag::err_atomic_op_bitwise_needs_atomic_int) - << IsC11 << Ptr->getType() << Ptr->getSourceRange(); + Diag(DRE->getBeginLoc(), diag::err_atomic_op_bitwise_needs_atomic_int) + << IsC11 << Ptr->getType() << Ptr->getSourceRange(); return ExprError(); } if (IsC11 && ValType->isPointerType() && - RequireCompleteType(Ptr->getLocStart(), ValType->getPointeeType(), + RequireCompleteType(Ptr->getBeginLoc(), ValType->getPointeeType(), diag::err_incomplete_type)) { return ExprError(); } } else if (IsN && !ValType->isIntegerType() && !ValType->isPointerType()) { // For __atomic_*_n operations, the value type must be a scalar integral or // pointer type which is 1, 2, 4, 8 or 16 bytes in length. - Diag(DRE->getLocStart(), diag::err_atomic_op_needs_atomic_int_or_ptr) - << IsC11 << Ptr->getType() << Ptr->getSourceRange(); + Diag(DRE->getBeginLoc(), diag::err_atomic_op_needs_atomic_int_or_ptr) + << IsC11 << Ptr->getType() << Ptr->getSourceRange(); return ExprError(); } @@ -4402,8 +4586,8 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, !AtomTy->isScalarType()) { // For GNU atomics, require a trivially-copyable type. This is not part of // the GNU atomics specification, but we enforce it for sanity. - Diag(DRE->getLocStart(), diag::err_atomic_op_needs_trivial_copy) - << Ptr->getType() << Ptr->getSourceRange(); + Diag(DRE->getBeginLoc(), diag::err_atomic_op_needs_trivial_copy) + << Ptr->getType() << Ptr->getSourceRange(); return ExprError(); } @@ -4418,8 +4602,8 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, case Qualifiers::OCL_Autoreleasing: // FIXME: Can this happen? By this point, ValType should be known // to be trivially copyable. - Diag(DRE->getLocStart(), diag::err_arc_atomic_ownership) - << ValType << Ptr->getSourceRange(); + Diag(DRE->getBeginLoc(), diag::err_arc_atomic_ownership) + << ValType << Ptr->getSourceRange(); return ExprError(); } @@ -4457,7 +4641,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, case 0: // The first argument is always a pointer. It has a fixed type. // It is always dereferenced, a nullptr is undefined. - CheckNonNullArgument(*this, TheCall->getArg(i), DRE->getLocStart()); + CheckNonNullArgument(*this, TheCall->getArg(i), DRE->getBeginLoc()); // Nothing else to do: we already know all we want about this pointer. continue; case 1: @@ -4471,14 +4655,14 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, else if (Form == Copy || Form == Xchg) { if (IsPassedByAddress) // The value pointer is always dereferenced, a nullptr is undefined. - CheckNonNullArgument(*this, TheCall->getArg(i), DRE->getLocStart()); + CheckNonNullArgument(*this, TheCall->getArg(i), DRE->getBeginLoc()); Ty = ByValType; } else if (Form == Arithmetic) Ty = Context.getPointerDiffType(); else { Expr *ValArg = TheCall->getArg(i); // The value pointer is always dereferenced, a nullptr is undefined. - CheckNonNullArgument(*this, ValArg, DRE->getLocStart()); + CheckNonNullArgument(*this, ValArg, DRE->getBeginLoc()); LangAS AS = LangAS::Default; // Keep address space of non-atomic pointer type. if (const PointerType *PtrTy = @@ -4493,7 +4677,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, // The third argument to compare_exchange / GNU exchange is the desired // value, either by-value (for the C11 and *_n variant) or as a pointer. if (IsPassedByAddress) - CheckNonNullArgument(*this, TheCall->getArg(i), DRE->getLocStart()); + CheckNonNullArgument(*this, TheCall->getArg(i), DRE->getBeginLoc()); Ty = ByValType; break; case 3: @@ -4558,7 +4742,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, llvm::APSInt Result(32); if (SubExprs[1]->isIntegerConstantExpr(Result, Context) && !isValidOrderingForOp(Result.getSExtValue(), Op)) - Diag(SubExprs[1]->getLocStart(), + Diag(SubExprs[1]->getBeginLoc(), diag::warn_atomic_op_has_invalid_memory_order) << SubExprs[1]->getSourceRange(); } @@ -4568,25 +4752,26 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, llvm::APSInt Result(32); if (Scope->isIntegerConstantExpr(Result, Context) && !ScopeModel->isValid(Result.getZExtValue())) { - Diag(Scope->getLocStart(), diag::err_atomic_op_has_invalid_synch_scope) + Diag(Scope->getBeginLoc(), diag::err_atomic_op_has_invalid_synch_scope) << Scope->getSourceRange(); } SubExprs.push_back(Scope); } - AtomicExpr *AE = new (Context) AtomicExpr(TheCall->getCallee()->getLocStart(), - SubExprs, ResultType, Op, - TheCall->getRParenLoc()); + AtomicExpr *AE = + new (Context) AtomicExpr(TheCall->getCallee()->getBeginLoc(), SubExprs, + ResultType, Op, TheCall->getRParenLoc()); if ((Op == AtomicExpr::AO__c11_atomic_load || Op == AtomicExpr::AO__c11_atomic_store || Op == AtomicExpr::AO__opencl_atomic_load || Op == AtomicExpr::AO__opencl_atomic_store ) && Context.AtomicUsesUnsupportedLibcall(AE)) - Diag(AE->getLocStart(), diag::err_atomic_load_store_uses_lib) + Diag(AE->getBeginLoc(), diag::err_atomic_load_store_uses_lib) << ((Op == AtomicExpr::AO__c11_atomic_load || - Op == AtomicExpr::AO__opencl_atomic_load) - ? 0 : 1); + Op == AtomicExpr::AO__opencl_atomic_load) + ? 0 + : 1); return AE; } @@ -4615,25 +4800,24 @@ static bool checkBuiltinArgument(Sema &S, CallExpr *E, unsigned ArgIndex) { return false; } -/// SemaBuiltinAtomicOverloaded - We have a call to a function like -/// __sync_fetch_and_add, which is an overloaded function based on the pointer -/// type of its first argument. The main ActOnCallExpr routines have already -/// promoted the types of arguments because all of these calls are prototyped as -/// void(...). +/// We have a call to a function like __sync_fetch_and_add, which is an +/// overloaded function based on the pointer type of its first argument. +/// The main ActOnCallExpr routines have already promoted the types of +/// arguments because all of these calls are prototyped as void(...). /// /// This function goes through and does final semantic checking for these -/// builtins, +/// builtins, as well as generating any warnings. ExprResult Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { - CallExpr *TheCall = (CallExpr *)TheCallResult.get(); - DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts()); + CallExpr *TheCall = static_cast<CallExpr *>(TheCallResult.get()); + Expr *Callee = TheCall->getCallee(); + DeclRefExpr *DRE = cast<DeclRefExpr>(Callee->IgnoreParenCasts()); FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl()); // Ensure that we have at least one argument to do type inference from. if (TheCall->getNumArgs() < 1) { - Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least) - << 0 << 1 << TheCall->getNumArgs() - << TheCall->getCallee()->getSourceRange(); + Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args_at_least) + << 0 << 1 << TheCall->getNumArgs() << Callee->getSourceRange(); return ExprError(); } @@ -4651,21 +4835,21 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { const PointerType *pointerType = FirstArg->getType()->getAs<PointerType>(); if (!pointerType) { - Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer) - << FirstArg->getType() << FirstArg->getSourceRange(); + Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer) + << FirstArg->getType() << FirstArg->getSourceRange(); return ExprError(); } QualType ValType = pointerType->getPointeeType(); if (!ValType->isIntegerType() && !ValType->isAnyPointerType() && !ValType->isBlockPointerType()) { - Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer_intptr) - << FirstArg->getType() << FirstArg->getSourceRange(); + Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intptr) + << FirstArg->getType() << FirstArg->getSourceRange(); return ExprError(); } if (ValType.isConstQualified()) { - Diag(DRE->getLocStart(), diag::err_atomic_builtin_cannot_be_const) + Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_cannot_be_const) << FirstArg->getType() << FirstArg->getSourceRange(); return ExprError(); } @@ -4679,8 +4863,8 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { case Qualifiers::OCL_Weak: case Qualifiers::OCL_Strong: case Qualifiers::OCL_Autoreleasing: - Diag(DRE->getLocStart(), diag::err_arc_atomic_ownership) - << ValType << FirstArg->getSourceRange(); + Diag(DRE->getBeginLoc(), diag::err_arc_atomic_ownership) + << ValType << FirstArg->getSourceRange(); return ExprError(); } @@ -4730,8 +4914,8 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { case 8: SizeIndex = 3; break; case 16: SizeIndex = 4; break; default: - Diag(DRE->getLocStart(), diag::err_atomic_builtin_pointer_size) - << FirstArg->getType() << FirstArg->getSourceRange(); + Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_pointer_size) + << FirstArg->getType() << FirstArg->getSourceRange(); return ExprError(); } @@ -4908,15 +5092,18 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { // Now that we know how many fixed arguments we expect, first check that we // have at least that many. if (TheCall->getNumArgs() < 1+NumFixed) { - Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least) - << 0 << 1+NumFixed << TheCall->getNumArgs() - << TheCall->getCallee()->getSourceRange(); + Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args_at_least) + << 0 << 1 + NumFixed << TheCall->getNumArgs() + << Callee->getSourceRange(); return ExprError(); } + Diag(TheCall->getEndLoc(), diag::warn_atomic_implicit_seq_cst) + << Callee->getSourceRange(); + if (WarnAboutSemanticsChange) { - Diag(TheCall->getLocEnd(), diag::warn_sync_fetch_and_nand_semantics_change) - << TheCall->getCallee()->getSourceRange(); + Diag(TheCall->getEndLoc(), diag::warn_sync_fetch_and_nand_semantics_change) + << Callee->getSourceRange(); } // Get the decl for the concrete builtin from this, we can tell what the @@ -4929,7 +5116,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { else { // Perform builtin lookup to avoid redeclaring it. DeclarationName DN(&Context.Idents.get(NewBuiltinName)); - LookupResult Res(*this, DN, DRE->getLocStart(), LookupOrdinaryName); + LookupResult Res(*this, DN, DRE->getBeginLoc(), LookupOrdinaryName); LookupName(Res, TUScope, /*AllowBuiltinCreation=*/true); assert(Res.getFoundDecl()); NewBuiltinDecl = dyn_cast<FunctionDecl>(Res.getFoundDecl()); @@ -4961,8 +5148,6 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { TheCall->setArg(i+1, Arg.get()); } - ASTContext& Context = this->getASTContext(); - // Create a new DeclRefExpr to refer to the new decl. DeclRefExpr* NewDRE = DeclRefExpr::Create( Context, @@ -5026,7 +5211,7 @@ ExprResult Sema::SemaBuiltinNontemporalOverloaded(ExprResult TheCallResult) { const PointerType *pointerType = PointerArg->getType()->getAs<PointerType>(); if (!pointerType) { - Diag(DRE->getLocStart(), diag::err_nontemporal_builtin_must_be_pointer) + Diag(DRE->getBeginLoc(), diag::err_nontemporal_builtin_must_be_pointer) << PointerArg->getType() << PointerArg->getSourceRange(); return ExprError(); } @@ -5038,7 +5223,7 @@ ExprResult Sema::SemaBuiltinNontemporalOverloaded(ExprResult TheCallResult) { if (!ValType->isIntegerType() && !ValType->isAnyPointerType() && !ValType->isBlockPointerType() && !ValType->isFloatingType() && !ValType->isVectorType()) { - Diag(DRE->getLocStart(), + Diag(DRE->getBeginLoc(), diag::err_nontemporal_builtin_must_be_pointer_intfltptr_or_vector) << PointerArg->getType() << PointerArg->getSourceRange(); return ExprError(); @@ -5070,8 +5255,8 @@ bool Sema::CheckObjCString(Expr *Arg) { StringLiteral *Literal = dyn_cast<StringLiteral>(Arg); if (!Literal || !Literal->isAscii()) { - Diag(Arg->getLocStart(), diag::err_cfstring_literal_not_string_constant) - << Arg->getSourceRange(); + Diag(Arg->getBeginLoc(), diag::err_cfstring_literal_not_string_constant) + << Arg->getSourceRange(); return true; } @@ -5087,8 +5272,8 @@ bool Sema::CheckObjCString(Expr *Arg) { ToPtr + NumBytes, llvm::strictConversion); // Check for conversion failure. if (Result != llvm::conversionOK) - Diag(Arg->getLocStart(), - diag::warn_cfstring_truncated) << Arg->getSourceRange(); + Diag(Arg->getBeginLoc(), diag::warn_cfstring_truncated) + << Arg->getSourceRange(); } return false; } @@ -5106,7 +5291,7 @@ ExprResult Sema::CheckOSLogFormatStringArg(Expr *Arg) { if (!Literal || (!Literal->isAscii() && !Literal->isUTF8())) { return ExprError( - Diag(Arg->getLocStart(), diag::err_os_log_format_not_string_constant) + Diag(Arg->getBeginLoc(), diag::err_os_log_format_not_string_constant) << Arg->getSourceRange()); } @@ -5133,7 +5318,7 @@ static bool checkVAStartABI(Sema &S, unsigned BuiltinID, Expr *Fn) { if (IsMSVAStart) { // Don't allow this in System V ABI functions. if (CC == CC_X86_64SysV || (!IsWindows && CC != CC_Win64)) - return S.Diag(Fn->getLocStart(), + return S.Diag(Fn->getBeginLoc(), diag::err_ms_va_start_used_in_sysv_function); } else { // On x86-64/AArch64 Unix, don't allow this in Win64 ABI functions. @@ -5142,7 +5327,7 @@ static bool checkVAStartABI(Sema &S, unsigned BuiltinID, Expr *Fn) { // System V ABI functions on Windows.) if ((IsWindows && CC == CC_X86_64SysV) || (!IsWindows && CC == CC_Win64)) - return S.Diag(Fn->getLocStart(), + return S.Diag(Fn->getBeginLoc(), diag::err_va_start_used_in_wrong_abi_function) << !IsWindows; } @@ -5150,7 +5335,7 @@ static bool checkVAStartABI(Sema &S, unsigned BuiltinID, Expr *Fn) { } if (IsMSVAStart) - return S.Diag(Fn->getLocStart(), diag::err_builtin_x64_aarch64_only); + return S.Diag(Fn->getBeginLoc(), diag::err_builtin_x64_aarch64_only); return false; } @@ -5173,16 +5358,16 @@ static bool checkVAStartIsInVariadicFunction(Sema &S, Expr *Fn, Params = MD->parameters(); } else if (isa<CapturedDecl>(Caller)) { // We don't support va_start in a CapturedDecl. - S.Diag(Fn->getLocStart(), diag::err_va_start_captured_stmt); + S.Diag(Fn->getBeginLoc(), diag::err_va_start_captured_stmt); return true; } else { // This must be some other declcontext that parses exprs. - S.Diag(Fn->getLocStart(), diag::err_va_start_outside_function); + S.Diag(Fn->getBeginLoc(), diag::err_va_start_outside_function); return true; } if (!IsVariadic) { - S.Diag(Fn->getLocStart(), diag::err_va_start_fixed_function); + S.Diag(Fn->getBeginLoc(), diag::err_va_start_fixed_function); return true; } @@ -5202,19 +5387,19 @@ bool Sema::SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall) { return true; if (TheCall->getNumArgs() > 2) { - Diag(TheCall->getArg(2)->getLocStart(), + Diag(TheCall->getArg(2)->getBeginLoc(), diag::err_typecheck_call_too_many_args) - << 0 /*function call*/ << 2 << TheCall->getNumArgs() - << Fn->getSourceRange() - << SourceRange(TheCall->getArg(2)->getLocStart(), - (*(TheCall->arg_end()-1))->getLocEnd()); + << 0 /*function call*/ << 2 << TheCall->getNumArgs() + << Fn->getSourceRange() + << SourceRange(TheCall->getArg(2)->getBeginLoc(), + (*(TheCall->arg_end() - 1))->getEndLoc()); return true; } if (TheCall->getNumArgs() < 2) { - return Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_few_args_at_least) - << 0 /*function call*/ << 2 << TheCall->getNumArgs(); + 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. @@ -5249,7 +5434,7 @@ bool Sema::SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall) { } if (!SecondArgIsLastNamedArgument) - Diag(TheCall->getArg(1)->getLocStart(), + Diag(TheCall->getArg(1)->getBeginLoc(), diag::warn_second_arg_of_va_start_not_last_named_param); else if (IsCRegister || Type->isReferenceType() || Type->isSpecificBuiltinType(BuiltinType::Float) || [=] { @@ -5266,7 +5451,7 @@ bool Sema::SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall) { unsigned Reason = 0; if (Type->isReferenceType()) Reason = 1; else if (IsCRegister) Reason = 2; - Diag(Arg->getLocStart(), diag::warn_va_start_type_is_undefined) << Reason; + Diag(Arg->getBeginLoc(), diag::warn_va_start_type_is_undefined) << Reason; Diag(ParamLoc, diag::note_parameter_type) << Type; } @@ -5281,7 +5466,7 @@ bool Sema::SemaBuiltinVAStartARMMicrosoft(CallExpr *Call) { Expr *Func = Call->getCallee(); if (Call->getNumArgs() < 3) - return Diag(Call->getLocEnd(), + return Diag(Call->getEndLoc(), diag::err_typecheck_call_too_few_args_at_least) << 0 /*function call*/ << 3 << Call->getNumArgs(); @@ -5305,20 +5490,18 @@ bool Sema::SemaBuiltinVAStartARMMicrosoft(CallExpr *Call) { Context.getPointerType(Context.CharTy.withConst()); if (!Arg1Ty->isPointerType() || Arg1Ty->getPointeeType().withoutLocalFastQualifiers() != Context.CharTy) - Diag(Arg1->getLocStart(), diag::err_typecheck_convert_incompatible) - << Arg1->getType() << ConstCharPtrTy - << 1 /* different class */ - << 0 /* qualifier difference */ - << 3 /* parameter mismatch */ + Diag(Arg1->getBeginLoc(), diag::err_typecheck_convert_incompatible) + << Arg1->getType() << ConstCharPtrTy << 1 /* different class */ + << 0 /* qualifier difference */ + << 3 /* parameter mismatch */ << 2 << Arg1->getType() << ConstCharPtrTy; const QualType SizeTy = Context.getSizeType(); if (Arg2Ty->getCanonicalTypeInternal().withoutLocalFastQualifiers() != SizeTy) - Diag(Arg2->getLocStart(), diag::err_typecheck_convert_incompatible) - << Arg2->getType() << SizeTy - << 1 /* different class */ - << 0 /* qualifier difference */ - << 3 /* parameter mismatch */ + Diag(Arg2->getBeginLoc(), diag::err_typecheck_convert_incompatible) + << Arg2->getType() << SizeTy << 1 /* different class */ + << 0 /* qualifier difference */ + << 3 /* parameter mismatch */ << 3 << Arg2->getType() << SizeTy; return false; @@ -5328,14 +5511,14 @@ bool Sema::SemaBuiltinVAStartARMMicrosoft(CallExpr *Call) { /// friends. This is declared to take (...), so we have to check everything. bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) { if (TheCall->getNumArgs() < 2) - return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) - << 0 << 2 << TheCall->getNumArgs()/*function call*/; + 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)->getLocStart(), + return Diag(TheCall->getArg(2)->getBeginLoc(), diag::err_typecheck_call_too_many_args) - << 0 /*function call*/ << 2 << TheCall->getNumArgs() - << SourceRange(TheCall->getArg(2)->getLocStart(), - (*(TheCall->arg_end()-1))->getLocEnd()); + << 0 /*function call*/ << 2 << TheCall->getNumArgs() + << SourceRange(TheCall->getArg(2)->getBeginLoc(), + (*(TheCall->arg_end() - 1))->getEndLoc()); ExprResult OrigArg0 = TheCall->getArg(0); ExprResult OrigArg1 = TheCall->getArg(1); @@ -5358,10 +5541,11 @@ bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) { // If the common type isn't a real floating type, then the arguments were // invalid for this operation. if (Res.isNull() || !Res->isRealFloatingType()) - return Diag(OrigArg0.get()->getLocStart(), + return Diag(OrigArg0.get()->getBeginLoc(), diag::err_typecheck_call_invalid_ordered_compare) - << OrigArg0.get()->getType() << OrigArg1.get()->getType() - << SourceRange(OrigArg0.get()->getLocStart(), OrigArg1.get()->getLocEnd()); + << OrigArg0.get()->getType() << OrigArg1.get()->getType() + << SourceRange(OrigArg0.get()->getBeginLoc(), + OrigArg1.get()->getEndLoc()); return false; } @@ -5372,14 +5556,14 @@ bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) { /// value. bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) { if (TheCall->getNumArgs() < NumArgs) - return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) - << 0 << NumArgs << TheCall->getNumArgs()/*function call*/; + 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)->getLocStart(), + return Diag(TheCall->getArg(NumArgs)->getBeginLoc(), diag::err_typecheck_call_too_many_args) - << 0 /*function call*/ << NumArgs << TheCall->getNumArgs() - << SourceRange(TheCall->getArg(NumArgs)->getLocStart(), - (*(TheCall->arg_end()-1))->getLocEnd()); + << 0 /*function call*/ << NumArgs << TheCall->getNumArgs() + << SourceRange(TheCall->getArg(NumArgs)->getBeginLoc(), + (*(TheCall->arg_end() - 1))->getEndLoc()); Expr *OrigArg = TheCall->getArg(NumArgs-1); @@ -5388,9 +5572,9 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) { // This operation requires a non-_Complex floating-point number. if (!OrigArg->getType()->isRealFloatingType()) - return Diag(OrigArg->getLocStart(), + return Diag(OrigArg->getBeginLoc(), diag::err_typecheck_call_invalid_unary_fp) - << OrigArg->getType() << OrigArg->getSourceRange(); + << OrigArg->getType() << OrigArg->getSourceRange(); // If this is an implicit conversion from float -> float, double, or // long double, remove it. @@ -5424,13 +5608,13 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) { bool Sema::SemaBuiltinVSX(CallExpr *TheCall) { unsigned ExpectedNumArgs = 3; if (TheCall->getNumArgs() < ExpectedNumArgs) - return Diag(TheCall->getLocEnd(), + return Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args_at_least) - << 0 /*function call*/ << ExpectedNumArgs << TheCall->getNumArgs() + << 0 /*function call*/ << ExpectedNumArgs << TheCall->getNumArgs() << TheCall->getSourceRange(); if (TheCall->getNumArgs() > ExpectedNumArgs) - return Diag(TheCall->getLocEnd(), + return Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_many_args_at_most) << 0 /*function call*/ << ExpectedNumArgs << TheCall->getNumArgs() << TheCall->getSourceRange(); @@ -5438,31 +5622,31 @@ bool Sema::SemaBuiltinVSX(CallExpr *TheCall) { // Check the third argument is a compile time constant llvm::APSInt Value; if(!TheCall->getArg(2)->isIntegerConstantExpr(Value, Context)) - return Diag(TheCall->getLocStart(), + return Diag(TheCall->getBeginLoc(), diag::err_vsx_builtin_nonconstant_argument) << 3 /* argument index */ << TheCall->getDirectCallee() - << SourceRange(TheCall->getArg(2)->getLocStart(), - TheCall->getArg(2)->getLocEnd()); + << SourceRange(TheCall->getArg(2)->getBeginLoc(), + TheCall->getArg(2)->getEndLoc()); QualType Arg1Ty = TheCall->getArg(0)->getType(); QualType Arg2Ty = TheCall->getArg(1)->getType(); // Check the type of argument 1 and argument 2 are vectors. - SourceLocation BuiltinLoc = TheCall->getLocStart(); + SourceLocation BuiltinLoc = TheCall->getBeginLoc(); if ((!Arg1Ty->isVectorType() && !Arg1Ty->isDependentType()) || (!Arg2Ty->isVectorType() && !Arg2Ty->isDependentType())) { return Diag(BuiltinLoc, diag::err_vec_builtin_non_vector) << TheCall->getDirectCallee() - << SourceRange(TheCall->getArg(0)->getLocStart(), - TheCall->getArg(1)->getLocEnd()); + << SourceRange(TheCall->getArg(0)->getBeginLoc(), + TheCall->getArg(1)->getEndLoc()); } // Check the first two arguments are the same type. if (!Context.hasSameUnqualifiedType(Arg1Ty, Arg2Ty)) { return Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector) << TheCall->getDirectCallee() - << SourceRange(TheCall->getArg(0)->getLocStart(), - TheCall->getArg(1)->getLocEnd()); + << SourceRange(TheCall->getArg(0)->getBeginLoc(), + TheCall->getArg(1)->getEndLoc()); } // When default clang type checking is turned off and the customized type @@ -5477,7 +5661,7 @@ bool Sema::SemaBuiltinVSX(CallExpr *TheCall) { // This is declared to take (...), so we have to check everything. ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { if (TheCall->getNumArgs() < 2) - return ExprError(Diag(TheCall->getLocEnd(), + return ExprError(Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args_at_least) << 0 /*function call*/ << 2 << TheCall->getNumArgs() << TheCall->getSourceRange()); @@ -5494,11 +5678,11 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { QualType RHSType = TheCall->getArg(1)->getType(); if (!LHSType->isVectorType() || !RHSType->isVectorType()) - return ExprError(Diag(TheCall->getLocStart(), - diag::err_vec_builtin_non_vector) - << TheCall->getDirectCallee() - << SourceRange(TheCall->getArg(0)->getLocStart(), - TheCall->getArg(1)->getLocEnd())); + return ExprError( + Diag(TheCall->getBeginLoc(), diag::err_vec_builtin_non_vector) + << TheCall->getDirectCallee() + << SourceRange(TheCall->getArg(0)->getBeginLoc(), + TheCall->getArg(1)->getEndLoc())); numElements = LHSType->getAs<VectorType>()->getNumElements(); unsigned numResElements = TheCall->getNumArgs() - 2; @@ -5509,17 +5693,17 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { if (TheCall->getNumArgs() == 2) { if (!RHSType->hasIntegerRepresentation() || RHSType->getAs<VectorType>()->getNumElements() != numElements) - return ExprError(Diag(TheCall->getLocStart(), + return ExprError(Diag(TheCall->getBeginLoc(), diag::err_vec_builtin_incompatible_vector) << TheCall->getDirectCallee() - << SourceRange(TheCall->getArg(1)->getLocStart(), - TheCall->getArg(1)->getLocEnd())); + << SourceRange(TheCall->getArg(1)->getBeginLoc(), + TheCall->getArg(1)->getEndLoc())); } else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) { - return ExprError(Diag(TheCall->getLocStart(), + return ExprError(Diag(TheCall->getBeginLoc(), diag::err_vec_builtin_incompatible_vector) << TheCall->getDirectCallee() - << SourceRange(TheCall->getArg(0)->getLocStart(), - TheCall->getArg(1)->getLocEnd())); + << SourceRange(TheCall->getArg(0)->getBeginLoc(), + TheCall->getArg(1)->getEndLoc())); } else if (numElements != numResElements) { QualType eltType = LHSType->getAs<VectorType>()->getElementType(); resType = Context.getVectorType(eltType, numResElements, @@ -5534,7 +5718,7 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { llvm::APSInt Result(32); if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context)) - return ExprError(Diag(TheCall->getLocStart(), + return ExprError(Diag(TheCall->getBeginLoc(), diag::err_shufflevector_nonconstant_argument) << TheCall->getArg(i)->getSourceRange()); @@ -5543,7 +5727,7 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { continue; if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2) - return ExprError(Diag(TheCall->getLocStart(), + return ExprError(Diag(TheCall->getBeginLoc(), diag::err_shufflevector_argument_too_large) << TheCall->getArg(i)->getSourceRange()); } @@ -5556,7 +5740,7 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { } return new (Context) ShuffleVectorExpr(Context, exprs, resType, - TheCall->getCallee()->getLocStart(), + TheCall->getCallee()->getBeginLoc(), TheCall->getRParenLoc()); } @@ -5597,10 +5781,9 @@ bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) { unsigned NumArgs = TheCall->getNumArgs(); if (NumArgs > 3) - return Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_many_args_at_most) - << 0 /*function call*/ << 3 << NumArgs - << TheCall->getSourceRange(); + return Diag(TheCall->getEndLoc(), + diag::err_typecheck_call_too_many_args_at_most) + << 0 /*function call*/ << 3 << NumArgs << TheCall->getSourceRange(); // Argument 0 is checked for us and the remaining arguments must be // constant integers. @@ -5619,9 +5802,9 @@ bool Sema::SemaBuiltinAssume(CallExpr *TheCall) { if (Arg->isInstantiationDependent()) return false; if (Arg->HasSideEffects(Context)) - Diag(Arg->getLocStart(), diag::warn_assume_side_effects) - << Arg->getSourceRange() - << cast<FunctionDecl>(TheCall->getCalleeDecl())->getIdentifier(); + Diag(Arg->getBeginLoc(), diag::warn_assume_side_effects) + << Arg->getSourceRange() + << cast<FunctionDecl>(TheCall->getCalleeDecl())->getIdentifier(); return false; } @@ -5637,26 +5820,24 @@ bool Sema::SemaBuiltinAllocaWithAlign(CallExpr *TheCall) { if (!Arg->isTypeDependent() && !Arg->isValueDependent()) { if (const auto *UE = dyn_cast<UnaryExprOrTypeTraitExpr>(Arg->IgnoreParenImpCasts())) - if (UE->getKind() == UETT_AlignOf) - Diag(TheCall->getLocStart(), diag::warn_alloca_align_alignof) - << Arg->getSourceRange(); + if (UE->getKind() == UETT_AlignOf || + UE->getKind() == UETT_PreferredAlignOf) + Diag(TheCall->getBeginLoc(), diag::warn_alloca_align_alignof) + << Arg->getSourceRange(); llvm::APSInt Result = Arg->EvaluateKnownConstInt(Context); if (!Result.isPowerOf2()) - return Diag(TheCall->getLocStart(), - diag::err_alignment_not_power_of_two) - << Arg->getSourceRange(); + return Diag(TheCall->getBeginLoc(), diag::err_alignment_not_power_of_two) + << Arg->getSourceRange(); if (Result < Context.getCharWidth()) - return Diag(TheCall->getLocStart(), diag::err_alignment_too_small) - << (unsigned)Context.getCharWidth() - << Arg->getSourceRange(); + return Diag(TheCall->getBeginLoc(), diag::err_alignment_too_small) + << (unsigned)Context.getCharWidth() << Arg->getSourceRange(); if (Result > std::numeric_limits<int32_t>::max()) - return Diag(TheCall->getLocStart(), diag::err_alignment_too_big) - << std::numeric_limits<int32_t>::max() - << Arg->getSourceRange(); + return Diag(TheCall->getBeginLoc(), diag::err_alignment_too_big) + << std::numeric_limits<int32_t>::max() << Arg->getSourceRange(); } return false; @@ -5668,10 +5849,9 @@ bool Sema::SemaBuiltinAssumeAligned(CallExpr *TheCall) { unsigned NumArgs = TheCall->getNumArgs(); if (NumArgs > 3) - return Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_many_args_at_most) - << 0 /*function call*/ << 3 << NumArgs - << TheCall->getSourceRange(); + return Diag(TheCall->getEndLoc(), + diag::err_typecheck_call_too_many_args_at_most) + << 0 /*function call*/ << 3 << NumArgs << TheCall->getSourceRange(); // The alignment must be a constant integer. Expr *Arg = TheCall->getArg(1); @@ -5683,9 +5863,8 @@ bool Sema::SemaBuiltinAssumeAligned(CallExpr *TheCall) { return true; if (!Result.isPowerOf2()) - return Diag(TheCall->getLocStart(), - diag::err_alignment_not_power_of_two) - << Arg->getSourceRange(); + return Diag(TheCall->getBeginLoc(), diag::err_alignment_not_power_of_two) + << Arg->getSourceRange(); } if (NumArgs > 2) { @@ -5708,12 +5887,12 @@ bool Sema::SemaBuiltinOSLogFormat(CallExpr *TheCall) { unsigned NumArgs = TheCall->getNumArgs(); unsigned NumRequiredArgs = IsSizeCall ? 1 : 2; if (NumArgs < NumRequiredArgs) { - return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) + return Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args) << 0 /* function call */ << NumRequiredArgs << NumArgs << TheCall->getSourceRange(); } if (NumArgs >= NumRequiredArgs + 0x100) { - return Diag(TheCall->getLocEnd(), + return Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_many_args_at_most) << 0 /* function call */ << (NumRequiredArgs + 0xff) << NumArgs << TheCall->getSourceRange(); @@ -5751,7 +5930,7 @@ bool Sema::SemaBuiltinOSLogFormat(CallExpr *TheCall) { return true; CharUnits ArgSize = Context.getTypeSizeInChars(Arg.get()->getType()); if (ArgSize.getQuantity() >= 0x100) { - return Diag(Arg.get()->getLocEnd(), diag::err_os_log_argument_too_big) + return Diag(Arg.get()->getEndLoc(), diag::err_os_log_argument_too_big) << i << (int)ArgSize.getQuantity() << 0xff << TheCall->getSourceRange(); } @@ -5766,7 +5945,7 @@ bool Sema::SemaBuiltinOSLogFormat(CallExpr *TheCall) { ArrayRef<const Expr *> Args(TheCall->getArgs(), TheCall->getNumArgs()); bool Success = CheckFormatArguments( Args, /*HasVAListArg*/ false, FormatIdx, FirstDataArg, FST_OSLog, - VariadicFunction, TheCall->getLocStart(), SourceRange(), + VariadicFunction, TheCall->getBeginLoc(), SourceRange(), CheckedVarArgs); if (!Success) return true; @@ -5791,8 +5970,8 @@ bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum, if (Arg->isTypeDependent() || Arg->isValueDependent()) return false; if (!Arg->isIntegerConstantExpr(Result, Context)) - return Diag(TheCall->getLocStart(), diag::err_constant_integer_arg_type) - << FDecl->getDeclName() << Arg->getSourceRange(); + return Diag(TheCall->getBeginLoc(), diag::err_constant_integer_arg_type) + << FDecl->getDeclName() << Arg->getSourceRange(); return false; } @@ -5814,15 +5993,15 @@ bool Sema::SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, if (Result.getSExtValue() < Low || Result.getSExtValue() > High) { if (RangeIsError) - return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) + return Diag(TheCall->getBeginLoc(), diag::err_argument_invalid_range) << Result.toString(10) << Low << High << Arg->getSourceRange(); else // Defer the warning until we know if the code will be emitted so that // dead code can ignore this. - DiagRuntimeBehavior(TheCall->getLocStart(), TheCall, - PDiag(diag::warn_argument_invalid_range) - << Result.toString(10) << Low << High - << Arg->getSourceRange()); + DiagRuntimeBehavior(TheCall->getBeginLoc(), TheCall, + PDiag(diag::warn_argument_invalid_range) + << Result.toString(10) << Low << High + << Arg->getSourceRange()); } return false; @@ -5844,8 +6023,8 @@ bool Sema::SemaBuiltinConstantArgMultiple(CallExpr *TheCall, int ArgNum, return true; if (Result.getSExtValue() % Num != 0) - return Diag(TheCall->getLocStart(), diag::err_argument_not_multiple) - << Num << Arg->getSourceRange(); + return Diag(TheCall->getBeginLoc(), diag::err_argument_not_multiple) + << Num << Arg->getSourceRange(); return false; } @@ -5876,7 +6055,7 @@ bool Sema::SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, // Check if the argument is a string literal. if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts())) - return Diag(TheCall->getLocStart(), diag::err_expr_not_string_literal) + return Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal) << Arg->getSourceRange(); // Check the type of special register given. @@ -5885,7 +6064,7 @@ bool Sema::SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, Reg.split(Fields, ":"); if (Fields.size() != ExpectedFieldNum && !(AllowName && Fields.size() == 1)) - return Diag(TheCall->getLocStart(), diag::err_arm_invalid_specialreg) + return Diag(TheCall->getBeginLoc(), diag::err_arm_invalid_specialreg) << Arg->getSourceRange(); // If the string is the name of a register then we cannot check that it is @@ -5927,7 +6106,7 @@ bool Sema::SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, } if (!ValidString) - return Diag(TheCall->getLocStart(), diag::err_arm_invalid_specialreg) + return Diag(TheCall->getBeginLoc(), diag::err_arm_invalid_specialreg) << Arg->getSourceRange(); } else if (IsAArch64Builtin && Fields.size() == 1) { // If the register name is one of those that appear in the condition below @@ -5955,8 +6134,8 @@ bool Sema::SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, /// that val is a constant 1. bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) { if (!Context.getTargetInfo().hasSjLjLowering()) - return Diag(TheCall->getLocStart(), diag::err_builtin_longjmp_unsupported) - << SourceRange(TheCall->getLocStart(), TheCall->getLocEnd()); + return Diag(TheCall->getBeginLoc(), diag::err_builtin_longjmp_unsupported) + << SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc()); Expr *Arg = TheCall->getArg(1); llvm::APSInt Result; @@ -5966,8 +6145,8 @@ bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) { return true; if (Result != 1) - return Diag(TheCall->getLocStart(), diag::err_builtin_longjmp_invalid_val) - << SourceRange(Arg->getLocStart(), Arg->getLocEnd()); + return Diag(TheCall->getBeginLoc(), diag::err_builtin_longjmp_invalid_val) + << SourceRange(Arg->getBeginLoc(), Arg->getEndLoc()); return false; } @@ -5976,8 +6155,8 @@ bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) { /// This checks that the target supports __builtin_setjmp. bool Sema::SemaBuiltinSetjmp(CallExpr *TheCall) { if (!Context.getTargetInfo().hasSjLjLowering()) - return Diag(TheCall->getLocStart(), diag::err_builtin_setjmp_unsupported) - << SourceRange(TheCall->getLocStart(), TheCall->getLocEnd()); + return Diag(TheCall->getBeginLoc(), diag::err_builtin_setjmp_unsupported) + << SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc()); return false; } @@ -6121,11 +6300,11 @@ class FormatStringLiteral { StartToken, StartTokenByteOffset); } - SourceLocation getLocStart() const LLVM_READONLY { - return FExpr->getLocStart().getLocWithOffset(Offset); + SourceLocation getBeginLoc() const LLVM_READONLY { + return FExpr->getBeginLoc().getLocWithOffset(Offset); } - SourceLocation getLocEnd() const LLVM_READONLY { return FExpr->getLocEnd(); } + SourceLocation getEndLoc() const LLVM_READONLY { return FExpr->getEndLoc(); } }; } // namespace @@ -6377,13 +6556,12 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args, return SLCT_NotALiteral; } case Stmt::BinaryOperatorClass: { - llvm::APSInt LResult; - llvm::APSInt RResult; - const BinaryOperator *BinOp = cast<BinaryOperator>(E); // A string literal + an int offset is still a string literal. if (BinOp->isAdditiveOp()) { + Expr::EvalResult LResult, RResult; + bool LIsInt = BinOp->getLHS()->EvaluateAsInt(LResult, S.Context); bool RIsInt = BinOp->getRHS()->EvaluateAsInt(RResult, S.Context); @@ -6392,12 +6570,12 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args, if (LIsInt) { if (BinOpKind == BO_Add) { - sumOffsets(Offset, LResult, BinOpKind, RIsInt); + sumOffsets(Offset, LResult.Val.getInt(), BinOpKind, RIsInt); E = BinOp->getRHS(); goto tryAgain; } } else { - sumOffsets(Offset, RResult, BinOpKind, RIsInt); + sumOffsets(Offset, RResult.Val.getInt(), BinOpKind, RIsInt); E = BinOp->getLHS(); goto tryAgain; } @@ -6410,9 +6588,10 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args, const UnaryOperator *UnaOp = cast<UnaryOperator>(E); auto ASE = dyn_cast<ArraySubscriptExpr>(UnaOp->getSubExpr()); if (UnaOp->getOpcode() == UO_AddrOf && ASE) { - llvm::APSInt IndexResult; + Expr::EvalResult IndexResult; if (ASE->getRHS()->EvaluateAsInt(IndexResult, S.Context)) { - sumOffsets(Offset, IndexResult, BO_Add, /*RHS is int*/ true); + sumOffsets(Offset, IndexResult.Val.getInt(), BO_Add, + /*RHS is int*/ true); E = ASE->getBase(); goto tryAgain; } @@ -6511,7 +6690,7 @@ bool Sema::CheckFormatArguments(ArrayRef<const Expr *> Args, // format is either NSString or CFString. This is a hack to prevent // diag when using the NSLocalizedString and CFCopyLocalizedString macros // which are usually used in place of NS and CF string literals. - SourceLocation FormatLoc = Args[format_idx]->getLocStart(); + SourceLocation FormatLoc = Args[format_idx]->getBeginLoc(); if (Type == FST_NSString && SourceMgr.isInSystemMacro(FormatLoc)) return false; @@ -6831,7 +7010,7 @@ void UncoveredArgHandler::Diagnose(Sema &S, bool IsFunctionCall, if (!ArgExpr) return; - SourceLocation Loc = ArgExpr->getLocStart(); + SourceLocation Loc = ArgExpr->getBeginLoc(); if (S.getSourceManager().isInSystemMacro(Loc)) return; @@ -7029,6 +7208,8 @@ public: const char *startSpecifier, unsigned specifierLen) override; + void handleInvalidMaskType(StringRef MaskType) override; + bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS, const char *startSpecifier, unsigned specifierLen) override; @@ -7080,6 +7261,10 @@ bool CheckPrintfHandler::HandleInvalidPrintfConversionSpecifier( CS.getStart(), CS.getLength()); } +void CheckPrintfHandler::handleInvalidMaskType(StringRef MaskType) { + S.Diag(getLocationOfByte(MaskType.data()), diag::err_invalid_mask_type_size); +} + bool CheckPrintfHandler::HandleAmount( const analyze_format_string::OptionalAmount &Amt, unsigned k, const char *startSpecifier, @@ -7276,10 +7461,9 @@ bool CheckPrintfHandler::checkForCStrMembers( if (Method->getMinRequiredArguments() == 0 && AT.matchesType(S.Context, Method->getReturnType())) { // FIXME: Suggest parens if the expression needs them. - SourceLocation EndLoc = S.getLocForEndOfToken(E->getLocEnd()); - S.Diag(E->getLocStart(), diag::note_printf_c_str) - << "c_str()" - << FixItHint::CreateInsertion(EndLoc, ".c_str()"); + SourceLocation EndLoc = S.getLocForEndOfToken(E->getEndLoc()); + S.Diag(E->getBeginLoc(), diag::note_printf_c_str) + << "c_str()" << FixItHint::CreateInsertion(EndLoc, ".c_str()"); return true; } } @@ -7353,22 +7537,22 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier ArgType(S.Context.IntTy) : ArgType::CPointerTy; if (AT.isValid() && !AT.matchesType(S.Context, Ex->getType())) EmitFormatDiagnostic( - S.PDiag(diag::warn_format_conversion_argument_type_mismatch) - << AT.getRepresentativeTypeName(S.Context) << Ex->getType() - << false << Ex->getSourceRange(), - Ex->getLocStart(), /*IsStringLocation*/false, - getSpecifierRange(startSpecifier, specifierLen)); + S.PDiag(diag::warn_format_conversion_argument_type_mismatch) + << AT.getRepresentativeTypeName(S.Context) << Ex->getType() + << false << Ex->getSourceRange(), + Ex->getBeginLoc(), /*IsStringLocation*/ false, + getSpecifierRange(startSpecifier, specifierLen)); // Type check the second argument (char * for both %b and %D) Ex = getDataArg(argIndex + 1); const analyze_printf::ArgType &AT2 = ArgType::CStrTy; if (AT2.isValid() && !AT2.matchesType(S.Context, Ex->getType())) EmitFormatDiagnostic( - S.PDiag(diag::warn_format_conversion_argument_type_mismatch) - << AT2.getRepresentativeTypeName(S.Context) << Ex->getType() - << false << Ex->getSourceRange(), - Ex->getLocStart(), /*IsStringLocation*/false, - getSpecifierRange(startSpecifier, specifierLen)); + S.PDiag(diag::warn_format_conversion_argument_type_mismatch) + << AT2.getRepresentativeTypeName(S.Context) << Ex->getType() + << false << Ex->getSourceRange(), + Ex->getBeginLoc(), /*IsStringLocation*/ false, + getSpecifierRange(startSpecifier, specifierLen)); return true; } @@ -7585,6 +7769,30 @@ shouldNotPrintDirectly(const ASTContext &Context, return std::make_pair(QualType(), StringRef()); } +/// Return true if \p ICE is an implicit argument promotion of an arithmetic +/// type. Bit-field 'promotions' from a higher ranked type to a lower ranked +/// type do not count. +static bool +isArithmeticArgumentPromotion(Sema &S, const ImplicitCastExpr *ICE) { + QualType From = ICE->getSubExpr()->getType(); + QualType To = ICE->getType(); + // It's an integer promotion if the destination type is the promoted + // source type. + if (ICE->getCastKind() == CK_IntegralCast && + From->isPromotableIntegerType() && + S.Context.getPromotedIntegerType(From) == To) + return true; + // Look through vector types, since we do default argument promotion for + // those in OpenCL. + if (const auto *VecTy = From->getAs<ExtVectorType>()) + From = VecTy->getElementType(); + if (const auto *VecTy = To->getAs<ExtVectorType>()) + To = VecTy->getElementType(); + // It's a floating promotion if the source type is a lower rank. + return ICE->getCastKind() == CK_FloatingCast && + S.Context.getFloatingTypeOrder(From, To) < 0; +} + bool CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, const char *StartSpecifier, @@ -7612,11 +7820,11 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, // Look through argument promotions for our error message's reported type. // This includes the integral and floating promotions, but excludes array - // and function pointer decay; seeing that an argument intended to be a - // string has type 'char [6]' is probably more confusing than 'char *'. + // and function pointer decay (seeing that an argument intended to be a + // string has type 'char [6]' is probably more confusing than 'char *') and + // certain bitfield promotions (bitfields can be 'demoted' to a lesser type). if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { - if (ICE->getCastKind() == CK_IntegralCast || - ICE->getCastKind() == CK_FloatingCast) { + if (isArithmeticArgumentPromotion(S, ICE)) { E = ICE->getSubExpr(); ExprTy = E->getType(); @@ -7666,7 +7874,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, return true; } - LookupResult Result(S, &S.Context.Idents.get("unichar"), E->getLocStart(), + LookupResult Result(S, &S.Context.Idents.get("unichar"), E->getBeginLoc(), Sema::LookupOrdinaryName); if (S.LookupName(Result, S.getCurScope())) { NamedDecl *ND = Result.getFoundDecl(); @@ -7718,7 +7926,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, EmitFormatDiagnostic(S.PDiag(Diag) << AT.getRepresentativeTypeName(S.Context) << IntendedTy << IsEnum << E->getSourceRange(), - E->getLocStart(), + E->getBeginLoc(), /*IsStringLocation*/ false, SpecRange, FixItHint::CreateReplacement(SpecRange, os.str())); } else { @@ -7747,15 +7955,15 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, } else if (!requiresParensToAddCast(E)) { // If the expression has high enough precedence, // just write the C-style cast. - Hints.push_back(FixItHint::CreateInsertion(E->getLocStart(), - CastFix.str())); + Hints.push_back( + FixItHint::CreateInsertion(E->getBeginLoc(), CastFix.str())); } else { // Otherwise, add parens around the expression as well as the cast. CastFix << "("; - Hints.push_back(FixItHint::CreateInsertion(E->getLocStart(), - CastFix.str())); + Hints.push_back( + FixItHint::CreateInsertion(E->getBeginLoc(), CastFix.str())); - SourceLocation After = S.getLocForEndOfToken(E->getLocEnd()); + SourceLocation After = S.getLocForEndOfToken(E->getEndLoc()); Hints.push_back(FixItHint::CreateInsertion(After, ")")); } @@ -7773,18 +7981,17 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, : diag::warn_format_argument_needs_cast; EmitFormatDiagnostic(S.PDiag(Diag) << Name << IntendedTy << IsEnum << E->getSourceRange(), - E->getLocStart(), /*IsStringLocation=*/false, + E->getBeginLoc(), /*IsStringLocation=*/false, SpecRange, Hints); } else { // In this case, the expression could be printed using a different // specifier, but we've decided that the specifier is probably correct // and we should cast instead. Just use the normal warning message. EmitFormatDiagnostic( - S.PDiag(diag::warn_format_conversion_argument_type_mismatch) - << AT.getRepresentativeTypeName(S.Context) << ExprTy << IsEnum - << E->getSourceRange(), - E->getLocStart(), /*IsStringLocation*/false, - SpecRange, Hints); + S.PDiag(diag::warn_format_conversion_argument_type_mismatch) + << AT.getRepresentativeTypeName(S.Context) << ExprTy << IsEnum + << E->getSourceRange(), + E->getBeginLoc(), /*IsStringLocation*/ false, SpecRange, Hints); } } } else { @@ -7804,41 +8011,34 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, EmitFormatDiagnostic( S.PDiag(Diag) << AT.getRepresentativeTypeName(S.Context) << ExprTy << IsEnum << CSR << E->getSourceRange(), - E->getLocStart(), /*IsStringLocation*/ false, CSR); + E->getBeginLoc(), /*IsStringLocation*/ false, CSR); break; } case Sema::VAK_Undefined: case Sema::VAK_MSVCUndefined: - EmitFormatDiagnostic( - S.PDiag(diag::warn_non_pod_vararg_with_format_string) - << S.getLangOpts().CPlusPlus11 - << ExprTy - << CallType - << AT.getRepresentativeTypeName(S.Context) - << CSR - << E->getSourceRange(), - E->getLocStart(), /*IsStringLocation*/false, CSR); + EmitFormatDiagnostic(S.PDiag(diag::warn_non_pod_vararg_with_format_string) + << S.getLangOpts().CPlusPlus11 << ExprTy + << CallType + << AT.getRepresentativeTypeName(S.Context) << CSR + << E->getSourceRange(), + E->getBeginLoc(), /*IsStringLocation*/ false, CSR); checkForCStrMembers(AT, E); break; case Sema::VAK_Invalid: if (ExprTy->isObjCObjectType()) EmitFormatDiagnostic( - S.PDiag(diag::err_cannot_pass_objc_interface_to_vararg_format) - << S.getLangOpts().CPlusPlus11 - << ExprTy - << CallType - << AT.getRepresentativeTypeName(S.Context) - << CSR - << E->getSourceRange(), - E->getLocStart(), /*IsStringLocation*/false, CSR); + S.PDiag(diag::err_cannot_pass_objc_interface_to_vararg_format) + << S.getLangOpts().CPlusPlus11 << ExprTy << CallType + << AT.getRepresentativeTypeName(S.Context) << CSR + << E->getSourceRange(), + E->getBeginLoc(), /*IsStringLocation*/ false, CSR); else // FIXME: If this is an initializer list, suggest removing the braces // or inserting a cast to the target type. - S.Diag(E->getLocStart(), diag::err_cannot_pass_to_vararg_format) - << isa<InitListExpr>(E) << ExprTy << CallType - << AT.getRepresentativeTypeName(S.Context) - << E->getSourceRange(); + S.Diag(E->getBeginLoc(), diag::err_cannot_pass_to_vararg_format) + << isa<InitListExpr>(E) << ExprTy << CallType + << AT.getRepresentativeTypeName(S.Context) << E->getSourceRange(); break; } @@ -8008,7 +8208,7 @@ bool CheckScanfHandler::HandleScanfSpecifier( EmitFormatDiagnostic( S.PDiag(Diag) << AT.getRepresentativeTypeName(S.Context) << Ex->getType() << false << Ex->getSourceRange(), - Ex->getLocStart(), + Ex->getBeginLoc(), /*IsStringLocation*/ false, getSpecifierRange(startSpecifier, specifierLen), FixItHint::CreateReplacement( @@ -8017,7 +8217,7 @@ bool CheckScanfHandler::HandleScanfSpecifier( EmitFormatDiagnostic(S.PDiag(Diag) << AT.getRepresentativeTypeName(S.Context) << Ex->getType() << false << Ex->getSourceRange(), - Ex->getLocStart(), + Ex->getBeginLoc(), /*IsStringLocation*/ false, getSpecifierRange(startSpecifier, specifierLen)); } @@ -8038,9 +8238,9 @@ static void CheckFormatString(Sema &S, const FormatStringLiteral *FExpr, // CHECK: is the format string a wide literal? if (!FExpr->isAscii() && !FExpr->isUTF8()) { CheckFormatHandler::EmitFormatDiagnostic( - S, inFunctionCall, Args[format_idx], - S.PDiag(diag::warn_format_string_is_wide_literal), FExpr->getLocStart(), - /*IsStringLocation*/true, OrigFormatExpr->getSourceRange()); + S, inFunctionCall, Args[format_idx], + S.PDiag(diag::warn_format_string_is_wide_literal), FExpr->getBeginLoc(), + /*IsStringLocation*/ true, OrigFormatExpr->getSourceRange()); return; } @@ -8062,7 +8262,7 @@ static void CheckFormatString(Sema &S, const FormatStringLiteral *FExpr, CheckFormatHandler::EmitFormatDiagnostic( S, inFunctionCall, Args[format_idx], S.PDiag(diag::warn_printf_format_string_not_null_terminated), - FExpr->getLocStart(), + FExpr->getBeginLoc(), /*IsStringLocation=*/true, OrigFormatExpr->getSourceRange()); return; } @@ -8070,9 +8270,9 @@ static void CheckFormatString(Sema &S, const FormatStringLiteral *FExpr, // CHECK: empty format string? if (StrLen == 0 && numDataArgs > 0) { CheckFormatHandler::EmitFormatDiagnostic( - S, inFunctionCall, Args[format_idx], - S.PDiag(diag::warn_empty_format_string), FExpr->getLocStart(), - /*IsStringLocation*/true, OrigFormatExpr->getSourceRange()); + S, inFunctionCall, Args[format_idx], + S.PDiag(diag::warn_empty_format_string), FExpr->getBeginLoc(), + /*IsStringLocation*/ true, OrigFormatExpr->getSourceRange()); return; } @@ -8587,8 +8787,9 @@ static bool CheckMemorySizeofForComparison(Sema &S, const Expr *E, S.Diag(Size->getOperatorLoc(), diag::warn_memsize_comparison) << SizeRange << FnName; S.Diag(FnLoc, diag::note_memsize_comparison_paren) - << FnName << FixItHint::CreateInsertion( - S.getLocForEndOfToken(Size->getLHS()->getLocEnd()), ")") + << FnName + << FixItHint::CreateInsertion( + S.getLocForEndOfToken(Size->getLHS()->getEndLoc()), ")") << FixItHint::CreateRemoval(RParenLoc); S.Diag(SizeRange.getBegin(), diag::note_memsize_comparison_cast_silence) << FixItHint::CreateInsertion(SizeRange.getBegin(), "(size_t)(") @@ -8853,7 +9054,7 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call, const Expr *LenExpr = Call->getArg(LenArg)->IgnoreParenImpCasts(); if (CheckMemorySizeofForComparison(*this, LenExpr, FnName, - Call->getLocStart(), Call->getRParenLoc())) + Call->getBeginLoc(), Call->getRParenLoc())) return; // Catch cases like 'memset(buf, sizeof(buf), 0)'. @@ -9075,7 +9276,7 @@ void Sema::CheckStrlcpycatArguments(const CallExpr *Call, const Expr *CompareWithSrc = nullptr; if (CheckMemorySizeofForComparison(*this, SizeArg, FnName, - Call->getLocStart(), Call->getRParenLoc())) + Call->getBeginLoc(), Call->getRParenLoc())) return; // Look for 'strlcpy(dst, x, sizeof(x))' @@ -9107,8 +9308,8 @@ void Sema::CheckStrlcpycatArguments(const CallExpr *Call, return; const Expr *OriginalSizeArg = Call->getArg(2); - Diag(CompareWithSrcDRE->getLocStart(), diag::warn_strlcpycat_wrong_size) - << OriginalSizeArg->getSourceRange() << FnName; + Diag(CompareWithSrcDRE->getBeginLoc(), diag::warn_strlcpycat_wrong_size) + << OriginalSizeArg->getSourceRange() << FnName; // Output a FIXIT hint if the destination is an array (rather than a // pointer to an array). This could be enhanced to handle some @@ -9124,9 +9325,9 @@ void Sema::CheckStrlcpycatArguments(const CallExpr *Call, DstArg->printPretty(OS, nullptr, getPrintingPolicy()); OS << ")"; - Diag(OriginalSizeArg->getLocStart(), diag::note_strlcpycat_wrong_size) - << FixItHint::CreateReplacement(OriginalSizeArg->getSourceRange(), - OS.str()); + Diag(OriginalSizeArg->getBeginLoc(), diag::note_strlcpycat_wrong_size) + << FixItHint::CreateReplacement(OriginalSizeArg->getSourceRange(), + OS.str()); } /// Check if two expressions refer to the same declaration. @@ -9159,7 +9360,7 @@ void Sema::CheckStrncatArguments(const CallExpr *CE, const Expr *SrcArg = CE->getArg(1)->IgnoreParenCasts(); const Expr *LenArg = CE->getArg(2)->IgnoreParenCasts(); - if (CheckMemorySizeofForComparison(*this, LenArg, FnName, CE->getLocStart(), + if (CheckMemorySizeofForComparison(*this, LenArg, FnName, CE->getBeginLoc(), CE->getRParenLoc())) return; @@ -9191,7 +9392,7 @@ void Sema::CheckStrncatArguments(const CallExpr *CE, return; // Generate the diagnostic. - SourceLocation SL = LenArg->getLocStart(); + SourceLocation SL = LenArg->getBeginLoc(); SourceRange SR = LenArg->getSourceRange(); SourceManager &SM = getSourceManager(); @@ -9738,7 +9939,7 @@ static bool IsEnumConstOrFromMacro(Sema &S, Expr *E) { return true; // Suppress cases where the '0' value is expanded from a macro. - if (E->getLocStart().isMacroID()) + if (E->getBeginLoc().isMacroID()) return true; return false; @@ -10159,8 +10360,8 @@ static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, Expr *OriginalInit = Init->IgnoreParenImpCasts(); unsigned FieldWidth = Bitfield->getBitWidthValue(S.Context); - llvm::APSInt Value; - if (!OriginalInit->EvaluateAsInt(Value, S.Context, + Expr::EvalResult Result; + if (!OriginalInit->EvaluateAsInt(Result, S.Context, Expr::SE_AllowSideEffects)) { // The RHS is not constant. If the RHS has an enum type, make sure the // bitfield is wide enough to hold all the values of the enum without @@ -10216,6 +10417,8 @@ static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, return false; } + llvm::APSInt Value = Result.Val.getInt(); + unsigned OriginalWidth = Value.getBitWidth(); if (!Value.isSigned() || Value.isNegative()) @@ -10268,6 +10471,10 @@ static void AnalyzeAssignment(Sema &S, BinaryOperator *E) { } AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc()); + + // Diagnose implicitly sequentially-consistent atomic assignment. + if (E->getLHS()->getType()->isAtomicType()) + S.Diag(E->getRHS()->getBeginLoc(), diag::warn_atomic_implicit_seq_cst); } /// Diagnose an implicit cast; purely a helper for CheckImplicitConversion. @@ -10292,33 +10499,6 @@ static void DiagnoseImpCast(Sema &S, Expr *E, QualType T, DiagnoseImpCast(S, E, E->getType(), T, CContext, diag, pruneControlFlow); } -/// Analyze the given compound assignment for the possible losing of -/// floating-point precision. -static void AnalyzeCompoundAssignment(Sema &S, BinaryOperator *E) { - assert(isa<CompoundAssignOperator>(E) && - "Must be compound assignment operation"); - // Recurse on the LHS and RHS in here - AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc()); - AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc()); - - // Now check the outermost expression - const auto *ResultBT = E->getLHS()->getType()->getAs<BuiltinType>(); - const auto *RBT = cast<CompoundAssignOperator>(E) - ->getComputationResultType() - ->getAs<BuiltinType>(); - - // If both source and target are floating points. - if (ResultBT && ResultBT->isFloatingPoint() && RBT && RBT->isFloatingPoint()) - // Builtin FP kinds are ordered by increasing FP rank. - if (ResultBT->getKind() < RBT->getKind()) - // We don't want to warn for system macro. - if (!S.SourceMgr.isInSystemMacro(E->getOperatorLoc())) - // warn about dropping FP rank. - DiagnoseImpCast(S, E->getRHS(), E->getLHS()->getType(), - E->getOperatorLoc(), - diag::warn_impcast_float_result_precision); -} - /// Diagnose an implicit cast from a floating point value to an integer value. static void DiagnoseFloatingImpCast(Sema &S, Expr *E, QualType T, SourceLocation CContext) { @@ -10421,6 +10601,42 @@ static void DiagnoseFloatingImpCast(Sema &S, Expr *E, QualType T, } } +/// Analyze the given compound assignment for the possible losing of +/// floating-point precision. +static void AnalyzeCompoundAssignment(Sema &S, BinaryOperator *E) { + assert(isa<CompoundAssignOperator>(E) && + "Must be compound assignment operation"); + // Recurse on the LHS and RHS in here + AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc()); + AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc()); + + if (E->getLHS()->getType()->isAtomicType()) + S.Diag(E->getOperatorLoc(), diag::warn_atomic_implicit_seq_cst); + + // Now check the outermost expression + const auto *ResultBT = E->getLHS()->getType()->getAs<BuiltinType>(); + const auto *RBT = cast<CompoundAssignOperator>(E) + ->getComputationResultType() + ->getAs<BuiltinType>(); + + // The below checks assume source is floating point. + if (!ResultBT || !RBT || !RBT->isFloatingPoint()) return; + + // If source is floating point but target is not. + if (!ResultBT->isFloatingPoint()) + return DiagnoseFloatingImpCast(S, E, E->getRHS()->getType(), + E->getExprLoc()); + + // If both source and target are floating points. + // Builtin FP kinds are ordered by increasing FP rank. + if (ResultBT->getKind() < RBT->getKind() && + // We don't want to warn for system macro. + !S.SourceMgr.isInSystemMacro(E->getOperatorLoc())) + // warn about dropping FP rank. + DiagnoseImpCast(S, E->getRHS(), E->getLHS()->getType(), E->getOperatorLoc(), + diag::warn_impcast_float_result_precision); +} + static std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) { if (!Range.Width) return "0"; @@ -10545,10 +10761,9 @@ static void checkObjCCollectionLiteralElement(Sema &S, ElementResult, false, false) != Sema::Compatible) { - S.Diag(Element->getLocStart(), - diag::warn_objc_collection_literal_element) - << ElementType << ElementKind << TargetElementType - << Element->getSourceRange(); + S.Diag(Element->getBeginLoc(), diag::warn_objc_collection_literal_element) + << ElementType << ElementKind << TargetElementType + << Element->getSourceRange(); } if (auto ArrayLiteral = dyn_cast<ObjCArrayLiteral>(Element)) @@ -10624,7 +10839,7 @@ static bool isSameWidthConstantConversion(Sema &S, Expr *E, QualType T, // to fill all the bits, even if there is a sign change. if (auto *IntLit = dyn_cast<IntegerLiteral>(E->IgnoreParenImpCasts())) { const char FirstLiteralCharacter = - S.getSourceManager().getCharacterData(IntLit->getLocStart())[0]; + S.getSourceManager().getCharacterData(IntLit->getBeginLoc())[0]; if (FirstLiteralCharacter == '0') return false; } @@ -10659,6 +10874,9 @@ CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC, if (CC.isInvalid()) return; + if (Source->isAtomicType()) + S.Diag(E->getExprLoc(), diag::warn_atomic_implicit_seq_cst); + // Diagnose implicit casts to bool. if (Target->isSpecificBuiltinType(BuiltinType::Bool)) { if (isa<StringLiteral>(E)) @@ -10813,8 +11031,11 @@ CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC, if (SourceRange.Width > TargetRange.Width) { // If the source is a constant, use a default-on diagnostic. // TODO: this should happen for bitfield stores, too. - llvm::APSInt Value(32); - if (E->EvaluateAsInt(Value, S.Context, Expr::SE_AllowSideEffects)) { + Expr::EvalResult Result; + if (E->EvaluateAsInt(Result, S.Context, Expr::SE_AllowSideEffects)) { + llvm::APSInt Value(32); + Value = Result.Val.getInt(); + if (S.SourceMgr.isInSystemMacro(CC)) return; @@ -10839,15 +11060,29 @@ CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC, return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_precision); } + if (TargetRange.Width > SourceRange.Width) { + if (auto *UO = dyn_cast<UnaryOperator>(E)) + if (UO->getOpcode() == UO_Minus) + if (Source->isUnsignedIntegerType()) { + if (Target->isUnsignedIntegerType()) + return DiagnoseImpCast(S, E, T, CC, + diag::warn_impcast_high_order_zero_bits); + if (Target->isSignedIntegerType()) + return DiagnoseImpCast(S, E, T, CC, + diag::warn_impcast_nonnegative_result); + } + } + if (TargetRange.Width == SourceRange.Width && !TargetRange.NonNegative && SourceRange.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. - llvm::APSInt Value; - if (E->EvaluateAsInt(Value, S.Context, Expr::SE_AllowSideEffects) && + Expr::EvalResult Result; + if (E->EvaluateAsInt(Result, S.Context, Expr::SE_AllowSideEffects) && !S.SourceMgr.isInSystemMacro(CC)) { + llvm::APSInt Value = Result.Val.getInt(); if (isSameWidthConstantConversion(S, E, T, CC)) { std::string PrettySourceValue = Value.toString(10); std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange); @@ -10954,11 +11189,13 @@ static void CheckConditionalOperator(Sema &S, ConditionalOperator *E, E->getType(), CC, &Suspicious); } -/// CheckBoolLikeConversion - Check conversion of given expression to boolean. +/// Check conversion of given expression to boolean. /// Input argument E is a logical expression. static void CheckBoolLikeConversion(Sema &S, Expr *E, SourceLocation CC) { if (S.getLangOpts().Bool) return; + if (E->IgnoreParenImpCasts()->getType()->isAtomicType()) + return; CheckImplicitConversion(S, E->IgnoreParenImpCasts(), S.Context.BoolTy, CC); } @@ -11003,8 +11240,10 @@ static void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, } // Skip past explicit casts. - if (isa<ExplicitCastExpr>(E)) { - E = cast<ExplicitCastExpr>(E)->getSubExpr()->IgnoreParenImpCasts(); + if (auto *CE = dyn_cast<ExplicitCastExpr>(E)) { + E = CE->getSubExpr()->IgnoreParenImpCasts(); + if (!CE->getType()->isVoidType() && E->getType()->isAtomicType()) + S.Diag(E->getBeginLoc(), diag::warn_atomic_implicit_seq_cst); return AnalyzeImplicitConversions(S, E, CC); } @@ -11057,9 +11296,15 @@ static void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, ::CheckBoolLikeConversion(S, SubExpr, BO->getExprLoc()); } - if (const UnaryOperator *U = dyn_cast<UnaryOperator>(E)) - if (U->getOpcode() == UO_LNot) + if (const UnaryOperator *U = dyn_cast<UnaryOperator>(E)) { + if (U->getOpcode() == UO_LNot) { ::CheckBoolLikeConversion(S, U->getSubExpr(), CC); + } else if (U->getOpcode() != UO_AddrOf) { + if (U->getSubExpr()->getType()->isAtomicType()) + S.Diag(U->getSubExpr()->getBeginLoc(), + diag::warn_atomic_implicit_seq_cst); + } + } } /// Diagnose integer type and any valid implicit conversion to it. @@ -11067,13 +11312,13 @@ static bool checkOpenCLEnqueueIntType(Sema &S, Expr *E, const QualType &IntT) { // Taking into account implicit conversions, // allow any integer. if (!E->getType()->isIntegerType()) { - S.Diag(E->getLocStart(), + S.Diag(E->getBeginLoc(), diag::err_opencl_enqueue_kernel_invalid_local_size_type); return true; } // Potentially emit standard warnings for implicit conversions if enabled // using -Wconversion. - CheckImplicitConversion(S, E, IntT, E->getLocStart()); + CheckImplicitConversion(S, E, IntT, E->getBeginLoc()); return false; } @@ -11281,7 +11526,7 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E, // Suggest '&' to silence the function warning. Diag(E->getExprLoc(), diag::note_function_warning_silence) - << FixItHint::CreateInsertion(E->getLocStart(), "&"); + << FixItHint::CreateInsertion(E->getBeginLoc(), "&"); // Check to see if '()' fixit should be emitted. QualType ReturnType; @@ -11310,7 +11555,7 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E, return; } Diag(E->getExprLoc(), diag::note_function_to_function_call) - << FixItHint::CreateInsertion(getLocForEndOfToken(E->getLocEnd()), "()"); + << FixItHint::CreateInsertion(getLocForEndOfToken(E->getEndLoc()), "()"); } /// Diagnoses "dangerous" implicit conversions within the given @@ -11663,30 +11908,42 @@ public: notePostUse(O, E); } - void VisitBinComma(BinaryOperator *BO) { - // C++11 [expr.comma]p1: - // Every value computation and side effect associated with the left - // expression is sequenced before every value computation and side - // effect associated with the right expression. - SequenceTree::Seq LHS = Tree.allocate(Region); - SequenceTree::Seq RHS = Tree.allocate(Region); + void VisitSequencedExpressions(Expr *SequencedBefore, Expr *SequencedAfter) { + SequenceTree::Seq BeforeRegion = Tree.allocate(Region); + SequenceTree::Seq AfterRegion = Tree.allocate(Region); SequenceTree::Seq OldRegion = Region; { - SequencedSubexpression SeqLHS(*this); - Region = LHS; - Visit(BO->getLHS()); + SequencedSubexpression SeqBefore(*this); + Region = BeforeRegion; + Visit(SequencedBefore); } - Region = RHS; - Visit(BO->getRHS()); + Region = AfterRegion; + Visit(SequencedAfter); Region = OldRegion; - // Forget that LHS and RHS are sequenced. They are both unsequenced - // with respect to other stuff. - Tree.merge(LHS); - Tree.merge(RHS); + Tree.merge(BeforeRegion); + Tree.merge(AfterRegion); + } + + void VisitArraySubscriptExpr(ArraySubscriptExpr *ASE) { + // C++17 [expr.sub]p1: + // The expression E1[E2] is identical (by definition) to *((E1)+(E2)). The + // expression E1 is sequenced before the expression E2. + if (SemaRef.getLangOpts().CPlusPlus17) + VisitSequencedExpressions(ASE->getLHS(), ASE->getRHS()); + else + Base::VisitStmt(ASE); + } + + void VisitBinComma(BinaryOperator *BO) { + // C++11 [expr.comma]p1: + // Every value computation and side effect associated with the left + // expression is sequenced before every value computation and side + // effect associated with the right expression. + VisitSequencedExpressions(BO->getLHS(), BO->getRHS()); } void VisitBinAssign(BinaryOperator *BO) { @@ -11992,6 +12249,18 @@ bool Sema::CheckParmsForFunctionDef(ArrayRef<ParmVarDecl *> Parameters, if (!Param->getType().isConstQualified()) Diag(Param->getLocation(), diag::err_attribute_pointers_only) << Attr->getSpelling() << 1; + + // Check for parameter names shadowing fields from the class. + if (LangOpts.CPlusPlus && !Param->isInvalidDecl()) { + // The owning context for the parameter should be the function, but we + // want to see if this function's declaration context is a record. + DeclContext *DC = Param->getDeclContext(); + if (DC && DC->isFunctionOrMethod()) { + if (auto *RD = dyn_cast<CXXRecordDecl>(DC->getParent())) + CheckShadowInheritedFields(Param->getLocation(), Param->getDeclName(), + RD, /*DeclIsField*/ false); + } + } } return HasInvalidParm; @@ -12120,13 +12389,18 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, BaseExpr->getType()->getPointeeOrArrayElementType(); BaseExpr = BaseExpr->IgnoreParenCasts(); const ConstantArrayType *ArrayTy = - Context.getAsConstantArrayType(BaseExpr->getType()); + Context.getAsConstantArrayType(BaseExpr->getType()); + if (!ArrayTy) return; - llvm::APSInt index; - if (!IndexExpr->EvaluateAsInt(index, Context, Expr::SE_AllowSideEffects)) + const Type *BaseType = ArrayTy->getElementType().getTypePtr(); + + Expr::EvalResult Result; + if (!IndexExpr->EvaluateAsInt(Result, Context, Expr::SE_AllowSideEffects)) return; + + llvm::APSInt index = Result.Val.getInt(); if (IndexNegated) index = -index; @@ -12137,11 +12411,19 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, ND = ME->getMemberDecl(); if (index.isUnsigned() || !index.isNegative()) { + // It is possible that the type of the base expression after + // IgnoreParenCasts is incomplete, even though the type of the base + // expression before IgnoreParenCasts is complete (see PR39746 for an + // example). In this case we have no information about whether the array + // access exceeds the array bounds. However we can still diagnose an array + // access which precedes the array bounds. + if (BaseType->isIncompleteType()) + return; + llvm::APInt size = ArrayTy->getSize(); if (!size.isStrictlyPositive()) return; - const Type *BaseType = BaseExpr->getType()->getPointeeOrArrayElementType(); if (BaseType != EffectiveType) { // Make sure we're comparing apples to apples when comparing index to size uint64_t ptrarith_typesize = Context.getTypeSize(EffectiveType); @@ -12183,8 +12465,8 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, SourceLocation RBracketLoc = SourceMgr.getSpellingLoc( ASE->getRBracketLoc()); if (SourceMgr.isInSystemHeader(RBracketLoc)) { - SourceLocation IndexLoc = SourceMgr.getSpellingLoc( - IndexExpr->getLocStart()); + SourceLocation IndexLoc = + SourceMgr.getSpellingLoc(IndexExpr->getBeginLoc()); if (SourceMgr.isWrittenInSameFile(RBracketLoc, IndexLoc)) return; } @@ -12194,11 +12476,11 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, if (ASE) DiagID = diag::warn_array_index_exceeds_bounds; - DiagRuntimeBehavior(BaseExpr->getLocStart(), BaseExpr, + DiagRuntimeBehavior(BaseExpr->getBeginLoc(), BaseExpr, PDiag(DiagID) << index.toString(10, true) - << size.toString(10, true) - << (unsigned)size.getLimitedValue(~0U) - << IndexExpr->getSourceRange()); + << size.toString(10, true) + << (unsigned)size.getLimitedValue(~0U) + << IndexExpr->getSourceRange()); } else { unsigned DiagID = diag::warn_array_index_precedes_bounds; if (!ASE) { @@ -12206,9 +12488,9 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, if (index.isNegative()) index = -index; } - DiagRuntimeBehavior(BaseExpr->getLocStart(), BaseExpr, + DiagRuntimeBehavior(BaseExpr->getBeginLoc(), BaseExpr, PDiag(DiagID) << index.toString(10, true) - << IndexExpr->getSourceRange()); + << IndexExpr->getSourceRange()); } if (!ND) { @@ -12223,9 +12505,9 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, } if (ND) - DiagRuntimeBehavior(ND->getLocStart(), BaseExpr, + DiagRuntimeBehavior(ND->getBeginLoc(), BaseExpr, PDiag(diag::note_array_index_out_of_bounds) - << ND->getDeclName()); + << ND->getDeclName()); } void Sema::CheckArrayAccess(const Expr *expr) { @@ -12965,15 +13247,13 @@ void Sema::DiagnoseEmptyLoopBody(const Stmt *S, if (!ProbableTypo) { bool BodyColInvalid; unsigned BodyCol = SourceMgr.getPresumedColumnNumber( - PossibleBody->getLocStart(), - &BodyColInvalid); + PossibleBody->getBeginLoc(), &BodyColInvalid); if (BodyColInvalid) return; bool StmtColInvalid; - unsigned StmtCol = SourceMgr.getPresumedColumnNumber( - S->getLocStart(), - &StmtColInvalid); + unsigned StmtCol = + SourceMgr.getPresumedColumnNumber(S->getBeginLoc(), &StmtColInvalid); if (StmtColInvalid) return; @@ -13493,7 +13773,7 @@ void Sema::DiagnoseMisalignedMembers() { if (const TypedefNameDecl *TD = m.RD->getTypedefNameForAnonDecl()) ND = TD; } - Diag(m.E->getLocStart(), diag::warn_taking_address_of_packed_member) + Diag(m.E->getBeginLoc(), diag::warn_taking_address_of_packed_member) << m.MD << ND << m.E->getSourceRange(); } MisalignedMembers.clear(); diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 30af826ef6cc0..d9f007a46da5e 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -10,6 +10,8 @@ // This file defines the code-completion semantic actions. // //===----------------------------------------------------------------------===// +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprCXX.h" @@ -32,6 +34,8 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Path.h" #include <list> #include <map> #include <vector> @@ -40,315 +44,309 @@ using namespace clang; using namespace sema; namespace { - /// A container of code-completion results. - class ResultBuilder { - public: - /// The type of a name-lookup filter, which can be provided to the - /// name-lookup routines to specify which declarations should be included in - /// the result set (when it returns true) and which declarations should be - /// filtered out (returns false). - typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const; - - typedef CodeCompletionResult Result; +/// A container of code-completion results. +class ResultBuilder { +public: + /// The type of a name-lookup filter, which can be provided to the + /// name-lookup routines to specify which declarations should be included in + /// the result set (when it returns true) and which declarations should be + /// filtered out (returns false). + typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const; - private: - /// The actual results we have found. - std::vector<Result> Results; + typedef CodeCompletionResult Result; - /// A record of all of the declarations we have found and placed - /// into the result set, used to ensure that no declaration ever gets into - /// the result set twice. - llvm::SmallPtrSet<const Decl*, 16> AllDeclsFound; +private: + /// The actual results we have found. + std::vector<Result> Results; - typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair; + /// A record of all of the declarations we have found and placed + /// into the result set, used to ensure that no declaration ever gets into + /// the result set twice. + llvm::SmallPtrSet<const Decl *, 16> AllDeclsFound; - /// An entry in the shadow map, which is optimized to store - /// a single (declaration, index) mapping (the common case) but - /// can also store a list of (declaration, index) mappings. - class ShadowMapEntry { - typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector; + typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair; - /// Contains either the solitary NamedDecl * or a vector - /// of (declaration, index) pairs. - llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector*> DeclOrVector; + /// An entry in the shadow map, which is optimized to store + /// a single (declaration, index) mapping (the common case) but + /// can also store a list of (declaration, index) mappings. + class ShadowMapEntry { + typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector; - /// When the entry contains a single declaration, this is - /// the index associated with that entry. - unsigned SingleDeclIndex; + /// Contains either the solitary NamedDecl * or a vector + /// of (declaration, index) pairs. + llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector *> DeclOrVector; - public: - ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { } + /// When the entry contains a single declaration, this is + /// the index associated with that entry. + unsigned SingleDeclIndex; - void Add(const NamedDecl *ND, unsigned Index) { - if (DeclOrVector.isNull()) { - // 0 - > 1 elements: just set the single element information. - DeclOrVector = ND; - SingleDeclIndex = Index; - return; - } + public: + ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) {} - if (const NamedDecl *PrevND = - DeclOrVector.dyn_cast<const NamedDecl *>()) { - // 1 -> 2 elements: create the vector of results and push in the - // existing declaration. - DeclIndexPairVector *Vec = new DeclIndexPairVector; - Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex)); - DeclOrVector = Vec; - } + void Add(const NamedDecl *ND, unsigned Index) { + if (DeclOrVector.isNull()) { + // 0 - > 1 elements: just set the single element information. + DeclOrVector = ND; + SingleDeclIndex = Index; + return; + } - // Add the new element to the end of the vector. - DeclOrVector.get<DeclIndexPairVector*>()->push_back( - DeclIndexPair(ND, Index)); + if (const NamedDecl *PrevND = + DeclOrVector.dyn_cast<const NamedDecl *>()) { + // 1 -> 2 elements: create the vector of results and push in the + // existing declaration. + DeclIndexPairVector *Vec = new DeclIndexPairVector; + Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex)); + DeclOrVector = Vec; } - void Destroy() { - if (DeclIndexPairVector *Vec - = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) { - delete Vec; - DeclOrVector = ((NamedDecl *)nullptr); - } + // Add the new element to the end of the vector. + DeclOrVector.get<DeclIndexPairVector *>()->push_back( + DeclIndexPair(ND, Index)); + } + + void Destroy() { + if (DeclIndexPairVector *Vec = + DeclOrVector.dyn_cast<DeclIndexPairVector *>()) { + delete Vec; + DeclOrVector = ((NamedDecl *)nullptr); } + } - // Iteration. - class iterator; - iterator begin() const; - iterator end() const; - }; + // Iteration. + class iterator; + iterator begin() const; + iterator end() const; + }; - /// A mapping from declaration names to the declarations that have - /// this name within a particular scope and their index within the list of - /// results. - typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap; + /// A mapping from declaration names to the declarations that have + /// this name within a particular scope and their index within the list of + /// results. + typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap; - /// The semantic analysis object for which results are being - /// produced. - Sema &SemaRef; + /// The semantic analysis object for which results are being + /// produced. + Sema &SemaRef; - /// The allocator used to allocate new code-completion strings. - CodeCompletionAllocator &Allocator; + /// The allocator used to allocate new code-completion strings. + CodeCompletionAllocator &Allocator; - CodeCompletionTUInfo &CCTUInfo; + CodeCompletionTUInfo &CCTUInfo; - /// If non-NULL, a filter function used to remove any code-completion - /// results that are not desirable. - LookupFilter Filter; + /// If non-NULL, a filter function used to remove any code-completion + /// results that are not desirable. + LookupFilter Filter; - /// Whether we should allow declarations as - /// nested-name-specifiers that would otherwise be filtered out. - bool AllowNestedNameSpecifiers; + /// Whether we should allow declarations as + /// nested-name-specifiers that would otherwise be filtered out. + bool AllowNestedNameSpecifiers; - /// If set, the type that we would prefer our resulting value - /// declarations to have. - /// - /// Closely matching the preferred type gives a boost to a result's - /// priority. - CanQualType PreferredType; + /// If set, the type that we would prefer our resulting value + /// declarations to have. + /// + /// Closely matching the preferred type gives a boost to a result's + /// priority. + CanQualType PreferredType; - /// A list of shadow maps, which is used to model name hiding at - /// different levels of, e.g., the inheritance hierarchy. - std::list<ShadowMap> ShadowMaps; + /// A list of shadow maps, which is used to model name hiding at + /// different levels of, e.g., the inheritance hierarchy. + std::list<ShadowMap> ShadowMaps; - /// If we're potentially referring to a C++ member function, the set - /// of qualifiers applied to the object type. - Qualifiers ObjectTypeQualifiers; + /// If we're potentially referring to a C++ member function, the set + /// of qualifiers applied to the object type. + Qualifiers ObjectTypeQualifiers; - /// Whether the \p ObjectTypeQualifiers field is active. - bool HasObjectTypeQualifiers; + /// Whether the \p ObjectTypeQualifiers field is active. + bool HasObjectTypeQualifiers; - /// The selector that we prefer. - Selector PreferredSelector; + /// The selector that we prefer. + Selector PreferredSelector; - /// The completion context in which we are gathering results. - CodeCompletionContext CompletionContext; + /// The completion context in which we are gathering results. + CodeCompletionContext CompletionContext; - /// If we are in an instance method definition, the \@implementation - /// object. - ObjCImplementationDecl *ObjCImplementation; + /// If we are in an instance method definition, the \@implementation + /// object. + ObjCImplementationDecl *ObjCImplementation; - void AdjustResultPriorityForDecl(Result &R); + void AdjustResultPriorityForDecl(Result &R); - void MaybeAddConstructorResults(Result R); + void MaybeAddConstructorResults(Result R); - public: - explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator, - CodeCompletionTUInfo &CCTUInfo, - const CodeCompletionContext &CompletionContext, - LookupFilter Filter = nullptr) +public: + explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo, + const CodeCompletionContext &CompletionContext, + LookupFilter Filter = nullptr) : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo), - Filter(Filter), - AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false), - CompletionContext(CompletionContext), - ObjCImplementation(nullptr) - { - // If this is an Objective-C instance method definition, dig out the - // corresponding implementation. - switch (CompletionContext.getKind()) { - case CodeCompletionContext::CCC_Expression: - case CodeCompletionContext::CCC_ObjCMessageReceiver: - case CodeCompletionContext::CCC_ParenthesizedExpression: - case CodeCompletionContext::CCC_Statement: - case CodeCompletionContext::CCC_Recovery: - if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) - if (Method->isInstanceMethod()) - if (ObjCInterfaceDecl *Interface = Method->getClassInterface()) - ObjCImplementation = Interface->getImplementation(); - break; + Filter(Filter), AllowNestedNameSpecifiers(false), + HasObjectTypeQualifiers(false), CompletionContext(CompletionContext), + ObjCImplementation(nullptr) { + // If this is an Objective-C instance method definition, dig out the + // corresponding implementation. + switch (CompletionContext.getKind()) { + case CodeCompletionContext::CCC_Expression: + case CodeCompletionContext::CCC_ObjCMessageReceiver: + case CodeCompletionContext::CCC_ParenthesizedExpression: + case CodeCompletionContext::CCC_Statement: + case CodeCompletionContext::CCC_Recovery: + if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) + if (Method->isInstanceMethod()) + if (ObjCInterfaceDecl *Interface = Method->getClassInterface()) + ObjCImplementation = Interface->getImplementation(); + break; - default: - break; - } - } - - /// Determine the priority for a reference to the given declaration. - unsigned getBasePriority(const NamedDecl *D); - - /// Whether we should include code patterns in the completion - /// results. - bool includeCodePatterns() const { - return SemaRef.CodeCompleter && - SemaRef.CodeCompleter->includeCodePatterns(); - } - - /// Set the filter used for code-completion results. - void setFilter(LookupFilter Filter) { - this->Filter = Filter; - } - - Result *data() { return Results.empty()? nullptr : &Results.front(); } - unsigned size() const { return Results.size(); } - bool empty() const { return Results.empty(); } - - /// Specify the preferred type. - void setPreferredType(QualType T) { - PreferredType = SemaRef.Context.getCanonicalType(T); + default: + break; } + } - /// Set the cv-qualifiers on the object type, for us in filtering - /// calls to member functions. - /// - /// When there are qualifiers in this set, they will be used to filter - /// out member functions that aren't available (because there will be a - /// cv-qualifier mismatch) or prefer functions with an exact qualifier - /// match. - void setObjectTypeQualifiers(Qualifiers Quals) { - ObjectTypeQualifiers = Quals; - HasObjectTypeQualifiers = true; - } - - /// Set the preferred selector. - /// - /// When an Objective-C method declaration result is added, and that - /// method's selector matches this preferred selector, we give that method - /// a slight priority boost. - void setPreferredSelector(Selector Sel) { - PreferredSelector = Sel; - } - - /// Retrieve the code-completion context for which results are - /// being collected. - const CodeCompletionContext &getCompletionContext() const { - return CompletionContext; - } - - /// Specify whether nested-name-specifiers are allowed. - void allowNestedNameSpecifiers(bool Allow = true) { - AllowNestedNameSpecifiers = Allow; - } - - /// Return the semantic analysis object for which we are collecting - /// code completion results. - Sema &getSema() const { return SemaRef; } - - /// Retrieve the allocator used to allocate code completion strings. - CodeCompletionAllocator &getAllocator() const { return Allocator; } - - CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; } - - /// Determine whether the given declaration is at all interesting - /// as a code-completion result. - /// - /// \param ND the declaration that we are inspecting. - /// - /// \param AsNestedNameSpecifier will be set true if this declaration is - /// only interesting when it is a nested-name-specifier. - bool isInterestingDecl(const NamedDecl *ND, - bool &AsNestedNameSpecifier) const; - - /// Check whether the result is hidden by the Hiding declaration. - /// - /// \returns true if the result is hidden and cannot be found, false if - /// the hidden result could still be found. When false, \p R may be - /// modified to describe how the result can be found (e.g., via extra - /// qualification). - bool CheckHiddenResult(Result &R, DeclContext *CurContext, - const NamedDecl *Hiding); - - /// Add a new result to this result set (if it isn't already in one - /// of the shadow maps), or replace an existing result (for, e.g., a - /// redeclaration). - /// - /// \param R the result to add (if it is unique). - /// - /// \param CurContext the context in which this result will be named. - void MaybeAddResult(Result R, DeclContext *CurContext = nullptr); - - /// Add a new result to this result set, where we already know - /// the hiding declaration (if any). - /// - /// \param R the result to add (if it is unique). - /// - /// \param CurContext the context in which this result will be named. - /// - /// \param Hiding the declaration that hides the result. - /// - /// \param InBaseClass whether the result was found in a base - /// class of the searched context. - void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding, - bool InBaseClass); - - /// Add a new non-declaration result to this result set. - void AddResult(Result R); - - /// Enter into a new scope. - void EnterNewScope(); - - /// Exit from the current scope. - void ExitScope(); - - /// Ignore this declaration, if it is seen again. - void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); } - - /// Add a visited context. - void addVisitedContext(DeclContext *Ctx) { - CompletionContext.addVisitedContext(Ctx); - } - - /// \name Name lookup predicates - /// - /// These predicates can be passed to the name lookup functions to filter the - /// results of name lookup. All of the predicates have the same type, so that - /// - //@{ - bool IsOrdinaryName(const NamedDecl *ND) const; - bool IsOrdinaryNonTypeName(const NamedDecl *ND) const; - bool IsIntegralConstantValue(const NamedDecl *ND) const; - bool IsOrdinaryNonValueName(const NamedDecl *ND) const; - bool IsNestedNameSpecifier(const NamedDecl *ND) const; - bool IsEnum(const NamedDecl *ND) const; - bool IsClassOrStruct(const NamedDecl *ND) const; - bool IsUnion(const NamedDecl *ND) const; - bool IsNamespace(const NamedDecl *ND) const; - bool IsNamespaceOrAlias(const NamedDecl *ND) const; - bool IsType(const NamedDecl *ND) const; - bool IsMember(const NamedDecl *ND) const; - bool IsObjCIvar(const NamedDecl *ND) const; - bool IsObjCMessageReceiver(const NamedDecl *ND) const; - bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const; - bool IsObjCCollection(const NamedDecl *ND) const; - bool IsImpossibleToSatisfy(const NamedDecl *ND) const; - //@} - }; -} + /// Determine the priority for a reference to the given declaration. + unsigned getBasePriority(const NamedDecl *D); + + /// Whether we should include code patterns in the completion + /// results. + bool includeCodePatterns() const { + return SemaRef.CodeCompleter && + SemaRef.CodeCompleter->includeCodePatterns(); + } + + /// Set the filter used for code-completion results. + void setFilter(LookupFilter Filter) { this->Filter = Filter; } + + Result *data() { return Results.empty() ? nullptr : &Results.front(); } + unsigned size() const { return Results.size(); } + bool empty() const { return Results.empty(); } + + /// Specify the preferred type. + void setPreferredType(QualType T) { + PreferredType = SemaRef.Context.getCanonicalType(T); + } + + /// Set the cv-qualifiers on the object type, for us in filtering + /// calls to member functions. + /// + /// When there are qualifiers in this set, they will be used to filter + /// out member functions that aren't available (because there will be a + /// cv-qualifier mismatch) or prefer functions with an exact qualifier + /// match. + void setObjectTypeQualifiers(Qualifiers Quals) { + ObjectTypeQualifiers = Quals; + HasObjectTypeQualifiers = true; + } + + /// Set the preferred selector. + /// + /// When an Objective-C method declaration result is added, and that + /// method's selector matches this preferred selector, we give that method + /// a slight priority boost. + void setPreferredSelector(Selector Sel) { PreferredSelector = Sel; } + + /// Retrieve the code-completion context for which results are + /// being collected. + const CodeCompletionContext &getCompletionContext() const { + return CompletionContext; + } + + /// Specify whether nested-name-specifiers are allowed. + void allowNestedNameSpecifiers(bool Allow = true) { + AllowNestedNameSpecifiers = Allow; + } + + /// Return the semantic analysis object for which we are collecting + /// code completion results. + Sema &getSema() const { return SemaRef; } + + /// Retrieve the allocator used to allocate code completion strings. + CodeCompletionAllocator &getAllocator() const { return Allocator; } + + CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; } + + /// Determine whether the given declaration is at all interesting + /// as a code-completion result. + /// + /// \param ND the declaration that we are inspecting. + /// + /// \param AsNestedNameSpecifier will be set true if this declaration is + /// only interesting when it is a nested-name-specifier. + bool isInterestingDecl(const NamedDecl *ND, + bool &AsNestedNameSpecifier) const; + + /// Check whether the result is hidden by the Hiding declaration. + /// + /// \returns true if the result is hidden and cannot be found, false if + /// the hidden result could still be found. When false, \p R may be + /// modified to describe how the result can be found (e.g., via extra + /// qualification). + bool CheckHiddenResult(Result &R, DeclContext *CurContext, + const NamedDecl *Hiding); + + /// Add a new result to this result set (if it isn't already in one + /// of the shadow maps), or replace an existing result (for, e.g., a + /// redeclaration). + /// + /// \param R the result to add (if it is unique). + /// + /// \param CurContext the context in which this result will be named. + void MaybeAddResult(Result R, DeclContext *CurContext = nullptr); + + /// Add a new result to this result set, where we already know + /// the hiding declaration (if any). + /// + /// \param R the result to add (if it is unique). + /// + /// \param CurContext the context in which this result will be named. + /// + /// \param Hiding the declaration that hides the result. + /// + /// \param InBaseClass whether the result was found in a base + /// class of the searched context. + void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding, + bool InBaseClass); + + /// Add a new non-declaration result to this result set. + void AddResult(Result R); + + /// Enter into a new scope. + void EnterNewScope(); + + /// Exit from the current scope. + void ExitScope(); + + /// Ignore this declaration, if it is seen again. + void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); } + + /// Add a visited context. + void addVisitedContext(DeclContext *Ctx) { + CompletionContext.addVisitedContext(Ctx); + } + + /// \name Name lookup predicates + /// + /// These predicates can be passed to the name lookup functions to filter the + /// results of name lookup. All of the predicates have the same type, so that + /// + //@{ + bool IsOrdinaryName(const NamedDecl *ND) const; + bool IsOrdinaryNonTypeName(const NamedDecl *ND) const; + bool IsIntegralConstantValue(const NamedDecl *ND) const; + bool IsOrdinaryNonValueName(const NamedDecl *ND) const; + bool IsNestedNameSpecifier(const NamedDecl *ND) const; + bool IsEnum(const NamedDecl *ND) const; + bool IsClassOrStruct(const NamedDecl *ND) const; + bool IsUnion(const NamedDecl *ND) const; + bool IsNamespace(const NamedDecl *ND) const; + bool IsNamespaceOrAlias(const NamedDecl *ND) const; + bool IsType(const NamedDecl *ND) const; + bool IsMember(const NamedDecl *ND) const; + bool IsObjCIvar(const NamedDecl *ND) const; + bool IsObjCMessageReceiver(const NamedDecl *ND) const; + bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const; + bool IsObjCCollection(const NamedDecl *ND) const; + bool IsImpossibleToSatisfy(const NamedDecl *ND) const; + //@} +}; +} // namespace class ResultBuilder::ShadowMapEntry::iterator { llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator; @@ -364,20 +362,18 @@ public: DeclIndexPair Value; public: - pointer(const DeclIndexPair &Value) : Value(Value) { } + pointer(const DeclIndexPair &Value) : Value(Value) {} - const DeclIndexPair *operator->() const { - return &Value; - } + const DeclIndexPair *operator->() const { return &Value; } }; iterator() : DeclOrIterator((NamedDecl *)nullptr), SingleDeclIndex(0) {} iterator(const NamedDecl *SingleDecl, unsigned Index) - : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { } + : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) {} iterator(const DeclIndexPair *Iterator) - : DeclOrIterator(Iterator), SingleDeclIndex(0) { } + : DeclOrIterator(Iterator), SingleDeclIndex(0) {} iterator &operator++() { if (DeclOrIterator.is<const NamedDecl *>()) { @@ -386,7 +382,7 @@ public: return *this; } - const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>(); + const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair *>(); ++I; DeclOrIterator = I; return *this; @@ -402,17 +398,15 @@ public: if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>()) return reference(ND, SingleDeclIndex); - return *DeclOrIterator.get<const DeclIndexPair*>(); + return *DeclOrIterator.get<const DeclIndexPair *>(); } - pointer operator->() const { - return pointer(**this); - } + pointer operator->() const { return pointer(**this); } friend bool operator==(const iterator &X, const iterator &Y) { - return X.DeclOrIterator.getOpaqueValue() - == Y.DeclOrIterator.getOpaqueValue() && - X.SingleDeclIndex == Y.SingleDeclIndex; + return X.DeclOrIterator.getOpaqueValue() == + Y.DeclOrIterator.getOpaqueValue() && + X.SingleDeclIndex == Y.SingleDeclIndex; } friend bool operator!=(const iterator &X, const iterator &Y) { @@ -453,8 +447,7 @@ ResultBuilder::ShadowMapEntry::end() const { /// \returns a nested name specifier that refers into the target context, or /// NULL if no qualification is needed. static NestedNameSpecifier * -getRequiredQualification(ASTContext &Context, - const DeclContext *CurContext, +getRequiredQualification(ASTContext &Context, const DeclContext *CurContext, const DeclContext *TargetContext) { SmallVector<const DeclContext *, 4> TargetParents; @@ -472,16 +465,14 @@ getRequiredQualification(ASTContext &Context, while (!TargetParents.empty()) { const DeclContext *Parent = TargetParents.pop_back_val(); - if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) { + if (const auto *Namespace = dyn_cast<NamespaceDecl>(Parent)) { if (!Namespace->getIdentifier()) continue; Result = NestedNameSpecifier::Create(Context, Result, Namespace); - } - else if (const TagDecl *TD = dyn_cast<TagDecl>(Parent)) - Result = NestedNameSpecifier::Create(Context, Result, - false, - Context.getTypeDeclType(TD).getTypePtr()); + } else if (const auto *TD = dyn_cast<TagDecl>(Parent)) + Result = NestedNameSpecifier::Create( + Context, Result, false, Context.getTypeDeclType(TD).getTypePtr()); } return Result; } @@ -494,8 +485,8 @@ static bool isReservedName(const IdentifierInfo *Id, return false; const char *Name = Id->getNameStart(); return Name[0] == '_' && - (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z' && - !doubleUnderscoreOnly)); + (Name[1] == '_' || + (Name[1] >= 'A' && Name[1] <= 'Z' && !doubleUnderscoreOnly)); } // Some declarations have reserved names that we don't want to ever show. @@ -514,9 +505,9 @@ static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) { // This allows for system headers providing private symbols with a single // underscore. if (isReservedName(Id, /*doubleUnderscoreOnly=*/true) && - SemaRef.SourceMgr.isInSystemHeader( - SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))) - return true; + SemaRef.SourceMgr.isInSystemHeader( + SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))) + return true; return false; } @@ -550,10 +541,8 @@ bool ResultBuilder::isInterestingDecl(const NamedDecl *ND, return false; if (Filter == &ResultBuilder::IsNestedNameSpecifier || - (isa<NamespaceDecl>(ND) && - Filter != &ResultBuilder::IsNamespace && - Filter != &ResultBuilder::IsNamespaceOrAlias && - Filter != nullptr)) + (isa<NamespaceDecl>(ND) && Filter != &ResultBuilder::IsNamespace && + Filter != &ResultBuilder::IsNamespaceOrAlias && Filter != nullptr)) AsNestedNameSpecifier = true; // Filter out any unwanted results. @@ -597,8 +586,7 @@ bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext, R.QualifierIsInformative = false; if (!R.Qualifier) - R.Qualifier = getRequiredQualification(SemaRef.Context, - CurContext, + R.Qualifier = getRequiredQualification(SemaRef.Context, CurContext, R.Declaration->getDeclContext()); return false; } @@ -609,23 +597,23 @@ SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) { switch (T->getTypeClass()) { case Type::Builtin: switch (cast<BuiltinType>(T)->getKind()) { - case BuiltinType::Void: - return STC_Void; + case BuiltinType::Void: + return STC_Void; - case BuiltinType::NullPtr: - return STC_Pointer; + case BuiltinType::NullPtr: + return STC_Pointer; - case BuiltinType::Overload: - case BuiltinType::Dependent: - return STC_Other; + case BuiltinType::Overload: + case BuiltinType::Dependent: + return STC_Other; - case BuiltinType::ObjCId: - case BuiltinType::ObjCClass: - case BuiltinType::ObjCSel: - return STC_ObjectiveC; + case BuiltinType::ObjCId: + case BuiltinType::ObjCClass: + case BuiltinType::ObjCSel: + return STC_ObjectiveC; - default: - return STC_Arithmetic; + default: + return STC_Arithmetic; } case Type::Complex: @@ -677,21 +665,21 @@ SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) { QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) { ND = ND->getUnderlyingDecl(); - if (const TypeDecl *Type = dyn_cast<TypeDecl>(ND)) + if (const auto *Type = dyn_cast<TypeDecl>(ND)) return C.getTypeDeclType(Type); - if (const ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND)) + if (const auto *Iface = dyn_cast<ObjCInterfaceDecl>(ND)) return C.getObjCInterfaceType(Iface); QualType T; if (const FunctionDecl *Function = ND->getAsFunction()) T = Function->getCallResultType(); - else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) + else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) T = Method->getSendResultType(); - else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) + else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext())); - else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) + else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND)) T = Property->getType(); - else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) + else if (const auto *Value = dyn_cast<ValueDecl>(ND)) T = Value->getType(); else return QualType(); @@ -700,12 +688,12 @@ QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) { // get down to the likely type of an expression when the entity is // used. do { - if (const ReferenceType *Ref = T->getAs<ReferenceType>()) { + if (const auto *Ref = T->getAs<ReferenceType>()) { T = Ref->getPointeeType(); continue; } - if (const PointerType *Pointer = T->getAs<PointerType>()) { + if (const auto *Pointer = T->getAs<PointerType>()) { if (Pointer->getPointeeType()->isFunctionType()) { T = Pointer->getPointeeType(); continue; @@ -714,12 +702,12 @@ QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) { break; } - if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) { + if (const auto *Block = T->getAs<BlockPointerType>()) { T = Block->getPointeeType(); continue; } - if (const FunctionType *Function = T->getAs<FunctionType>()) { + if (const auto *Function = T->getAs<FunctionType>()) { T = Function->getReturnType(); continue; } @@ -738,8 +726,7 @@ unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) { const DeclContext *LexicalDC = ND->getLexicalDeclContext(); if (LexicalDC->isFunctionOrMethod()) { // _cmd is relatively rare - if (const ImplicitParamDecl *ImplicitParam = - dyn_cast<ImplicitParamDecl>(ND)) + if (const auto *ImplicitParam = dyn_cast<ImplicitParamDecl>(ND)) if (ImplicitParam->getIdentifier() && ImplicitParam->getIdentifier()->isStr("_cmd")) return CCP_ObjC_cmd; @@ -770,10 +757,10 @@ unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) { // likely that the user will want to write a type as other declarations. if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) && !(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement || - CompletionContext.getKind() - == CodeCompletionContext::CCC_ObjCMessageReceiver || - CompletionContext.getKind() - == CodeCompletionContext::CCC_ParenthesizedExpression)) + CompletionContext.getKind() == + CodeCompletionContext::CCC_ObjCMessageReceiver || + CompletionContext.getKind() == + CodeCompletionContext::CCC_ParenthesizedExpression)) return CCP_Type; return CCP_Declaration; @@ -783,7 +770,7 @@ void ResultBuilder::AdjustResultPriorityForDecl(Result &R) { // If this is an Objective-C method declaration whose selector matches our // preferred selector, give it a priority boost. if (!PreferredSelector.isNull()) - if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration)) + if (const auto *Method = dyn_cast<ObjCMethodDecl>(R.Declaration)) if (PreferredSelector == Method->getSelector()) R.Priority += CCD_SelectorMatch; @@ -797,20 +784,28 @@ void ResultBuilder::AdjustResultPriorityForDecl(Result &R) { if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC)) R.Priority /= CCF_ExactTypeMatch; // Check for nearly-matching types, based on classification of each. - else if ((getSimplifiedTypeClass(PreferredType) - == getSimplifiedTypeClass(TC)) && + else if ((getSimplifiedTypeClass(PreferredType) == + getSimplifiedTypeClass(TC)) && !(PreferredType->isEnumeralType() && TC->isEnumeralType())) R.Priority /= CCF_SimilarTypeMatch; } } } +DeclContext::lookup_result getConstructors(ASTContext &Context, + const CXXRecordDecl *Record) { + QualType RecordTy = Context.getTypeDeclType(Record); + DeclarationName ConstructorName = + Context.DeclarationNames.getCXXConstructorName( + Context.getCanonicalType(RecordTy)); + return Record->lookup(ConstructorName); +} + void ResultBuilder::MaybeAddConstructorResults(Result R) { if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration || !CompletionContext.wantConstructorResults()) return; - ASTContext &Context = SemaRef.Context; const NamedDecl *D = R.Declaration; const CXXRecordDecl *Record = nullptr; if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D)) @@ -828,16 +823,8 @@ void ResultBuilder::MaybeAddConstructorResults(Result R) { if (!Record) return; - - QualType RecordTy = Context.getTypeDeclType(Record); - DeclarationName ConstructorName - = Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(RecordTy)); - DeclContext::lookup_result Ctors = Record->lookup(ConstructorName); - for (DeclContext::lookup_iterator I = Ctors.begin(), - E = Ctors.end(); - I != E; ++I) { - R.Declaration = *I; + for (NamedDecl *Ctor : getConstructors(SemaRef.Context, Record)) { + R.Declaration = Ctor; R.CursorKind = getCursorKindForDecl(R.Declaration); Results.push_back(R); } @@ -919,8 +906,8 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { continue; // Protocols are in distinct namespaces from everything else. - if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) - || (IDNS & Decl::IDNS_ObjCProtocol)) && + if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) || + (IDNS & Decl::IDNS_ObjCProtocol)) && I->first->getIdentifierNamespace() != IDNS) continue; @@ -942,18 +929,19 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { R.StartsNestedNameSpecifier = true; R.Priority = CCP_NestedNameSpecifier; } else - AdjustResultPriorityForDecl(R); + AdjustResultPriorityForDecl(R); // If this result is supposed to have an informative qualifier, add one. if (R.QualifierIsInformative && !R.Qualifier && !R.StartsNestedNameSpecifier) { const DeclContext *Ctx = R.Declaration->getDeclContext(); if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx)) - R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr, - Namespace); + R.Qualifier = + NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace); else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx)) - R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr, - false, SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); + R.Qualifier = NestedNameSpecifier::Create( + SemaRef.Context, nullptr, false, + SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); else R.QualifierIsInformative = false; } @@ -967,6 +955,11 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { MaybeAddConstructorResults(R); } +static void setInBaseClass(ResultBuilder::Result &R) { + R.Priority += CCD_InBaseClass; + R.InBaseClass = true; +} + void ResultBuilder::AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding, bool InBaseClass = false) { if (R.Kind != Result::RK_Declaration) { @@ -976,7 +969,7 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, } // Look through using declarations. - if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) { + if (const auto *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) { CodeCompletionResult Result(Using->getTargetDecl(), getBasePriority(Using->getTargetDecl()), R.Qualifier); @@ -1015,27 +1008,27 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, if (R.QualifierIsInformative && !R.Qualifier && !R.StartsNestedNameSpecifier) { const DeclContext *Ctx = R.Declaration->getDeclContext(); - if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx)) - R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr, - Namespace); - else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx)) - R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr, false, - SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); + if (const auto *Namespace = dyn_cast<NamespaceDecl>(Ctx)) + R.Qualifier = + NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace); + else if (const auto *Tag = dyn_cast<TagDecl>(Ctx)) + R.Qualifier = NestedNameSpecifier::Create( + SemaRef.Context, nullptr, false, + SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); else R.QualifierIsInformative = false; } // Adjust the priority if this result comes from a base class. if (InBaseClass) - R.Priority += CCD_InBaseClass; + setInBaseClass(R); AdjustResultPriorityForDecl(R); if (HasObjectTypeQualifiers) - if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration)) + if (const auto *Method = dyn_cast<CXXMethodDecl>(R.Declaration)) if (Method->isInstance()) { - Qualifiers MethodQuals - = Qualifiers::fromCVRMask(Method->getTypeQualifiers()); + Qualifiers MethodQuals = Method->getTypeQualifiers(); if (ObjectTypeQualifiers == MethodQuals) R.Priority += CCD_ObjectQualifierMatch; else if (ObjectTypeQualifiers - MethodQuals) { @@ -1054,7 +1047,7 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, void ResultBuilder::AddResult(Result R) { assert(R.Kind != Result::RK_Declaration && - "Declaration results need more context"); + "Declaration results need more context"); Results.push_back(R); } @@ -1064,9 +1057,8 @@ void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); } /// Exit from the current scope. void ResultBuilder::ExitScope() { for (ShadowMap::iterator E = ShadowMaps.back().begin(), - EEnd = ShadowMaps.back().end(); - E != EEnd; - ++E) + EEnd = ShadowMaps.back().end(); + E != EEnd; ++E) E->second.Destroy(); ShadowMaps.pop_back(); @@ -1082,7 +1074,7 @@ bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const { unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern; if (SemaRef.getLangOpts().CPlusPlus) IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member; - else if (SemaRef.getLangOpts().ObjC1) { + else if (SemaRef.getLangOpts().ObjC) { if (isa<ObjCIvarDecl>(ND)) return true; } @@ -1107,7 +1099,7 @@ bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const { unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern; if (SemaRef.getLangOpts().CPlusPlus) IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member; - else if (SemaRef.getLangOpts().ObjC1) { + else if (SemaRef.getLangOpts().ObjC) { if (isa<ObjCIvarDecl>(ND)) return true; } @@ -1119,7 +1111,7 @@ bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const { if (!IsOrdinaryNonTypeName(ND)) return 0; - if (const ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl())) + if (const auto *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl())) if (VD->getType()->isIntegralOrEnumerationType()) return true; @@ -1135,16 +1127,15 @@ bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const { if (SemaRef.getLangOpts().CPlusPlus) IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace; - return (ND->getIdentifierNamespace() & IDNS) && - !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) && - !isa<ObjCPropertyDecl>(ND); + return (ND->getIdentifierNamespace() & IDNS) && !isa<ValueDecl>(ND) && + !isa<FunctionTemplateDecl>(ND) && !isa<ObjCPropertyDecl>(ND); } /// Determines whether the given declaration is suitable as the /// start of a C++ nested-name-specifier, e.g., a class or namespace. bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const { // Allow us to find class templates, too. - if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) + if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) ND = ClassTemplate->getTemplatedDecl(); return SemaRef.isAcceptableNestedNameSpecifier(ND); @@ -1158,14 +1149,13 @@ bool ResultBuilder::IsEnum(const NamedDecl *ND) const { /// Determines whether the given declaration is a class or struct. bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const { // Allow us to find class templates, too. - if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) + if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) ND = ClassTemplate->getTemplatedDecl(); // For purposes of this check, interfaces match too. - if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND)) - return RD->getTagKind() == TTK_Class || - RD->getTagKind() == TTK_Struct || - RD->getTagKind() == TTK_Interface; + if (const auto *RD = dyn_cast<RecordDecl>(ND)) + return RD->getTagKind() == TTK_Class || RD->getTagKind() == TTK_Struct || + RD->getTagKind() == TTK_Interface; return false; } @@ -1173,10 +1163,10 @@ bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const { /// Determines whether the given declaration is a union. bool ResultBuilder::IsUnion(const NamedDecl *ND) const { // Allow us to find class templates, too. - if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) + if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) ND = ClassTemplate->getTemplatedDecl(); - if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND)) + if (const auto *RD = dyn_cast<RecordDecl>(ND)) return RD->getTagKind() == TTK_Union; return false; @@ -1250,11 +1240,12 @@ bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const { return isObjCReceiverType(SemaRef.Context, T); } -bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const { +bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture( + const NamedDecl *ND) const { if (IsObjCMessageReceiver(ND)) return true; - const VarDecl *Var = dyn_cast<VarDecl>(ND); + const auto *Var = dyn_cast<VarDecl>(ND); if (!Var) return false; @@ -1287,34 +1278,80 @@ bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const { } namespace { - /// Visible declaration consumer that adds a code-completion result - /// for each visible declaration. - class CodeCompletionDeclConsumer : public VisibleDeclConsumer { - ResultBuilder &Results; - DeclContext *CurContext; - std::vector<FixItHint> FixIts; - public: - CodeCompletionDeclConsumer( - ResultBuilder &Results, DeclContext *CurContext, - std::vector<FixItHint> FixIts = std::vector<FixItHint>()) - : Results(Results), CurContext(CurContext), FixIts(std::move(FixIts)) {} +/// Visible declaration consumer that adds a code-completion result +/// for each visible declaration. +class CodeCompletionDeclConsumer : public VisibleDeclConsumer { + ResultBuilder &Results; + DeclContext *InitialLookupCtx; + // NamingClass and BaseType are used for access-checking. See + // Sema::IsSimplyAccessible for details. + CXXRecordDecl *NamingClass; + QualType BaseType; + std::vector<FixItHint> FixIts; - void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx, - bool InBaseClass) override { - bool Accessible = true; - if (Ctx) - Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx); - ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr, - false, Accessible, FixIts); - Results.AddResult(Result, CurContext, Hiding, InBaseClass); +public: + CodeCompletionDeclConsumer( + ResultBuilder &Results, DeclContext *InitialLookupCtx, + QualType BaseType = QualType(), + std::vector<FixItHint> FixIts = std::vector<FixItHint>()) + : Results(Results), InitialLookupCtx(InitialLookupCtx), + FixIts(std::move(FixIts)) { + NamingClass = llvm::dyn_cast<CXXRecordDecl>(InitialLookupCtx); + // If BaseType was not provided explicitly, emulate implicit 'this->'. + if (BaseType.isNull()) { + auto ThisType = Results.getSema().getCurrentThisType(); + if (!ThisType.isNull()) { + assert(ThisType->isPointerType()); + BaseType = ThisType->getPointeeType(); + if (!NamingClass) + NamingClass = BaseType->getAsCXXRecordDecl(); + } } - - void EnteredContext(DeclContext* Ctx) override { - Results.addVisitedContext(Ctx); + this->BaseType = BaseType; + } + + void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx, + bool InBaseClass) override { + ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr, + false, IsAccessible(ND, Ctx), FixIts); + Results.AddResult(Result, InitialLookupCtx, Hiding, InBaseClass); + } + + void EnteredContext(DeclContext *Ctx) override { + Results.addVisitedContext(Ctx); + } + +private: + bool IsAccessible(NamedDecl *ND, DeclContext *Ctx) { + // Naming class to use for access check. In most cases it was provided + // explicitly (e.g. member access (lhs.foo) or qualified lookup (X::)), + // for unqualified lookup we fallback to the \p Ctx in which we found the + // member. + auto *NamingClass = this->NamingClass; + QualType BaseType = this->BaseType; + if (auto *Cls = llvm::dyn_cast_or_null<CXXRecordDecl>(Ctx)) { + if (!NamingClass) + NamingClass = Cls; + // When we emulate implicit 'this->' in an unqualified lookup, we might + // end up with an invalid naming class. In that case, we avoid emulating + // 'this->' qualifier to satisfy preconditions of the access checking. + if (NamingClass->getCanonicalDecl() != Cls->getCanonicalDecl() && + !NamingClass->isDerivedFrom(Cls)) { + NamingClass = Cls; + BaseType = QualType(); + } + } else { + // The decl was found outside the C++ class, so only ObjC access checks + // apply. Those do not rely on NamingClass and BaseType, so we clear them + // out. + NamingClass = nullptr; + BaseType = QualType(); } - }; -} + return Results.getSema().IsSimplyAccessible(ND, NamingClass, BaseType); + } +}; +} // namespace /// Add type specifiers for the current language as keyword results. static void AddTypeSpecifierResults(const LangOptions &LangOpts, @@ -1347,8 +1384,8 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts, Results.getCodeCompletionTUInfo()); if (LangOpts.CPlusPlus) { // C++-specific - Results.AddResult(Result("bool", CCP_Type + - (LangOpts.ObjC1? CCD_bool_in_ObjC : 0))); + Results.AddResult( + Result("bool", CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0))); Results.AddResult(Result("class", CCP_Type)); Results.AddResult(Result("wchar_t", CCP_Type)); @@ -1464,14 +1501,11 @@ static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC, static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt); static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt); static void AddObjCVisibilityResults(const LangOptions &LangOpts, - ResultBuilder &Results, - bool NeedAt); + ResultBuilder &Results, bool NeedAt); static void AddObjCImplementationResults(const LangOptions &LangOpts, - ResultBuilder &Results, - bool NeedAt); + ResultBuilder &Results, bool NeedAt); static void AddObjCInterfaceResults(const LangOptions &LangOpts, - ResultBuilder &Results, - bool NeedAt); + ResultBuilder &Results, bool NeedAt); static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt); static void AddTypedefResult(ResultBuilder &Results) { @@ -1509,7 +1543,7 @@ static bool WantTypesInContext(Sema::ParserCompletionContext CCC, return false; case Sema::PCC_ForInit: - return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99; + return LangOpts.CPlusPlus || LangOpts.ObjC || LangOpts.C99; } llvm_unreachable("Invalid ParserCompletionContext!"); @@ -1535,8 +1569,7 @@ static PrintingPolicy getCompletionPrintingPolicy(Sema &S) { /// /// This routine provides a fast path where we provide constant strings for /// common type names. -static const char *GetCompletionTypeString(QualType T, - ASTContext &Context, +static const char *GetCompletionTypeString(QualType T, ASTContext &Context, const PrintingPolicy &Policy, CodeCompletionAllocator &Allocator) { if (!T.getLocalQualifiers()) { @@ -1549,11 +1582,16 @@ static const char *GetCompletionTypeString(QualType T, if (TagDecl *Tag = TagT->getDecl()) if (!Tag->hasNameForLinkage()) { switch (Tag->getTagKind()) { - case TTK_Struct: return "struct <anonymous>"; - case TTK_Interface: return "__interface <anonymous>"; - case TTK_Class: return "class <anonymous>"; - case TTK_Union: return "union <anonymous>"; - case TTK_Enum: return "enum <anonymous>"; + case TTK_Struct: + return "struct <anonymous>"; + case TTK_Interface: + return "__interface <anonymous>"; + case TTK_Class: + return "class <anonymous>"; + case TTK_Union: + return "union <anonymous>"; + case TTK_Enum: + return "enum <anonymous>"; } } } @@ -1573,10 +1611,8 @@ static void addThisCompletion(Sema &S, ResultBuilder &Results) { CodeCompletionAllocator &Allocator = Results.getAllocator(); CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); PrintingPolicy Policy = getCompletionPrintingPolicy(S); - Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy, - S.Context, - Policy, - Allocator)); + Builder.AddResultTypeChunk( + GetCompletionTypeString(ThisTy, S.Context, Policy, Allocator)); Builder.AddTypedTextChunk("this"); Results.AddResult(CodeCompletionResult(Builder.TakeString())); } @@ -1596,11 +1632,76 @@ static void AddStaticAssertResult(CodeCompletionBuilder &Builder, Results.AddResult(CodeCompletionResult(Builder.TakeString())); } +static void printOverrideString(llvm::raw_ostream &OS, + CodeCompletionString *CCS) { + for (const auto &C : *CCS) { + if (C.Kind == CodeCompletionString::CK_Optional) + printOverrideString(OS, C.Optional); + else + OS << C.Text; + // Add a space after return type. + if (C.Kind == CodeCompletionString::CK_ResultType) + OS << ' '; + } +} + +static void AddOverrideResults(ResultBuilder &Results, + const CodeCompletionContext &CCContext, + CodeCompletionBuilder &Builder) { + Sema &S = Results.getSema(); + const auto *CR = llvm::dyn_cast<CXXRecordDecl>(S.CurContext); + // If not inside a class/struct/union return empty. + if (!CR) + return; + // First store overrides within current class. + // These are stored by name to make querying fast in the later step. + llvm::StringMap<std::vector<FunctionDecl *>> Overrides; + for (auto *Method : CR->methods()) { + if (!Method->isVirtual() || !Method->getIdentifier()) + continue; + Overrides[Method->getName()].push_back(Method); + } + + for (const auto &Base : CR->bases()) { + const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl(); + if (!BR) + continue; + for (auto *Method : BR->methods()) { + if (!Method->isVirtual() || !Method->getIdentifier()) + continue; + const auto it = Overrides.find(Method->getName()); + bool IsOverriden = false; + if (it != Overrides.end()) { + for (auto *MD : it->second) { + // If the method in current body is not an overload of this virtual + // function, then it overrides this one. + if (!S.IsOverload(MD, Method, false)) { + IsOverriden = true; + break; + } + } + } + if (!IsOverriden) { + // Generates a new CodeCompletionResult by taking this function and + // converting it into an override declaration with only one chunk in the + // final CodeCompletionString as a TypedTextChunk. + std::string OverrideSignature; + llvm::raw_string_ostream OS(OverrideSignature); + CodeCompletionResult CCR(Method, 0); + PrintingPolicy Policy = + getCompletionPrintingPolicy(S.getASTContext(), S.getPreprocessor()); + auto *CCS = CCR.createCodeCompletionStringForOverride( + S.getPreprocessor(), S.getASTContext(), Builder, + /*IncludeBriefComments=*/false, CCContext, Policy); + Results.AddResult(CodeCompletionResult(CCS, Method, CCP_CodePattern)); + } + } + } +} + /// Add language constructs that show up for "ordinary" names. -static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, - Scope *S, - Sema &SemaRef, - ResultBuilder &Results) { +static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S, + Sema &SemaRef, ResultBuilder &Results) { CodeCompletionAllocator &Allocator = Results.getAllocator(); CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); @@ -1649,10 +1750,12 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("declaration"); Results.AddResult(Result(Builder.TakeString())); + } else { + Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword)); } } - if (SemaRef.getLangOpts().ObjC1) + if (SemaRef.getLangOpts().ObjC) AddObjCTopLevelResults(Results, true); AddTypedefResult(Results); @@ -1704,6 +1807,12 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, if (IsNotInheritanceScope && Results.includeCodePatterns()) Builder.AddChunk(CodeCompletionString::CK_Colon); Results.AddResult(Result(Builder.TakeString())); + + // FIXME: This adds override results only if we are at the first word of + // the declaration/definition. Also call this from other sides to have + // more use-cases. + AddOverrideResults(Results, CodeCompletionContext::CCC_ClassStructUnion, + Builder); } } LLVM_FALLTHROUGH; @@ -1717,6 +1826,8 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddPlaceholderChunk("parameters"); Builder.AddChunk(CodeCompletionString::CK_RightAngle); Results.AddResult(Result(Builder.TakeString())); + } else { + Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword)); } AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); @@ -1760,7 +1871,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddChunk(CodeCompletionString::CK_RightBrace); Results.AddResult(Result(Builder.TakeString())); } - if (SemaRef.getLangOpts().ObjC1) + if (SemaRef.getLangOpts().ObjC) AddObjCStatementResults(Results, true); if (Results.includeCodePatterns()) { @@ -1793,7 +1904,8 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, } // Switch-specific statements. - if (!SemaRef.getCurFunction()->SwitchStack.empty()) { + if (SemaRef.getCurFunction() && + !SemaRef.getCurFunction()->SwitchStack.empty()) { // case expression: Builder.AddTypedTextChunk("case"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -1869,10 +1981,9 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, // "return expression ;" or "return ;", depending on whether we // know the function is void or not. bool isVoid = false; - if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext)) + if (const auto *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext)) isVoid = Function->getReturnType()->isVoidType(); - else if (ObjCMethodDecl *Method - = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext)) + else if (const auto *Method = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext)) isVoid = Method->getReturnType()->isVoidType(); else if (SemaRef.getCurBlock() && !SemaRef.getCurBlock()->ReturnType.isNull()) @@ -1900,7 +2011,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts()); } - LLVM_FALLTHROUGH; + LLVM_FALLTHROUGH; // Fall through (for statement expressions). case Sema::PCC_ForInit: @@ -2087,7 +2198,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, } } - if (SemaRef.getLangOpts().ObjC1) { + if (SemaRef.getLangOpts().ObjC) { // Add "super", if we're in an Objective-C class with a superclass. if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) { // The interface can be NULL. @@ -2146,8 +2257,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, /// type chunk. static void AddResultTypeChunk(ASTContext &Context, const PrintingPolicy &Policy, - const NamedDecl *ND, - QualType BaseType, + const NamedDecl *ND, QualType BaseType, CodeCompletionBuilder &Result) { if (!ND) return; @@ -2161,24 +2271,24 @@ static void AddResultTypeChunk(ASTContext &Context, QualType T; if (const FunctionDecl *Function = ND->getAsFunction()) T = Function->getReturnType(); - else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) { + else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) { if (!BaseType.isNull()) T = Method->getSendResultType(BaseType); else T = Method->getReturnType(); - } else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) { + } else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) { T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext())); T = clang::TypeName::getFullyQualifiedType(T, Context); } else if (isa<UnresolvedUsingValueDecl>(ND)) { /* Do nothing: ignore unresolved using declarations*/ - } else if (const ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(ND)) { + } else if (const auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) { if (!BaseType.isNull()) T = Ivar->getUsageType(BaseType); else T = Ivar->getType(); - } else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) { + } else if (const auto *Value = dyn_cast<ValueDecl>(ND)) { T = Value->getType(); - } else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) { + } else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND)) { if (!BaseType.isNull()) T = Property->getUsageType(BaseType); else @@ -2188,8 +2298,8 @@ static void AddResultTypeChunk(ASTContext &Context, if (T.isNull() || Context.hasSameType(T, Context.DependentTy)) return; - Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy, - Result.getAllocator())); + Result.AddResultTypeChunk( + GetCompletionTypeString(T, Context, Policy, Result.getAllocator())); } static void MaybeAddSentinel(Preprocessor &PP, @@ -2197,7 +2307,7 @@ static void MaybeAddSentinel(Preprocessor &PP, CodeCompletionBuilder &Result) { if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>()) if (Sentinel->getSentinel() == 0) { - if (PP.getLangOpts().ObjC1 && PP.isMacroDefined("nil")) + if (PP.getLangOpts().ObjC && PP.isMacroDefined("nil")) Result.AddTextChunk(", nil"); else if (PP.isMacroDefined("NULL")) Result.AddTextChunk(", NULL"); @@ -2295,11 +2405,10 @@ formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl, bool SuppressBlock = false, Optional<ArrayRef<QualType>> ObjCSubsts = None); -static std::string FormatFunctionParameter(const PrintingPolicy &Policy, - const ParmVarDecl *Param, - bool SuppressName = false, - bool SuppressBlock = false, - Optional<ArrayRef<QualType>> ObjCSubsts = None) { +static std::string +FormatFunctionParameter(const PrintingPolicy &Policy, const ParmVarDecl *Param, + bool SuppressName = false, bool SuppressBlock = false, + Optional<ArrayRef<QualType>> ObjCSubsts = None) { bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext()); if (Param->getType()->isDependentType() || !Param->getType()->isBlockPointerType()) { @@ -2315,8 +2424,8 @@ static std::string FormatFunctionParameter(const PrintingPolicy &Policy, Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts, ObjCSubstitutionContext::Parameter); if (ObjCMethodParam) { - Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(), - Type); + Result = + "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type); Result += Type.getAsString(Policy) + ")"; if (Param->getIdentifier() && !SuppressName) Result += Param->getIdentifier()->getName(); @@ -2447,13 +2556,15 @@ static std::string GetDefaultValueString(const ParmVarDecl *Param, bool Invalid = CharSrcRange.isInvalid(); if (Invalid) return ""; - StringRef srcText = Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid); + StringRef srcText = + Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid); if (Invalid) return ""; if (srcText.empty() || srcText == "=") { // Lexer can't determine the value. - // This happens if the code is incorrect (for example class is forward declared). + // This happens if the code is incorrect (for example class is forward + // declared). return ""; } std::string DefValue(srcText.str()); @@ -2461,7 +2572,8 @@ static std::string GetDefaultValueString(const ParmVarDecl *Param, // this value always has (or always does not have) '=' in front of it if (DefValue.at(0) != '=') { // If we don't have '=' in front of value. - // Lexer returns built-in types values without '=' and user-defined types values with it. + // Lexer returns built-in types values without '=' and user-defined types + // values with it. return " = " + DefValue; } return " " + DefValue; @@ -2501,18 +2613,18 @@ static void AddFunctionParameterChunks(Preprocessor &PP, // Format the placeholder string. std::string PlaceholderStr = FormatFunctionParameter(Policy, Param); if (Param->hasDefaultArg()) - PlaceholderStr += GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts()); + PlaceholderStr += + GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts()); if (Function->isVariadic() && P == N - 1) PlaceholderStr += ", ..."; // Add the placeholder string. Result.AddPlaceholderChunk( - Result.getAllocator().CopyString(PlaceholderStr)); + Result.getAllocator().CopyString(PlaceholderStr)); } - if (const FunctionProtoType *Proto - = Function->getType()->getAs<FunctionProtoType>()) + if (const auto *Proto = Function->getType()->getAs<FunctionProtoType>()) if (Proto->isVariadic()) { if (Proto->getNumParams() == 0) Result.AddPlaceholderChunk("..."); @@ -2522,13 +2634,10 @@ static void AddFunctionParameterChunks(Preprocessor &PP, } /// Add template parameter chunks to the given code completion string. -static void AddTemplateParameterChunks(ASTContext &Context, - const PrintingPolicy &Policy, - const TemplateDecl *Template, - CodeCompletionBuilder &Result, - unsigned MaxParameters = 0, - unsigned Start = 0, - bool InDefaultArg = false) { +static void AddTemplateParameterChunks( + ASTContext &Context, const PrintingPolicy &Policy, + const TemplateDecl *Template, CodeCompletionBuilder &Result, + unsigned MaxParameters = 0, unsigned Start = 0, bool InDefaultArg = false) { bool FirstParameter = true; // Prefer to take the template parameter names from the first declaration of @@ -2539,8 +2648,8 @@ static void AddTemplateParameterChunks(ASTContext &Context, TemplateParameterList::iterator PEnd = Params->end(); if (MaxParameters) PEnd = Params->begin() + MaxParameters; - for (TemplateParameterList::iterator P = Params->begin() + Start; - P != PEnd; ++P) { + for (TemplateParameterList::iterator P = Params->begin() + Start; P != PEnd; + ++P) { bool HasDefaultArg = false; std::string PlaceholderStr; if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) { @@ -2555,8 +2664,8 @@ static void AddTemplateParameterChunks(ASTContext &Context, } HasDefaultArg = TTP->hasDefaultArgument(); - } else if (NonTypeTemplateParmDecl *NTTP - = dyn_cast<NonTypeTemplateParmDecl>(*P)) { + } else if (NonTypeTemplateParmDecl *NTTP = + dyn_cast<NonTypeTemplateParmDecl>(*P)) { if (NTTP->getIdentifier()) PlaceholderStr = NTTP->getIdentifier()->getName(); NTTP->getType().getAsStringInternal(PlaceholderStr, Policy); @@ -2598,18 +2707,17 @@ static void AddTemplateParameterChunks(ASTContext &Context, // Add the placeholder string. Result.AddPlaceholderChunk( - Result.getAllocator().CopyString(PlaceholderStr)); + Result.getAllocator().CopyString(PlaceholderStr)); } } /// Add a qualifier to the given code-completion string, if the /// provided nested-name-specifier is non-NULL. -static void -AddQualifierToCompletionString(CodeCompletionBuilder &Result, - NestedNameSpecifier *Qualifier, - bool QualifierIsInformative, - ASTContext &Context, - const PrintingPolicy &Policy) { +static void AddQualifierToCompletionString(CodeCompletionBuilder &Result, + NestedNameSpecifier *Qualifier, + bool QualifierIsInformative, + ASTContext &Context, + const PrintingPolicy &Policy) { if (!Qualifier) return; @@ -2627,25 +2735,24 @@ AddQualifierToCompletionString(CodeCompletionBuilder &Result, static void AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result, const FunctionDecl *Function) { - const FunctionProtoType *Proto - = Function->getType()->getAs<FunctionProtoType>(); + const auto *Proto = Function->getType()->getAs<FunctionProtoType>(); if (!Proto || !Proto->getTypeQuals()) return; // FIXME: Add ref-qualifier! // Handle single qualifiers without copying - if (Proto->getTypeQuals() == Qualifiers::Const) { + if (Proto->getTypeQuals().hasOnlyConst()) { Result.AddInformativeChunk(" const"); return; } - if (Proto->getTypeQuals() == Qualifiers::Volatile) { + if (Proto->getTypeQuals().hasOnlyVolatile()) { Result.AddInformativeChunk(" volatile"); return; } - if (Proto->getTypeQuals() == Qualifiers::Restrict) { + if (Proto->getTypeQuals().hasOnlyRestrict()) { Result.AddInformativeChunk(" restrict"); return; } @@ -2670,37 +2777,51 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy, return; switch (Name.getNameKind()) { - case DeclarationName::CXXOperatorName: { - const char *OperatorName = nullptr; - switch (Name.getCXXOverloadedOperator()) { - case OO_None: - case OO_Conditional: - case NUM_OVERLOADED_OPERATORS: - OperatorName = "operator"; - break; + case DeclarationName::CXXOperatorName: { + const char *OperatorName = nullptr; + switch (Name.getCXXOverloadedOperator()) { + case OO_None: + case OO_Conditional: + case NUM_OVERLOADED_OPERATORS: + OperatorName = "operator"; + break; -#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ - case OO_##Name: OperatorName = "operator" Spelling; break; -#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly) +#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \ + case OO_##Name: \ + OperatorName = "operator" Spelling; \ + break; +#define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemberOnly) #include "clang/Basic/OperatorKinds.def" - case OO_New: OperatorName = "operator new"; break; - case OO_Delete: OperatorName = "operator delete"; break; - case OO_Array_New: OperatorName = "operator new[]"; break; - case OO_Array_Delete: OperatorName = "operator delete[]"; break; - case OO_Call: OperatorName = "operator()"; break; - case OO_Subscript: OperatorName = "operator[]"; break; - } - Result.AddTypedTextChunk(OperatorName); + case OO_New: + OperatorName = "operator new"; + break; + case OO_Delete: + OperatorName = "operator delete"; + break; + case OO_Array_New: + OperatorName = "operator new[]"; + break; + case OO_Array_Delete: + OperatorName = "operator delete[]"; + break; + case OO_Call: + OperatorName = "operator()"; + break; + case OO_Subscript: + OperatorName = "operator[]"; break; } + Result.AddTypedTextChunk(OperatorName); + break; + } case DeclarationName::Identifier: case DeclarationName::CXXConversionFunctionName: case DeclarationName::CXXDestructorName: case DeclarationName::CXXLiteralOperatorName: Result.AddTypedTextChunk( - Result.getAllocator().CopyString(ND->getNameAsString())); + Result.getAllocator().CopyString(ND->getNameAsString())); break; case DeclarationName::CXXDeductionGuideName: @@ -2713,19 +2834,18 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy, case DeclarationName::CXXConstructorName: { CXXRecordDecl *Record = nullptr; QualType Ty = Name.getCXXNameType(); - if (const RecordType *RecordTy = Ty->getAs<RecordType>()) + if (const auto *RecordTy = Ty->getAs<RecordType>()) Record = cast<CXXRecordDecl>(RecordTy->getDecl()); - else if (const InjectedClassNameType *InjectedTy - = Ty->getAs<InjectedClassNameType>()) + else if (const auto *InjectedTy = Ty->getAs<InjectedClassNameType>()) Record = InjectedTy->getDecl(); else { Result.AddTypedTextChunk( - Result.getAllocator().CopyString(ND->getNameAsString())); + Result.getAllocator().CopyString(ND->getNameAsString())); break; } Result.AddTypedTextChunk( - Result.getAllocator().CopyString(Record->getNameAsString())); + Result.getAllocator().CopyString(Record->getNameAsString())); if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) { Result.AddChunk(CodeCompletionString::CK_LeftAngle); AddTemplateParameterChunks(Context, Policy, Template, Result); @@ -2736,11 +2856,10 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy, } } -CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S, - const CodeCompletionContext &CCContext, - CodeCompletionAllocator &Allocator, - CodeCompletionTUInfo &CCTUInfo, - bool IncludeBriefComments) { +CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString( + Sema &S, const CodeCompletionContext &CCContext, + CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo, + bool IncludeBriefComments) { return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator, CCTUInfo, IncludeBriefComments); } @@ -2797,13 +2916,10 @@ CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro( /// \returns Either a new, heap-allocated code completion string describing /// how to use this result, or NULL to indicate that the string or name of the /// result is all that is needed. -CodeCompletionString * -CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, - Preprocessor &PP, - const CodeCompletionContext &CCContext, - CodeCompletionAllocator &Allocator, - CodeCompletionTUInfo &CCTUInfo, - bool IncludeBriefComments) { +CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString( + ASTContext &Ctx, Preprocessor &PP, const CodeCompletionContext &CCContext, + CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo, + bool IncludeBriefComments) { if (Kind == RK_Macro) return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo); @@ -2832,6 +2948,30 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, return Result.TakeString(); } assert(Kind == RK_Declaration && "Missed a result kind?"); + return createCodeCompletionStringForDecl( + PP, Ctx, Result, IncludeBriefComments, CCContext, Policy); +} + +CodeCompletionString * +CodeCompletionResult::createCodeCompletionStringForOverride( + Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result, + bool IncludeBriefComments, const CodeCompletionContext &CCContext, + PrintingPolicy &Policy) { + std::string OverrideSignature; + llvm::raw_string_ostream OS(OverrideSignature); + auto *CCS = createCodeCompletionStringForDecl(PP, Ctx, Result, + /*IncludeBriefComments=*/false, + CCContext, Policy); + printOverrideString(OS, CCS); + OS << " override"; + Result.AddTypedTextChunk(Result.getAllocator().CopyString(OS.str())); + return Result.TakeString(); +} + +CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl( + Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result, + bool IncludeBriefComments, const CodeCompletionContext &CCContext, + PrintingPolicy &Policy) { const NamedDecl *ND = Declaration; Result.addParentContext(ND->getDeclContext()); @@ -2844,7 +2984,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, if (StartsNestedNameSpecifier) { Result.AddTypedTextChunk( - Result.getAllocator().CopyString(ND->getNameAsString())); + Result.getAllocator().CopyString(ND->getNameAsString())); Result.AddTextChunk("::"); return Result.TakeString(); } @@ -2854,7 +2994,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result); - if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) { + if (const auto *Function = dyn_cast<FunctionDecl>(ND)) { AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, Ctx, Policy); AddTypedNameChunk(Ctx, Policy, ND, Result); @@ -2865,7 +3005,8 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, return Result.TakeString(); } - if (const FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) { + if (const FunctionTemplateDecl *FunTmpl = + dyn_cast<FunctionTemplateDecl>(ND)) { AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, Ctx, Policy); FunctionDecl *Function = FunTmpl->getTemplatedDecl(); @@ -2884,16 +3025,16 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, // FIXME: We need to abstract template parameters better! bool HasDefaultArg = false; NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam( - LastDeducibleArgument - 1); + LastDeducibleArgument - 1); if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) HasDefaultArg = TTP->hasDefaultArgument(); - else if (NonTypeTemplateParmDecl *NTTP - = dyn_cast<NonTypeTemplateParmDecl>(Param)) + else if (NonTypeTemplateParmDecl *NTTP = + dyn_cast<NonTypeTemplateParmDecl>(Param)) HasDefaultArg = NTTP->hasDefaultArgument(); else { assert(isa<TemplateTemplateParmDecl>(Param)); - HasDefaultArg - = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument(); + HasDefaultArg = + cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument(); } if (!HasDefaultArg) @@ -2919,22 +3060,21 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, return Result.TakeString(); } - if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) { + if (const auto *Template = dyn_cast<TemplateDecl>(ND)) { AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, Ctx, Policy); Result.AddTypedTextChunk( - Result.getAllocator().CopyString(Template->getNameAsString())); + Result.getAllocator().CopyString(Template->getNameAsString())); Result.AddChunk(CodeCompletionString::CK_LeftAngle); AddTemplateParameterChunks(Ctx, Policy, Template, Result); Result.AddChunk(CodeCompletionString::CK_RightAngle); return Result.TakeString(); } - - if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) { + if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) { Selector Sel = Method->getSelector(); if (Sel.isUnarySelector()) { - Result.AddTypedTextChunk(Result.getAllocator().CopyString( - Sel.getNameForSlot(0))); + Result.AddTypedTextChunk( + Result.getAllocator().CopyString(Sel.getNameForSlot(0))); return Result.TakeString(); } @@ -2952,7 +3092,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, } unsigned Idx = 0; for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(), - PEnd = Method->param_end(); + PEnd = Method->param_end(); P != PEnd; (void)++P, ++Idx) { if (Idx > 0) { std::string Keyword; @@ -2979,12 +3119,11 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, if (ParamType->isBlockPointerType() && !DeclaringEntity) Arg = FormatFunctionParameter(Policy, *P, true, - /*SuppressBlock=*/false, - ObjCSubsts); + /*SuppressBlock=*/false, ObjCSubsts); else { if (ObjCSubsts) - ParamType = ParamType.substObjCTypeArgs(Ctx, *ObjCSubsts, - ObjCSubstitutionContext::Parameter); + ParamType = ParamType.substObjCTypeArgs( + Ctx, *ObjCSubsts, ObjCSubstitutionContext::Parameter); Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(), ParamType); Arg += ParamType.getAsString(Policy) + ")"; @@ -3025,7 +3164,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, Ctx, Policy); Result.AddTypedTextChunk( - Result.getAllocator().CopyString(ND->getNameAsString())); + Result.getAllocator().CopyString(ND->getNameAsString())); return Result.TakeString(); } @@ -3037,7 +3176,7 @@ const RawComment *clang::getCompletionComment(const ASTContext &Ctx, return RC; // Try to find comment from a property for ObjC methods. - const ObjCMethodDecl *M = dyn_cast<ObjCMethodDecl>(ND); + const auto *M = dyn_cast<ObjCMethodDecl>(ND); if (!M) return nullptr; const ObjCPropertyDecl *PDecl = M->findPropertyDecl(); @@ -3049,7 +3188,7 @@ const RawComment *clang::getCompletionComment(const ASTContext &Ctx, const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx, const NamedDecl *ND) { - const ObjCMethodDecl *M = dyn_cast_or_null<ObjCMethodDecl>(ND); + const auto *M = dyn_cast_or_null<ObjCMethodDecl>(ND); if (!M || !M->isPropertyAccessor()) return nullptr; @@ -3072,8 +3211,7 @@ const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx, const RawComment *clang::getParameterComment( const ASTContext &Ctx, - const CodeCompleteConsumer::OverloadCandidate &Result, - unsigned ArgIndex) { + const CodeCompleteConsumer::OverloadCandidate &Result, unsigned ArgIndex) { auto FDecl = Result.getFunction(); if (!FDecl) return nullptr; @@ -3089,12 +3227,11 @@ static void AddOverloadParameterChunks(ASTContext &Context, const FunctionDecl *Function, const FunctionProtoType *Prototype, CodeCompletionBuilder &Result, - unsigned CurrentArg, - unsigned Start = 0, + unsigned CurrentArg, unsigned Start = 0, bool InOptional = false) { bool FirstParameter = true; - unsigned NumParams = Function ? Function->getNumParams() - : Prototype->getNumParams(); + unsigned NumParams = + Function ? Function->getNumParams() : Prototype->getNumParams(); for (unsigned P = Start; P != NumParams; ++P) { if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) { @@ -3124,14 +3261,15 @@ static void AddOverloadParameterChunks(ASTContext &Context, const ParmVarDecl *Param = Function->getParamDecl(P); Placeholder = FormatFunctionParameter(Policy, Param); if (Param->hasDefaultArg()) - Placeholder += GetDefaultValueString(Param, Context.getSourceManager(), Context.getLangOpts()); + Placeholder += GetDefaultValueString(Param, Context.getSourceManager(), + Context.getLangOpts()); } else { Placeholder = Prototype->getParamType(P).getAsString(Policy); } if (P == CurrentArg) Result.AddCurrentParameterChunk( - Result.getAllocator().CopyString(Placeholder)); + Result.getAllocator().CopyString(Placeholder)); else Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder)); } @@ -3153,23 +3291,22 @@ static void AddOverloadParameterChunks(ASTContext &Context, CodeCompletionString * CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( - unsigned CurrentArg, Sema &S, - CodeCompletionAllocator &Allocator, - CodeCompletionTUInfo &CCTUInfo, - bool IncludeBriefComments) const { + unsigned CurrentArg, Sema &S, CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments) const { PrintingPolicy Policy = getCompletionPrintingPolicy(S); // FIXME: Set priority, availability appropriately. - CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available); + CodeCompletionBuilder Result(Allocator, CCTUInfo, 1, + CXAvailability_Available); FunctionDecl *FDecl = getFunction(); - const FunctionProtoType *Proto - = dyn_cast<FunctionProtoType>(getFunctionType()); + const FunctionProtoType *Proto = + dyn_cast<FunctionProtoType>(getFunctionType()); if (!FDecl && !Proto) { // Function without a prototype. Just give the return type and a // highlighted ellipsis. const FunctionType *FT = getFunctionType(); Result.AddResultTypeChunk(Result.getAllocator().CopyString( - FT->getReturnType().getAsString(Policy))); + FT->getReturnType().getAsString(Policy))); Result.AddChunk(CodeCompletionString::CK_LeftParen); Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "..."); Result.AddChunk(CodeCompletionString::CK_RightParen); @@ -3183,10 +3320,9 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( } AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result); Result.AddTextChunk( - Result.getAllocator().CopyString(FDecl->getNameAsString())); + Result.getAllocator().CopyString(FDecl->getNameAsString())); } else { - Result.AddResultTypeChunk( - Result.getAllocator().CopyString( + Result.AddResultTypeChunk(Result.getAllocator().CopyString( Proto->getReturnType().getAsString(Policy))); } @@ -3216,8 +3352,7 @@ unsigned clang::getMacroUsagePriority(StringRef MacroName, Priority = CCP_Constant; // Treat "bool" as a type. else if (MacroName.equals("bool")) - Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0); - + Priority = CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0); return Priority; } @@ -3227,105 +3362,142 @@ CXCursorKind clang::getCursorKindForDecl(const Decl *D) { return CXCursor_UnexposedDecl; switch (D->getKind()) { - case Decl::Enum: return CXCursor_EnumDecl; - case Decl::EnumConstant: return CXCursor_EnumConstantDecl; - case Decl::Field: return CXCursor_FieldDecl; - case Decl::Function: - return CXCursor_FunctionDecl; - case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl; - case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl; - case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl; - - case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl; - case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl; - case Decl::ObjCMethod: - return cast<ObjCMethodDecl>(D)->isInstanceMethod() - ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl; - case Decl::CXXMethod: return CXCursor_CXXMethod; - case Decl::CXXConstructor: return CXCursor_Constructor; - case Decl::CXXDestructor: return CXCursor_Destructor; - case Decl::CXXConversion: return CXCursor_ConversionFunction; - case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl; - case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl; - case Decl::ParmVar: return CXCursor_ParmDecl; - case Decl::Typedef: return CXCursor_TypedefDecl; - case Decl::TypeAlias: return CXCursor_TypeAliasDecl; - case Decl::TypeAliasTemplate: return CXCursor_TypeAliasTemplateDecl; - case Decl::Var: return CXCursor_VarDecl; - case Decl::Namespace: return CXCursor_Namespace; - case Decl::NamespaceAlias: return CXCursor_NamespaceAlias; - case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter; - case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter; - case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter; - case Decl::FunctionTemplate: return CXCursor_FunctionTemplate; - case Decl::ClassTemplate: return CXCursor_ClassTemplate; - case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier; - case Decl::ClassTemplatePartialSpecialization: - return CXCursor_ClassTemplatePartialSpecialization; - case Decl::UsingDirective: return CXCursor_UsingDirective; - case Decl::StaticAssert: return CXCursor_StaticAssert; - case Decl::Friend: return CXCursor_FriendDecl; - case Decl::TranslationUnit: return CXCursor_TranslationUnit; - - case Decl::Using: - case Decl::UnresolvedUsingValue: - case Decl::UnresolvedUsingTypename: - return CXCursor_UsingDeclaration; - - case Decl::ObjCPropertyImpl: - switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) { - case ObjCPropertyImplDecl::Dynamic: - return CXCursor_ObjCDynamicDecl; - - case ObjCPropertyImplDecl::Synthesize: - return CXCursor_ObjCSynthesizeDecl; - } + case Decl::Enum: + return CXCursor_EnumDecl; + case Decl::EnumConstant: + return CXCursor_EnumConstantDecl; + case Decl::Field: + return CXCursor_FieldDecl; + case Decl::Function: + return CXCursor_FunctionDecl; + case Decl::ObjCCategory: + return CXCursor_ObjCCategoryDecl; + case Decl::ObjCCategoryImpl: + return CXCursor_ObjCCategoryImplDecl; + case Decl::ObjCImplementation: + return CXCursor_ObjCImplementationDecl; + + case Decl::ObjCInterface: + return CXCursor_ObjCInterfaceDecl; + case Decl::ObjCIvar: + return CXCursor_ObjCIvarDecl; + case Decl::ObjCMethod: + return cast<ObjCMethodDecl>(D)->isInstanceMethod() + ? CXCursor_ObjCInstanceMethodDecl + : CXCursor_ObjCClassMethodDecl; + case Decl::CXXMethod: + return CXCursor_CXXMethod; + case Decl::CXXConstructor: + return CXCursor_Constructor; + case Decl::CXXDestructor: + return CXCursor_Destructor; + case Decl::CXXConversion: + return CXCursor_ConversionFunction; + case Decl::ObjCProperty: + return CXCursor_ObjCPropertyDecl; + case Decl::ObjCProtocol: + return CXCursor_ObjCProtocolDecl; + case Decl::ParmVar: + return CXCursor_ParmDecl; + case Decl::Typedef: + return CXCursor_TypedefDecl; + case Decl::TypeAlias: + return CXCursor_TypeAliasDecl; + case Decl::TypeAliasTemplate: + return CXCursor_TypeAliasTemplateDecl; + case Decl::Var: + return CXCursor_VarDecl; + case Decl::Namespace: + return CXCursor_Namespace; + case Decl::NamespaceAlias: + return CXCursor_NamespaceAlias; + case Decl::TemplateTypeParm: + return CXCursor_TemplateTypeParameter; + case Decl::NonTypeTemplateParm: + return CXCursor_NonTypeTemplateParameter; + case Decl::TemplateTemplateParm: + return CXCursor_TemplateTemplateParameter; + case Decl::FunctionTemplate: + return CXCursor_FunctionTemplate; + case Decl::ClassTemplate: + return CXCursor_ClassTemplate; + case Decl::AccessSpec: + return CXCursor_CXXAccessSpecifier; + case Decl::ClassTemplatePartialSpecialization: + return CXCursor_ClassTemplatePartialSpecialization; + case Decl::UsingDirective: + return CXCursor_UsingDirective; + case Decl::StaticAssert: + return CXCursor_StaticAssert; + case Decl::Friend: + return CXCursor_FriendDecl; + case Decl::TranslationUnit: + return CXCursor_TranslationUnit; + + case Decl::Using: + case Decl::UnresolvedUsingValue: + case Decl::UnresolvedUsingTypename: + return CXCursor_UsingDeclaration; + + case Decl::ObjCPropertyImpl: + switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) { + case ObjCPropertyImplDecl::Dynamic: + return CXCursor_ObjCDynamicDecl; + + case ObjCPropertyImplDecl::Synthesize: + return CXCursor_ObjCSynthesizeDecl; + } + llvm_unreachable("Unexpected Kind!"); + + case Decl::Import: + return CXCursor_ModuleImportDecl; + + case Decl::ObjCTypeParam: + return CXCursor_TemplateTypeParameter; - case Decl::Import: - return CXCursor_ModuleImportDecl; - - case Decl::ObjCTypeParam: return CXCursor_TemplateTypeParameter; - - default: - if (const TagDecl *TD = dyn_cast<TagDecl>(D)) { - switch (TD->getTagKind()) { - case TTK_Interface: // fall through - case TTK_Struct: return CXCursor_StructDecl; - case TTK_Class: return CXCursor_ClassDecl; - case TTK_Union: return CXCursor_UnionDecl; - case TTK_Enum: return CXCursor_EnumDecl; - } + default: + if (const auto *TD = dyn_cast<TagDecl>(D)) { + switch (TD->getTagKind()) { + case TTK_Interface: // fall through + case TTK_Struct: + return CXCursor_StructDecl; + case TTK_Class: + return CXCursor_ClassDecl; + case TTK_Union: + return CXCursor_UnionDecl; + case TTK_Enum: + return CXCursor_EnumDecl; } + } } return CXCursor_UnexposedDecl; } static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results, - bool IncludeUndefined, + bool LoadExternal, bool IncludeUndefined, bool TargetTypeIsPointer = false) { typedef CodeCompletionResult Result; Results.EnterNewScope(); - for (Preprocessor::macro_iterator M = PP.macro_begin(), - MEnd = PP.macro_end(); + for (Preprocessor::macro_iterator M = PP.macro_begin(LoadExternal), + MEnd = PP.macro_end(LoadExternal); M != MEnd; ++M) { auto MD = PP.getMacroDefinition(M->first); if (IncludeUndefined || MD) { - if (MacroInfo *MI = MD.getMacroInfo()) - if (MI->isUsedForHeaderGuard()) - continue; + MacroInfo *MI = MD.getMacroInfo(); + if (MI && MI->isUsedForHeaderGuard()) + continue; - Results.AddResult(Result(M->first, - getMacroUsagePriority(M->first->getName(), - PP.getLangOpts(), - TargetTypeIsPointer))); + Results.AddResult( + Result(M->first, MI, + getMacroUsagePriority(M->first->getName(), PP.getLangOpts(), + TargetTypeIsPointer))); } } Results.ExitScope(); - } static void AddPrettyFunctionResults(const LangOptions &LangOpts, @@ -3350,8 +3522,8 @@ static void HandleCodeCompleteResults(Sema *S, CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults); } -static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S, - Sema::ParserCompletionContext PCC) { +static CodeCompletionContext +mapCodeCompletionContext(Sema &S, Sema::ParserCompletionContext PCC) { switch (PCC) { case Sema::PCC_Namespace: return CodeCompletionContext::CCC_TopLevel; @@ -3381,14 +3553,16 @@ static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S, case Sema::PCC_ForInit: if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 || - S.getLangOpts().ObjC1) + S.getLangOpts().ObjC) return CodeCompletionContext::CCC_ParenthesizedExpression; else return CodeCompletionContext::CCC_Expression; case Sema::PCC_Expression: - case Sema::PCC_Condition: return CodeCompletionContext::CCC_Expression; + case Sema::PCC_Condition: + return CodeCompletionContext(CodeCompletionContext::CCC_Expression, + S.getASTContext().BoolTy); case Sema::PCC_Statement: return CodeCompletionContext::CCC_Statement; @@ -3421,7 +3595,6 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext, while (isa<BlockDecl>(CurContext)) CurContext = CurContext->getParent(); - CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext); if (!Method || !Method->isVirtual()) return; @@ -3441,9 +3614,8 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext, // If we need a nested-name-specifier, add one now. if (!InContext) { - NestedNameSpecifier *NNS - = getRequiredQualification(S.Context, CurContext, - Overridden->getDeclContext()); + NestedNameSpecifier *NNS = getRequiredQualification( + S.Context, CurContext, Overridden->getDeclContext()); if (NNS) { std::string Str; llvm::raw_string_ostream OS(Str); @@ -3453,8 +3625,8 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext, } else if (!InContext->Equals(Overridden->getDeclContext())) continue; - Builder.AddTypedTextChunk(Results.getAllocator().CopyString( - Overridden->getNameAsString())); + Builder.AddTypedTextChunk( + Results.getAllocator().CopyString(Overridden->getNameAsString())); Builder.AddChunk(CodeCompletionString::CK_LeftParen); bool FirstParam = true; for (auto P : Method->parameters()) { @@ -3467,11 +3639,9 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext, Results.getAllocator().CopyString(P->getIdentifier()->getName())); } Builder.AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(CodeCompletionResult(Builder.TakeString(), - CCP_SuperCompletion, - CXCursor_CXXMethod, - CXAvailability_Available, - Overridden)); + Results.AddResult(CodeCompletionResult( + Builder.TakeString(), CCP_SuperCompletion, CXCursor_CXXMethod, + CXAvailability_Available, Overridden)); Results.Ignore(Overridden); } } @@ -3493,39 +3663,35 @@ void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc, PP.getHeaderSearchInfo().collectAllModules(Modules); for (unsigned I = 0, N = Modules.size(); I != N; ++I) { Builder.AddTypedTextChunk( - Builder.getAllocator().CopyString(Modules[I]->Name)); - Results.AddResult(Result(Builder.TakeString(), - CCP_Declaration, - CXCursor_ModuleImportDecl, - Modules[I]->isAvailable() - ? CXAvailability_Available - : CXAvailability_NotAvailable)); + Builder.getAllocator().CopyString(Modules[I]->Name)); + Results.AddResult(Result( + Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl, + Modules[I]->isAvailable() ? CXAvailability_Available + : CXAvailability_NotAvailable)); } } else if (getLangOpts().Modules) { // Load the named module. - Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path, - Module::AllVisible, - /*IsInclusionDirective=*/false); + Module *Mod = + PP.getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible, + /*IsInclusionDirective=*/false); // Enumerate submodules. if (Mod) { for (Module::submodule_iterator Sub = Mod->submodule_begin(), - SubEnd = Mod->submodule_end(); + SubEnd = Mod->submodule_end(); Sub != SubEnd; ++Sub) { Builder.AddTypedTextChunk( - Builder.getAllocator().CopyString((*Sub)->Name)); - Results.AddResult(Result(Builder.TakeString(), - CCP_Declaration, - CXCursor_ModuleImportDecl, - (*Sub)->isAvailable() - ? CXAvailability_Available - : CXAvailability_NotAvailable)); + Builder.getAllocator().CopyString((*Sub)->Name)); + Results.AddResult(Result( + Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl, + (*Sub)->isAvailable() ? CXAvailability_Available + : CXAvailability_NotAvailable)); } } } Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(),Results.size()); + Results.data(), Results.size()); } void Sema::CodeCompleteOrdinaryName(Scope *S, @@ -3572,10 +3738,9 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, // If we are in a C++ non-static member function, check the qualifiers on // the member function to filter/prioritize the results list. - if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext)) - if (CurMethod->isInstance()) - Results.setObjectTypeQualifiers( - Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers())); + auto ThisType = getCurrentThisType(); + if (!ThisType.isNull()) + Results.setObjectTypeQualifiers(ThisType->getPointeeType().getQualifiers()); CodeCompletionDeclConsumer Consumer(Results, CurContext); LookupVisibleDecls(S, LookupOrdinaryName, Consumer, @@ -3609,28 +3774,30 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, } if (CodeCompleter->includeMacros()) - AddMacroResults(PP, Results, false); + AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(),Results.size()); + Results.data(), Results.size()); } static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, ParsedType Receiver, ArrayRef<IdentifierInfo *> SelIdents, - bool AtArgumentExpression, - bool IsSuper, + bool AtArgumentExpression, bool IsSuper, ResultBuilder &Results); void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, bool AllowNonIdentifiers, bool AllowNestedNameSpecifiers) { typedef CodeCompletionResult Result; - ResultBuilder Results(*this, CodeCompleter->getAllocator(), - CodeCompleter->getCodeCompletionTUInfo(), - AllowNestedNameSpecifiers - ? CodeCompletionContext::CCC_PotentiallyQualifiedName - : CodeCompletionContext::CCC_Name); + ResultBuilder Results( + *this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + AllowNestedNameSpecifiers + // FIXME: Try to separate codepath leading here to deduce whether we + // need an existing symbol or a new one. + ? CodeCompletionContext::CCC_SymbolOrNewName + : CodeCompletionContext::CCC_NewName); Results.EnterNewScope(); // Type qualifiers can come after names. @@ -3671,12 +3838,11 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, DS.getTypeSpecType() == DeclSpec::TST_typename && DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified && DS.getTypeSpecSign() == DeclSpec::TSS_unspecified && - !DS.isTypeAltiVecVector() && - S && + !DS.isTypeAltiVecVector() && S && (S->getFlags() & Scope::DeclScope) != 0 && (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope | - Scope::FunctionPrototypeScope | - Scope::AtCatchScope)) == 0) { + Scope::FunctionPrototypeScope | Scope::AtCatchScope)) == + 0) { ParsedType T = DS.getRepAsType(); if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType()) AddClassMessageCompletions(*this, S, T, None, false, false, Results); @@ -3685,15 +3851,14 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, // Note that we intentionally suppress macro results here, since we do not // encourage using macros to produce the names of entities. - HandleCodeCompleteResults(this, CodeCompleter, - Results.getCompletionContext(), + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); } struct Sema::CodeCompleteExpressionData { CodeCompleteExpressionData(QualType PreferredType = QualType()) - : PreferredType(PreferredType), IntegralConstantExpression(false), - ObjCCollection(false) { } + : PreferredType(PreferredType), IntegralConstantExpression(false), + ObjCCollection(false) {} QualType PreferredType; bool IntegralConstantExpression; @@ -3737,31 +3902,35 @@ void Sema::CodeCompleteExpression(Scope *S, bool PreferredTypeIsPointer = false; if (!Data.PreferredType.isNull()) - PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() - || Data.PreferredType->isMemberPointerType() - || Data.PreferredType->isBlockPointerType(); + PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() || + Data.PreferredType->isMemberPointerType() || + Data.PreferredType->isBlockPointerType(); - if (S->getFnParent() && - !Data.ObjCCollection && + if (S->getFnParent() && !Data.ObjCCollection && !Data.IntegralConstantExpression) AddPrettyFunctionResults(getLangOpts(), Results); if (CodeCompleter->includeMacros()) - AddMacroResults(PP, Results, false, PreferredTypeIsPointer); + AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false, + PreferredTypeIsPointer); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); } +void Sema::CodeCompleteExpression(Scope *S, QualType PreferredType) { + return CodeCompleteExpression(S, CodeCompleteExpressionData(PreferredType)); +} + void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) { if (E.isInvalid()) CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction); - else if (getLangOpts().ObjC1) + else if (getLangOpts().ObjC) CodeCompleteObjCInstanceMessage(S, E.get(), None, false); } /// The set of properties that have already been added, referenced by /// property name. -typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet; +typedef llvm::SmallPtrSet<IdentifierInfo *, 16> AddedPropertiesSet; /// Retrieve the container definition, if any? static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) { @@ -3819,11 +3988,13 @@ static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy, Builder.AddChunk(CodeCompletionString::CK_RightParen); } -static void AddObjCProperties( - const CodeCompletionContext &CCContext, ObjCContainerDecl *Container, - bool AllowCategories, bool AllowNullaryMethods, DeclContext *CurContext, - AddedPropertiesSet &AddedProperties, ResultBuilder &Results, - bool IsBaseExprStatement = false, bool IsClassProperty = false) { +static void +AddObjCProperties(const CodeCompletionContext &CCContext, + ObjCContainerDecl *Container, bool AllowCategories, + bool AllowNullaryMethods, DeclContext *CurContext, + AddedPropertiesSet &AddedProperties, ResultBuilder &Results, + bool IsBaseExprStatement = false, + bool IsClassProperty = false, bool InOriginalClass = true) { typedef CodeCompletionResult Result; // Retrieve the definition. @@ -3838,8 +4009,10 @@ static void AddObjCProperties( // expressions. if (!P->getType().getTypePtr()->isBlockPointerType() || !IsBaseExprStatement) { - Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr), - CurContext); + Result R = Result(P, Results.getBasePriority(P), nullptr); + if (!InOriginalClass) + setInBaseClass(R); + Results.MaybeAddResult(R, CurContext); return; } @@ -3850,8 +4023,10 @@ static void AddObjCProperties( findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc, BlockProtoLoc); if (!BlockLoc) { - Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr), - CurContext); + Result R = Result(P, Results.getBasePriority(P), nullptr); + if (!InOriginalClass) + setInBaseClass(R); + Results.MaybeAddResult(R, CurContext); return; } @@ -3862,9 +4037,10 @@ static void AddObjCProperties( AddObjCBlockCall(Container->getASTContext(), getCompletionPrintingPolicy(Results.getSema()), Builder, P, BlockLoc, BlockProtoLoc); - Results.MaybeAddResult( - Result(Builder.TakeString(), P, Results.getBasePriority(P)), - CurContext); + Result R = Result(Builder.TakeString(), P, Results.getBasePriority(P)); + if (!InOriginalClass) + setInBaseClass(R); + Results.MaybeAddResult(R, CurContext); // Provide additional block setter completion iff the base expression is a // statement and the block property is mutable. @@ -3890,13 +4066,15 @@ static void AddObjCProperties( // otherwise the setter completion should show up before the default // property completion, as we normally want to use the result of the // call. - Results.MaybeAddResult( + Result R = Result(Builder.TakeString(), P, Results.getBasePriority(P) + (BlockLoc.getTypePtr()->getReturnType()->isVoidType() ? CCD_BlockPropertySetter - : -CCD_BlockPropertySetter)), - CurContext); + : -CCD_BlockPropertySetter)); + if (!InOriginalClass) + setInBaseClass(R); + Results.MaybeAddResult(R, CurContext); } }; @@ -3924,10 +4102,11 @@ static void AddObjCProperties( AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder); Builder.AddTypedTextChunk( Results.getAllocator().CopyString(Name->getName())); - Results.MaybeAddResult( - Result(Builder.TakeString(), M, - CCP_MemberDeclaration + CCD_MethodAsProperty), - CurContext); + Result R = Result(Builder.TakeString(), M, + CCP_MemberDeclaration + CCD_MethodAsProperty); + if (!InOriginalClass) + setInBaseClass(R); + Results.MaybeAddResult(R, CurContext); }; if (IsClassProperty) { @@ -3953,42 +4132,47 @@ static void AddObjCProperties( for (auto *P : Protocol->protocols()) AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods, CurContext, AddedProperties, Results, - IsBaseExprStatement, IsClassProperty); - } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){ + IsBaseExprStatement, IsClassProperty, + /*InOriginalClass*/ false); + } else if (ObjCInterfaceDecl *IFace = + dyn_cast<ObjCInterfaceDecl>(Container)) { if (AllowCategories) { // Look through categories. for (auto *Cat : IFace->known_categories()) AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods, CurContext, AddedProperties, Results, - IsBaseExprStatement, IsClassProperty); + IsBaseExprStatement, IsClassProperty, + InOriginalClass); } // Look through protocols. for (auto *I : IFace->all_referenced_protocols()) AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods, CurContext, AddedProperties, Results, - IsBaseExprStatement, IsClassProperty); + IsBaseExprStatement, IsClassProperty, + /*InOriginalClass*/ false); // Look in the superclass. if (IFace->getSuperClass()) AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories, AllowNullaryMethods, CurContext, AddedProperties, - Results, IsBaseExprStatement, IsClassProperty); - } else if (const ObjCCategoryDecl *Category - = dyn_cast<ObjCCategoryDecl>(Container)) { + Results, IsBaseExprStatement, IsClassProperty, + /*InOriginalClass*/ false); + } else if (const auto *Category = + dyn_cast<ObjCCategoryDecl>(Container)) { // Look through protocols. for (auto *P : Category->protocols()) AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods, CurContext, AddedProperties, Results, - IsBaseExprStatement, IsClassProperty); + IsBaseExprStatement, IsClassProperty, + /*InOriginalClass*/ false); } } -static void AddRecordMembersCompletionResults(Sema &SemaRef, - ResultBuilder &Results, Scope *S, - QualType BaseType, - RecordDecl *RD, - Optional<FixItHint> AccessOpFixIt) { +static void +AddRecordMembersCompletionResults(Sema &SemaRef, ResultBuilder &Results, + Scope *S, QualType BaseType, RecordDecl *RD, + Optional<FixItHint> AccessOpFixIt) { // Indicate that we are performing a member access, and the cv-qualifiers // for the base object type. Results.setObjectTypeQualifiers(BaseType.getQualifiers()); @@ -3997,8 +4181,8 @@ static void AddRecordMembersCompletionResults(Sema &SemaRef, Results.allowNestedNameSpecifiers(); std::vector<FixItHint> FixIts; if (AccessOpFixIt) - FixIts.emplace_back(AccessOpFixIt.getValue()); - CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext, std::move(FixIts)); + FixIts.emplace_back(AccessOpFixIt.getValue()); + CodeCompletionDeclConsumer Consumer(Results, RD, BaseType, std::move(FixIts)); SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer, SemaRef.CodeCompleter->includeGlobals(), /*IncludeDependentBases=*/true, @@ -4039,7 +4223,7 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, enum CodeCompletionContext::Kind contextKind; if (IsArrow) { - if (const PointerType *Ptr = ConvertedBaseType->getAs<PointerType>()) + if (const auto *Ptr = ConvertedBaseType->getAs<PointerType>()) ConvertedBaseType = Ptr->getPointeeType(); } @@ -4059,7 +4243,8 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, CodeCompleter->getCodeCompletionTUInfo(), CCContext, &ResultBuilder::IsMember); - auto DoCompletion = [&](Expr *Base, bool IsArrow, Optional<FixItHint> AccessOpFixIt) -> bool { + auto DoCompletion = [&](Expr *Base, bool IsArrow, + Optional<FixItHint> AccessOpFixIt) -> bool { if (!Base) return false; @@ -4113,7 +4298,8 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals()) AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true, CurContext, AddedProperties, Results, - IsBaseExprStatement); + IsBaseExprStatement, /*IsClassProperty*/ false, + /*InOriginalClass*/ false); } else if ((IsArrow && BaseType->isObjCObjectPointerType()) || (!IsArrow && BaseType->isObjCObjectType())) { // Objective-C instance variable access. @@ -4126,7 +4312,7 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, // Add all ivars from this class and its superclasses. if (Class) { - CodeCompletionDeclConsumer Consumer(Results, CurContext); + CodeCompletionDeclConsumer Consumer(Results, Class, BaseType); Results.setFilter(&ResultBuilder::IsObjCIvar); LookupVisibleDecls( Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(), @@ -4188,8 +4374,8 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { return; ResultBuilder::LookupFilter Filter = nullptr; - enum CodeCompletionContext::Kind ContextKind - = CodeCompletionContext::CCC_Other; + enum CodeCompletionContext::Kind ContextKind = + CodeCompletionContext::CCC_Other; switch ((DeclSpec::TST)TagSpec) { case DeclSpec::TST_enum: Filter = &ResultBuilder::IsEnum; @@ -4231,7 +4417,7 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { } HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(),Results.size()); + Results.data(), Results.size()); } static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results, @@ -4255,8 +4441,7 @@ void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) { Results.EnterNewScope(); AddTypeQualifierResults(DS, Results, LangOpts); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, - Results.getCompletionContext(), + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); } @@ -4291,6 +4476,9 @@ void Sema::CodeCompleteCase(Scope *S) { return; SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer(); + // Condition expression might be invalid, do not continue in this case. + if (!Switch->getCond()) + return; QualType type = Switch->getCond()->IgnoreImplicit()->getType(); if (!type->isEnumeralType()) { CodeCompleteExpressionData Data(type); @@ -4318,9 +4506,9 @@ void Sema::CodeCompleteCase(Scope *S) { continue; Expr *CaseVal = Case->getLHS()->IgnoreParenCasts(); - if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal)) - if (EnumConstantDecl *Enumerator - = dyn_cast<EnumConstantDecl>(DRE->getDecl())) { + if (auto *DRE = dyn_cast<DeclRefExpr>(CaseVal)) + if (auto *Enumerator = + dyn_cast<EnumConstantDecl>(DRE->getDecl())) { // We look into the AST of the case statement to determine which // enumerator was named. Alternatively, we could compute the value of // the integral constant expression, then compare it against the @@ -4366,7 +4554,7 @@ void Sema::CodeCompleteCase(Scope *S) { Results.ExitScope(); if (CodeCompleter->includeMacros()) { - AddMacroResults(PP, Results, false); + AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); } HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); @@ -4385,10 +4573,9 @@ static bool anyNullArguments(ArrayRef<Expr *> Args) { typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate; -static void mergeCandidatesWithResults(Sema &SemaRef, - SmallVectorImpl<ResultCandidate> &Results, - OverloadCandidateSet &CandidateSet, - SourceLocation Loc) { +static void mergeCandidatesWithResults( + Sema &SemaRef, SmallVectorImpl<ResultCandidate> &Results, + OverloadCandidateSet &CandidateSet, SourceLocation Loc) { if (!CandidateSet.empty()) { // Sort the overload candidate set by placing the best overloads first. std::stable_sort( @@ -4399,7 +4586,7 @@ static void mergeCandidatesWithResults(Sema &SemaRef, }); // Add the remaining viable overload candidates as code-completion results. - for (auto &Candidate : CandidateSet) { + for (OverloadCandidate &Candidate : CandidateSet) { if (Candidate.Function && Candidate.Function->isDeleted()) continue; if (Candidate.Viable) @@ -4411,22 +4598,21 @@ static void mergeCandidatesWithResults(Sema &SemaRef, /// Get the type of the Nth parameter from a given set of overload /// candidates. static QualType getParamType(Sema &SemaRef, - ArrayRef<ResultCandidate> Candidates, - unsigned N) { + ArrayRef<ResultCandidate> Candidates, unsigned N) { // Given the overloads 'Candidates' for a function call matching all arguments // up to N, return the type of the Nth parameter if it is the same for all // overload candidates. QualType ParamType; for (auto &Candidate : Candidates) { - if (auto FType = Candidate.getFunctionType()) - if (auto Proto = dyn_cast<FunctionProtoType>(FType)) + if (const auto *FType = Candidate.getFunctionType()) + if (const auto *Proto = dyn_cast<FunctionProtoType>(FType)) if (N < Proto->getNumParams()) { if (ParamType.isNull()) ParamType = Proto->getParamType(N); else if (!SemaRef.Context.hasSameUnqualifiedType( - ParamType.getNonReferenceType(), - Proto->getParamType(N).getNonReferenceType())) + ParamType.getNonReferenceType(), + Proto->getParamType(N).getNonReferenceType())) // Otherwise return a default-constructed QualType. return QualType(); } @@ -4435,41 +4621,28 @@ static QualType getParamType(Sema &SemaRef, return ParamType; } -static void CodeCompleteOverloadResults(Sema &SemaRef, Scope *S, - MutableArrayRef<ResultCandidate> Candidates, - unsigned CurrentArg, - bool CompleteExpressionWithCurrentArg = true) { - QualType ParamType; - if (CompleteExpressionWithCurrentArg) - ParamType = getParamType(SemaRef, Candidates, CurrentArg); - - if (ParamType.isNull()) - SemaRef.CodeCompleteOrdinaryName(S, Sema::PCC_Expression); - else - SemaRef.CodeCompleteExpression(S, ParamType); - - if (!Candidates.empty()) - SemaRef.CodeCompleter->ProcessOverloadCandidates(SemaRef, CurrentArg, - Candidates.data(), - Candidates.size()); +static QualType +ProduceSignatureHelp(Sema &SemaRef, Scope *S, + MutableArrayRef<ResultCandidate> Candidates, + unsigned CurrentArg, SourceLocation OpenParLoc) { + if (Candidates.empty()) + return QualType(); + SemaRef.CodeCompleter->ProcessOverloadCandidates( + SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc); + return getParamType(SemaRef, Candidates, CurrentArg); } -void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) { +QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn, + ArrayRef<Expr *> Args, + SourceLocation OpenParLoc) { if (!CodeCompleter) - return; - - // When we're code-completing for a call, we fall back to ordinary - // name code-completion whenever we can't produce specific - // results. We may want to revisit this strategy in the future, - // e.g., by merging the two kinds of results. + return QualType(); // FIXME: Provide support for variadic template functions. - // Ignore type-dependent call expressions entirely. if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) || Expr::hasAnyTypeDependentArguments(Args)) { - CodeCompleteOrdinaryName(S, PCC_Expression); - return; + return QualType(); } // Build an overload candidate set based on the functions we find. @@ -4498,13 +4671,12 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) { const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase(); AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs, /*SuppressUsedConversions=*/false, - /*PartialOverloading=*/true, - FirstArgumentIsBase); + /*PartialOverloading=*/true, FirstArgumentIsBase); } else { FunctionDecl *FD = nullptr; - if (auto MCE = dyn_cast<MemberExpr>(NakedFn)) + if (auto *MCE = dyn_cast<MemberExpr>(NakedFn)) FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl()); - else if (auto DRE = dyn_cast<DeclRefExpr>(NakedFn)) + else if (auto *DRE = dyn_cast<DeclRefExpr>(NakedFn)) FD = dyn_cast<FunctionDecl>(DRE->getDecl()); if (FD) { // We check whether it's a resolved function declaration. if (!getLangOpts().CPlusPlus || @@ -4521,8 +4693,8 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) { // call operator, so we check if it does and add them as candidates. // A complete type is needed to lookup for member function call operators. if (isCompleteType(Loc, NakedFn->getType())) { - DeclarationName OpName = Context.DeclarationNames - .getCXXOperatorName(OO_Call); + DeclarationName OpName = + Context.DeclarationNames.getCXXOperatorName(OO_Call); LookupResult R(*this, OpName, Loc, LookupOrdinaryName); LookupQualifiedName(R, DC); R.suppressDiagnostics(); @@ -4542,7 +4714,7 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) { if (auto FP = T->getAs<FunctionProtoType>()) { if (!TooManyArguments(FP->getNumParams(), Args.size(), - /*PartialOverloading=*/true) || + /*PartialOverloading=*/true) || FP->isVariadic()) Results.push_back(ResultCandidate(FP)); } else if (auto FT = T->getAs<FunctionType>()) @@ -4550,49 +4722,67 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) { Results.push_back(ResultCandidate(FT)); } } - mergeCandidatesWithResults(*this, Results, CandidateSet, Loc); - CodeCompleteOverloadResults(*this, S, Results, Args.size(), - !CandidateSet.empty()); + QualType ParamType = + ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc); + return !CandidateSet.empty() ? ParamType : QualType(); } -void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc, - ArrayRef<Expr *> Args) { +QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type, + SourceLocation Loc, + ArrayRef<Expr *> Args, + SourceLocation OpenParLoc) { if (!CodeCompleter) - return; + return QualType(); // A complete type is needed to lookup for constructors. CXXRecordDecl *RD = isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr; - if (!RD) { - CodeCompleteExpression(S, Type); - return; - } + if (!RD) + return Type; // FIXME: Provide support for member initializers. // FIXME: Provide support for variadic template constructors. OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); - for (auto C : LookupConstructors(RD)) { - if (auto FD = dyn_cast<FunctionDecl>(C)) { - AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), - Args, CandidateSet, + for (NamedDecl *C : LookupConstructors(RD)) { + if (auto *FD = dyn_cast<FunctionDecl>(C)) { + AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args, + CandidateSet, /*SuppressUsedConversions=*/false, /*PartialOverloading=*/true); - } else if (auto FTD = dyn_cast<FunctionTemplateDecl>(C)) { - AddTemplateOverloadCandidate(FTD, - DeclAccessPair::make(FTD, C->getAccess()), - /*ExplicitTemplateArgs=*/nullptr, - Args, CandidateSet, - /*SuppressUsedConversions=*/false, - /*PartialOverloading=*/true); + } else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(C)) { + AddTemplateOverloadCandidate( + FTD, DeclAccessPair::make(FTD, C->getAccess()), + /*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet, + /*SuppressUsedConversions=*/false, + /*PartialOverloading=*/true); } } SmallVector<ResultCandidate, 8> Results; mergeCandidatesWithResults(*this, Results, CandidateSet, Loc); - CodeCompleteOverloadResults(*this, S, Results, Args.size()); + return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc); +} + +QualType Sema::ProduceCtorInitMemberSignatureHelp( + Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy, + ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc) { + if (!CodeCompleter) + return QualType(); + + CXXConstructorDecl *Constructor = + dyn_cast<CXXConstructorDecl>(ConstructorDecl); + if (!Constructor) + return QualType(); + // FIXME: Add support for Base class constructors as well. + if (ValueDecl *MemberDecl = tryLookupCtorInitMemberDecl( + Constructor->getParent(), SS, TemplateTypeTy, II)) + return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(), + MemberDecl->getLocation(), ArgExprs, + OpenParLoc); + return QualType(); } void Sema::CodeCompleteInitializer(Scope *S, Decl *D) { @@ -4602,7 +4792,12 @@ void Sema::CodeCompleteInitializer(Scope *S, Decl *D) { return; } - CodeCompleteExpression(S, VD->getType()); + CodeCompleteExpressionData Data; + Data.PreferredType = VD->getType(); + // Ignore VD to avoid completing the variable itself, e.g. in 'int foo = ^'. + Data.IgnoreDecls.push_back(VD); + + CodeCompleteExpression(S, Data); } void Sema::CodeCompleteReturn(Scope *S) { @@ -4610,9 +4805,9 @@ void Sema::CodeCompleteReturn(Scope *S) { if (isa<BlockDecl>(CurContext)) { if (BlockScopeInfo *BSI = getCurBlock()) ResultType = BSI->ReturnType; - } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext)) + } else if (const auto *Function = dyn_cast<FunctionDecl>(CurContext)) ResultType = Function->getReturnType(); - else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext)) + else if (const auto *Method = dyn_cast<ObjCMethodDecl>(CurContext)) ResultType = Method->getReturnType(); if (ResultType.isNull()) @@ -4676,21 +4871,99 @@ void Sema::CodeCompleteAfterIf(Scope *S) { AddPrettyFunctionResults(getLangOpts(), Results); if (CodeCompleter->includeMacros()) - AddMacroResults(PP, Results, false); + AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(),Results.size()); + Results.data(), Results.size()); +} + +static QualType getPreferredTypeOfBinaryRHS(Sema &S, Expr *LHS, + tok::TokenKind Op) { + if (!LHS) + return QualType(); + + QualType LHSType = LHS->getType(); + if (LHSType->isPointerType()) { + if (Op == tok::plus || Op == tok::plusequal || Op == tok::minusequal) + return S.getASTContext().getPointerDiffType(); + // Pointer difference is more common than subtracting an int from a pointer. + if (Op == tok::minus) + return LHSType; + } + + switch (Op) { + // No way to infer the type of RHS from LHS. + case tok::comma: + return QualType(); + // Prefer the type of the left operand for all of these. + // Arithmetic operations. + case tok::plus: + case tok::plusequal: + case tok::minus: + case tok::minusequal: + case tok::percent: + case tok::percentequal: + case tok::slash: + case tok::slashequal: + case tok::star: + case tok::starequal: + // Assignment. + case tok::equal: + // Comparison operators. + case tok::equalequal: + case tok::exclaimequal: + case tok::less: + case tok::lessequal: + case tok::greater: + case tok::greaterequal: + case tok::spaceship: + return LHS->getType(); + // Binary shifts are often overloaded, so don't try to guess those. + case tok::greatergreater: + case tok::greatergreaterequal: + case tok::lessless: + case tok::lesslessequal: + if (LHSType->isIntegralOrEnumerationType()) + return S.getASTContext().IntTy; + return QualType(); + // Logical operators, assume we want bool. + case tok::ampamp: + case tok::pipepipe: + case tok::caretcaret: + return S.getASTContext().BoolTy; + // Operators often used for bit manipulation are typically used with the type + // of the left argument. + case tok::pipe: + case tok::pipeequal: + case tok::caret: + case tok::caretequal: + case tok::amp: + case tok::ampequal: + if (LHSType->isIntegralOrEnumerationType()) + return LHSType; + return QualType(); + // RHS should be a pointer to a member of the 'LHS' type, but we can't give + // any particular type here. + case tok::periodstar: + case tok::arrowstar: + return QualType(); + default: + // FIXME(ibiryukov): handle the missing op, re-add the assertion. + // assert(false && "unhandled binary op"); + return QualType(); + } } -void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) { - if (LHS) - CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType()); +void Sema::CodeCompleteBinaryRHS(Scope *S, Expr *LHS, tok::TokenKind Op) { + auto PreferredType = getPreferredTypeOfBinaryRHS(*this, LHS, Op); + if (!PreferredType.isNull()) + CodeCompleteExpression(S, PreferredType); else CodeCompleteOrdinaryName(S, PCC_Expression); } void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, - bool EnteringContext) { + bool EnteringContext, QualType BaseType) { if (SS.isEmpty() || !CodeCompleter) return; @@ -4699,7 +4972,7 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, // it can be useful for global code completion which have information about // contexts/symbols that are not in the AST. if (SS.isInvalid()) { - CodeCompletionContext CC(CodeCompletionContext::CCC_Name); + CodeCompletionContext CC(CodeCompletionContext::CCC_Symbol); CC.setCXXScopeSpecifier(SS); HandleCodeCompleteResults(this, CodeCompleter, CC, nullptr, 0); return; @@ -4717,7 +4990,7 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), - CodeCompletionContext::CCC_Name); + CodeCompletionContext::CCC_Symbol); Results.EnterNewScope(); // The "template" keyword can follow "::" in the grammar, but only @@ -4737,7 +5010,7 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, if (CodeCompleter->includeNamespaceLevelDecls() || (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) { - CodeCompletionDeclConsumer Consumer(Results, CurContext); + CodeCompletionDeclConsumer Consumer(Results, Ctx, BaseType); LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer, /*IncludeGlobalScope=*/true, /*IncludeDependentBases=*/true, @@ -4757,7 +5030,10 @@ void Sema::CodeCompleteUsing(Scope *S) { ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), - CodeCompletionContext::CCC_PotentiallyQualifiedName, + // This can be both a using alias or using + // declaration, in the former we expect a new name and a + // symbol in the latter case. + CodeCompletionContext::CCC_SymbolOrNewName, &ResultBuilder::IsNestedNameSpecifier); Results.EnterNewScope(); @@ -4797,7 +5073,7 @@ void Sema::CodeCompleteUsingDirective(Scope *S) { Results.data(), Results.size()); } -void Sema::CodeCompleteNamespaceDecl(Scope *S) { +void Sema::CodeCompleteNamespaceDecl(Scope *S) { if (!CodeCompleter) return; @@ -4805,14 +5081,14 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) { if (!S->getParent()) Ctx = Context.getTranslationUnitDecl(); - bool SuppressedGlobalResults - = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx); + bool SuppressedGlobalResults = + Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx); ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), SuppressedGlobalResults - ? CodeCompletionContext::CCC_Namespace - : CodeCompletionContext::CCC_Other, + ? CodeCompletionContext::CCC_Namespace + : CodeCompletionContext::CCC_Other, &ResultBuilder::IsNamespace); if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) { @@ -4822,7 +5098,8 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) { // definition of each namespace. std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest; for (DeclContext::specific_decl_iterator<NamespaceDecl> - NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end()); + NS(Ctx->decls_begin()), + NSEnd(Ctx->decls_end()); NS != NSEnd; ++NS) OrigToLatest[NS->getOriginalNamespace()] = *NS; @@ -4830,22 +5107,21 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) { // namespace to the list of results. Results.EnterNewScope(); for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator - NS = OrigToLatest.begin(), - NSEnd = OrigToLatest.end(); + NS = OrigToLatest.begin(), + NSEnd = OrigToLatest.end(); NS != NSEnd; ++NS) - Results.AddResult(CodeCompletionResult( - NS->second, Results.getBasePriority(NS->second), - nullptr), - CurContext, nullptr, false); + Results.AddResult( + CodeCompletionResult(NS->second, Results.getBasePriority(NS->second), + nullptr), + CurContext, nullptr, false); Results.ExitScope(); } - HandleCodeCompleteResults(this, CodeCompleter, - Results.getCompletionContext(), - Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } -void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) { +void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) { if (!CodeCompleter) return; @@ -4858,9 +5134,8 @@ void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) { LookupVisibleDecls(S, LookupOrdinaryName, Consumer, CodeCompleter->includeGlobals(), CodeCompleter->loadExternal()); - HandleCodeCompleteResults(this, CodeCompleter, - Results.getCompletionContext(), - Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } void Sema::CodeCompleteOperatorName(Scope *S) { @@ -4875,8 +5150,8 @@ void Sema::CodeCompleteOperatorName(Scope *S) { Results.EnterNewScope(); // Add the names of overloadable operators. -#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ - if (std::strcmp(Spelling, "?")) \ +#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \ + if (std::strcmp(Spelling, "?")) \ Results.AddResult(Result(Spelling)); #include "clang/Basic/OperatorKinds.def" @@ -4896,20 +5171,19 @@ void Sema::CodeCompleteOperatorName(Scope *S) { } void Sema::CodeCompleteConstructorInitializer( - Decl *ConstructorD, - ArrayRef <CXXCtorInitializer *> Initializers) { + Decl *ConstructorD, ArrayRef<CXXCtorInitializer *> Initializers) { if (!ConstructorD) return; AdjustDeclIfTemplate(ConstructorD); - CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD); + auto *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD); if (!Constructor) return; ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), - CodeCompletionContext::CCC_PotentiallyQualifiedName); + CodeCompletionContext::CCC_Symbol); Results.EnterNewScope(); // Fill in any already-initialized fields or base classes. @@ -4917,39 +5191,96 @@ void Sema::CodeCompleteConstructorInitializer( llvm::SmallPtrSet<CanQualType, 4> InitializedBases; for (unsigned I = 0, E = Initializers.size(); I != E; ++I) { if (Initializers[I]->isBaseInitializer()) - InitializedBases.insert( - Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0))); + InitializedBases.insert(Context.getCanonicalType( + QualType(Initializers[I]->getBaseClass(), 0))); else - InitializedFields.insert(cast<FieldDecl>( - Initializers[I]->getAnyMember())); + InitializedFields.insert( + cast<FieldDecl>(Initializers[I]->getAnyMember())); } // Add completions for base classes. - CodeCompletionBuilder Builder(Results.getAllocator(), - Results.getCodeCompletionTUInfo()); PrintingPolicy Policy = getCompletionPrintingPolicy(*this); bool SawLastInitializer = Initializers.empty(); CXXRecordDecl *ClassDecl = Constructor->getParent(); + + auto GenerateCCS = [&](const NamedDecl *ND, const char *Name) { + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); + Builder.AddTypedTextChunk(Name); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + if (const auto *Function = dyn_cast<FunctionDecl>(ND)) + AddFunctionParameterChunks(PP, Policy, Function, Builder); + else if (const auto *FunTemplDecl = dyn_cast<FunctionTemplateDecl>(ND)) + AddFunctionParameterChunks(PP, Policy, FunTemplDecl->getTemplatedDecl(), + Builder); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + return Builder.TakeString(); + }; + auto AddDefaultCtorInit = [&](const char *Name, const char *Type, + const NamedDecl *ND) { + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); + Builder.AddTypedTextChunk(Name); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk(Type); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + if (ND) { + auto CCR = CodeCompletionResult( + Builder.TakeString(), ND, + SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration); + if (isa<FieldDecl>(ND)) + CCR.CursorKind = CXCursor_MemberRef; + return Results.AddResult(CCR); + } + return Results.AddResult(CodeCompletionResult( + Builder.TakeString(), + SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration)); + }; + auto AddCtorsWithName = [&](const CXXRecordDecl *RD, unsigned int Priority, + const char *Name, const FieldDecl *FD) { + if (!RD) + return AddDefaultCtorInit(Name, + FD ? Results.getAllocator().CopyString( + FD->getType().getAsString(Policy)) + : Name, + FD); + auto Ctors = getConstructors(Context, RD); + if (Ctors.begin() == Ctors.end()) + return AddDefaultCtorInit(Name, Name, RD); + for (const NamedDecl *Ctor : Ctors) { + auto CCR = CodeCompletionResult(GenerateCCS(Ctor, Name), RD, Priority); + CCR.CursorKind = getCursorKindForDecl(Ctor); + Results.AddResult(CCR); + } + }; + auto AddBase = [&](const CXXBaseSpecifier &Base) { + const char *BaseName = + Results.getAllocator().CopyString(Base.getType().getAsString(Policy)); + const auto *RD = Base.getType()->getAsCXXRecordDecl(); + AddCtorsWithName( + RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration, + BaseName, nullptr); + }; + auto AddField = [&](const FieldDecl *FD) { + const char *FieldName = + Results.getAllocator().CopyString(FD->getIdentifier()->getName()); + const CXXRecordDecl *RD = FD->getType()->getAsCXXRecordDecl(); + AddCtorsWithName( + RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration, + FieldName, FD); + }; + for (const auto &Base : ClassDecl->bases()) { if (!InitializedBases.insert(Context.getCanonicalType(Base.getType())) .second) { - SawLastInitializer - = !Initializers.empty() && - Initializers.back()->isBaseInitializer() && - Context.hasSameUnqualifiedType(Base.getType(), - QualType(Initializers.back()->getBaseClass(), 0)); + SawLastInitializer = + !Initializers.empty() && Initializers.back()->isBaseInitializer() && + Context.hasSameUnqualifiedType( + Base.getType(), QualType(Initializers.back()->getBaseClass(), 0)); continue; } - Builder.AddTypedTextChunk( - Results.getAllocator().CopyString( - Base.getType().getAsString(Policy))); - Builder.AddChunk(CodeCompletionString::CK_LeftParen); - Builder.AddPlaceholderChunk("args"); - Builder.AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(CodeCompletionResult(Builder.TakeString(), - SawLastInitializer? CCP_NextInitializer - : CCP_MemberDeclaration)); + AddBase(Base); SawLastInitializer = false; } @@ -4957,23 +5288,14 @@ void Sema::CodeCompleteConstructorInitializer( for (const auto &Base : ClassDecl->vbases()) { if (!InitializedBases.insert(Context.getCanonicalType(Base.getType())) .second) { - SawLastInitializer - = !Initializers.empty() && - Initializers.back()->isBaseInitializer() && - Context.hasSameUnqualifiedType(Base.getType(), - QualType(Initializers.back()->getBaseClass(), 0)); + SawLastInitializer = + !Initializers.empty() && Initializers.back()->isBaseInitializer() && + Context.hasSameUnqualifiedType( + Base.getType(), QualType(Initializers.back()->getBaseClass(), 0)); continue; } - Builder.AddTypedTextChunk( - Builder.getAllocator().CopyString( - Base.getType().getAsString(Policy))); - Builder.AddChunk(CodeCompletionString::CK_LeftParen); - Builder.AddPlaceholderChunk("args"); - Builder.AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(CodeCompletionResult(Builder.TakeString(), - SawLastInitializer? CCP_NextInitializer - : CCP_MemberDeclaration)); + AddBase(Base); SawLastInitializer = false; } @@ -4981,27 +5303,16 @@ void Sema::CodeCompleteConstructorInitializer( for (auto *Field : ClassDecl->fields()) { if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl())) .second) { - SawLastInitializer - = !Initializers.empty() && - Initializers.back()->isAnyMemberInitializer() && - Initializers.back()->getAnyMember() == Field; + SawLastInitializer = !Initializers.empty() && + Initializers.back()->isAnyMemberInitializer() && + Initializers.back()->getAnyMember() == Field; continue; } if (!Field->getDeclName()) continue; - Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( - Field->getIdentifier()->getName())); - Builder.AddChunk(CodeCompletionString::CK_LeftParen); - Builder.AddPlaceholderChunk("args"); - Builder.AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(CodeCompletionResult(Builder.TakeString(), - SawLastInitializer? CCP_NextInitializer - : CCP_MemberDeclaration, - CXCursor_MemberRef, - CXAvailability_Available, - Field)); + AddField(Field); SawLastInitializer = false; } Results.ExitScope(); @@ -5042,9 +5353,7 @@ void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro, for (; S && !isNamespaceScope(S); S = S->getParent()) { for (const auto *D : S->decls()) { const auto *Var = dyn_cast<VarDecl>(D); - if (!Var || - !Var->hasLocalStorage() || - Var->hasAttr<BlocksAttr>()) + if (!Var || !Var->hasLocalStorage() || Var->hasAttr<BlocksAttr>()) continue; if (Known.insert(Var->getIdentifier()).second) @@ -5065,26 +5374,25 @@ void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro, /// Macro that optionally prepends an "@" to the string literal passed in via /// Keyword, depending on whether NeedAt is true or false. -#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword) +#define OBJC_AT_KEYWORD_NAME(NeedAt, Keyword) ((NeedAt) ? "@" Keyword : Keyword) static void AddObjCImplementationResults(const LangOptions &LangOpts, - ResultBuilder &Results, - bool NeedAt) { + ResultBuilder &Results, bool NeedAt) { typedef CodeCompletionResult Result; // Since we have an implementation, we can end it. - Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end"))); + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end"))); CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo()); - if (LangOpts.ObjC2) { + if (LangOpts.ObjC) { // @dynamic - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "dynamic")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("property"); Results.AddResult(Result(Builder.TakeString())); // @synthesize - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synthesize")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("property"); Results.AddResult(Result(Builder.TakeString())); @@ -5092,22 +5400,21 @@ static void AddObjCImplementationResults(const LangOptions &LangOpts, } static void AddObjCInterfaceResults(const LangOptions &LangOpts, - ResultBuilder &Results, - bool NeedAt) { + ResultBuilder &Results, bool NeedAt) { typedef CodeCompletionResult Result; // Since we have an interface or protocol, we can end it. - Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end"))); + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end"))); - if (LangOpts.ObjC2) { + if (LangOpts.ObjC) { // @property - Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property"))); + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "property"))); // @required - Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required"))); + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "required"))); // @optional - Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional"))); + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "optional"))); } } @@ -5117,7 +5424,7 @@ static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) { Results.getCodeCompletionTUInfo()); // @class name ; - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "class")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("name"); Results.AddResult(Result(Builder.TakeString())); @@ -5126,26 +5433,27 @@ static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) { // @interface name // FIXME: Could introduce the whole pattern, including superclasses and // such. - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "interface")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("class"); Results.AddResult(Result(Builder.TakeString())); // @protocol name - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("protocol"); Results.AddResult(Result(Builder.TakeString())); // @implementation name - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "implementation")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("class"); Results.AddResult(Result(Builder.TakeString())); } // @compatibility_alias name - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias")); + Builder.AddTypedTextChunk( + OBJC_AT_KEYWORD_NAME(NeedAt, "compatibility_alias")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("alias"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -5188,7 +5496,7 @@ static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) { Results.getSema().getLangOpts().ConstStrings) EncodeType = "const char[]"; Builder.AddResultTypeChunk(EncodeType); - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "encode")); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("type-name"); Builder.AddChunk(CodeCompletionString::CK_RightParen); @@ -5196,7 +5504,7 @@ static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) { // @protocol ( protocol-name ) Builder.AddResultTypeChunk("Protocol *"); - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol")); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("protocol-name"); Builder.AddChunk(CodeCompletionString::CK_RightParen); @@ -5204,7 +5512,7 @@ static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) { // @selector ( selector ) Builder.AddResultTypeChunk("SEL"); - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "selector")); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("selector"); Builder.AddChunk(CodeCompletionString::CK_RightParen); @@ -5212,21 +5520,21 @@ static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) { // @"string" Builder.AddResultTypeChunk("NSString *"); - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\"")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "\"")); Builder.AddPlaceholderChunk("string"); Builder.AddTextChunk("\""); Results.AddResult(Result(Builder.TakeString())); // @[objects, ...] Builder.AddResultTypeChunk("NSArray *"); - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"[")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "[")); Builder.AddPlaceholderChunk("objects, ..."); Builder.AddChunk(CodeCompletionString::CK_RightBracket); Results.AddResult(Result(Builder.TakeString())); // @{key : object, ...} Builder.AddResultTypeChunk("NSDictionary *"); - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "{")); Builder.AddPlaceholderChunk("key"); Builder.AddChunk(CodeCompletionString::CK_Colon); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -5250,7 +5558,7 @@ static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) { if (Results.includeCodePatterns()) { // @try { statements } @catch ( declaration ) { statements } @finally // { statements } - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "try")); Builder.AddChunk(CodeCompletionString::CK_LeftBrace); Builder.AddPlaceholderChunk("statements"); Builder.AddChunk(CodeCompletionString::CK_RightBrace); @@ -5269,14 +5577,14 @@ static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) { } // @throw - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "throw")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("expression"); Results.AddResult(Result(Builder.TakeString())); if (Results.includeCodePatterns()) { // @synchronized ( expression ) { statements } - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synchronized")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("expression"); @@ -5289,14 +5597,13 @@ static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) { } static void AddObjCVisibilityResults(const LangOptions &LangOpts, - ResultBuilder &Results, - bool NeedAt) { + ResultBuilder &Results, bool NeedAt) { typedef CodeCompletionResult Result; - Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private"))); - Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected"))); - Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public"))); - if (LangOpts.ObjC2) - Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package"))); + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "private"))); + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "protected"))); + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "public"))); + if (LangOpts.ObjC) + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "package"))); } void Sema::CodeCompleteObjCAtVisibility(Scope *S) { @@ -5348,14 +5655,12 @@ static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) { return true; // Check for more than one of { assign, copy, retain, strong, weak }. - unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign | - ObjCDeclSpec::DQ_PR_unsafe_unretained | - ObjCDeclSpec::DQ_PR_copy | - ObjCDeclSpec::DQ_PR_retain | - ObjCDeclSpec::DQ_PR_strong | - ObjCDeclSpec::DQ_PR_weak); - if (AssignCopyRetMask && - AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign && + unsigned AssignCopyRetMask = + Attributes & + (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_unsafe_unretained | + ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain | + ObjCDeclSpec::DQ_PR_strong | ObjCDeclSpec::DQ_PR_weak); + if (AssignCopyRetMask && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain && @@ -5433,11 +5738,10 @@ void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { enum ObjCMethodKind { MK_Any, ///< Any kind of method, provided it means other specified criteria. MK_ZeroArgSelector, ///< Zero-argument (unary) selector. - MK_OneArgSelector ///< One-argument selector. + MK_OneArgSelector ///< One-argument selector. }; -static bool isAcceptableObjCSelector(Selector Sel, - ObjCMethodKind WantKind, +static bool isAcceptableObjCSelector(Selector Sel, ObjCMethodKind WantKind, ArrayRef<IdentifierInfo *> SelIdents, bool AllowSameLength = true) { unsigned NumSelIdents = SelIdents.size(); @@ -5445,9 +5749,12 @@ static bool isAcceptableObjCSelector(Selector Sel, return false; switch (WantKind) { - case MK_Any: break; - case MK_ZeroArgSelector: return Sel.isUnarySelector(); - case MK_OneArgSelector: return Sel.getNumArgs() == 1; + case MK_Any: + break; + case MK_ZeroArgSelector: + return Sel.isUnarySelector(); + case MK_OneArgSelector: + return Sel.getNumArgs() == 1; } if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs()) @@ -5468,11 +5775,9 @@ static bool isAcceptableObjCMethod(ObjCMethodDecl *Method, AllowSameLength); } -namespace { - /// A set of selectors, which is used to avoid introducing multiple - /// completions with the same selector into the result set. - typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet; -} +/// A set of selectors, which is used to avoid introducing multiple +/// completions with the same selector into the result set. +typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet; /// Add all of the Objective-C methods in the given Objective-C /// container to the set of results. @@ -5505,7 +5810,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container, Container = getContainerDef(Container); ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container); IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass()); - for (auto *M : Container->methods()) { + for (ObjCMethodDecl *M : Container->methods()) { // The instance methods on the root class can be messaged via the // metaclass. if (M->isInstanceMethod() == WantInstanceMethods || @@ -5522,16 +5827,16 @@ static void AddObjCMethods(ObjCContainerDecl *Container, R.StartParameter = SelIdents.size(); R.AllParametersAreInformative = (WantKind != MK_Any); if (!InOriginalClass) - R.Priority += CCD_InBaseClass; + setInBaseClass(R); Results.MaybeAddResult(R, CurContext); } } // Visit the protocols of protocols. - if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { + if (const auto *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { if (Protocol->hasDefinition()) { - const ObjCList<ObjCProtocolDecl> &Protocols - = Protocol->getReferencedProtocols(); + const ObjCList<ObjCProtocolDecl> &Protocols = + Protocol->getReferencedProtocols(); for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) @@ -5544,19 +5849,19 @@ static void AddObjCMethods(ObjCContainerDecl *Container, return; // Add methods in protocols. - for (auto *I : IFace->protocols()) + for (ObjCProtocolDecl *I : IFace->protocols()) AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext, Selectors, AllowSameLength, Results, false, IsRootClass); // Add methods in categories. - for (auto *CatDecl : IFace->known_categories()) { + for (ObjCCategoryDecl *CatDecl : IFace->known_categories()) { AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents, CurContext, Selectors, AllowSameLength, Results, InOriginalClass, IsRootClass); // Add a categories protocol methods. - const ObjCList<ObjCProtocolDecl> &Protocols - = CatDecl->getReferencedProtocols(); + const ObjCList<ObjCProtocolDecl> &Protocols = + CatDecl->getReferencedProtocols(); for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) @@ -5584,13 +5889,12 @@ static void AddObjCMethods(ObjCContainerDecl *Container, IsRootClass); } - void Sema::CodeCompleteObjCPropertyGetter(Scope *S) { // Try to find the interface where getters might live. ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext); if (!Class) { - if (ObjCCategoryDecl *Category - = dyn_cast_or_null<ObjCCategoryDecl>(CurContext)) + if (ObjCCategoryDecl *Category = + dyn_cast_or_null<ObjCCategoryDecl>(CurContext)) Class = Category->getClassInterface(); if (!Class) @@ -5613,11 +5917,10 @@ void Sema::CodeCompleteObjCPropertyGetter(Scope *S) { void Sema::CodeCompleteObjCPropertySetter(Scope *S) { // Try to find the interface where setters might live. - ObjCInterfaceDecl *Class - = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext); + ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext); if (!Class) { - if (ObjCCategoryDecl *Category - = dyn_cast_or_null<ObjCCategoryDecl>(CurContext)) + if (ObjCCategoryDecl *Category = + dyn_cast_or_null<ObjCCategoryDecl>(CurContext)) Class = Category->getClassInterface(); if (!Class) @@ -5631,8 +5934,8 @@ void Sema::CodeCompleteObjCPropertySetter(Scope *S) { Results.EnterNewScope(); VisitedSelectorSet Selectors; - AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext, - Selectors, /*AllowSameLength=*/true, Results); + AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext, Selectors, + /*AllowSameLength=*/true, Results); Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), @@ -5663,9 +5966,9 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, if ((DS.getObjCDeclQualifier() & (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref | ObjCDeclSpec::DQ_Oneway)) == 0) { - Results.AddResult("bycopy"); - Results.AddResult("byref"); - Results.AddResult("oneway"); + Results.AddResult("bycopy"); + Results.AddResult("byref"); + Results.AddResult("oneway"); } if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) { Results.AddResult("nonnull"); @@ -5710,7 +6013,7 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, CodeCompleter->loadExternal()); if (CodeCompleter->includeMacros()) - AddMacroResults(PP, Results, false); + AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); @@ -5721,7 +6024,7 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, /// common uses of Objective-C. This routine returns that class type, /// or NULL if no better result could be determined. static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) { - ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E); + auto *Msg = dyn_cast_or_null<ObjCMessageExpr>(E); if (!Msg) return nullptr; @@ -5741,8 +6044,8 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) { ObjCInterfaceDecl *IFace = nullptr; switch (Msg->getReceiverKind()) { case ObjCMessageExpr::Class: - if (const ObjCObjectType *ObjType - = Msg->getClassReceiver()->getAs<ObjCObjectType>()) + if (const ObjCObjectType *ObjType = + Msg->getClassReceiver()->getAs<ObjCObjectType>()) IFace = ObjType->getInterface(); break; @@ -5764,27 +6067,27 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) { ObjCInterfaceDecl *Super = IFace->getSuperClass(); if (Method->isInstanceMethod()) return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName()) - .Case("retain", IFace) - .Case("strong", IFace) - .Case("autorelease", IFace) - .Case("copy", IFace) - .Case("copyWithZone", IFace) - .Case("mutableCopy", IFace) - .Case("mutableCopyWithZone", IFace) - .Case("awakeFromCoder", IFace) - .Case("replacementObjectFromCoder", IFace) + .Case("retain", IFace) + .Case("strong", IFace) + .Case("autorelease", IFace) + .Case("copy", IFace) + .Case("copyWithZone", IFace) + .Case("mutableCopy", IFace) + .Case("mutableCopyWithZone", IFace) + .Case("awakeFromCoder", IFace) + .Case("replacementObjectFromCoder", IFace) + .Case("class", IFace) + .Case("classForCoder", IFace) + .Case("superclass", Super) + .Default(nullptr); + + return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName()) + .Case("new", IFace) + .Case("alloc", IFace) + .Case("allocWithZone", IFace) .Case("class", IFace) - .Case("classForCoder", IFace) .Case("superclass", Super) .Default(nullptr); - - return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName()) - .Case("new", IFace) - .Case("alloc", IFace) - .Case("allocWithZone", IFace) - .Case("class", IFace) - .Case("superclass", Super) - .Default(nullptr); } // Add a special completion for a message send to "super", which fills in the @@ -5803,10 +6106,10 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) { /// /// \returns the Objective-C method declaration that would be invoked by /// this "super" completion. If NULL, no completion was added. -static ObjCMethodDecl *AddSuperSendCompletion( - Sema &S, bool NeedSuperKeyword, - ArrayRef<IdentifierInfo *> SelIdents, - ResultBuilder &Results) { +static ObjCMethodDecl * +AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword, + ArrayRef<IdentifierInfo *> SelIdents, + ResultBuilder &Results) { ObjCMethodDecl *CurMethod = S.getCurMethodDecl(); if (!CurMethod) return nullptr; @@ -5826,7 +6129,7 @@ static ObjCMethodDecl *AddSuperSendCompletion( if (!SuperMethod) { for (const auto *Cat : Class->known_categories()) { if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(), - CurMethod->isInstanceMethod()))) + CurMethod->isInstanceMethod()))) break; } } @@ -5841,8 +6144,8 @@ static ObjCMethodDecl *AddSuperSendCompletion( return nullptr; for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(), - CurPEnd = CurMethod->param_end(), - SuperP = SuperMethod->param_begin(); + CurPEnd = CurMethod->param_end(), + SuperP = SuperMethod->param_begin(); CurP != CurPEnd; ++CurP, ++SuperP) { // Make sure the parameter types are compatible. if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(), @@ -5860,8 +6163,7 @@ static ObjCMethodDecl *AddSuperSendCompletion( // Give this completion a return type. AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod, - Results.getCompletionContext().getBaseType(), - Builder); + Results.getCompletionContext().getBaseType(), Builder); // If we need the "super" keyword, add it (plus some spacing). if (NeedSuperKeyword) { @@ -5872,11 +6174,11 @@ static ObjCMethodDecl *AddSuperSendCompletion( Selector Sel = CurMethod->getSelector(); if (Sel.isUnarySelector()) { if (NeedSuperKeyword) - Builder.AddTextChunk(Builder.getAllocator().CopyString( - Sel.getNameForSlot(0))); + Builder.AddTextChunk( + Builder.getAllocator().CopyString(Sel.getNameForSlot(0))); else - Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( - Sel.getNameForSlot(0))); + Builder.AddTypedTextChunk( + Builder.getAllocator().CopyString(Sel.getNameForSlot(0))); } else { ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(); for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) { @@ -5885,20 +6187,17 @@ static ObjCMethodDecl *AddSuperSendCompletion( if (I < SelIdents.size()) Builder.AddInformativeChunk( - Builder.getAllocator().CopyString( - Sel.getNameForSlot(I) + ":")); + Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":")); else if (NeedSuperKeyword || I > SelIdents.size()) { Builder.AddTextChunk( - Builder.getAllocator().CopyString( - Sel.getNameForSlot(I) + ":")); + Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":")); Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString( - (*CurP)->getIdentifier()->getName())); + (*CurP)->getIdentifier()->getName())); } else { Builder.AddTypedTextChunk( - Builder.getAllocator().CopyString( - Sel.getNameForSlot(I) + ":")); + Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":")); Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString( - (*CurP)->getIdentifier()->getName())); + (*CurP)->getIdentifier()->getName())); } } } @@ -5910,12 +6209,13 @@ static ObjCMethodDecl *AddSuperSendCompletion( void Sema::CodeCompleteObjCMessageReceiver(Scope *S) { typedef CodeCompletionResult Result; - ResultBuilder Results(*this, CodeCompleter->getAllocator(), - CodeCompleter->getCodeCompletionTUInfo(), - CodeCompletionContext::CCC_ObjCMessageReceiver, - getLangOpts().CPlusPlus11 - ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture - : &ResultBuilder::IsObjCMessageReceiver); + ResultBuilder Results( + *this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_ObjCMessageReceiver, + getLangOpts().CPlusPlus11 + ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture + : &ResultBuilder::IsObjCMessageReceiver); CodeCompletionDeclConsumer Consumer(Results, CurContext); Results.EnterNewScope(); @@ -5939,10 +6239,9 @@ void Sema::CodeCompleteObjCMessageReceiver(Scope *S) { Results.ExitScope(); if (CodeCompleter->includeMacros()) - AddMacroResults(PP, Results, false); + AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); - } void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, @@ -5965,8 +6264,7 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, // send [super ...] is actually calling an instance method on the // current object. return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents, - AtArgumentExpression, - CDecl); + AtArgumentExpression, CDecl); } // Fall through to send to the superclass in CDecl. @@ -5974,13 +6272,12 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, // "super" may be the name of a type or variable. Figure out which // it is. IdentifierInfo *Super = getSuperIdentifier(); - NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, - LookupOrdinaryName); + NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, LookupOrdinaryName); if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) { // "super" names an interface. Use it. } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) { - if (const ObjCObjectType *Iface - = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>()) + if (const ObjCObjectType *Iface = + Context.getTypeDeclType(TD)->getAs<ObjCObjectType>()) CDecl = Iface->getInterface(); } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) { // "super" names an unresolved type; we can't be more specific. @@ -5990,11 +6287,10 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, SourceLocation TemplateKWLoc; UnqualifiedId id; id.setIdentifier(Super, SuperLoc); - ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id, - false, false); + ExprResult SuperExpr = + ActOnIdExpression(S, SS, TemplateKWLoc, id, false, false); return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(), - SelIdents, - AtArgumentExpression); + SelIdents, AtArgumentExpression); } // Fall through @@ -6025,8 +6321,8 @@ static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results, if (R.Priority <= BestPriority) { const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration); if (NumSelIdents <= Method->param_size()) { - QualType MyPreferredType = Method->parameters()[NumSelIdents - 1] - ->getType(); + QualType MyPreferredType = + Method->parameters()[NumSelIdents - 1]->getType(); if (R.Priority < BestPriority || PreferredType.isNull()) { BestPriority = R.Priority; PreferredType = MyPreferredType; @@ -6045,8 +6341,7 @@ static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results, static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, ParsedType Receiver, ArrayRef<IdentifierInfo *> SelIdents, - bool AtArgumentExpression, - bool IsSuper, + bool AtArgumentExpression, bool IsSuper, ResultBuilder &Results) { typedef CodeCompletionResult Result; ObjCInterfaceDecl *CDecl = nullptr; @@ -6067,8 +6362,8 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, // If this is a send-to-super, try to add the special "super" send // completion. if (IsSuper) { - if (ObjCMethodDecl *SuperMethod - = AddSuperSendCompletion(SemaRef, false, SelIdents, Results)) + if (ObjCMethodDecl *SuperMethod = + AddSuperSendCompletion(SemaRef, false, SelIdents, Results)) Results.Ignore(SuperMethod); } @@ -6079,9 +6374,8 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, VisitedSelectorSet Selectors; if (CDecl) - AddObjCMethods(CDecl, false, MK_Any, SelIdents, - SemaRef.CurContext, Selectors, AtArgumentExpression, - Results); + AddObjCMethods(CDecl, false, MK_Any, SelIdents, SemaRef.CurContext, + Selectors, AtArgumentExpression, Results); else { // We're messaging "id" as a type; provide all class/factory methods. @@ -6100,11 +6394,10 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, } for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(), - MEnd = SemaRef.MethodPool.end(); + MEnd = SemaRef.MethodPool.end(); M != MEnd; ++M) { for (ObjCMethodList *MethList = &M->second.second; - MethList && MethList->getMethod(); - MethList = MethList->getNext()) { + MethList && MethList->getMethod(); MethList = MethList->getNext()) { if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents)) continue; @@ -6127,10 +6420,11 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, QualType T = this->GetTypeFromParser(Receiver); - ResultBuilder Results(*this, CodeCompleter->getAllocator(), - CodeCompleter->getCodeCompletionTUInfo(), - CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, - T, SelIdents)); + ResultBuilder Results( + *this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, T, + SelIdents)); AddClassMessageCompletions(*this, S, Receiver, SelIdents, AtArgumentExpression, IsSuper, Results); @@ -6141,8 +6435,8 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, // code-complete the expression using the corresponding parameter type as // our preferred type, improving completion results. if (AtArgumentExpression) { - QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results, - SelIdents.size()); + QualType PreferredType = + getPreferredArgumentTypeForMessageSend(Results, SelIdents.size()); if (PreferredType.isNull()) CodeCompleteOrdinaryName(S, PCC_Expression); else @@ -6150,8 +6444,7 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, return; } - HandleCodeCompleteResults(this, CodeCompleter, - Results.getCompletionContext(), + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); } @@ -6171,10 +6464,11 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, return; RecExpr = Conv.get(); } - QualType ReceiverType = RecExpr? RecExpr->getType() - : Super? Context.getObjCObjectPointerType( + QualType ReceiverType = RecExpr + ? RecExpr->getType() + : Super ? Context.getObjCObjectPointerType( Context.getObjCInterfaceType(Super)) - : Context.getObjCIdType(); + : Context.getObjCIdType(); // If we're messaging an expression with type "id" or "Class", check // whether we know something special about the receiver that allows @@ -6182,13 +6476,12 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) { if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) { if (ReceiverType->isObjCClassType()) - return CodeCompleteObjCClassMessage(S, - ParsedType::make(Context.getObjCInterfaceType(IFace)), - SelIdents, - AtArgumentExpression, Super); + return CodeCompleteObjCClassMessage( + S, ParsedType::make(Context.getObjCInterfaceType(IFace)), SelIdents, + AtArgumentExpression, Super); - ReceiverType = Context.getObjCObjectPointerType( - Context.getObjCInterfaceType(IFace)); + ReceiverType = + Context.getObjCObjectPointerType(Context.getObjCInterfaceType(IFace)); } } else if (RecExpr && getLangOpts().CPlusPlus) { ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr); @@ -6199,18 +6492,19 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, } // Build the set of methods we can see. - ResultBuilder Results(*this, CodeCompleter->getAllocator(), - CodeCompleter->getCodeCompletionTUInfo(), - CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage, - ReceiverType, SelIdents)); + ResultBuilder Results( + *this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage, + ReceiverType, SelIdents)); Results.EnterNewScope(); // If this is a send-to-super, try to add the special "super" send // completion. if (Super) { - if (ObjCMethodDecl *SuperMethod - = AddSuperSendCompletion(*this, false, SelIdents, Results)) + if (ObjCMethodDecl *SuperMethod = + AddSuperSendCompletion(*this, false, SelIdents, Results)) Results.Ignore(SuperMethod); } @@ -6229,30 +6523,29 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, ReceiverType->isObjCQualifiedClassType()) { if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) { if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface()) - AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, - CurContext, Selectors, AtArgumentExpression, Results); + AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, CurContext, + Selectors, AtArgumentExpression, Results); } } // Handle messages to a qualified ID ("id<foo>"). - else if (const ObjCObjectPointerType *QualID - = ReceiverType->getAsObjCQualifiedIdType()) { + else if (const ObjCObjectPointerType *QualID = + ReceiverType->getAsObjCQualifiedIdType()) { // Search protocols for instance methods. for (auto *I : QualID->quals()) - AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, - Selectors, AtArgumentExpression, Results); + AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors, + AtArgumentExpression, Results); } // Handle messages to a pointer to interface type. - else if (const ObjCObjectPointerType *IFacePtr - = ReceiverType->getAsObjCInterfacePointerType()) { + else if (const ObjCObjectPointerType *IFacePtr = + ReceiverType->getAsObjCInterfacePointerType()) { // Search the class, its superclasses, etc., for instance methods. AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents, - CurContext, Selectors, AtArgumentExpression, - Results); + CurContext, Selectors, AtArgumentExpression, Results); // Search protocols for instance methods. for (auto *I : IFacePtr->quals()) - AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, - Selectors, AtArgumentExpression, Results); + AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors, + AtArgumentExpression, Results); } // Handle messages to "id". else if (ReceiverType->isObjCIdType()) { @@ -6276,8 +6569,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, MEnd = MethodPool.end(); M != MEnd; ++M) { for (ObjCMethodList *MethList = &M->second.first; - MethList && MethList->getMethod(); - MethList = MethList->getNext()) { + MethList && MethList->getMethod(); MethList = MethList->getNext()) { if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents)) continue; @@ -6294,15 +6586,14 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, } Results.ExitScope(); - // If we're actually at the argument expression (rather than prior to the // selector), we're actually performing code completion for an expression. // Determine whether we have a single, best method. If so, we can // code-complete the expression using the corresponding parameter type as // our preferred type, improving completion results. if (AtArgumentExpression) { - QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results, - SelIdents.size()); + QualType PreferredType = + getPreferredArgumentTypeForMessageSend(Results, SelIdents.size()); if (PreferredType.isNull()) CodeCompleteOrdinaryName(S, PCC_Expression); else @@ -6310,9 +6601,8 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, return; } - HandleCodeCompleteResults(this, CodeCompleter, - Results.getCompletionContext(), - Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } void Sema::CodeCompleteObjCForCollection(Scope *S, @@ -6336,8 +6626,8 @@ void Sema::CodeCompleteObjCSelector(Scope *S, // If we have an external source, load the entire class method // pool from the AST file. if (ExternalSource) { - for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); - I != N; ++I) { + for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N; + ++I) { Selector Sel = ExternalSource->GetExternalSelector(I); if (Sel.isNull() || MethodPool.count(Sel)) continue; @@ -6351,7 +6641,7 @@ void Sema::CodeCompleteObjCSelector(Scope *S, CodeCompletionContext::CCC_SelectorName); Results.EnterNewScope(); for (GlobalMethodPool::iterator M = MethodPool.begin(), - MEnd = MethodPool.end(); + MEnd = MethodPool.end(); M != MEnd; ++M) { Selector Sel = M->first; @@ -6361,8 +6651,8 @@ void Sema::CodeCompleteObjCSelector(Scope *S, CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo()); if (Sel.isUnarySelector()) { - Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( - Sel.getNameForSlot(0))); + Builder.AddTypedTextChunk( + Builder.getAllocator().CopyString(Sel.getNameForSlot(0))); Results.AddResult(Builder.TakeString()); continue; } @@ -6371,8 +6661,8 @@ void Sema::CodeCompleteObjCSelector(Scope *S, for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) { if (I == SelIdents.size()) { if (!Accumulator.empty()) { - Builder.AddInformativeChunk(Builder.getAllocator().CopyString( - Accumulator)); + Builder.AddInformativeChunk( + Builder.getAllocator().CopyString(Accumulator)); Accumulator.clear(); } } @@ -6380,7 +6670,7 @@ void Sema::CodeCompleteObjCSelector(Scope *S, Accumulator += Sel.getNameForSlot(I); Accumulator += ':'; } - Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator)); + Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(Accumulator)); Results.AddResult(Builder.TakeString()); } Results.ExitScope(); @@ -6400,13 +6690,14 @@ static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext, // Record any protocols we find. if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D)) if (!OnlyForwardDeclarations || !Proto->hasDefinition()) - Results.AddResult(Result(Proto, Results.getBasePriority(Proto),nullptr), - CurContext, nullptr, false); + Results.AddResult( + Result(Proto, Results.getBasePriority(Proto), nullptr), CurContext, + nullptr, false); } } void Sema::CodeCompleteObjCProtocolReferences( - ArrayRef<IdentifierLocPair> Protocols) { + ArrayRef<IdentifierLocPair> Protocols) { ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_ObjCProtocolName); @@ -6418,8 +6709,7 @@ void Sema::CodeCompleteObjCProtocolReferences( // already seen. // FIXME: This doesn't work when caching code-completion results. for (const IdentifierLocPair &Pair : Protocols) - if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first, - Pair.second)) + if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first, Pair.second)) Results.Ignore(Protocol); // Add all protocols. @@ -6465,8 +6755,9 @@ static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext, if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D)) if ((!OnlyForwardDeclarations || !Class->hasDefinition()) && (!OnlyUnimplemented || !Class->getImplementation())) - Results.AddResult(Result(Class, Results.getBasePriority(Class),nullptr), - CurContext, nullptr, false); + Results.AddResult( + Result(Class, Results.getBasePriority(Class), nullptr), CurContext, + nullptr, false); } } @@ -6496,8 +6787,8 @@ void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName, Results.EnterNewScope(); // Make sure that we ignore the class we're currently defining. - NamedDecl *CurClass - = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); + NamedDecl *CurClass = + LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); if (CurClass && isa<ObjCInterfaceDecl>(CurClass)) Results.Ignore(CurClass); @@ -6543,9 +6834,10 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S, // Ignore any categories we find that have already been implemented by this // interface. llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames; - NamedDecl *CurClass - = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); - if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){ + NamedDecl *CurClass = + LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); + if (ObjCInterfaceDecl *Class = + dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)) { for (const auto *Cat : Class->visible_categories()) CategoryNames.insert(Cat->getIdentifier()); } @@ -6556,9 +6848,9 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S, for (const auto *D : TU->decls()) if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D)) if (CategoryNames.insert(Category->getIdentifier()).second) - Results.AddResult(Result(Category, Results.getBasePriority(Category), - nullptr), - CurContext, nullptr, false); + Results.AddResult( + Result(Category, Results.getBasePriority(Category), nullptr), + CurContext, nullptr, false); Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), @@ -6573,8 +6865,8 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S, // Find the corresponding interface. If we couldn't find the interface, the // program itself is ill-formed. However, we'll try to be helpful still by // providing the list of all of the categories we know about. - NamedDecl *CurClass - = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); + NamedDecl *CurClass = + LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass); if (!Class) return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc); @@ -6609,15 +6901,13 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S, void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) { CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other); ResultBuilder Results(*this, CodeCompleter->getAllocator(), - CodeCompleter->getCodeCompletionTUInfo(), - CCContext); + CodeCompleter->getCodeCompletionTUInfo(), CCContext); // Figure out where this @synthesize lives. - ObjCContainerDecl *Container - = dyn_cast_or_null<ObjCContainerDecl>(CurContext); - if (!Container || - (!isa<ObjCImplementationDecl>(Container) && - !isa<ObjCCategoryImplDecl>(Container))) + ObjCContainerDecl *Container = + dyn_cast_or_null<ObjCContainerDecl>(CurContext); + if (!Container || (!isa<ObjCImplementationDecl>(Container) && + !isa<ObjCCategoryImplDecl>(Container))) return; // Ignore any properties that have already been implemented. @@ -6629,8 +6919,8 @@ void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) { // Add any properties that we find. AddedPropertiesSet AddedProperties; Results.EnterNewScope(); - if (ObjCImplementationDecl *ClassImpl - = dyn_cast<ObjCImplementationDecl>(Container)) + if (ObjCImplementationDecl *ClassImpl = + dyn_cast<ObjCImplementationDecl>(Container)) AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false, /*AllowNullaryMethods=*/false, CurContext, AddedProperties, Results); @@ -6645,37 +6935,37 @@ void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) { Results.data(), Results.size()); } -void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, - IdentifierInfo *PropertyName) { +void Sema::CodeCompleteObjCPropertySynthesizeIvar( + Scope *S, IdentifierInfo *PropertyName) { typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); // Figure out where this @synthesize lives. - ObjCContainerDecl *Container - = dyn_cast_or_null<ObjCContainerDecl>(CurContext); - if (!Container || - (!isa<ObjCImplementationDecl>(Container) && - !isa<ObjCCategoryImplDecl>(Container))) + ObjCContainerDecl *Container = + dyn_cast_or_null<ObjCContainerDecl>(CurContext); + if (!Container || (!isa<ObjCImplementationDecl>(Container) && + !isa<ObjCCategoryImplDecl>(Container))) return; // Figure out which interface we're looking into. ObjCInterfaceDecl *Class = nullptr; - if (ObjCImplementationDecl *ClassImpl - = dyn_cast<ObjCImplementationDecl>(Container)) + if (ObjCImplementationDecl *ClassImpl = + dyn_cast<ObjCImplementationDecl>(Container)) Class = ClassImpl->getClassInterface(); else - Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl() - ->getClassInterface(); + Class = cast<ObjCCategoryImplDecl>(Container) + ->getCategoryDecl() + ->getClassInterface(); // Determine the type of the property we're synthesizing. QualType PropertyType = Context.getObjCIdType(); if (Class) { if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration( PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) { - PropertyType - = Property->getType().getNonReferenceType().getUnqualifiedType(); + PropertyType = + Property->getType().getNonReferenceType().getUnqualifiedType(); // Give preference to ivars Results.setPreferredType(PropertyType); @@ -6690,7 +6980,7 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, NameWithPrefix += PropertyName->getName(); std::string NameWithSuffix = PropertyName->getName().str(); NameWithSuffix += '_'; - for(; Class; Class = Class->getSuperClass()) { + for (; Class; Class = Class->getSuperClass()) { for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar; Ivar = Ivar->getNextIvar()) { Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr), @@ -6706,8 +6996,8 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, // Reduce the priority of this result by one, to give it a slight // advantage over other results whose names don't match so closely. if (Results.size() && - Results.data()[Results.size() - 1].Kind - == CodeCompletionResult::RK_Declaration && + Results.data()[Results.size() - 1].Kind == + CodeCompletionResult::RK_Declaration && Results.data()[Results.size() - 1].Declaration == Ivar) Results.data()[Results.size() - 1].Priority--; } @@ -6721,14 +7011,14 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, typedef CodeCompletionResult Result; CodeCompletionAllocator &Allocator = Results.getAllocator(); CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(), - Priority,CXAvailability_Available); + Priority, CXAvailability_Available); PrintingPolicy Policy = getCompletionPrintingPolicy(*this); - Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context, - Policy, Allocator)); + Builder.AddResultTypeChunk( + GetCompletionTypeString(PropertyType, Context, Policy, Allocator)); Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix)); - Results.AddResult(Result(Builder.TakeString(), Priority, - CXCursor_ObjCIvarDecl)); + Results.AddResult( + Result(Builder.TakeString(), Priority, CXCursor_ObjCIvarDecl)); } Results.ExitScope(); @@ -6739,8 +7029,9 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, // Mapping from selectors to the methods that implement that selector, along // with the "in original class" flag. -typedef llvm::DenseMap< - Selector, llvm::PointerIntPair<ObjCMethodDecl *, 1, bool> > KnownMethodsMap; +typedef llvm::DenseMap<Selector, + llvm::PointerIntPair<ObjCMethodDecl *, 1, bool>> + KnownMethodsMap; /// Find all of the methods that reside in the given container /// (and its superclasses, protocols, etc.) that meet the given @@ -6760,8 +7051,8 @@ static void FindImplementableMethods(ASTContext &Context, IFace = IFace->getDefinition(); Container = IFace; - const ObjCList<ObjCProtocolDecl> &Protocols - = IFace->getReferencedProtocols(); + const ObjCList<ObjCProtocolDecl> &Protocols = + IFace->getReferencedProtocols(); for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) @@ -6777,14 +7068,14 @@ static void FindImplementableMethods(ASTContext &Context, // Visit the superclass. if (IFace->getSuperClass()) FindImplementableMethods(Context, IFace->getSuperClass(), - WantInstanceMethods, ReturnType, - KnownMethods, false); + WantInstanceMethods, ReturnType, KnownMethods, + false); } if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) { // Recurse into protocols. - const ObjCList<ObjCProtocolDecl> &Protocols - = Category->getReferencedProtocols(); + const ObjCList<ObjCProtocolDecl> &Protocols = + Category->getReferencedProtocols(); for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) @@ -6806,10 +7097,10 @@ static void FindImplementableMethods(ASTContext &Context, Container = Protocol; // Recurse into protocols. - const ObjCList<ObjCProtocolDecl> &Protocols - = Protocol->getReferencedProtocols(); + const ObjCList<ObjCProtocolDecl> &Protocols = + Protocol->getReferencedProtocols(); for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), - E = Protocols.end(); + E = Protocols.end(); I != E; ++I) FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, KnownMethods, false); @@ -6832,8 +7123,7 @@ static void FindImplementableMethods(ASTContext &Context, /// Add the parenthesized return or parameter type chunk to a code /// completion string. -static void AddObjCPassingTypeChunk(QualType Type, - unsigned ObjCDeclQuals, +static void AddObjCPassingTypeChunk(QualType Type, unsigned ObjCDeclQuals, ASTContext &Context, const PrintingPolicy &Policy, CodeCompletionBuilder &Builder) { @@ -6841,15 +7131,14 @@ static void AddObjCPassingTypeChunk(QualType Type, std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type); if (!Quals.empty()) Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals)); - Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy, - Builder.getAllocator())); + Builder.AddTextChunk( + GetCompletionTypeString(Type, Context, Policy, Builder.getAllocator())); Builder.AddChunk(CodeCompletionString::CK_RightParen); } /// Determine whether the given class is or inherits from a class by /// the given name. -static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, - StringRef Name) { +static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, StringRef Name) { if (!Class) return false; @@ -6863,8 +7152,7 @@ static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, /// Key-Value Observing (KVO). static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, bool IsInstanceMethod, - QualType ReturnType, - ASTContext &Context, + QualType ReturnType, ASTContext &Context, VisitedSelectorSet &KnownSelectors, ResultBuilder &Results) { IdentifierInfo *PropName = Property->getIdentifier(); @@ -6889,7 +7177,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, const char *CopiedKey; KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key) - : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {} + : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {} operator const char *() { if (CopiedKey) @@ -6904,19 +7192,19 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, if (!UpperKey.empty()) UpperKey[0] = toUppercase(UpperKey[0]); - bool ReturnTypeMatchesProperty = ReturnType.isNull() || - Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(), - Property->getType()); - bool ReturnTypeMatchesVoid - = ReturnType.isNull() || ReturnType->isVoidType(); + bool ReturnTypeMatchesProperty = + ReturnType.isNull() || + Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(), + Property->getType()); + bool ReturnTypeMatchesVoid = ReturnType.isNull() || ReturnType->isVoidType(); // Add the normal accessor -(type)key. if (IsInstanceMethod && KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second && ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) { if (ReturnType.isNull()) - AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, - Context, Policy, Builder); + AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy, + Builder); Builder.AddTypedTextChunk(Key); Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, @@ -6928,9 +7216,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, if (IsInstanceMethod && ((!ReturnType.isNull() && (ReturnType->isIntegerType() || ReturnType->isBooleanType())) || - (ReturnType.isNull() && - (Property->getType()->isIntegerType() || - Property->getType()->isBooleanType())))) { + (ReturnType.isNull() && (Property->getType()->isIntegerType() || + Property->getType()->isBooleanType())))) { std::string SelectorName = (Twine("is") + UpperKey).str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId)) @@ -6941,8 +7228,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddChunk(CodeCompletionString::CK_RightParen); } - Builder.AddTypedTextChunk( - Allocator.CopyString(SelectorId->getName())); + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName())); Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, CXCursor_ObjCInstanceMethodDecl)); } @@ -6960,11 +7246,10 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddChunk(CodeCompletionString::CK_RightParen); } - Builder.AddTypedTextChunk( - Allocator.CopyString(SelectorId->getName())); + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName())); Builder.AddTypedTextChunk(":"); - AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, - Context, Policy, Builder); + AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy, + Builder); Builder.AddTextChunk(Key); Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, CXCursor_ObjCInstanceMethodDecl)); @@ -6976,8 +7261,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, unsigned IndexedSetterPriority = CCP_CodePattern; unsigned UnorderedGetterPriority = CCP_CodePattern; unsigned UnorderedSetterPriority = CCP_CodePattern; - if (const ObjCObjectPointerType *ObjCPointer - = Property->getType()->getAs<ObjCObjectPointerType>()) { + if (const auto *ObjCPointer = + Property->getType()->getAs<ObjCObjectPointerType>()) { if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) { // If this interface type is not provably derived from a known // collection, penalize the corresponding completions. @@ -7013,12 +7298,11 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddChunk(CodeCompletionString::CK_RightParen); } - Builder.AddTypedTextChunk( - Allocator.CopyString(SelectorId->getName())); - Results.AddResult(Result(Builder.TakeString(), - std::min(IndexedGetterPriority, - UnorderedGetterPriority), - CXCursor_ObjCInstanceMethodDecl)); + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName())); + Results.AddResult( + Result(Builder.TakeString(), + std::min(IndexedGetterPriority, UnorderedGetterPriority), + CXCursor_ObjCInstanceMethodDecl)); } } @@ -7026,8 +7310,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, // Add -(id)objectInKeyAtIndex:(NSUInteger)index if (IsInstanceMethod && (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) { - std::string SelectorName - = (Twine("objectIn") + UpperKey + "AtIndex").str(); + std::string SelectorName = (Twine("objectIn") + UpperKey + "AtIndex").str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { if (ReturnType.isNull()) { @@ -7051,10 +7334,10 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, (ReturnType.isNull() || (ReturnType->isObjCObjectPointerType() && ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() && - ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() - ->getName() == "NSArray"))) { - std::string SelectorName - = (Twine(Property->getName()) + "AtIndexes").str(); + ReturnType->getAs<ObjCObjectPointerType>() + ->getInterfaceDecl() + ->getName() == "NSArray"))) { + std::string SelectorName = (Twine(Property->getName()) + "AtIndexes").str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { if (ReturnType.isNull()) { @@ -7076,10 +7359,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, // Add -(void)getKey:(type **)buffer range:(NSRange)inRange if (IsInstanceMethod && ReturnTypeMatchesVoid) { std::string SelectorName = (Twine("get") + UpperKey).str(); - IdentifierInfo *SelectorIds[2] = { - &Context.Idents.get(SelectorName), - &Context.Idents.get("range") - }; + IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName), + &Context.Idents.get("range")}; if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) { if (ReturnType.isNull()) { @@ -7110,10 +7391,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index if (IsInstanceMethod && ReturnTypeMatchesVoid) { std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str(); - IdentifierInfo *SelectorIds[2] = { - &Context.Idents.get("insertObject"), - &Context.Idents.get(SelectorName) - }; + IdentifierInfo *SelectorIds[2] = {&Context.Idents.get("insertObject"), + &Context.Idents.get(SelectorName)}; if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) { if (ReturnType.isNull()) { @@ -7142,10 +7421,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes if (IsInstanceMethod && ReturnTypeMatchesVoid) { std::string SelectorName = (Twine("insert") + UpperKey).str(); - IdentifierInfo *SelectorIds[2] = { - &Context.Idents.get(SelectorName), - &Context.Idents.get("atIndexes") - }; + IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName), + &Context.Idents.get("atIndexes")}; if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) { if (ReturnType.isNull()) { @@ -7172,8 +7449,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index if (IsInstanceMethod && ReturnTypeMatchesVoid) { - std::string SelectorName - = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str(); + std::string SelectorName = + (Twine("removeObjectFrom") + UpperKey + "AtIndex").str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { if (ReturnType.isNull()) { @@ -7194,8 +7471,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes if (IsInstanceMethod && ReturnTypeMatchesVoid) { - std::string SelectorName - = (Twine("remove") + UpperKey + "AtIndexes").str(); + std::string SelectorName = (Twine("remove") + UpperKey + "AtIndexes").str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { if (ReturnType.isNull()) { @@ -7216,12 +7492,10 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object if (IsInstanceMethod && ReturnTypeMatchesVoid) { - std::string SelectorName - = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str(); - IdentifierInfo *SelectorIds[2] = { - &Context.Idents.get(SelectorName), - &Context.Idents.get("withObject") - }; + std::string SelectorName = + (Twine("replaceObjectIn") + UpperKey + "AtIndex").str(); + IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName), + &Context.Idents.get("withObject")}; if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) { if (ReturnType.isNull()) { @@ -7248,13 +7522,11 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array if (IsInstanceMethod && ReturnTypeMatchesVoid) { - std::string SelectorName1 - = (Twine("replace") + UpperKey + "AtIndexes").str(); + std::string SelectorName1 = + (Twine("replace") + UpperKey + "AtIndexes").str(); std::string SelectorName2 = (Twine("with") + UpperKey).str(); - IdentifierInfo *SelectorIds[2] = { - &Context.Idents.get(SelectorName1), - &Context.Idents.get(SelectorName2) - }; + IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName1), + &Context.Idents.get(SelectorName2)}; if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) { if (ReturnType.isNull()) { @@ -7285,8 +7557,9 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, (ReturnType.isNull() || (ReturnType->isObjCObjectPointerType() && ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() && - ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() - ->getName() == "NSEnumerator"))) { + ReturnType->getAs<ObjCObjectPointerType>() + ->getInterfaceDecl() + ->getName() == "NSEnumerator"))) { std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId)) @@ -7299,7 +7572,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName)); Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority, - CXCursor_ObjCInstanceMethodDecl)); + CXCursor_ObjCInstanceMethodDecl)); } } @@ -7322,9 +7595,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddPlaceholderChunk("object-type"); Builder.AddTextChunk(" *"); } else { - Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context, - Policy, - Builder.getAllocator())); + Builder.AddTextChunk(GetCompletionTypeString( + ReturnType, Context, Policy, Builder.getAllocator())); } Builder.AddChunk(CodeCompletionString::CK_RightParen); Builder.AddTextChunk("object"); @@ -7336,8 +7608,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, // Mutable unordered accessors // - (void)addKeyObject:(type *)object if (IsInstanceMethod && ReturnTypeMatchesVoid) { - std::string SelectorName - = (Twine("add") + UpperKey + Twine("Object")).str(); + std::string SelectorName = + (Twine("add") + UpperKey + Twine("Object")).str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { if (ReturnType.isNull()) { @@ -7380,8 +7652,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, // - (void)removeKeyObject:(type *)object if (IsInstanceMethod && ReturnTypeMatchesVoid) { - std::string SelectorName - = (Twine("remove") + UpperKey + Twine("Object")).str(); + std::string SelectorName = + (Twine("remove") + UpperKey + Twine("Object")).str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { if (ReturnType.isNull()) { @@ -7449,10 +7721,11 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, (ReturnType.isNull() || (ReturnType->isObjCObjectPointerType() && ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() && - ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() - ->getName() == "NSSet"))) { - std::string SelectorName - = (Twine("keyPathsForValuesAffecting") + UpperKey).str(); + ReturnType->getAs<ObjCObjectPointerType>() + ->getInterfaceDecl() + ->getName() == "NSSet"))) { + std::string SelectorName = + (Twine("keyPathsForValuesAffecting") + UpperKey).str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId)) .second) { @@ -7464,17 +7737,16 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName)); Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, - CXCursor_ObjCClassMethodDecl)); + CXCursor_ObjCClassMethodDecl)); } } // + (BOOL)automaticallyNotifiesObserversForKey if (!IsInstanceMethod && - (ReturnType.isNull() || - ReturnType->isIntegerType() || + (ReturnType.isNull() || ReturnType->isIntegerType() || ReturnType->isBooleanType())) { - std::string SelectorName - = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str(); + std::string SelectorName = + (Twine("automaticallyNotifiesObserversOf") + UpperKey).str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId)) .second) { @@ -7486,7 +7758,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName)); Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, - CXCursor_ObjCClassMethodDecl)); + CXCursor_ObjCClassMethodDecl)); } } } @@ -7498,8 +7770,8 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod, QualType ReturnType = GetTypeFromParser(ReturnTy); Decl *IDecl = nullptr; if (CurContext->isObjCContainer()) { - ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext); - IDecl = OCD; + ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext); + IDecl = OCD; } // Determine where we should start searching for methods. ObjCContainerDecl *SearchDecl = nullptr; @@ -7508,8 +7780,8 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod, if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) { SearchDecl = Impl->getClassInterface(); IsInImplementation = true; - } else if (ObjCCategoryImplDecl *CatImpl - = dyn_cast<ObjCCategoryImplDecl>(D)) { + } else if (ObjCCategoryImplDecl *CatImpl = + dyn_cast<ObjCCategoryImplDecl>(D)) { SearchDecl = CatImpl->getCategoryDecl(); IsInImplementation = true; } else @@ -7523,15 +7795,14 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod, if (!SearchDecl) { HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_Other, - nullptr, 0); + CodeCompletionContext::CCC_Other, nullptr, 0); return; } // Find all of the methods that we could declare/implement here. KnownMethodsMap KnownMethods; - FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, - ReturnType, KnownMethods); + FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, ReturnType, + KnownMethods); // Add declarations or definitions for each of the known methods. typedef CodeCompletionResult Result; @@ -7541,7 +7812,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod, Results.EnterNewScope(); PrintingPolicy Policy = getCompletionPrintingPolicy(*this); for (KnownMethodsMap::iterator M = KnownMethods.begin(), - MEnd = KnownMethods.end(); + MEnd = KnownMethods.end(); M != MEnd; ++M) { ObjCMethodDecl *Method = M->second.getPointer(); CodeCompletionBuilder Builder(Results.getAllocator(), @@ -7558,21 +7829,20 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod, if (ReturnType.isNull()) { QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context); AttributedType::stripOuterNullability(ResTy); - AddObjCPassingTypeChunk(ResTy, - Method->getObjCDeclQualifier(), Context, Policy, - Builder); + AddObjCPassingTypeChunk(ResTy, Method->getObjCDeclQualifier(), Context, + Policy, Builder); } Selector Sel = Method->getSelector(); // Add the first part of the selector to the pattern. - Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( - Sel.getNameForSlot(0))); + Builder.AddTypedTextChunk( + Builder.getAllocator().CopyString(Sel.getNameForSlot(0))); // Add parameters to the pattern. unsigned I = 0; for (ObjCMethodDecl::param_iterator P = Method->param_begin(), - PEnd = Method->param_end(); + PEnd = Method->param_end(); P != PEnd; (void)++P, ++I) { // Add the part of the selector name. if (I == 0) @@ -7580,7 +7850,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod, else if (I < Sel.getNumArgs()) { Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddTypedTextChunk( - Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":")); + Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":")); } else break; @@ -7590,16 +7860,14 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod, ParamType = (*P)->getType(); else ParamType = (*P)->getOriginalType(); - ParamType = ParamType.substObjCTypeArgs(Context, {}, - ObjCSubstitutionContext::Parameter); + ParamType = ParamType.substObjCTypeArgs( + Context, {}, ObjCSubstitutionContext::Parameter); AttributedType::stripOuterNullability(ParamType); - AddObjCPassingTypeChunk(ParamType, - (*P)->getObjCDeclQualifier(), - Context, Policy, - Builder); + AddObjCPassingTypeChunk(ParamType, (*P)->getObjCDeclQualifier(), Context, + Policy, Builder); if (IdentifierInfo *Id = (*P)->getIdentifier()) - Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName())); + Builder.AddTextChunk(Builder.getAllocator().CopyString(Id->getName())); } if (Method->isVariadic()) { @@ -7627,25 +7895,24 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod, } unsigned Priority = CCP_CodePattern; + auto R = Result(Builder.TakeString(), Method, Priority); if (!M->second.getInt()) - Priority += CCD_InBaseClass; - - Results.AddResult(Result(Builder.TakeString(), Method, Priority)); + setInBaseClass(R); + Results.AddResult(std::move(R)); } // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of // the properties in this class and its categories. - if (Context.getLangOpts().ObjC2) { + if (Context.getLangOpts().ObjC) { SmallVector<ObjCContainerDecl *, 4> Containers; Containers.push_back(SearchDecl); VisitedSelectorSet KnownSelectors; for (KnownMethodsMap::iterator M = KnownMethods.begin(), - MEnd = KnownMethods.end(); + MEnd = KnownMethods.end(); M != MEnd; ++M) KnownSelectors.insert(M->first); - ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl); if (!IFace) if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl)) @@ -7669,16 +7936,14 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod, Results.data(), Results.size()); } -void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, - bool IsInstanceMethod, - bool AtParameterName, - ParsedType ReturnTy, - ArrayRef<IdentifierInfo *> SelIdents) { +void Sema::CodeCompleteObjCMethodDeclSelector( + Scope *S, bool IsInstanceMethod, bool AtParameterName, ParsedType ReturnTy, + ArrayRef<IdentifierInfo *> SelIdents) { // If we have an external source, load the entire class method // pool from the AST file. if (ExternalSource) { - for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); - I != N; ++I) { + for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N; + ++I) { Selector Sel = ExternalSource->GetExternalSelector(I); if (Sel.isNull() || MethodPool.count(Sel)) continue; @@ -7700,10 +7965,9 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, for (GlobalMethodPool::iterator M = MethodPool.begin(), MEnd = MethodPool.end(); M != MEnd; ++M) { - for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first : - &M->second.second; - MethList && MethList->getMethod(); - MethList = MethList->getNext()) { + for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first + : &M->second.second; + MethList && MethList->getMethod(); MethList = MethList->getNext()) { if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents)) continue; @@ -7718,7 +7982,7 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo()); Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( - Param->getIdentifier()->getName())); + Param->getIdentifier()->getName())); Results.AddResult(Builder.TakeString()); } } @@ -7864,7 +8128,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) { Builder.AddPlaceholderChunk("arguments"); Results.AddResult(Builder.TakeString()); - if (getLangOpts().ObjC1) { + if (getLangOpts().ObjC) { // #import "header" Builder.AddTypedTextChunk("import"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -7916,29 +8180,27 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) { } void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) { - CodeCompleteOrdinaryName(S, - S->getFnParent()? Sema::PCC_RecoveryInFunction - : Sema::PCC_Namespace); + CodeCompleteOrdinaryName(S, S->getFnParent() ? Sema::PCC_RecoveryInFunction + : Sema::PCC_Namespace); } void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) { ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), - IsDefinition? CodeCompletionContext::CCC_MacroName - : CodeCompletionContext::CCC_MacroNameUse); + IsDefinition ? CodeCompletionContext::CCC_MacroName + : CodeCompletionContext::CCC_MacroNameUse); if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) { // Add just the names of macros, not their arguments. CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo()); Results.EnterNewScope(); for (Preprocessor::macro_iterator M = PP.macro_begin(), - MEnd = PP.macro_end(); + MEnd = PP.macro_end(); M != MEnd; ++M) { - Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( - M->first->getName())); - Results.AddResult(CodeCompletionResult(Builder.TakeString(), - CCP_CodePattern, - CXCursor_MacroDefinition)); + Builder.AddTypedTextChunk( + Builder.getAllocator().CopyString(M->first->getName())); + Results.AddResult(CodeCompletionResult( + Builder.TakeString(), CCP_CodePattern, CXCursor_MacroDefinition)); } Results.ExitScope(); } else if (IsDefinition) { @@ -7955,9 +8217,11 @@ void Sema::CodeCompletePreprocessorExpression() { CodeCompletionContext::CCC_PreprocessorExpression); if (!CodeCompleter || CodeCompleter->includeMacros()) - AddMacroResults(PP, Results, true); + AddMacroResults(PP, Results, + CodeCompleter ? CodeCompleter->loadExternal() : false, + true); - // defined (<macro>) + // defined (<macro>) Results.EnterNewScope(); CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo()); @@ -7984,10 +8248,118 @@ void Sema::CodeCompletePreprocessorMacroArgument(Scope *S, // for the expanded tokens. } +// This handles completion inside an #include filename, e.g. #include <foo/ba +// We look for the directory "foo" under each directory on the include path, +// list its files, and reassemble the appropriate #include. +void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) { + // RelDir should use /, but unescaped \ is possible on windows! + // Our completions will normalize to / for simplicity, this case is rare. + std::string RelDir = llvm::sys::path::convert_to_slash(Dir); + // We need the native slashes for the actual file system interactions. + SmallString<128> NativeRelDir = StringRef(RelDir); + llvm::sys::path::native(NativeRelDir); + auto FS = getSourceManager().getFileManager().getVirtualFileSystem(); + + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_IncludedFile); + llvm::DenseSet<StringRef> SeenResults; // To deduplicate results. + + // Helper: adds one file or directory completion result. + auto AddCompletion = [&](StringRef Filename, bool IsDirectory) { + SmallString<64> TypedChunk = Filename; + // Directory completion is up to the slash, e.g. <sys/ + TypedChunk.push_back(IsDirectory ? '/' : Angled ? '>' : '"'); + auto R = SeenResults.insert(TypedChunk); + if (R.second) { // New completion + const char *InternedTyped = Results.getAllocator().CopyString(TypedChunk); + *R.first = InternedTyped; // Avoid dangling StringRef. + CodeCompletionBuilder Builder(CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo()); + Builder.AddTypedTextChunk(InternedTyped); + // The result is a "Pattern", which is pretty opaque. + // We may want to include the real filename to allow smart ranking. + Results.AddResult(CodeCompletionResult(Builder.TakeString())); + } + }; + + // Helper: scans IncludeDir for nice files, and adds results for each. + auto AddFilesFromIncludeDir = [&](StringRef IncludeDir, bool IsSystem) { + llvm::SmallString<128> Dir = IncludeDir; + if (!NativeRelDir.empty()) + llvm::sys::path::append(Dir, NativeRelDir); + + std::error_code EC; + unsigned Count = 0; + for (auto It = FS->dir_begin(Dir, EC); + !EC && It != llvm::vfs::directory_iterator(); It.increment(EC)) { + if (++Count == 2500) // If we happen to hit a huge directory, + break; // bail out early so we're not too slow. + StringRef Filename = llvm::sys::path::filename(It->path()); + switch (It->type()) { + case llvm::sys::fs::file_type::directory_file: + AddCompletion(Filename, /*IsDirectory=*/true); + break; + case llvm::sys::fs::file_type::regular_file: + // Only files that really look like headers. (Except in system dirs). + if (!IsSystem) { + // Header extensions from Types.def, which we can't depend on here. + if (!(Filename.endswith_lower(".h") || + Filename.endswith_lower(".hh") || + Filename.endswith_lower(".hpp") || + Filename.endswith_lower(".inc"))) + break; + } + AddCompletion(Filename, /*IsDirectory=*/false); + break; + default: + break; + } + } + }; + + // Helper: adds results relative to IncludeDir, if possible. + auto AddFilesFromDirLookup = [&](const DirectoryLookup &IncludeDir, + bool IsSystem) { + switch (IncludeDir.getLookupType()) { + case DirectoryLookup::LT_HeaderMap: + // header maps are not (currently) enumerable. + break; + case DirectoryLookup::LT_NormalDir: + AddFilesFromIncludeDir(IncludeDir.getDir()->getName(), IsSystem); + break; + case DirectoryLookup::LT_Framework: + AddFilesFromIncludeDir(IncludeDir.getFrameworkDir()->getName(), IsSystem); + break; + } + }; + + // Finally with all our helpers, we can scan the include path. + // Do this in standard order so deduplication keeps the right file. + // (In case we decide to add more details to the results later). + const auto &S = PP.getHeaderSearchInfo(); + using llvm::make_range; + if (!Angled) { + // The current directory is on the include path for "quoted" includes. + auto *CurFile = PP.getCurrentFileLexer()->getFileEntry(); + if (CurFile && CurFile->getDir()) + AddFilesFromIncludeDir(CurFile->getDir()->getName(), false); + for (const auto &D : make_range(S.quoted_dir_begin(), S.quoted_dir_end())) + AddFilesFromDirLookup(D, false); + } + for (const auto &D : make_range(S.angled_dir_begin(), S.angled_dir_end())) + AddFilesFromDirLookup(D, false); + for (const auto &D : make_range(S.system_dir_begin(), S.system_dir_end())) + AddFilesFromDirLookup(D, true); + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); +} + void Sema::CodeCompleteNaturalLanguage() { HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_NaturalLanguage, - nullptr, 0); + CodeCompletionContext::CCC_NaturalLanguage, nullptr, + 0); } void Sema::CodeCompleteAvailabilityPlatformName() { @@ -8006,9 +8378,9 @@ void Sema::CodeCompleteAvailabilityPlatformName() { Results.data(), Results.size()); } -void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator, - CodeCompletionTUInfo &CCTUInfo, - SmallVectorImpl<CodeCompletionResult> &Results) { +void Sema::GatherGlobalCodeCompletions( + CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo, + SmallVectorImpl<CodeCompletionResult> &Results) { ResultBuilder Builder(*this, Allocator, CCTUInfo, CodeCompletionContext::CCC_Recovery); if (!CodeCompleter || CodeCompleter->includeGlobals()) { @@ -8020,9 +8392,11 @@ void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator, } if (!CodeCompleter || CodeCompleter->includeMacros()) - AddMacroResults(PP, Builder, true); + AddMacroResults(PP, Builder, + CodeCompleter ? CodeCompleter->loadExternal() : false, + true); Results.clear(); - Results.insert(Results.end(), - Builder.data(), Builder.data() + Builder.size()); + Results.insert(Results.end(), Builder.data(), + Builder.data() + Builder.size()); } diff --git a/lib/Sema/SemaCoroutine.cpp b/lib/Sema/SemaCoroutine.cpp index 1d5454ca778bc..181efa6d3dd09 100644 --- a/lib/Sema/SemaCoroutine.cpp +++ b/lib/Sema/SemaCoroutine.cpp @@ -84,8 +84,7 @@ static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD, // ref-qualifier or with the & ref-qualifier // -- "rvalue reference to cv X" for functions declared with the && // ref-qualifier - QualType T = - MD->getThisType(S.Context)->getAs<PointerType>()->getPointeeType(); + QualType T = MD->getThisType()->getAs<PointerType>()->getPointeeType(); T = FnType->getRefQualifier() == RQ_RValue ? S.Context.getRValueReferenceType(T) : S.Context.getLValueReferenceType(T, /*SpelledAsLValue*/ true); @@ -453,7 +452,7 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise, // to bool. ExprResult Conv = S.PerformContextuallyConvertToBool(AwaitReady); if (Conv.isInvalid()) { - S.Diag(AwaitReady->getDirectCallee()->getLocStart(), + S.Diag(AwaitReady->getDirectCallee()->getBeginLoc(), diag::note_await_ready_no_bool_conversion); S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required) << AwaitReady->getDirectCallee() << E->getSourceRange(); @@ -506,7 +505,7 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) { auto *FD = cast<FunctionDecl>(CurContext); bool IsThisDependentType = [&] { if (auto *MD = dyn_cast_or_null<CXXMethodDecl>(FD)) - return MD->isInstance() && MD->getThisType(Context)->isDependentType(); + return MD->isInstance() && MD->getThisType()->isDependentType(); else return false; }(); @@ -565,8 +564,8 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) { // Create an initialization sequence for the promise type using the // constructor arguments, wrapped in a parenthesized list expression. - Expr *PLE = new (Context) ParenListExpr(Context, FD->getLocation(), - CtorArgExprs, FD->getLocation()); + Expr *PLE = ParenListExpr::Create(Context, FD->getLocation(), + CtorArgExprs, FD->getLocation()); InitializedEntity Entity = InitializedEntity::InitializeVariable(VD); InitializationKind Kind = InitializationKind::CreateForInit( VD->getLocation(), /*DirectInit=*/true, PLE); @@ -647,7 +646,7 @@ bool Sema::ActOnCoroutineBodyStart(Scope *SC, SourceLocation KWLoc, return StmtError(); Suspend = BuildResolvedCoawaitExpr(Loc, Suspend.get(), /*IsImplicit*/ true); - Suspend = ActOnFinishFullExpr(Suspend.get()); + Suspend = ActOnFinishFullExpr(Suspend.get(), /*DiscardedValue*/ false); if (Suspend.isInvalid()) { Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required) << ((Name == "initial_suspend") ? 0 : 1); @@ -841,6 +840,19 @@ StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E, E = R.get(); } + // Move the return value if we can + if (E) { + auto NRVOCandidate = this->getCopyElisionCandidate(E->getType(), E, CES_AsIfByStdMove); + if (NRVOCandidate) { + InitializedEntity Entity = + InitializedEntity::InitializeResult(Loc, E->getType(), NRVOCandidate); + ExprResult MoveResult = this->PerformMoveOrCopyInitialization( + Entity, NRVOCandidate, E->getType(), E); + if (MoveResult.get()) + E = MoveResult.get(); + } + } + // FIXME: If the operand is a reference to a variable that's about to go out // of scope, we should treat the operand as an xvalue for this overload // resolution. @@ -855,7 +867,7 @@ StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E, if (PC.isInvalid()) return StmtError(); - Expr *PCE = ActOnFinishFullExpr(PC.get()).get(); + Expr *PCE = ActOnFinishFullExpr(PC.get(), /*DiscardedValue*/ false).get(); Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE, IsImplicit); return Res; @@ -1224,7 +1236,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() { ExprResult NewExpr = S.ActOnCallExpr(S.getCurScope(), NewRef.get(), Loc, NewArgs, Loc); - NewExpr = S.ActOnFinishFullExpr(NewExpr.get()); + NewExpr = S.ActOnFinishFullExpr(NewExpr.get(), /*DiscardedValue*/ false); if (NewExpr.isInvalid()) return false; @@ -1250,7 +1262,8 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() { ExprResult DeleteExpr = S.ActOnCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc); - DeleteExpr = S.ActOnFinishFullExpr(DeleteExpr.get()); + DeleteExpr = + S.ActOnFinishFullExpr(DeleteExpr.get(), /*DiscardedValue*/ false); if (DeleteExpr.isInvalid()) return false; @@ -1335,7 +1348,8 @@ bool CoroutineStmtBuilder::makeOnException() { ExprResult UnhandledException = buildPromiseCall(S, Fn.CoroutinePromise, Loc, "unhandled_exception", None); - UnhandledException = S.ActOnFinishFullExpr(UnhandledException.get(), Loc); + UnhandledException = S.ActOnFinishFullExpr(UnhandledException.get(), Loc, + /*DiscardedValue*/ false); if (UnhandledException.isInvalid()) return false; @@ -1388,7 +1402,8 @@ bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() { "get_return_object type must no longer be dependent"); if (FnRetType->isVoidType()) { - ExprResult Res = S.ActOnFinishFullExpr(this->ReturnValue, Loc); + ExprResult Res = + S.ActOnFinishFullExpr(this->ReturnValue, Loc, /*DiscardedValue*/ false); if (Res.isInvalid()) return false; @@ -1420,7 +1435,7 @@ bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() { if (Res.isInvalid()) return false; - Res = S.ActOnFinishFullExpr(Res.get()); + Res = S.ActOnFinishFullExpr(Res.get(), /*DiscardedValue*/ false); if (Res.isInvalid()) return false; @@ -1460,7 +1475,7 @@ static Expr *castForMoving(Sema &S, Expr *E, QualType T = QualType()) { T = E->getType(); QualType TargetType = S.BuildReferenceType( T, /*SpelledAsLValue*/ false, SourceLocation(), DeclarationName()); - SourceLocation ExprLoc = E->getLocStart(); + SourceLocation ExprLoc = E->getBeginLoc(); TypeSourceInfo *TargetLoc = S.Context.getTrivialTypeSourceInfo(TargetType, ExprLoc); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index b92d76ad42049..23c99d45a78d4 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1735,12 +1735,13 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { static void GenerateFixForUnusedDecl(const NamedDecl *D, ASTContext &Ctx, FixItHint &Hint) { if (isa<LabelDecl>(D)) { - SourceLocation AfterColon = Lexer::findLocationAfterToken(D->getLocEnd(), - tok::colon, Ctx.getSourceManager(), Ctx.getLangOpts(), true); + SourceLocation AfterColon = Lexer::findLocationAfterToken( + D->getEndLoc(), tok::colon, Ctx.getSourceManager(), Ctx.getLangOpts(), + true); if (AfterColon.isInvalid()) return; - Hint = FixItHint::CreateRemoval(CharSourceRange:: - getCharRange(D->getLocStart(), AfterColon)); + Hint = FixItHint::CreateRemoval( + CharSourceRange::getCharRange(D->getBeginLoc(), AfterColon)); } } @@ -2110,7 +2111,7 @@ void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New, // Allow multiple definitions for ObjC built-in typedefs. // FIXME: Verify the underlying types are equivalent! - if (getLangOpts().ObjC1) { + if (getLangOpts().ObjC) { const IdentifierInfo *TypeID = New->getIdentifier(); switch (TypeID->getLength()) { default: break; @@ -2474,14 +2475,9 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, else if (const auto *OA = dyn_cast<OptimizeNoneAttr>(Attr)) NewAttr = S.mergeOptimizeNoneAttr(D, OA->getRange(), AttrSpellingListIndex); else if (const auto *InternalLinkageA = dyn_cast<InternalLinkageAttr>(Attr)) - NewAttr = S.mergeInternalLinkageAttr( - D, InternalLinkageA->getRange(), - &S.Context.Idents.get(InternalLinkageA->getSpelling()), - AttrSpellingListIndex); + NewAttr = S.mergeInternalLinkageAttr(D, *InternalLinkageA); else if (const auto *CommonA = dyn_cast<CommonAttr>(Attr)) - NewAttr = S.mergeCommonAttr(D, CommonA->getRange(), - &S.Context.Idents.get(CommonA->getSpelling()), - AttrSpellingListIndex); + NewAttr = S.mergeCommonAttr(D, *CommonA); else if (isa<AlignedAttr>(Attr)) // AlignedAttrs are handled separately, because we need to handle all // such attributes on a declaration at the same time. @@ -3249,20 +3245,15 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, // Redeclarations or specializations of a function or function template // with a declared return type that uses a placeholder type shall also // use that placeholder, not a deduced type. - QualType OldDeclaredReturnType = - (Old->getTypeSourceInfo() - ? Old->getTypeSourceInfo()->getType()->castAs<FunctionType>() - : OldType)->getReturnType(); - QualType NewDeclaredReturnType = - (New->getTypeSourceInfo() - ? New->getTypeSourceInfo()->getType()->castAs<FunctionType>() - : NewType)->getReturnType(); + QualType OldDeclaredReturnType = Old->getDeclaredReturnType(); + QualType NewDeclaredReturnType = New->getDeclaredReturnType(); if (!Context.hasSameType(OldDeclaredReturnType, NewDeclaredReturnType) && - !((NewQType->isDependentType() || OldQType->isDependentType()) && - New->isLocalExternDecl())) { + canFullyTypeCheckRedeclaration(New, Old, NewDeclaredReturnType, + OldDeclaredReturnType)) { QualType ResQT; if (NewDeclaredReturnType->isObjCObjectPointerType() && OldDeclaredReturnType->isObjCObjectPointerType()) + // FIXME: This does the wrong thing for a deduced return type. ResQT = Context.mergeObjCGCQualifiers(NewQType, OldQType); if (ResQT.isNull()) { if (New->isCXXClassMember() && New->isOutOfLine()) @@ -3427,13 +3418,11 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, if (OldQTypeForComparison == NewQType) return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld); - if ((NewQType->isDependentType() || OldQType->isDependentType()) && - New->isLocalExternDecl()) { - // It's OK if we couldn't merge types for a local function declaraton - // if either the old or new type is dependent. We'll merge the types - // when we instantiate the function. + // If the types are imprecise (due to dependent constructs in friends or + // local extern declarations), it's OK if they differ. We'll check again + // during instantiation. + if (!canFullyTypeCheckRedeclaration(New, Old, NewQType, OldQType)) return false; - } // Fall through for conflicting redeclarations and redefinitions. } @@ -4356,8 +4345,8 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, Record = UT->getDecl(); if (Record && getLangOpts().MicrosoftExt) { - Diag(DS.getLocStart(), diag::ext_ms_anonymous_record) - << Record->isUnion() << DS.getSourceRange(); + Diag(DS.getBeginLoc(), diag::ext_ms_anonymous_record) + << Record->isUnion() << DS.getSourceRange(); return BuildMicrosoftCAnonymousStruct(S, DS, Record); } @@ -4380,8 +4369,8 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, if (!DS.isMissingDeclaratorOk()) { // Customize diagnostic for a typedef missing a name. if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) - Diag(DS.getLocStart(), diag::ext_typedef_without_a_name) - << DS.getSourceRange(); + Diag(DS.getBeginLoc(), diag::ext_typedef_without_a_name) + << DS.getSourceRange(); else DeclaresAnything = false; } @@ -4405,7 +4394,7 @@ 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.getLocStart(), diag::ext_no_declarators) << DS.getSourceRange(); + Diag(DS.getBeginLoc(), diag::ext_no_declarators) << DS.getSourceRange(); return TagD; } @@ -4815,14 +4804,11 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, // Create a declaration for this anonymous struct/union. NamedDecl *Anon = nullptr; if (RecordDecl *OwningClass = dyn_cast<RecordDecl>(Owner)) { - Anon = FieldDecl::Create(Context, OwningClass, - DS.getLocStart(), - Record->getLocation(), - /*IdentifierInfo=*/nullptr, - Context.getTypeDeclType(Record), - TInfo, - /*BitWidth=*/nullptr, /*Mutable=*/false, - /*InitStyle=*/ICIS_NoInit); + Anon = FieldDecl::Create( + Context, OwningClass, DS.getBeginLoc(), Record->getLocation(), + /*IdentifierInfo=*/nullptr, Context.getTypeDeclType(Record), TInfo, + /*BitWidth=*/nullptr, /*Mutable=*/false, + /*InitStyle=*/ICIS_NoInit); Anon->setAccess(AS); if (getLangOpts().CPlusPlus) FieldCollector->Add(cast<FieldDecl>(Anon)); @@ -4837,11 +4823,9 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, SC = SC_None; } - Anon = VarDecl::Create(Context, Owner, - DS.getLocStart(), + Anon = VarDecl::Create(Context, Owner, DS.getBeginLoc(), Record->getLocation(), /*IdentifierInfo=*/nullptr, - Context.getTypeDeclType(Record), - TInfo, SC); + Context.getTypeDeclType(Record), TInfo, SC); // Default-initialize the implicit variable. This initialization will be // trivial in almost all cases, except if a union member has an in-class @@ -4913,15 +4897,11 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS, QualType RecTy = Context.getTypeDeclType(Record); // Create a declaration for this anonymous struct. - NamedDecl *Anon = FieldDecl::Create(Context, - ParentDecl, - DS.getLocStart(), - DS.getLocStart(), - /*IdentifierInfo=*/nullptr, - RecTy, - TInfo, - /*BitWidth=*/nullptr, /*Mutable=*/false, - /*InitStyle=*/ICIS_NoInit); + NamedDecl *Anon = + FieldDecl::Create(Context, ParentDecl, DS.getBeginLoc(), DS.getBeginLoc(), + /*IdentifierInfo=*/nullptr, RecTy, TInfo, + /*BitWidth=*/nullptr, /*Mutable=*/false, + /*InitStyle=*/ICIS_NoInit); Anon->setImplicit(); // Add the anonymous struct object to the current context. @@ -4962,7 +4942,6 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { case UnqualifiedIdKind::IK_ImplicitSelfParam: case UnqualifiedIdKind::IK_Identifier: NameInfo.setName(Name.Identifier); - NameInfo.setLoc(Name.StartLocation); return NameInfo; case UnqualifiedIdKind::IK_DeductionGuideName: { @@ -4989,14 +4968,12 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { NameInfo.setName( Context.DeclarationNames.getCXXDeductionGuideName(Template)); - NameInfo.setLoc(Name.StartLocation); return NameInfo; } case UnqualifiedIdKind::IK_OperatorFunctionId: NameInfo.setName(Context.DeclarationNames.getCXXOperatorName( Name.OperatorFunctionId.Operator)); - NameInfo.setLoc(Name.StartLocation); NameInfo.getInfo().CXXOperatorName.BeginOpNameLoc = Name.OperatorFunctionId.SymbolLocations[0]; NameInfo.getInfo().CXXOperatorName.EndOpNameLoc @@ -5006,7 +4983,6 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { case UnqualifiedIdKind::IK_LiteralOperatorId: NameInfo.setName(Context.DeclarationNames.getCXXLiteralOperatorName( Name.Identifier)); - NameInfo.setLoc(Name.StartLocation); NameInfo.setCXXLiteralOperatorNameLoc(Name.EndLocation); return NameInfo; @@ -5017,7 +4993,6 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { return DeclarationNameInfo(); NameInfo.setName(Context.DeclarationNames.getCXXConversionFunctionName( Context.getCanonicalType(Ty))); - NameInfo.setLoc(Name.StartLocation); NameInfo.setNamedTypeInfo(TInfo); return NameInfo; } @@ -5029,7 +5004,6 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { return DeclarationNameInfo(); NameInfo.setName(Context.DeclarationNames.getCXXConstructorName( Context.getCanonicalType(Ty))); - NameInfo.setLoc(Name.StartLocation); NameInfo.setNamedTypeInfo(TInfo); return NameInfo; } @@ -5051,7 +5025,6 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { NameInfo.setName(Context.DeclarationNames.getCXXConstructorName( Context.getCanonicalType(CurClassType))); - NameInfo.setLoc(Name.StartLocation); // FIXME: should we retrieve TypeSourceInfo? NameInfo.setNamedTypeInfo(nullptr); return NameInfo; @@ -5064,7 +5037,6 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { return DeclarationNameInfo(); NameInfo.setName(Context.DeclarationNames.getCXXDestructorName( Context.getCanonicalType(Ty))); - NameInfo.setLoc(Name.StartLocation); NameInfo.setNamedTypeInfo(TInfo); return NameInfo; } @@ -5349,9 +5321,8 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, return ActOnDecompositionDeclarator(S, D, TemplateParamLists); } else if (!Name) { if (!D.isInvalidType()) // Reject this if we think it is valid. - Diag(D.getDeclSpec().getLocStart(), - diag::err_declarator_need_ident) - << D.getDeclSpec().getSourceRange() << D.getSourceRange(); + Diag(D.getDeclSpec().getBeginLoc(), diag::err_declarator_need_ident) + << D.getDeclSpec().getSourceRange() << D.getSourceRange(); return nullptr; } else if (DiagnoseUnexpandedParameterPack(NameInfo, UPPC_DeclarationType)) return nullptr; @@ -5542,15 +5513,8 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, // If this has an identifier and is not a function template specialization, // add it to the scope stack. - if (New->getDeclName() && AddToScope) { - // Only make a locally-scoped extern declaration visible if it is the first - // declaration of this entity. Qualified lookup for such an entity should - // only find this declaration if there is no visible declaration of it. - bool AddToContext = !D.isRedeclaration() || !New->isLocalExternDecl(); - PushOnScopeChains(New, S, AddToContext); - if (!AddToContext) - CurContext->addHiddenDecl(New); - } + if (New->getDeclName() && AddToScope) + PushOnScopeChains(New, S); if (isInOpenMPDeclareTargetContext()) checkDeclIsAllowedInOpenMPTarget(nullptr, New); @@ -5604,11 +5568,13 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T, if (VLATy->getElementType()->isVariablyModifiedType()) return QualType(); - llvm::APSInt Res; + Expr::EvalResult Result; if (!VLATy->getSizeExpr() || - !VLATy->getSizeExpr()->EvaluateAsInt(Res, Context)) + !VLATy->getSizeExpr()->EvaluateAsInt(Result, Context)) return QualType(); + llvm::APSInt Res = Result.Val.getInt(); + // Check whether the array size is negative. if (Res.isSigned() && Res.isNegative()) { SizeIsNegative = true; @@ -5897,10 +5863,10 @@ isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC, return true; } -static void SetNestedNameSpecifier(DeclaratorDecl *DD, Declarator &D) { +static void SetNestedNameSpecifier(Sema &S, DeclaratorDecl *DD, Declarator &D) { CXXScopeSpec &SS = D.getCXXScopeSpec(); if (!SS.isSet()) return; - DD->setQualifierInfo(SS.getWithLocInContext(DD->getASTContext())); + DD->setQualifierInfo(SS.getWithLocInContext(S.Context)); } bool Sema::inferObjCARCLifetime(ValueDecl *decl) { @@ -6021,14 +5987,14 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) { // The [[lifetimebound]] attribute can be applied to the implicit object // parameter of a non-static member function (other than a ctor or dtor) // by applying it to the function type. - if (ATL.getAttrKind() == AttributedType::attr_lifetimebound) { + if (const auto *A = ATL.getAttrAs<LifetimeBoundAttr>()) { const auto *MD = dyn_cast<CXXMethodDecl>(FD); if (!MD || MD->isStatic()) { - S.Diag(ATL.getAttrNameLoc(), diag::err_lifetimebound_no_object_param) - << !MD << ATL.getLocalSourceRange(); + S.Diag(A->getLocation(), diag::err_lifetimebound_no_object_param) + << !MD << A->getRange(); } else if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) { - S.Diag(ATL.getAttrNameLoc(), diag::err_lifetimebound_ctor_dtor) - << isa<CXXDestructorDecl>(MD) << ATL.getLocalSourceRange(); + S.Diag(A->getLocation(), diag::err_lifetimebound_ctor_dtor) + << isa<CXXDestructorDecl>(MD) << A->getRange(); } } } @@ -6383,7 +6349,7 @@ NamedDecl *Sema::ActOnVariableDeclarator( // address space qualifiers. if (R->isEventT()) { if (R.getAddressSpace() != LangAS::opencl_private) { - Diag(D.getLocStart(), diag::err_event_t_addr_space_qual); + Diag(D.getBeginLoc(), diag::err_event_t_addr_space_qual); D.setInvalidType(); } } @@ -6457,9 +6423,8 @@ NamedDecl *Sema::ActOnVariableDeclarator( VarTemplateDecl *NewTemplate = nullptr; TemplateParameterList *TemplateParams = nullptr; if (!getLangOpts().CPlusPlus) { - NewVD = VarDecl::Create(Context, DC, D.getLocStart(), - D.getIdentifierLoc(), II, - R, TInfo, SC); + NewVD = VarDecl::Create(Context, DC, D.getBeginLoc(), D.getIdentifierLoc(), + II, R, TInfo, SC); if (R->getContainedDeducedType()) ParsingInitForAutoVars.insert(NewVD); @@ -6521,7 +6486,7 @@ NamedDecl *Sema::ActOnVariableDeclarator( // Match up the template parameter lists with the scope specifier, then // determine whether we have a template or a template specialization. TemplateParams = MatchTemplateParametersToScopeSpecifier( - D.getDeclSpec().getLocStart(), D.getIdentifierLoc(), + D.getDeclSpec().getBeginLoc(), D.getIdentifierLoc(), D.getCXXScopeSpec(), D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId ? D.getName().TemplateId @@ -6580,11 +6545,11 @@ NamedDecl *Sema::ActOnVariableDeclarator( NewVD = cast<VarDecl>(Res.get()); AddToScope = false; } else if (D.isDecompositionDeclarator()) { - NewVD = DecompositionDecl::Create(Context, DC, D.getLocStart(), + NewVD = DecompositionDecl::Create(Context, DC, D.getBeginLoc(), D.getIdentifierLoc(), R, TInfo, SC, Bindings); } else - NewVD = VarDecl::Create(Context, DC, D.getLocStart(), + NewVD = VarDecl::Create(Context, DC, D.getBeginLoc(), D.getIdentifierLoc(), II, R, TInfo, SC); // If this is supposed to be a variable template, create it as such. @@ -6606,7 +6571,7 @@ NamedDecl *Sema::ActOnVariableDeclarator( NewTemplate->setInvalidDecl(); } - SetNestedNameSpecifier(NewVD, D); + SetNestedNameSpecifier(*this, NewVD, D); // If we have any template parameter lists that don't directly belong to // the variable (matching the scope specifier), store them. @@ -6801,7 +6766,7 @@ NamedDecl *Sema::ActOnVariableDeclarator( } if (!R->isIntegralType(Context) && !R->isPointerType()) { - Diag(D.getLocStart(), diag::err_asm_bad_register_type); + Diag(D.getBeginLoc(), diag::err_asm_bad_register_type); NewVD->setInvalidDecl(true); } } @@ -6931,12 +6896,12 @@ NamedDecl *Sema::ActOnVariableDeclarator( // C++ [basic.start.main]p3 // A program that declares a variable main at global scope is ill-formed. if (getLangOpts().CPlusPlus) - Diag(D.getLocStart(), diag::err_main_global_variable); + Diag(D.getBeginLoc(), diag::err_main_global_variable); // In C, and external-linkage variable named main results in undefined // behavior. else if (NewVD->hasExternalFormalLinkage()) - Diag(D.getLocStart(), diag::warn_main_redefined); + Diag(D.getBeginLoc(), diag::warn_main_redefined); } if (D.isRedeclaration() && !Previous.empty()) { @@ -7382,19 +7347,23 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { return; } } - // OpenCL v1.2 s6.5 - All program scope variables must be declared in the + // OpenCL C v1.2 s6.5 - All program scope variables must be declared in the // __constant address space. - // OpenCL v2.0 s6.5.1 - Variables defined at program scope and static + // OpenCL C v2.0 s6.5.1 - Variables defined at program scope and static // variables inside a function can also be declared in the global // address space. + // OpenCL C++ v1.0 s2.5 inherits rule from OpenCL C v2.0 and allows local + // address space additionally. + // FIXME: Add local AS for OpenCL C++. if (NewVD->isFileVarDecl() || NewVD->isStaticLocal() || NewVD->hasExternalStorage()) { if (!T->isSamplerT() && !(T.getAddressSpace() == LangAS::opencl_constant || (T.getAddressSpace() == LangAS::opencl_global && - getLangOpts().OpenCLVersion == 200))) { + (getLangOpts().OpenCLVersion == 200 || + getLangOpts().OpenCLCPlusPlus)))) { int Scope = NewVD->isStaticLocal() | NewVD->hasExternalStorage() << 1; - if (getLangOpts().OpenCLVersion == 200) + if (getLangOpts().OpenCLVersion == 200 || getLangOpts().OpenCLCPlusPlus) Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space) << Scope << "global or constant"; else @@ -7747,8 +7716,10 @@ static NamedDecl *DiagnoseInvalidRedeclaration( SmallVector<std::pair<FunctionDecl *, unsigned>, 1> NearMatches; TypoCorrection Correction; bool IsDefinition = ExtraArgs.D.isFunctionDefinition(); - unsigned DiagMsg = IsLocalFriend ? diag::err_no_matching_local_friend - : diag::err_member_decl_does_not_match; + unsigned DiagMsg = + IsLocalFriend ? diag::err_no_matching_local_friend : + NewFD->getFriendObjectKind() ? diag::err_qualified_friend_no_match : + diag::err_member_decl_does_not_match; LookupResult Prev(SemaRef, Name, NewFD->getLocation(), IsLocalFriend ? Sema::LookupLocalFriendName : Sema::LookupOrdinaryName, @@ -7938,10 +7909,8 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, (D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) || (!R->getAsAdjusted<FunctionType>() && R->isFunctionProtoType()); - NewFD = FunctionDecl::Create(SemaRef.Context, DC, - D.getLocStart(), NameInfo, R, - TInfo, SC, isInline, - HasPrototype, false); + NewFD = FunctionDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), NameInfo, + R, TInfo, SC, isInline, HasPrototype, false); if (D.isInvalidType()) NewFD->setInvalidDecl(); @@ -7966,31 +7935,26 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, "Constructors can only be declared in a member context"); R = SemaRef.CheckConstructorDeclarator(D, R, SC); - return CXXConstructorDecl::Create(SemaRef.Context, cast<CXXRecordDecl>(DC), - D.getLocStart(), NameInfo, - R, TInfo, isExplicit, isInline, - /*isImplicitlyDeclared=*/false, - isConstexpr); + return CXXConstructorDecl::Create( + SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R, + TInfo, isExplicit, isInline, + /*isImplicitlyDeclared=*/false, isConstexpr); } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) { // This is a C++ destructor declaration. if (DC->isRecord()) { R = SemaRef.CheckDestructorDeclarator(D, R, SC); CXXRecordDecl *Record = cast<CXXRecordDecl>(DC); - CXXDestructorDecl *NewDD = CXXDestructorDecl::Create( - SemaRef.Context, Record, - D.getLocStart(), - NameInfo, R, TInfo, isInline, - /*isImplicitlyDeclared=*/false); - - // If the class is complete, then we now create the implicit exception - // specification. If the class is incomplete or dependent, we can't do - // it yet. - if (SemaRef.getLangOpts().CPlusPlus11 && !Record->isDependentType() && - Record->getDefinition() && !Record->isBeingDefined() && - R->getAs<FunctionProtoType>()->getExceptionSpecType() == EST_None) { - SemaRef.AdjustDestructorExceptionSpec(Record, NewDD); - } + CXXDestructorDecl *NewDD = + CXXDestructorDecl::Create(SemaRef.Context, Record, D.getBeginLoc(), + NameInfo, R, TInfo, isInline, + /*isImplicitlyDeclared=*/false); + + // If the destructor needs an implicit exception specification, set it + // now. FIXME: It'd be nice to be able to create the right type to start + // with, but the type needs to reference the destructor declaration. + if (SemaRef.getLangOpts().CPlusPlus11) + SemaRef.AdjustDestructorExceptionSpec(NewDD); IsVirtualOkay = true; return NewDD; @@ -8001,10 +7965,9 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, // Create a FunctionDecl to satisfy the function definition parsing // code path. - return FunctionDecl::Create(SemaRef.Context, DC, - D.getLocStart(), - D.getIdentifierLoc(), Name, R, TInfo, - SC, isInline, + return FunctionDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), + D.getIdentifierLoc(), Name, R, TInfo, SC, + isInline, /*hasPrototype=*/true, isConstexpr); } @@ -8017,17 +7980,16 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, SemaRef.CheckConversionDeclarator(D, R, SC); IsVirtualOkay = true; - return CXXConversionDecl::Create(SemaRef.Context, cast<CXXRecordDecl>(DC), - D.getLocStart(), NameInfo, - R, TInfo, isInline, isExplicit, - isConstexpr, SourceLocation()); + return CXXConversionDecl::Create( + SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R, + TInfo, isInline, isExplicit, isConstexpr, SourceLocation()); } else if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) { SemaRef.CheckDeductionGuideDeclarator(D, R, SC); - return CXXDeductionGuideDecl::Create(SemaRef.Context, DC, D.getLocStart(), + return CXXDeductionGuideDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), isExplicit, NameInfo, R, TInfo, - D.getLocEnd()); + D.getEndLoc()); } else if (DC->isRecord()) { // If the name of the function is the same as the name of the record, // then this must be an invalid constructor that has a return type. @@ -8042,11 +8004,9 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, } // This is a C++ method declaration. - CXXMethodDecl *Ret = CXXMethodDecl::Create(SemaRef.Context, - cast<CXXRecordDecl>(DC), - D.getLocStart(), NameInfo, R, - TInfo, SC, isInline, - isConstexpr, SourceLocation()); + CXXMethodDecl *Ret = CXXMethodDecl::Create( + SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R, + TInfo, SC, isInline, isConstexpr, SourceLocation()); IsVirtualOkay = !Ret->isStatic(); return Ret; } else { @@ -8058,10 +8018,9 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, // Determine whether the function was written with a // prototype. This true when: // - we're in C++ (where every function has a prototype), - return FunctionDecl::Create(SemaRef.Context, DC, - D.getLocStart(), - NameInfo, R, TInfo, SC, isInline, - true/*HasPrototype*/, isConstexpr); + return FunctionDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), NameInfo, + R, TInfo, SC, isInline, true /*HasPrototype*/, + isConstexpr); } } @@ -8137,7 +8096,7 @@ static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) { const Type *UnderlyingTy = PT->getPointeeOrArrayElementType(); // Call ourself to check an underlying type of an array. Since the // getPointeeOrArrayElementType returns an innermost type which is not an - // array, this recusive call only happens once. + // array, this recursive call only happens once. return getOpenCLKernelParameterType(S, QualType(UnderlyingTy, 0)); } @@ -8415,7 +8374,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_virtual_in_union); } - SetNestedNameSpecifier(NewFD, D); + SetNestedNameSpecifier(*this, NewFD, D); isMemberSpecialization = false; isFunctionTemplateSpecialization = false; if (D.isInvalidType()) @@ -8426,7 +8385,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, bool Invalid = false; if (TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier( - D.getDeclSpec().getLocStart(), D.getIdentifierLoc(), + D.getDeclSpec().getBeginLoc(), D.getIdentifierLoc(), D.getCXXScopeSpec(), D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId ? D.getName().TemplateId @@ -8496,8 +8455,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, << FixItHint::CreateInsertion(InsertLoc, "<>"); } } - } - else { + } else { // All template param lists were matched against the scope specifier: // this is NOT (an explicit specialization of) a template. if (TemplateParamLists.size() > 0) @@ -9067,10 +9025,14 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // selecting a friend based on a dependent factor. But there // are situations where these conditions don't apply and we // can actually do this check immediately. + // + // Unless the scope is dependent, it's always an error if qualified + // redeclaration lookup found nothing at all. Diagnose that now; + // nothing will diagnose that error later. if (isFriend && - (TemplateParamLists.size() || - D.getCXXScopeSpec().getScopeRep()->isDependent() || - CurContext->isDependentContext())) { + (D.getCXXScopeSpec().getScopeRep()->isDependent() || + (!Previous.empty() && (TemplateParamLists.size() || + CurContext->isDependentContext())))) { // ignore these } else { // The user tried to provide an out-of-line definition for a @@ -9336,6 +9298,39 @@ Attr *Sema::getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD, } return nullptr; } + +/// Determines if we can perform a correct type check for \p D as a +/// redeclaration of \p PrevDecl. If not, we can generally still perform a +/// best-effort check. +/// +/// \param NewD The new declaration. +/// \param OldD The old declaration. +/// \param NewT The portion of the type of the new declaration to check. +/// \param OldT The portion of the type of the old declaration to check. +bool Sema::canFullyTypeCheckRedeclaration(ValueDecl *NewD, ValueDecl *OldD, + QualType NewT, QualType OldT) { + if (!NewD->getLexicalDeclContext()->isDependentContext()) + return true; + + // For dependently-typed local extern declarations and friends, we can't + // perform a correct type check in general until instantiation: + // + // int f(); + // template<typename T> void g() { T f(); } + // + // (valid if g() is only instantiated with T = int). + if (NewT->isDependentType() && + (NewD->isLocalExternDecl() || NewD->getFriendObjectKind())) + return false; + + // Similarly, if the previous declaration was a dependent local extern + // declaration, we don't really know its type yet. + if (OldT->isDependentType() && OldD->isLocalExternDecl()) + return false; + + return true; +} + /// Checks if the new declaration declared in dependent context must be /// put in the same redeclaration chain as the specified declaration. /// @@ -9346,36 +9341,32 @@ Attr *Sema::getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD, /// belongs to. /// bool Sema::shouldLinkDependentDeclWithPrevious(Decl *D, Decl *PrevDecl) { - // Any declarations should be put into redeclaration chains except for - // friend declaration in a dependent context that names a function in - // namespace scope. + if (!D->getLexicalDeclContext()->isDependentContext()) + return true; + + // Don't chain dependent friend function definitions until instantiation, to + // permit cases like // - // This allows to compile code like: + // void func(); + // template<typename T> class C1 { friend void func() {} }; + // template<typename T> class C2 { friend void func() {} }; // - // void func(); - // template<typename T> class C1 { friend void func() { } }; - // template<typename T> class C2 { friend void func() { } }; + // ... which is valid if only one of C1 and C2 is ever instantiated. // - // This code snippet is a valid code unless both templates are instantiated. - return !(D->getLexicalDeclContext()->isDependentContext() && - D->getDeclContext()->isFileContext() && - D->getFriendObjectKind() != Decl::FOK_None); -} + // FIXME: This need only apply to function definitions. For now, we proxy + // this by checking for a file-scope function. We do not want this to apply + // to friend declarations nominating member functions, because that gets in + // the way of access checks. + if (D->getFriendObjectKind() && D->getDeclContext()->isFileContext()) + return false; -namespace MultiVersioning { -enum Type { None, Target, CPUSpecific, CPUDispatch}; -} // MultiVersionType - -static MultiVersioning::Type -getMultiVersionType(const FunctionDecl *FD) { - if (FD->hasAttr<TargetAttr>()) - return MultiVersioning::Target; - if (FD->hasAttr<CPUDispatchAttr>()) - return MultiVersioning::CPUDispatch; - if (FD->hasAttr<CPUSpecificAttr>()) - return MultiVersioning::CPUSpecific; - return MultiVersioning::None; + auto *VD = dyn_cast<ValueDecl>(D); + auto *PrevVD = dyn_cast<ValueDecl>(PrevDecl); + return !VD || !PrevVD || + canFullyTypeCheckRedeclaration(VD, PrevVD, VD->getType(), + PrevVD->getType()); } + /// Check the target attribute of the function for MultiVersion /// validity. /// @@ -9412,10 +9403,31 @@ static bool CheckMultiVersionValue(Sema &S, const FunctionDecl *FD) { return false; } +static bool HasNonMultiVersionAttributes(const FunctionDecl *FD, + MultiVersionKind MVType) { + for (const Attr *A : FD->attrs()) { + switch (A->getKind()) { + case attr::CPUDispatch: + case attr::CPUSpecific: + if (MVType != MultiVersionKind::CPUDispatch && + MVType != MultiVersionKind::CPUSpecific) + return true; + break; + case attr::Target: + if (MVType != MultiVersionKind::Target) + return true; + break; + default: + return true; + } + } + return false; +} + static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD, const FunctionDecl *NewFD, bool CausesMV, - MultiVersioning::Type MVType) { + MultiVersionKind MVType) { enum DoesntSupport { FuncTemplates = 0, VirtFuncs = 1, @@ -9436,8 +9448,8 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD, }; bool IsCPUSpecificCPUDispatchMVType = - MVType == MultiVersioning::CPUDispatch || - MVType == MultiVersioning::CPUSpecific; + MVType == MultiVersionKind::CPUDispatch || + MVType == MultiVersionKind::CPUSpecific; if (OldFD && !OldFD->getType()->getAs<FunctionProtoType>()) { S.Diag(OldFD->getLocation(), diag::err_multiversion_noproto); @@ -9457,15 +9469,14 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD, // 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 && - std::distance(OldFD->attr_begin(), OldFD->attr_end()) != 1) { + 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); return true; } - if (std::distance(NewFD->attr_begin(), NewFD->attr_end()) != 1) + if (HasNonMultiVersionAttributes(NewFD, MVType)) return S.Diag(NewFD->getLocation(), diag::err_multiversion_no_other_attrs) << IsCPUSpecificCPUDispatchMVType; @@ -9498,8 +9509,8 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD, return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support) << IsCPUSpecificCPUDispatchMVType << DefaultedFuncs; - if (NewFD->isConstexpr() && (MVType == MultiVersioning::CPUDispatch || - MVType == MultiVersioning::CPUSpecific)) + if (NewFD->isConstexpr() && (MVType == MultiVersionKind::CPUDispatch || + MVType == MultiVersionKind::CPUSpecific)) return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support) << IsCPUSpecificCPUDispatchMVType << ConstexprFuncs; @@ -9563,19 +9574,19 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD, /// /// Returns true if there was an error, false otherwise. static bool CheckMultiVersionFirstFunction(Sema &S, FunctionDecl *FD, - MultiVersioning::Type MVType, + MultiVersionKind MVType, const TargetAttr *TA, const CPUDispatchAttr *CPUDisp, const CPUSpecificAttr *CPUSpec) { - assert(MVType != MultiVersioning::None && + assert(MVType != MultiVersionKind::None && "Function lacks multiversion attribute"); // Target only causes MV if it is default, otherwise this is a normal // function. - if (MVType == MultiVersioning::Target && !TA->isDefaultVersion()) + if (MVType == MultiVersionKind::Target && !TA->isDefaultVersion()) return false; - if (MVType == MultiVersioning::Target && CheckMultiVersionValue(S, FD)) { + if (MVType == MultiVersionKind::Target && CheckMultiVersionValue(S, FD)) { FD->setInvalidDecl(); return true; } @@ -9589,6 +9600,15 @@ static bool CheckMultiVersionFirstFunction(Sema &S, FunctionDecl *FD, return false; } +static bool PreviousDeclsHaveMultiVersionAttribute(const FunctionDecl *FD) { + for (const Decl *D = FD->getPreviousDecl(); D; D = D->getPreviousDecl()) { + if (D->getAsFunction()->getMultiVersionKind() != MultiVersionKind::None) + return true; + } + + return false; +} + static bool CheckTargetCausesMultiVersioning( Sema &S, FunctionDecl *OldFD, FunctionDecl *NewFD, const TargetAttr *NewTA, bool &Redeclaration, NamedDecl *&OldDecl, bool &MergeTypeWithPrevious, @@ -9596,11 +9616,12 @@ static bool CheckTargetCausesMultiVersioning( const auto *OldTA = OldFD->getAttr<TargetAttr>(); TargetAttr::ParsedTargetAttr NewParsed = NewTA->parse(); // Sort order doesn't matter, it just needs to be consistent. - llvm::sort(NewParsed.Features.begin(), NewParsed.Features.end()); + llvm::sort(NewParsed.Features); // If the old decl is NOT MultiVersioned yet, and we don't cause that // to change, this is a simple redeclaration. - if (!OldTA || OldTA->getFeaturesStr() == NewTA->getFeaturesStr()) + if (!NewTA->isDefaultVersion() && + (!OldTA || OldTA->getFeaturesStr() == NewTA->getFeaturesStr())) return false; // Otherwise, this decl causes MultiVersioning. @@ -9612,7 +9633,7 @@ static bool CheckTargetCausesMultiVersioning( } if (CheckMultiVersionAdditionalRules(S, OldFD, NewFD, true, - MultiVersioning::Target)) { + MultiVersionKind::Target)) { NewFD->setInvalidDecl(); return true; } @@ -9622,6 +9643,15 @@ static bool CheckTargetCausesMultiVersioning( return true; } + // If this is 'default', permit the forward declaration. + if (!OldFD->isMultiVersion() && !OldTA && NewTA->isDefaultVersion()) { + Redeclaration = true; + OldDecl = OldFD; + OldFD->setIsMultiVersion(); + NewFD->setIsMultiVersion(); + return false; + } + if (CheckMultiVersionValue(S, OldFD)) { S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here); NewFD->setInvalidDecl(); @@ -9640,7 +9670,10 @@ static bool CheckTargetCausesMultiVersioning( for (const auto *FD : OldFD->redecls()) { const auto *CurTA = FD->getAttr<TargetAttr>(); - if (!CurTA || CurTA->isInherited()) { + // We allow forward declarations before ANY multiversioning attributes, but + // nothing after the fact. + if (PreviousDeclsHaveMultiVersionAttribute(FD) && + (!CurTA || CurTA->isInherited())) { S.Diag(FD->getLocation(), diag::err_multiversion_required_in_redecl) << 0; S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here); @@ -9662,17 +9695,17 @@ static bool CheckTargetCausesMultiVersioning( /// multiversioned declaration collection. static bool CheckMultiVersionAdditionalDecl( Sema &S, FunctionDecl *OldFD, FunctionDecl *NewFD, - MultiVersioning::Type NewMVType, const TargetAttr *NewTA, + MultiVersionKind NewMVType, const TargetAttr *NewTA, const CPUDispatchAttr *NewCPUDisp, const CPUSpecificAttr *NewCPUSpec, bool &Redeclaration, NamedDecl *&OldDecl, bool &MergeTypeWithPrevious, LookupResult &Previous) { - MultiVersioning::Type OldMVType = getMultiVersionType(OldFD); + MultiVersionKind OldMVType = OldFD->getMultiVersionKind(); // Disallow mixing of multiversioning types. - if ((OldMVType == MultiVersioning::Target && - NewMVType != MultiVersioning::Target) || - (NewMVType == MultiVersioning::Target && - OldMVType != MultiVersioning::Target)) { + if ((OldMVType == MultiVersionKind::Target && + NewMVType != MultiVersionKind::Target) || + (NewMVType == MultiVersionKind::Target && + OldMVType != MultiVersionKind::Target)) { S.Diag(NewFD->getLocation(), diag::err_multiversion_types_mixed); S.Diag(OldFD->getLocation(), diag::note_previous_declaration); NewFD->setInvalidDecl(); @@ -9682,7 +9715,7 @@ static bool CheckMultiVersionAdditionalDecl( TargetAttr::ParsedTargetAttr NewParsed; if (NewTA) { NewParsed = NewTA->parse(); - llvm::sort(NewParsed.Features.begin(), NewParsed.Features.end()); + llvm::sort(NewParsed.Features); } bool UseMemberUsingDeclRules = @@ -9697,7 +9730,7 @@ static bool CheckMultiVersionAdditionalDecl( if (S.IsOverload(NewFD, CurFD, UseMemberUsingDeclRules)) continue; - if (NewMVType == MultiVersioning::Target) { + if (NewMVType == MultiVersionKind::Target) { const auto *CurTA = CurFD->getAttr<TargetAttr>(); if (CurTA->getFeaturesStr() == NewTA->getFeaturesStr()) { NewFD->setIsMultiVersion(); @@ -9720,7 +9753,7 @@ static bool CheckMultiVersionAdditionalDecl( // Handle CPUDispatch/CPUSpecific versions. // Only 1 CPUDispatch function is allowed, this will make it go through // the redeclaration errors. - if (NewMVType == MultiVersioning::CPUDispatch && + if (NewMVType == MultiVersionKind::CPUDispatch && CurFD->hasAttr<CPUDispatchAttr>()) { if (CurCPUDisp->cpus_size() == NewCPUDisp->cpus_size() && std::equal( @@ -9741,7 +9774,7 @@ static bool CheckMultiVersionAdditionalDecl( NewFD->setInvalidDecl(); return true; } - if (NewMVType == MultiVersioning::CPUSpecific && CurCPUSpec) { + if (NewMVType == MultiVersionKind::CPUSpecific && CurCPUSpec) { if (CurCPUSpec->cpus_size() == NewCPUSpec->cpus_size() && std::equal( @@ -9777,17 +9810,27 @@ static bool CheckMultiVersionAdditionalDecl( // Else, this is simply a non-redecl case. Checking the 'value' is only // necessary in the Target case, since The CPUSpecific/Dispatch cases are // handled in the attribute adding step. - if (NewMVType == MultiVersioning::Target && + if (NewMVType == MultiVersionKind::Target && CheckMultiVersionValue(S, NewFD)) { NewFD->setInvalidDecl(); return true; } - if (CheckMultiVersionAdditionalRules(S, OldFD, NewFD, false, NewMVType)) { + if (CheckMultiVersionAdditionalRules(S, OldFD, NewFD, + !OldFD->isMultiVersion(), NewMVType)) { NewFD->setInvalidDecl(); return true; } + // Permit forward declarations in the case where these two are compatible. + if (!OldFD->isMultiVersion()) { + OldFD->setIsMultiVersion(); + NewFD->setIsMultiVersion(); + Redeclaration = true; + OldDecl = OldFD; + return false; + } + NewFD->setIsMultiVersion(); Redeclaration = false; MergeTypeWithPrevious = false; @@ -9819,14 +9862,14 @@ static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD, return true; } - MultiVersioning::Type MVType = getMultiVersionType(NewFD); + MultiVersionKind MVType = NewFD->getMultiVersionKind(); // Main isn't allowed to become a multiversion function, however it IS // permitted to have 'main' be marked with the 'target' optimization hint. if (NewFD->isMain()) { - if ((MVType == MultiVersioning::Target && NewTA->isDefaultVersion()) || - MVType == MultiVersioning::CPUDispatch || - MVType == MultiVersioning::CPUSpecific) { + if ((MVType == MultiVersionKind::Target && NewTA->isDefaultVersion()) || + MVType == MultiVersionKind::CPUDispatch || + MVType == MultiVersionKind::CPUSpecific) { S.Diag(NewFD->getLocation(), diag::err_multiversion_not_allowed_on_main); NewFD->setInvalidDecl(); return true; @@ -9839,7 +9882,7 @@ static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD, NewFD->getDeclContext()->getRedeclContext()) { // If there's no previous declaration, AND this isn't attempting to cause // multiversioning, this isn't an error condition. - if (MVType == MultiVersioning::None) + if (MVType == MultiVersionKind::None) return false; return CheckMultiVersionFirstFunction(S, NewFD, MVType, NewTA, NewCPUDisp, NewCPUSpec); @@ -9847,29 +9890,21 @@ static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD, FunctionDecl *OldFD = OldDecl->getAsFunction(); - if (!OldFD->isMultiVersion() && MVType == MultiVersioning::None) + if (!OldFD->isMultiVersion() && MVType == MultiVersionKind::None) return false; - if (OldFD->isMultiVersion() && MVType == MultiVersioning::None) { + if (OldFD->isMultiVersion() && MVType == MultiVersionKind::None) { S.Diag(NewFD->getLocation(), diag::err_multiversion_required_in_redecl) - << (getMultiVersionType(OldFD) != MultiVersioning::Target); + << (OldFD->getMultiVersionKind() != MultiVersionKind::Target); NewFD->setInvalidDecl(); return true; } // Handle the target potentially causes multiversioning case. - if (!OldFD->isMultiVersion() && MVType == MultiVersioning::Target) + if (!OldFD->isMultiVersion() && MVType == MultiVersionKind::Target) return CheckTargetCausesMultiVersioning(S, OldFD, NewFD, NewTA, Redeclaration, OldDecl, MergeTypeWithPrevious, Previous); - // Previous declarations lack CPUDispatch/CPUSpecific. - if (!OldFD->isMultiVersion()) { - S.Diag(OldFD->getLocation(), diag::err_multiversion_required_in_redecl) - << 1; - S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here); - NewFD->setInvalidDecl(); - return true; - } // At this point, we have a multiversion function decl (in OldFD) AND an // appropriate attribute in the current function decl. Resolve that these are @@ -9982,7 +10017,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD); if (!getLangOpts().CPlusPlus14 && MD && MD->isConstexpr() && !MD->isStatic() && !isa<CXXConstructorDecl>(MD) && - (MD->getTypeQualifiers() & Qualifiers::Const) == 0) { + !MD->getTypeQualifiers().hasConst()) { CXXMethodDecl *OldMD = nullptr; if (OldDecl) OldMD = dyn_cast_or_null<CXXMethodDecl>(OldDecl->getAsFunction()); @@ -9990,7 +10025,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); - EPI.TypeQuals |= Qualifiers::Const; + EPI.TypeQuals.addConst(); MD->setType(Context.getFunctionType(FPT->getReturnType(), FPT->getParamTypes(), EPI)); @@ -10022,11 +10057,17 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, if (FunctionTemplateDecl *OldTemplateDecl = dyn_cast<FunctionTemplateDecl>(OldDecl)) { auto *OldFD = OldTemplateDecl->getTemplatedDecl(); - NewFD->setPreviousDeclaration(OldFD); - adjustDeclContextForDeclaratorDecl(NewFD, OldFD); FunctionTemplateDecl *NewTemplateDecl = NewFD->getDescribedFunctionTemplate(); assert(NewTemplateDecl && "Template/non-template mismatch"); + + // The call to MergeFunctionDecl above may have created some state in + // NewTemplateDecl that needs to be merged with OldTemplateDecl before we + // can add it as a redeclaration. + NewTemplateDecl->mergePrevDecl(OldTemplateDecl); + + NewFD->setPreviousDeclaration(OldFD); + adjustDeclContextForDeclaratorDecl(NewFD, OldFD); if (NewFD->isCXXClassMember()) { NewFD->setAccess(OldTemplateDecl->getAccess()); NewTemplateDecl->setAccess(OldTemplateDecl->getAccess()); @@ -10116,7 +10157,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // A deduction guide is not on the list of entities that can be // explicitly specialized. if (Guide->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) - Diag(Guide->getLocStart(), diag::err_deduction_guide_specialized) + Diag(Guide->getBeginLoc(), diag::err_deduction_guide_specialized) << /*explicit specialization*/ 1; } @@ -10479,7 +10520,7 @@ namespace { Expr *Base = E; bool ReferenceField = false; - // Get the field memebers used. + // Get the field members used. while (MemberExpr *ME = dyn_cast<MemberExpr>(Base)) { FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()); if (!FD) @@ -10719,11 +10760,10 @@ namespace { return; } - S.DiagRuntimeBehavior(DRE->getLocStart(), DRE, + S.DiagRuntimeBehavior(DRE->getBeginLoc(), DRE, S.PDiag(diag) - << DRE->getDecl() - << OrigDecl->getLocation() - << DRE->getSourceRange()); + << DRE->getDecl() << OrigDecl->getLocation() + << DRE->getSourceRange()); } }; @@ -10768,7 +10808,7 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl, DeclarationName Name, QualType Type, TypeSourceInfo *TSI, SourceRange Range, bool DirectInit, - Expr *Init) { + Expr *&Init) { bool IsInitCapture = !VDecl; assert((!VDecl || !VDecl->isInitCapture()) && "init captures are expected to be deduced prior to initialization"); @@ -10822,7 +10862,7 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl, if (DeduceInits.empty()) { // It isn't possible to write this directly, but it is possible to // end up in this situation with "auto x(some_pack...);" - Diag(Init->getLocStart(), IsInitCapture + Diag(Init->getBeginLoc(), IsInitCapture ? diag::err_init_capture_no_expression : diag::err_auto_var_init_no_expression) << VN << Type << Range; @@ -10830,7 +10870,7 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl, } if (DeduceInits.size() > 1) { - Diag(DeduceInits[1]->getLocStart(), + Diag(DeduceInits[1]->getBeginLoc(), IsInitCapture ? diag::err_init_capture_multiple_expressions : diag::err_auto_var_init_multiple_expressions) << VN << Type << Range; @@ -10839,7 +10879,7 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl, Expr *DeduceInit = DeduceInits[0]; if (DirectInit && isa<InitListExpr>(DeduceInit)) { - Diag(Init->getLocStart(), IsInitCapture + Diag(Init->getBeginLoc(), IsInitCapture ? diag::err_init_capture_paren_braces : diag::err_auto_var_init_paren_braces) << isa<InitListExpr>(Init) << VN << Type << Range; @@ -10884,7 +10924,8 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl, << (DeduceInit->getType().isNull() ? TSI->getType() : DeduceInit->getType()) << DeduceInit->getSourceRange(); - } + } else + Init = DeduceInit; // Warn if we deduced 'id'. 'auto' usually implies type-safety, but using // 'id' instead of a specific object type prevents most of our usual @@ -10901,7 +10942,7 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl, } bool Sema::DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit, - Expr *Init) { + Expr *&Init) { QualType DeducedType = deduceVarTypeFromInitializer( VDecl, VDecl->getDeclName(), VDecl->getType(), VDecl->getTypeSourceInfo(), VDecl->getSourceRange(), DirectInit, Init); @@ -11144,7 +11185,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { if ((VDecl->getType().getObjCLifetime() == Qualifiers::OCL_Strong || VDecl->getType().isNonWeakInMRRWithObjCWeak(Context)) && !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, - Init->getLocStart())) + Init->getBeginLoc())) FSI->markSafeWeakUse(Init); } @@ -11159,9 +11200,9 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { // struct T { S a, b; } t = { Temp(), Temp() } // // we should destroy the first Temp before constructing the second. - ExprResult Result = ActOnFinishFullExpr(Init, VDecl->getLocation(), - false, - VDecl->isConstexpr()); + ExprResult Result = + ActOnFinishFullExpr(Init, VDecl->getLocation(), + /*DiscardedValue*/ false, VDecl->isConstexpr()); if (Result.isInvalid()) { VDecl->setInvalidDecl(); return; @@ -11276,9 +11317,9 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { Diag(VDecl->getLocation(), diag::ext_in_class_initializer_float_type_cxx11) << DclT << Init->getSourceRange(); - Diag(VDecl->getLocStart(), + Diag(VDecl->getBeginLoc(), diag::note_in_class_initializer_float_type_cxx11) - << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr "); + << FixItHint::CreateInsertion(VDecl->getBeginLoc(), "constexpr "); } else { Diag(VDecl->getLocation(), diag::ext_in_class_initializer_float_type) << DclT << Init->getSourceRange(); @@ -11293,8 +11334,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { // Suggest adding 'constexpr' in C++11 for literal types. } else if (getLangOpts().CPlusPlus11 && DclT->isLiteralType(Context)) { Diag(VDecl->getLocation(), diag::err_in_class_initializer_literal_type) - << DclT << Init->getSourceRange() - << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr "); + << DclT << Init->getSourceRange() + << FixItHint::CreateInsertion(VDecl->getBeginLoc(), "constexpr "); VDecl->setConstexpr(true); } else { @@ -11407,8 +11448,9 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { return; } + Expr *TmpInit = nullptr; if (Type->isUndeducedType() && - DeduceVariableDeclarationType(Var, false, nullptr)) + DeduceVariableDeclarationType(Var, false, TmpInit)) return; // C++11 [class.static.data]p3: A static data member can be declared with @@ -11708,7 +11750,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { // In Objective-C, don't allow jumps past the implicit initialization of a // local retaining variable. - if (getLangOpts().ObjC1 && + if (getLangOpts().ObjC && var->hasLocalStorage()) { switch (var->getType().getObjCLifetime()) { case Qualifiers::OCL_None: @@ -11827,29 +11869,8 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { QualType type = var->getType(); if (type->isDependentType()) return; - // __block variables might require us to capture a copy-initializer. - if (var->hasAttr<BlocksAttr>()) { - // It's currently invalid to ever have a __block variable with an - // array type; should we diagnose that here? - - // Regardless, we don't want to ignore array nesting when - // constructing this copy. - if (type->isStructureOrClassType()) { - EnterExpressionEvaluationContext scope( - *this, ExpressionEvaluationContext::PotentiallyEvaluated); - SourceLocation poi = var->getLocation(); - Expr *varRef =new (Context) DeclRefExpr(var, false, type, VK_LValue, poi); - ExprResult result - = PerformMoveOrCopyInitialization( - InitializedEntity::InitializeBlock(poi, type, false), - var, var->getType(), varRef, /*AllowNRVO=*/true); - if (!result.isInvalid()) { - result = MaybeCreateExprWithCleanups(result); - Expr *init = result.getAs<Expr>(); - Context.setBlockVarCopyInits(var, init); - } - } - } + if (var->hasAttr<BlocksAttr>()) + getCurFunction()->addByrefBlockVar(var); Expr *Init = var->getInit(); bool IsGlobal = GlobalStorage && !var->isStaticLocal(); @@ -11940,6 +11961,49 @@ static bool hasDependentAlignment(VarDecl *VD) { return false; } +/// Check if VD needs to be dllexport/dllimport due to being in a +/// dllexport/import function. +void Sema::CheckStaticLocalForDllExport(VarDecl *VD) { + assert(VD->isStaticLocal()); + + auto *FD = dyn_cast_or_null<FunctionDecl>(VD->getParentFunctionOrMethod()); + + // Find outermost function when VD is in lambda function. + while (FD && !getDLLAttr(FD) && + !FD->hasAttr<DLLExportStaticLocalAttr>() && + !FD->hasAttr<DLLImportStaticLocalAttr>()) { + FD = dyn_cast_or_null<FunctionDecl>(FD->getParentFunctionOrMethod()); + } + + if (!FD) + return; + + // Static locals inherit dll attributes from their function. + if (Attr *A = getDLLAttr(FD)) { + auto *NewAttr = cast<InheritableAttr>(A->clone(getASTContext())); + NewAttr->setInherited(true); + VD->addAttr(NewAttr); + } else if (Attr *A = FD->getAttr<DLLExportStaticLocalAttr>()) { + auto *NewAttr = ::new (getASTContext()) DLLExportAttr(A->getRange(), + getASTContext(), + A->getSpellingListIndex()); + NewAttr->setInherited(true); + VD->addAttr(NewAttr); + + // Export this function to enforce exporting this static variable even + // if it is not used in this compilation unit. + if (!FD->hasAttr<DLLExportAttr>()) + FD->addAttr(NewAttr); + + } else if (Attr *A = FD->getAttr<DLLImportStaticLocalAttr>()) { + auto *NewAttr = ::new (getASTContext()) DLLImportAttr(A->getRange(), + getASTContext(), + A->getSpellingListIndex()); + NewAttr->setInherited(true); + VD->addAttr(NewAttr); + } +} + /// FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform /// any semantic actions necessary after any initializer has been attached. void Sema::FinalizeDeclaration(Decl *ThisDecl) { @@ -11993,14 +12057,9 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) { } if (VD->isStaticLocal()) { - if (FunctionDecl *FD = - dyn_cast_or_null<FunctionDecl>(VD->getParentFunctionOrMethod())) { - // Static locals inherit dll attributes from their function. - if (Attr *A = getDLLAttr(FD)) { - auto *NewAttr = cast<InheritableAttr>(A->clone(getASTContext())); - NewAttr->setInherited(true); - VD->addAttr(NewAttr); - } + 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. @@ -12375,11 +12434,9 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { // Temporarily put parameter variables in the translation unit, not // the enclosing context. This prevents them from accidentally // looking like class members in C++. - ParmVarDecl *New = CheckParameter(Context.getTranslationUnitDecl(), - D.getLocStart(), - D.getIdentifierLoc(), II, - parmDeclType, TInfo, - SC); + ParmVarDecl *New = + CheckParameter(Context.getTranslationUnitDecl(), D.getBeginLoc(), + D.getIdentifierLoc(), II, parmDeclType, TInfo, SC); if (D.isInvalidType()) New->setInvalidDecl(); @@ -12508,7 +12565,7 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc, // passed by reference. if (T->isObjCObjectType()) { SourceLocation TypeEndLoc = - getLocForEndOfToken(TSInfo->getTypeLoc().getLocEnd()); + getLocForEndOfToken(TSInfo->getTypeLoc().getEndLoc()); Diag(NameLoc, diag::err_object_cannot_be_passed_returned_by_value) << 1 << T << FixItHint::CreateInsertion(TypeEndLoc, "*"); @@ -12682,6 +12739,29 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD, } } } + + 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; @@ -12701,6 +12781,7 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD, Definition->getDescribedFunctionTemplate() || Definition->getNumTemplateParameterLists())) { SkipBody->ShouldSkip = true; + SkipBody->Previous = const_cast<FunctionDecl*>(Definition); if (auto *TD = Definition->getDescribedFunctionTemplate()) makeMergedDefinitionVisible(TD); makeMergedDefinitionVisible(const_cast<FunctionDecl*>(Definition)); @@ -12772,6 +12853,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, // Parsing the function declaration failed in some way. Push on a fake scope // anyway so we can try to parse the function body. PushFunctionScope(); + PushExpressionEvaluationContext(ExprEvalContexts.back().Context); return D; } @@ -12782,6 +12864,11 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, else FD = cast<FunctionDecl>(D); + // Do not push if it is a lambda because one is already pushed when building + // the lambda in ActOnStartOfLambdaDefinition(). + if (!isLambdaCallOperator(FD)) + PushExpressionEvaluationContext(ExprEvalContexts.back().Context); + // Check for defining attributes before the check for redefinition. if (const auto *Attr = FD->getAttr<AliasAttr>()) { Diag(Attr->getLocation(), diag::err_alias_is_definition) << FD << 0; @@ -12990,6 +13077,21 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) { return ActOnFinishFunctionBody(D, BodyArg, false); } +/// RAII object that pops an ExpressionEvaluationContext when exiting a function +/// body. +class ExitFunctionBodyRAII { +public: + ExitFunctionBodyRAII(Sema &S, bool IsLambda) : S(S), IsLambda(IsLambda) {} + ~ExitFunctionBodyRAII() { + if (!IsLambda) + S.PopExpressionEvaluationContext(); + } + +private: + Sema &S; + bool IsLambda = false; +}; + Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, bool IsInstantiation) { FunctionDecl *FD = dcl ? dcl->getAsFunction() : nullptr; @@ -13000,6 +13102,11 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, if (getLangOpts().CoroutinesTS && getCurFunction()->isCoroutine()) CheckCompletedCoroutineBody(FD, Body); + // Do not call PopExpressionEvaluationContext() if it is a lambda because one + // is already popped when finishing the lambda in BuildLambdaExpr(). This is + // meant to pop the context added in ActOnStartOfFunctionDef(). + ExitFunctionBodyRAII ExitRAII(*this, isLambdaCallOperator(FD)); + if (FD) { FD->setBody(Body); FD->setWillHaveBody(false); @@ -13054,7 +13161,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, if (!FD->isInvalidDecl()) { // Don't diagnose unused parameters of defaulted or deleted functions. - if (!FD->isDeleted() && !FD->isDefaulted()) + if (!FD->isDeleted() && !FD->isDefaulted() && !FD->hasSkippedBody()) DiagnoseUnusedParameters(FD->parameters()); DiagnoseSizeOfParametersAndReturnValue(FD->parameters(), FD->getReturnType(), FD); @@ -13116,7 +13223,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, if (FD->isMultiVersion() && FD->hasAttr<CPUDispatchAttr>() && Body) if (const auto *CmpndBody = dyn_cast<CompoundStmt>(Body)) if (!CmpndBody->body_empty()) - Diag(CmpndBody->body_front()->getLocStart(), + Diag(CmpndBody->body_front()->getBeginLoc(), diag::warn_dispatch_body_ignored); if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) { @@ -13149,7 +13256,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, assert(MD == getCurMethodDecl() && "Method parsing confused"); MD->setBody(Body); if (!MD->isInvalidDecl()) { - DiagnoseUnusedParameters(MD->parameters()); + if (!MD->hasSkippedBody()) + DiagnoseUnusedParameters(MD->parameters()); DiagnoseSizeOfParametersAndReturnValue(MD->parameters(), MD->getReturnType(), MD); @@ -13157,8 +13265,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, computeNRVO(Body, getCurFunction()); } if (getCurFunction()->ObjCShouldCallSuper) { - Diag(MD->getLocEnd(), diag::warn_objc_missing_super_call) - << MD->getSelector().getAsString(); + Diag(MD->getEndLoc(), diag::warn_objc_missing_super_call) + << MD->getSelector().getAsString(); getCurFunction()->ObjCShouldCallSuper = false; } if (getCurFunction()->ObjCWarnForNoDesignatedInitChain) { @@ -13267,7 +13375,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, if (RegisterVariables) continue; if (!isa<AsmStmt>(S) && !isa<NullStmt>(S)) { - Diag(S->getLocStart(), diag::err_non_asm_stmt_in_naked_function); + Diag(S->getBeginLoc(), diag::err_non_asm_stmt_in_naked_function); Diag(FD->getAttr<NakedAttr>()->getLocation(), diag::note_attribute); FD->setInvalidDecl(); break; @@ -13354,15 +13462,17 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, } // Extension in C99. Legal in C90, but warn about it. - // OpenCL v2.0 s6.9.u - Implicit function declaration is not supported. unsigned diag_id; if (II.getName().startswith("__builtin_")) diag_id = diag::warn_builtin_unknown; - else if (getLangOpts().C99 || getLangOpts().OpenCL) + // OpenCL v2.0 s6.9.u - Implicit function declaration is not supported. + else if (getLangOpts().OpenCL) + diag_id = diag::err_opencl_implicit_function_decl; + else if (getLangOpts().C99) diag_id = diag::ext_implicit_function_decl; else diag_id = diag::warn_implicit_function_decl; - Diag(Loc, diag_id) << &II << getLangOpts().OpenCL; + Diag(Loc, diag_id) << &II; // If we found a prior declaration of this function, don't bother building // another one. We've already pushed that one into scope, so there's nothing @@ -13400,12 +13510,8 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, /*NumParams=*/0, /*EllipsisLoc=*/NoLoc, /*RParenLoc=*/NoLoc, - /*TypeQuals=*/0, /*RefQualifierIsLvalueRef=*/true, /*RefQualifierLoc=*/NoLoc, - /*ConstQualifierLoc=*/NoLoc, - /*VolatileQualifierLoc=*/NoLoc, - /*RestrictQualifierLoc=*/NoLoc, /*MutableLoc=*/NoLoc, EST_None, /*ESpecRange=*/SourceRange(), /*Exceptions=*/nullptr, @@ -13573,11 +13679,9 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, } // Scope manipulation handled by caller. - TypedefDecl *NewTD = TypedefDecl::Create(Context, CurContext, - D.getLocStart(), - D.getIdentifierLoc(), - D.getIdentifier(), - TInfo); + TypedefDecl *NewTD = + TypedefDecl::Create(Context, CurContext, D.getBeginLoc(), + D.getIdentifierLoc(), D.getIdentifier(), TInfo); // Bail out immediately if we have an invalid declaration. if (D.isInvalidType()) { @@ -13739,76 +13843,106 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous, // struct class-key shall be used to refer to a class (clause 9) // declared using the class or struct class-key. TagTypeKind OldTag = Previous->getTagKind(); - if (!isDefinition || !isClassCompatTagKind(NewTag)) - if (OldTag == NewTag) + if (OldTag != NewTag && + !(isClassCompatTagKind(OldTag) && isClassCompatTagKind(NewTag))) + return false; + + // Tags are compatible, but we might still want to warn on mismatched tags. + // Non-class tags can't be mismatched at this point. + if (!isClassCompatTagKind(NewTag)) + return true; + + // Declarations for which -Wmismatched-tags is disabled are entirely ignored + // by our warning analysis. We don't want to warn about mismatches with (eg) + // declarations in system headers that are designed to be specialized, but if + // a user asks us to warn, we should warn if their code contains mismatched + // declarations. + auto IsIgnoredLoc = [&](SourceLocation Loc) { + return getDiagnostics().isIgnored(diag::warn_struct_class_tag_mismatch, + Loc); + }; + if (IsIgnoredLoc(NewTagLoc)) + return true; + + auto IsIgnored = [&](const TagDecl *Tag) { + return IsIgnoredLoc(Tag->getLocation()); + }; + while (IsIgnored(Previous)) { + Previous = Previous->getPreviousDecl(); + if (!Previous) return true; + OldTag = Previous->getTagKind(); + } - if (isClassCompatTagKind(OldTag) && isClassCompatTagKind(NewTag)) { - // Warn about the struct/class tag mismatch. - bool isTemplate = false; - if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Previous)) - isTemplate = Record->getDescribedClassTemplate(); + bool isTemplate = false; + if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Previous)) + isTemplate = Record->getDescribedClassTemplate(); - if (inTemplateInstantiation()) { + if (inTemplateInstantiation()) { + if (OldTag != NewTag) { // In a template instantiation, do not offer fix-its for tag mismatches // since they usually mess up the template instead of fixing the problem. Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch) << getRedeclDiagFromTagKind(NewTag) << isTemplate << Name << getRedeclDiagFromTagKind(OldTag); + // FIXME: Note previous location? + } + return true; + } + + if (isDefinition) { + // On definitions, check all previous tags and issue a fix-it for each + // one that doesn't match the current tag. + if (Previous->getDefinition()) { + // Don't suggest fix-its for redefinitions. return true; } - if (isDefinition) { - // On definitions, check previous tags and issue a fix-it for each - // one that doesn't match the current tag. - if (Previous->getDefinition()) { - // Don't suggest fix-its for redefinitions. - return true; - } + bool previousMismatch = false; + for (const TagDecl *I : Previous->redecls()) { + if (I->getTagKind() != NewTag) { + // Ignore previous declarations for which the warning was disabled. + if (IsIgnored(I)) + continue; - bool previousMismatch = false; - for (auto I : Previous->redecls()) { - if (I->getTagKind() != NewTag) { - if (!previousMismatch) { - previousMismatch = true; - Diag(NewTagLoc, diag::warn_struct_class_previous_tag_mismatch) - << getRedeclDiagFromTagKind(NewTag) << isTemplate << Name - << getRedeclDiagFromTagKind(I->getTagKind()); - } - Diag(I->getInnerLocStart(), diag::note_struct_class_suggestion) - << getRedeclDiagFromTagKind(NewTag) - << FixItHint::CreateReplacement(I->getInnerLocStart(), - TypeWithKeyword::getTagTypeKindName(NewTag)); + if (!previousMismatch) { + previousMismatch = true; + Diag(NewTagLoc, diag::warn_struct_class_previous_tag_mismatch) + << getRedeclDiagFromTagKind(NewTag) << isTemplate << Name + << getRedeclDiagFromTagKind(I->getTagKind()); } + Diag(I->getInnerLocStart(), diag::note_struct_class_suggestion) + << getRedeclDiagFromTagKind(NewTag) + << FixItHint::CreateReplacement(I->getInnerLocStart(), + TypeWithKeyword::getTagTypeKindName(NewTag)); } - return true; - } - - // Check for a previous definition. If current tag and definition - // are same type, do nothing. If no definition, but disagree with - // with previous tag type, give a warning, but no fix-it. - const TagDecl *Redecl = Previous->getDefinition() ? - Previous->getDefinition() : Previous; - if (Redecl->getTagKind() == NewTag) { - return true; } + return true; + } + // Identify the prevailing tag kind: this is the kind of the definition (if + // there is a non-ignored definition), or otherwise the kind of the prior + // (non-ignored) declaration. + const TagDecl *PrevDef = Previous->getDefinition(); + if (PrevDef && IsIgnored(PrevDef)) + PrevDef = nullptr; + const TagDecl *Redecl = PrevDef ? PrevDef : Previous; + if (Redecl->getTagKind() != NewTag) { Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch) << getRedeclDiagFromTagKind(NewTag) << isTemplate << Name << getRedeclDiagFromTagKind(OldTag); Diag(Redecl->getLocation(), diag::note_previous_use); // If there is a previous definition, suggest a fix-it. - if (Previous->getDefinition()) { - Diag(NewTagLoc, diag::note_struct_class_suggestion) - << getRedeclDiagFromTagKind(Redecl->getTagKind()) - << FixItHint::CreateReplacement(SourceRange(NewTagLoc), - TypeWithKeyword::getTagTypeKindName(Redecl->getTagKind())); + if (PrevDef) { + Diag(NewTagLoc, diag::note_struct_class_suggestion) + << getRedeclDiagFromTagKind(Redecl->getTagKind()) + << FixItHint::CreateReplacement(SourceRange(NewTagLoc), + TypeWithKeyword::getTagTypeKindName(Redecl->getTagKind())); } - - return true; } - return false; + + return true; } /// Add a minimal nested name specifier fixit hint to allow lookup of a tag name @@ -14031,7 +14165,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // many points during the parsing of a struct declaration (because // the #pragma tokens are effectively skipped over during the // parsing of the struct). - if (TUK == TUK_Definition) { + if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip)) { AddAlignmentAttributesForRecord(RD); AddMsStructLayoutForRecord(RD); } @@ -14462,12 +14596,15 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // comparison. SkipBody->CheckSameAsPrevious = true; SkipBody->New = createTagFromNewDecl(); - SkipBody->Previous = Hidden; + SkipBody->Previous = Def; + return Def; } else { SkipBody->ShouldSkip = true; + SkipBody->Previous = Def; makeMergedDefinitionVisible(Hidden); + // Carry on and handle it like a normal definition. We'll + // skip starting the definitiion later. } - return Def; } else if (!IsExplicitSpecializationAfterInstantiation) { // A redeclaration in function prototype scope in C isn't // visible elsewhere, so merely issue a warning. @@ -14606,7 +14743,7 @@ CreateNewDecl: // If this is an undefined enum, warn. if (TUK != TUK_Definition && !Invalid) { TagDecl *Def; - if (IsFixed && (getLangOpts().CPlusPlus11 || getLangOpts().ObjC2) && + if (IsFixed && (getLangOpts().CPlusPlus11 || getLangOpts().ObjC) && cast<EnumDecl>(New)->isFixed()) { // C++0x: 7.2p2: opaque-enum-declaration. // Conflicts are diagnosed above. Do nothing. @@ -14696,7 +14833,7 @@ CreateNewDecl: // many points during the parsing of a struct declaration (because // the #pragma tokens are effectively skipped over during the // parsing of the struct). - if (TUK == TUK_Definition) { + if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip)) { AddAlignmentAttributesForRecord(RD); AddMsStructLayoutForRecord(RD); } @@ -14758,7 +14895,7 @@ CreateNewDecl: if (PrevDecl) CheckRedeclarationModuleOwnership(New, PrevDecl); - if (TUK == TUK_Definition) + if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip)) New->startDefinition(); ProcessDeclAttributeList(S, New, Attrs); @@ -14808,6 +14945,8 @@ CreateNewDecl: if (auto RD = dyn_cast<RecordDecl>(New)) RD->completeDefinition(); return nullptr; + } else if (SkipBody && SkipBody->ShouldSkip) { + return SkipBody->Previous; } else { return New; } @@ -14868,12 +15007,11 @@ void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, // class itself; this is known as the injected-class-name. For // purposes of access checking, the injected-class-name is treated // as if it were a public member name. - CXXRecordDecl *InjectedClassName - = CXXRecordDecl::Create(Context, Record->getTagKind(), CurContext, - Record->getLocStart(), Record->getLocation(), - Record->getIdentifier(), - /*PrevDecl=*/nullptr, - /*DelayTypeCreation=*/true); + CXXRecordDecl *InjectedClassName = CXXRecordDecl::Create( + Context, Record->getTagKind(), CurContext, Record->getBeginLoc(), + Record->getLocation(), Record->getIdentifier(), + /*PrevDecl=*/nullptr, + /*DelayTypeCreation=*/true); Context.getTypeDeclType(InjectedClassName, Record); InjectedClassName->setImplicit(); InjectedClassName->setAccess(AS_public); @@ -15080,22 +15218,6 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, } } - // TR 18037 does not allow fields to be declared with address spaces. - if (T.getQualifiers().hasAddressSpace() || - T->isDependentAddressSpaceType() || - T->getBaseElementTypeUnsafe()->isDependentAddressSpaceType()) { - Diag(Loc, diag::err_field_with_address_space); - D.setInvalidType(); - } - - // OpenCL v1.2 s6.9b,r & OpenCL v2.0 s6.12.5 - The following types cannot be - // used as structure or union field: image, sampler, event or block types. - if (LangOpts.OpenCL && (T->isEventT() || T->isImageType() || - T->isSamplerT() || T->isBlockPointerType())) { - Diag(Loc, diag::err_opencl_type_struct_or_union_field) << T; - D.setInvalidType(); - } - DiagnoseFunctionSpecifiers(D.getDeclSpec()); if (D.getDeclSpec().isInlineSpecified()) @@ -15140,7 +15262,7 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, bool Mutable = (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_mutable); - SourceLocation TSSL = D.getLocStart(); + SourceLocation TSSL = D.getBeginLoc(); FieldDecl *NewFD = CheckFieldDecl(II, T, TInfo, Record, Loc, Mutable, BitWidth, InitStyle, TSSL, AS, PrevDecl, &D); @@ -15207,12 +15329,30 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, } } - // OpenCL v1.2 s6.9.c: bitfields are not supported. - if (BitWidth && getLangOpts().OpenCL) { - Diag(Loc, diag::err_opencl_bitfields); + // TR 18037 does not allow fields to be declared with address space + if (T.getQualifiers().hasAddressSpace() || T->isDependentAddressSpaceType() || + T->getBaseElementTypeUnsafe()->isDependentAddressSpaceType()) { + Diag(Loc, diag::err_field_with_address_space); + Record->setInvalidDecl(); InvalidDecl = true; } + if (LangOpts.OpenCL) { + // OpenCL v1.2 s6.9b,r & OpenCL v2.0 s6.12.5 - The following types cannot be + // used as structure or union field: image, sampler, event or block types. + if (T->isEventT() || T->isImageType() || T->isSamplerT() || + T->isBlockPointerType()) { + Diag(Loc, diag::err_opencl_type_struct_or_union_field) << T; + Record->setInvalidDecl(); + InvalidDecl = true; + } + // OpenCL v1.2 s6.9.c: bitfields are not supported. + if (BitWidth) { + Diag(Loc, diag::err_opencl_bitfields); + InvalidDecl = true; + } + } + // Anonymous bit-fields cannot be cv-qualified (CWG 2229). if (!InvalidDecl && getLangOpts().CPlusPlus && !II && BitWidth && T.hasQualifiers()) { @@ -15602,6 +15742,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, } RecordDecl *Record = dyn_cast<RecordDecl>(EnclosingDecl); + CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(EnclosingDecl); // Start counting up the number of named members; make sure to include // members of anonymous structs and unions in the total. @@ -15691,9 +15832,8 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, // virtual bases after the derived members. This would make a flexible // array member declared at the end of an object not adjacent to the end // of the type. - if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Record)) - if (RD->getNumVBases() != 0) - Diag(FD->getLocation(), diag::err_flexible_array_virtual_base) + if (CXXRecord && CXXRecord->getNumVBases() != 0) + Diag(FD->getLocation(), diag::err_flexible_array_virtual_base) << FD->getDeclName() << Record->getTagKind(); if (!getLangOpts().C99) Diag(FD->getLocation(), diag::ext_c99_flexible_array_member) @@ -15784,7 +15924,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, } ObjCFieldLifetimeErrReported = true; } - } else if (getLangOpts().ObjC1 && + } else if (getLangOpts().ObjC && getLangOpts().getGC() != LangOptions::NonGC && Record && !Record->hasObjectMember()) { if (FD->getType()->isObjCObjectPointerType() || @@ -15831,7 +15971,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, // Okay, we successfully defined 'Record'. if (Record) { bool Completed = false; - if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record)) { + if (CXXRecord) { if (!CXXRecord->isInvalidDecl()) { // Set access bits correctly on the directly-declared conversions. for (CXXRecordDecl::conversion_iterator @@ -15841,13 +15981,6 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, } if (!CXXRecord->isDependentType()) { - if (CXXRecord->hasUserDeclaredDestructor()) { - // Adjust user-defined destructor exception spec. - if (getLangOpts().CPlusPlus11) - AdjustDestructorExceptionSpec(CXXRecord, - CXXRecord->getDestructor()); - } - // Add any implicitly-declared members to this class. AddImplicitlyDeclaredMembersToClass(CXXRecord); @@ -15902,7 +16035,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, ProcessDeclAttributeList(S, Record, Attrs); // We may have deferred checking for a deleted destructor. Check now. - if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record)) { + if (CXXRecord) { auto *Dtor = CXXRecord->getDestructor(); if (Dtor && Dtor->isImplicit() && ShouldDeleteSpecialMember(Dtor, CXXDestructor)) { @@ -16289,8 +16422,10 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, // Verify that there isn't already something declared with this name in this // scope. - NamedDecl *PrevDecl = LookupSingleName(S, Id, IdLoc, LookupOrdinaryName, - ForVisibleRedeclaration); + LookupResult R(*this, Id, IdLoc, LookupOrdinaryName, ForVisibleRedeclaration); + LookupName(R, S); + NamedDecl *PrevDecl = R.getAsSingle<NamedDecl>(); + if (PrevDecl && PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. DiagnoseTemplateParameterShadow(IdLoc, PrevDecl); @@ -16313,6 +16448,11 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, return nullptr; if (PrevDecl) { + if (!TheEnumDecl->isScoped() && isa<ValueDecl>(PrevDecl)) { + // Check for other kinds of shadowing not already handled. + CheckShadow(New, PrevDecl, R); + } + // When in C++, we may get a TagDecl with the same name; in this case the // enum constant will 'hide' the tag. assert((getLangOpts().CPlusPlus || !isa<TagDecl>(PrevDecl)) && @@ -16399,7 +16539,7 @@ static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements, typedef SmallVector<std::unique_ptr<ECDVector>, 3> DuplicatesVector; typedef llvm::PointerUnion<EnumConstantDecl*, ECDVector*> DeclOrVector; - typedef llvm::DenseMap<int64_t, DeclOrVector> ValueToVectorMap; + typedef std::unordered_map<int64_t, DeclOrVector> ValueToVectorMap; // Use int64_t as a key to avoid needing special handling for DenseMap keys. auto EnumConstantToKey = [](const EnumConstantDecl *D) { @@ -16570,7 +16710,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, NumNegativeBits = std::max(NumNegativeBits, (unsigned)InitVal.getMinSignedBits()); - // Keep track of whether every enum element has type int (very commmon). + // Keep track of whether every enum element has type int (very common). if (AllElementsInt) AllElementsInt = ECD->getType() == Context.IntTy; } @@ -16776,7 +16916,7 @@ static void checkModuleImportContext(Sema &S, Module *M, switch (LSD->getLanguage()) { case LinkageSpecDecl::lang_c: if (ExternCLoc.isInvalid()) - ExternCLoc = LSD->getLocStart(); + ExternCLoc = LSD->getBeginLoc(); break; case LinkageSpecDecl::lang_cxx: break; @@ -16792,8 +16932,9 @@ static void checkModuleImportContext(Sema &S, Module *M, ? diag::ext_module_import_not_at_top_level_noop : diag::err_module_import_not_at_top_level_fatal) << M->getFullModuleName() << DC; - S.Diag(cast<Decl>(DC)->getLocStart(), - diag::note_module_import_not_at_top_level) << DC; + S.Diag(cast<Decl>(DC)->getBeginLoc(), + diag::note_module_import_not_at_top_level) + << DC; } else if (!M->IsExternC && ExternCLoc.isValid()) { S.Diag(ImportLoc, diag::ext_module_import_in_extern_c) << M->getFullModuleName(); @@ -16830,6 +16971,10 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc, case LangOptions::CMK_ModuleMap: Diag(ModuleLoc, diag::err_module_decl_in_module_map_module); return nullptr; + + case LangOptions::CMK_HeaderModule: + Diag(ModuleLoc, diag::err_module_decl_in_header_module); + return nullptr; } assert(ModuleScopes.size() == 1 && "expected to be at global module scope"); @@ -16898,7 +17043,8 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc, case ModuleDeclKind::Implementation: std::pair<IdentifierInfo *, SourceLocation> ModuleNameLoc( PP.getIdentifierInfo(ModuleName), Path[0].second); - Mod = getModuleLoader().loadModule(ModuleLoc, Path, Module::AllVisible, + Mod = getModuleLoader().loadModule(ModuleLoc, {ModuleNameLoc}, + Module::AllVisible, /*IsIncludeDirective=*/false); if (!Mod) { Diag(ModuleLoc, diag::err_module_not_defined) << ModuleName; @@ -16928,6 +17074,19 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc, DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc, SourceLocation ImportLoc, ModuleIdPath Path) { + // Flatten the module path for a Modules TS module name. + std::pair<IdentifierInfo *, SourceLocation> ModuleNameLoc; + if (getLangOpts().ModulesTS) { + std::string ModuleName; + for (auto &Piece : Path) { + if (!ModuleName.empty()) + ModuleName += "."; + ModuleName += Piece.first->getName(); + } + ModuleNameLoc = {PP.getIdentifierInfo(ModuleName), Path[0].second}; + Path = ModuleIdPath(ModuleNameLoc); + } + Module *Mod = getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible, /*IsIncludeDirective=*/false); diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 77deed6047f47..0e10804a2ec76 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -93,6 +93,17 @@ static unsigned getFunctionOrMethodNumParams(const Decl *D) { return cast<ObjCMethodDecl>(D)->param_size(); } +static const ParmVarDecl *getFunctionOrMethodParam(const Decl *D, + unsigned Idx) { + if (const auto *FD = dyn_cast<FunctionDecl>(D)) + return FD->getParamDecl(Idx); + if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) + return MD->getParamDecl(Idx); + if (const auto *BD = dyn_cast<BlockDecl>(D)) + return BD->getParamDecl(Idx); + return nullptr; +} + static QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx) { if (const FunctionType *FnTy = D->getFunctionType()) return cast<FunctionProtoType>(FnTy)->getParamType(Idx); @@ -103,12 +114,8 @@ static QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx) { } static SourceRange getFunctionOrMethodParamRange(const Decl *D, unsigned Idx) { - if (const auto *FD = dyn_cast<FunctionDecl>(D)) - return FD->getParamDecl(Idx)->getSourceRange(); - if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) - return MD->parameters()[Idx]->getSourceRange(); - if (const auto *BD = dyn_cast<BlockDecl>(D)) - return BD->getParamDecl(Idx)->getSourceRange(); + if (auto *PVD = getFunctionOrMethodParam(D, Idx)) + return PVD->getSourceRange(); return SourceRange(); } @@ -182,7 +189,7 @@ static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL, unsigned Num, unsigned Diag, Compare Comp) { if (Comp(getNumAttributeArgs(AL), Num)) { - S.Diag(AL.getLoc(), Diag) << AL.getName() << Num; + S.Diag(AL.getLoc(), Diag) << AL << Num; return false; } @@ -225,34 +232,25 @@ getAttrLoc(const AttrInfo &AL) { } static SourceLocation getAttrLoc(const ParsedAttr &AL) { return AL.getLoc(); } -/// A helper function to provide Attribute Name for the Attr types -/// AND the ParsedAttr. -template <typename AttrInfo> -static typename std::enable_if<std::is_base_of<Attr, AttrInfo>::value, - const AttrInfo *>::type -getAttrName(const AttrInfo &AL) { - return &AL; -} -static const IdentifierInfo *getAttrName(const ParsedAttr &AL) { - return AL.getName(); -} - /// If Expr is a valid integer constant, get the value of the integer /// expression and return success or failure. May output an error. +/// +/// Negative argument is implicitly converted to unsigned, unless +/// \p StrictlyUnsigned is true. template <typename AttrInfo> static bool checkUInt32Argument(Sema &S, const AttrInfo &AI, const Expr *Expr, - uint32_t &Val, unsigned Idx = UINT_MAX) { + uint32_t &Val, unsigned Idx = UINT_MAX, + bool StrictlyUnsigned = false) { llvm::APSInt I(32); if (Expr->isTypeDependent() || Expr->isValueDependent() || !Expr->isIntegerConstantExpr(I, S.Context)) { if (Idx != UINT_MAX) S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type) - << getAttrName(AI) << Idx << AANT_ArgumentIntegerConstant - << Expr->getSourceRange(); + << AI << Idx << AANT_ArgumentIntegerConstant + << Expr->getSourceRange(); else S.Diag(getAttrLoc(AI), diag::err_attribute_argument_type) - << getAttrName(AI) << AANT_ArgumentIntegerConstant - << Expr->getSourceRange(); + << AI << AANT_ArgumentIntegerConstant << Expr->getSourceRange(); return false; } @@ -262,6 +260,12 @@ static bool checkUInt32Argument(Sema &S, const AttrInfo &AI, const Expr *Expr, return false; } + 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(); return true; } @@ -291,10 +295,19 @@ static bool checkPositiveIntArgument(Sema &S, const AttrInfo &AI, const Expr *Ex /// Diagnose mutually exclusive attributes when present on a given /// declaration. Returns true if diagnosed. template <typename AttrTy> -static bool checkAttrMutualExclusion(Sema &S, Decl *D, SourceRange Range, - IdentifierInfo *Ident) { +static bool checkAttrMutualExclusion(Sema &S, Decl *D, const ParsedAttr &AL) { if (const auto *A = D->getAttr<AttrTy>()) { - S.Diag(Range.getBegin(), diag::err_attributes_are_not_compatible) << Ident + S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) << AL << A; + S.Diag(A->getLocation(), diag::note_conflicting_attribute); + return true; + } + return false; +} + +template <typename AttrTy> +static bool checkAttrMutualExclusion(Sema &S, Decl *D, const Attr &AL) { + if (const auto *A = D->getAttr<AttrTy>()) { + S.Diag(AL.getLocation(), diag::err_attributes_are_not_compatible) << &AL << A; S.Diag(A->getLocation(), diag::note_conflicting_attribute); return true; @@ -324,22 +337,21 @@ static bool checkFunctionOrMethodParameterIndex( if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() || !IdxExpr->isIntegerConstantExpr(IdxInt, S.Context)) { S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type) - << getAttrName(AI) << AttrArgNum << AANT_ArgumentIntegerConstant - << IdxExpr->getSourceRange(); + << &AI << AttrArgNum << AANT_ArgumentIntegerConstant + << IdxExpr->getSourceRange(); return false; } unsigned IdxSource = IdxInt.getLimitedValue(UINT_MAX); if (IdxSource < 1 || (!IV && IdxSource > NumParams)) { S.Diag(getAttrLoc(AI), diag::err_attribute_argument_out_of_bounds) - << getAttrName(AI) << AttrArgNum << IdxExpr->getSourceRange(); + << &AI << AttrArgNum << IdxExpr->getSourceRange(); return false; } if (HasImplicitThisParam && !CanIndexImplicitThis) { if (IdxSource == 1) { - S.Diag(getAttrLoc(AI), - diag::err_attribute_invalid_implicit_this_argument) - << getAttrName(AI) << IdxExpr->getSourceRange(); + S.Diag(getAttrLoc(AI), diag::err_attribute_invalid_implicit_this_argument) + << &AI << IdxExpr->getSourceRange(); return false; } } @@ -359,7 +371,7 @@ bool Sema::checkStringLiteralArgumentAttr(const ParsedAttr &AL, unsigned ArgNum, if (AL.isArgIdent(ArgNum)) { IdentifierLoc *Loc = AL.getArgAsIdent(ArgNum); Diag(Loc->Loc, diag::err_attribute_argument_type) - << AL.getName() << AANT_ArgumentString + << AL << AANT_ArgumentString << FixItHint::CreateInsertion(Loc->Loc, "\"") << FixItHint::CreateInsertion(getLocForEndOfToken(Loc->Loc), "\""); Str = Loc->Ident->getName(); @@ -372,11 +384,11 @@ bool Sema::checkStringLiteralArgumentAttr(const ParsedAttr &AL, unsigned ArgNum, Expr *ArgExpr = AL.getArgAsExpr(ArgNum); const auto *Literal = dyn_cast<StringLiteral>(ArgExpr->IgnoreParenCasts()); if (ArgLocation) - *ArgLocation = ArgExpr->getLocStart(); + *ArgLocation = ArgExpr->getBeginLoc(); if (!Literal || !Literal->isAscii()) { - Diag(ArgExpr->getLocStart(), diag::err_attribute_argument_type) - << AL.getName() << AANT_ArgumentString; + Diag(ArgExpr->getBeginLoc(), diag::err_attribute_argument_type) + << AL << AANT_ArgumentString; return false; } @@ -387,9 +399,59 @@ bool Sema::checkStringLiteralArgumentAttr(const ParsedAttr &AL, unsigned ArgNum, /// Applies the given attribute to the Decl without performing any /// additional semantic checking. template <typename AttrType> +static void handleSimpleAttribute(Sema &S, Decl *D, SourceRange SR, + unsigned SpellingIndex) { + D->addAttr(::new (S.Context) AttrType(SR, S.Context, SpellingIndex)); +} + +template <typename AttrType> static void handleSimpleAttribute(Sema &S, Decl *D, const ParsedAttr &AL) { - D->addAttr(::new (S.Context) AttrType(AL.getRange(), S.Context, - AL.getAttributeSpellingListIndex())); + handleSimpleAttribute<AttrType>(S, D, AL.getRange(), + AL.getAttributeSpellingListIndex()); +} + + +template <typename... DiagnosticArgs> +static const Sema::SemaDiagnosticBuilder& +appendDiagnostics(const Sema::SemaDiagnosticBuilder &Bldr) { + return Bldr; +} + +template <typename T, typename... DiagnosticArgs> +static const Sema::SemaDiagnosticBuilder& +appendDiagnostics(const Sema::SemaDiagnosticBuilder &Bldr, T &&ExtraArg, + DiagnosticArgs &&... ExtraArgs) { + return appendDiagnostics(Bldr << std::forward<T>(ExtraArg), + std::forward<DiagnosticArgs>(ExtraArgs)...); +} + +/// Add an attribute {@code AttrType} to declaration {@code D}, provided that +/// {@code PassesCheck} is true. +/// Otherwise, emit diagnostic {@code DiagID}, passing in all parameters +/// specified in {@code ExtraArgs}. +template <typename AttrType, typename... DiagnosticArgs> +static void +handleSimpleAttributeOrDiagnose(Sema &S, Decl *D, SourceRange SR, + unsigned SpellingIndex, + bool PassesCheck, + unsigned DiagID, DiagnosticArgs&&... ExtraArgs) { + if (!PassesCheck) { + Sema::SemaDiagnosticBuilder DB = S.Diag(D->getBeginLoc(), DiagID); + appendDiagnostics(DB, std::forward<DiagnosticArgs>(ExtraArgs)...); + return; + } + handleSimpleAttribute<AttrType>(S, D, SR, SpellingIndex); +} + +template <typename AttrType, typename... DiagnosticArgs> +static void +handleSimpleAttributeOrDiagnose(Sema &S, Decl *D, const ParsedAttr &AL, + bool PassesCheck, + unsigned DiagID, + DiagnosticArgs&&... ExtraArgs) { + return handleSimpleAttributeOrDiagnose<AttrType>( + S, D, AL.getRange(), AL.getAttributeSpellingListIndex(), PassesCheck, + DiagID, std::forward<DiagnosticArgs>(ExtraArgs)...); } template <typename AttrType> @@ -404,8 +466,7 @@ template <typename AttrType, typename IncompatibleAttrType, typename... IncompatibleAttrTypes> static void handleSimpleAttributeWithExclusions(Sema &S, Decl *D, const ParsedAttr &AL) { - if (checkAttrMutualExclusion<IncompatibleAttrType>(S, D, AL.getRange(), - AL.getName())) + if (checkAttrMutualExclusion<IncompatibleAttrType>(S, D, AL)) return; handleSimpleAttributeWithExclusions<AttrType, IncompatibleAttrTypes...>(S, D, AL); @@ -421,17 +482,36 @@ static bool isIntOrBool(Expr *Exp) { // Check to see if the type is a smart pointer of some kind. We assume // it's a smart pointer if it defines both operator-> and operator*. static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) { - DeclContextLookupResult Res1 = RT->getDecl()->lookup( - S.Context.DeclarationNames.getCXXOperatorName(OO_Star)); - if (Res1.empty()) - return false; + auto IsOverloadedOperatorPresent = [&S](const RecordDecl *Record, + OverloadedOperatorKind Op) { + DeclContextLookupResult Result = + Record->lookup(S.Context.DeclarationNames.getCXXOperatorName(Op)); + return !Result.empty(); + }; + + const RecordDecl *Record = RT->getDecl(); + bool foundStarOperator = IsOverloadedOperatorPresent(Record, OO_Star); + bool foundArrowOperator = IsOverloadedOperatorPresent(Record, OO_Arrow); + if (foundStarOperator && foundArrowOperator) + return true; - DeclContextLookupResult Res2 = RT->getDecl()->lookup( - S.Context.DeclarationNames.getCXXOperatorName(OO_Arrow)); - if (Res2.empty()) + const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record); + if (!CXXRecord) return false; - return true; + for (auto BaseSpecifier : CXXRecord->bases()) { + if (!foundStarOperator) + foundStarOperator = IsOverloadedOperatorPresent( + BaseSpecifier.getType()->getAsRecordDecl(), OO_Star); + if (!foundArrowOperator) + foundArrowOperator = IsOverloadedOperatorPresent( + BaseSpecifier.getType()->getAsRecordDecl(), OO_Arrow); + } + + if (foundStarOperator && foundArrowOperator) + return true; + + return false; } /// Check if passed in Decl is a pointer type. @@ -455,8 +535,7 @@ static bool threadSafetyCheckIsPointer(Sema &S, const Decl *D, return true; } - S.Diag(AL.getLoc(), diag::warn_thread_attribute_decl_not_pointer) - << AL.getName() << QT; + S.Diag(AL.getLoc(), diag::warn_thread_attribute_decl_not_pointer) << AL << QT; return false; } @@ -473,6 +552,29 @@ static const RecordType *getRecordType(QualType QT) { return nullptr; } +template <typename AttrType> +static bool checkRecordDeclForAttr(const RecordDecl *RD) { + // Check if the record itself has the attribute. + if (RD->hasAttr<AttrType>()) + return true; + + // Else check if any base classes have the attribute. + if (const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) { + CXXBasePaths BPaths(false, false); + if (CRD->lookupInBases( + [](const CXXBaseSpecifier *BS, CXXBasePath &) { + const auto &Ty = *BS->getType(); + // If it's type-dependent, we assume it could have the attribute. + if (Ty.isDependentType()) + return true; + return Ty.getAs<RecordType>()->getDecl()->hasAttr<AttrType>(); + }, + BPaths, true)) + return true; + } + return false; +} + static bool checkRecordTypeForCapability(Sema &S, QualType Ty) { const RecordType *RT = getRecordType(Ty); @@ -488,21 +590,7 @@ static bool checkRecordTypeForCapability(Sema &S, QualType Ty) { if (threadSafetyCheckIsSmartPointer(S, RT)) return true; - // Check if the record itself has a capability. - RecordDecl *RD = RT->getDecl(); - if (RD->hasAttr<CapabilityAttr>()) - return true; - - // Else check if any base classes have a capability. - if (const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) { - CXXBasePaths BPaths(false, false); - if (CRD->lookupInBases([](const CXXBaseSpecifier *BS, CXXBasePath &) { - const auto *Type = BS->getType()->getAs<RecordType>(); - return Type->getDecl()->hasAttr<CapabilityAttr>(); - }, BPaths)) - return true; - } - return false; + return checkRecordDeclForAttr<CapabilityAttr>(RT->getDecl()); } static bool checkTypedefTypeForCapability(QualType Ty) { @@ -560,8 +648,27 @@ static bool isCapabilityExpr(Sema &S, const Expr *Ex) { static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D, const ParsedAttr &AL, SmallVectorImpl<Expr *> &Args, - int Sidx = 0, + unsigned Sidx = 0, bool ParamIdxOk = false) { + if (Sidx == AL.getNumArgs()) { + // If we don't have any capability arguments, the attribute implicitly + // refers to 'this'. So we need to make sure that 'this' exists, i.e. we're + // a non-static method, and that the class is a (scoped) capability. + const auto *MD = dyn_cast<const CXXMethodDecl>(D); + if (MD && !MD->isStatic()) { + const CXXRecordDecl *RD = MD->getParent(); + // FIXME -- need to check this again on template instantiation + if (!checkRecordDeclForAttr<CapabilityAttr>(RD) && + !checkRecordDeclForAttr<ScopedLockableAttr>(RD)) + S.Diag(AL.getLoc(), + diag::warn_thread_attribute_not_on_capability_member) + << AL << MD->getParent(); + } else { + S.Diag(AL.getLoc(), diag::warn_thread_attribute_not_on_non_static_member) + << AL; + } + } + for (unsigned Idx = Sidx; Idx < AL.getNumArgs(); ++Idx) { Expr *ArgExp = AL.getArgAsExpr(Idx); @@ -582,7 +689,7 @@ static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D, // We allow constant strings to be used as a placeholder for expressions // that are not valid C++ syntax, but warn that they are ignored. - S.Diag(AL.getLoc(), diag::warn_thread_attribute_ignored) << AL.getName(); + S.Diag(AL.getLoc(), diag::warn_thread_attribute_ignored) << AL; Args.push_back(ArgExp); continue; } @@ -611,7 +718,7 @@ static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D, uint64_t ParamIdxFromZero = ParamIdxFromOne - 1; if (!ArgValue.isStrictlyPositive() || ParamIdxFromOne > NumParams) { S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_range) - << AL.getName() << Idx + 1 << NumParams; + << AL << Idx + 1 << NumParams; continue; } ArgTy = FD->getParamDecl(ParamIdxFromZero)->getType(); @@ -624,7 +731,7 @@ static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D, // boolean logic expression. Eg) requires_capability(A || B && !C) if (!typeHasCapability(S, ArgTy) && !isCapabilityExpr(S, ArgExp)) S.Diag(AL.getLoc(), diag::warn_thread_attribute_argument_not_lockable) - << AL.getName() << ArgTy; + << AL << ArgTy; Args.push_back(ArgExp); } @@ -686,8 +793,7 @@ static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL, // Check that this attribute only applies to lockable types. QualType QT = cast<ValueDecl>(D)->getType(); if (!QT->isDependentType() && !typeHasCapability(S, QT)) { - S.Diag(AL.getLoc(), diag::warn_thread_attribute_decl_not_lockable) - << AL.getName(); + S.Diag(AL.getLoc(), diag::warn_thread_attribute_decl_not_lockable) << AL; return false; } @@ -772,9 +878,9 @@ static bool checkParamIsIntegerType(Sema &S, const FunctionDecl *FD, const ParmVarDecl *Param = FD->getParamDecl(Idx.getASTIndex()); if (!Param->getType()->isIntegerType() && !Param->getType()->isCharType()) { - SourceLocation SrcLoc = AttrArg->getLocStart(); + SourceLocation SrcLoc = AttrArg->getBeginLoc(); S.Diag(SrcLoc, diag::err_attribute_integers_only) - << getAttrName(AI) << Param->getSourceRange(); + << AI << Param->getSourceRange(); return false; } return true; @@ -787,8 +893,7 @@ static void handleAllocSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { const auto *FD = cast<FunctionDecl>(D); if (!FD->getReturnType()->isPointerType()) { - S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only) - << AL.getName(); + S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only) << AL; return; } @@ -825,7 +930,7 @@ static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL, if (!isIntOrBool(AL.getArgAsExpr(0))) { S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) - << AL.getName() << 1 << AANT_ArgumentIntOrBool; + << AL << 1 << AANT_ArgumentIntOrBool; return false; } @@ -907,8 +1012,7 @@ static bool checkFunctionConditionAttr(Sema &S, Decl *D, const ParsedAttr &AL, if (isa<FunctionDecl>(D) && !Cond->isValueDependent() && !Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(D), Diags)) { - S.Diag(AL.getLoc(), diag::err_attr_cond_never_constant_expr) - << AL.getName(); + S.Diag(AL.getLoc(), diag::err_attr_cond_never_constant_expr) << AL; for (const PartialDiagnosticAt &PDiag : Diags) S.Diag(PDiag.first, PDiag.second); return false; @@ -987,7 +1091,7 @@ static void handleDiagnoseIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) { DiagnoseIfAttr::DiagnosticType DiagType; if (!DiagnoseIfAttr::ConvertStrToDiagnosticType(DiagTypeStr, DiagType)) { - S.Diag(AL.getArgAsExpr(2)->getLocStart(), + S.Diag(AL.getArgAsExpr(2)->getBeginLoc(), diag::err_diagnose_if_invalid_diagnostic_type); return; } @@ -1002,8 +1106,7 @@ static void handleDiagnoseIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) { static void handlePassObjectSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (D->hasAttr<PassObjectSizeAttr>()) { - S.Diag(D->getLocStart(), diag::err_attribute_only_once_per_parameter) - << AL.getName(); + S.Diag(D->getBeginLoc(), diag::err_attribute_only_once_per_parameter) << AL; return; } @@ -1016,8 +1119,8 @@ static void handlePassObjectSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // __builtin_object_size. So, it has the same constraints as that second // argument; namely, it must be in the range [0, 3]. if (Type > 3) { - S.Diag(E->getLocStart(), diag::err_attribute_argument_outof_range) - << AL.getName() << 0 << 3 << E->getSourceRange(); + S.Diag(E->getBeginLoc(), diag::err_attribute_argument_outof_range) + << AL << 0 << 3 << E->getSourceRange(); return; } @@ -1026,8 +1129,7 @@ static void handlePassObjectSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // At this point, we have no clue if `D` belongs to a function declaration or // definition, so we defer the constness check until later. if (!cast<ParmVarDecl>(D)->getType()->isPointerType()) { - S.Diag(D->getLocStart(), diag::err_attribute_pointers_only) - << AL.getName() << 1; + S.Diag(D->getBeginLoc(), diag::err_attribute_pointers_only) << AL << 1; return; } @@ -1042,13 +1144,13 @@ static void handleConsumableAttr(Sema &S, Decl *D, const ParsedAttr &AL) { IdentifierLoc *IL = AL.getArgAsIdent(0); if (!ConsumableAttr::ConvertStrToConsumedState(IL->Ident->getName(), DefaultState)) { - S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) - << AL.getName() << IL->Ident; + S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL + << IL->Ident; return; } } else { S.Diag(AL.getLoc(), diag::err_attribute_argument_type) - << AL.getName() << AANT_ArgumentIdentifier; + << AL << AANT_ArgumentIdentifier; return; } @@ -1059,8 +1161,7 @@ static void handleConsumableAttr(Sema &S, Decl *D, const ParsedAttr &AL) { static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD, const ParsedAttr &AL) { - ASTContext &CurrContext = S.getASTContext(); - QualType ThisType = MD->getThisType(CurrContext)->getPointeeType(); + QualType ThisType = MD->getThisType()->getPointeeType(); if (const CXXRecordDecl *RD = ThisType->getAsCXXRecordDecl()) { if (!RD->hasAttr<ConsumableAttr>()) { @@ -1098,8 +1199,7 @@ static void handleCallableWhenAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!CallableWhenAttr::ConvertStrToConsumedState(StateString, CallableState)) { - S.Diag(Loc, diag::warn_attribute_type_not_supported) - << AL.getName() << StateString; + S.Diag(Loc, diag::warn_attribute_type_not_supported) << AL << StateString; return; } @@ -1121,12 +1221,12 @@ static void handleParamTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!ParamTypestateAttr::ConvertStrToConsumedState(StateString, ParamState)) { S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) - << AL.getName() << StateString; + << AL << StateString; return; } } else { - S.Diag(AL.getLoc(), diag::err_attribute_argument_type) << - AL.getName() << AANT_ArgumentIdentifier; + S.Diag(AL.getLoc(), diag::err_attribute_argument_type) + << AL << AANT_ArgumentIdentifier; return; } @@ -1154,13 +1254,13 @@ static void handleReturnTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { IdentifierLoc *IL = AL.getArgAsIdent(0); if (!ReturnTypestateAttr::ConvertStrToConsumedState(IL->Ident->getName(), ReturnState)) { - S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) - << AL.getName() << IL->Ident; + S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL + << IL->Ident; return; } } else { - S.Diag(AL.getLoc(), diag::err_attribute_argument_type) << - AL.getName() << AANT_ArgumentIdentifier; + S.Diag(AL.getLoc(), diag::err_attribute_argument_type) + << AL << AANT_ArgumentIdentifier; return; } @@ -1174,7 +1274,7 @@ static void handleReturnTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // //} else if (const CXXConstructorDecl *Constructor = // dyn_cast<CXXConstructorDecl>(D)) { - // ReturnType = Constructor->getThisType(S.getASTContext())->getPointeeType(); + // ReturnType = Constructor->getThisType()->getPointeeType(); // //} else { // @@ -1203,13 +1303,13 @@ static void handleSetTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { IdentifierLoc *Ident = AL.getArgAsIdent(0); StringRef Param = Ident->Ident->getName(); if (!SetTypestateAttr::ConvertStrToConsumedState(Param, NewState)) { - S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) - << AL.getName() << Param; + S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) << AL + << Param; return; } } else { - S.Diag(AL.getLoc(), diag::err_attribute_argument_type) << - AL.getName() << AANT_ArgumentIdentifier; + S.Diag(AL.getLoc(), diag::err_attribute_argument_type) + << AL << AANT_ArgumentIdentifier; return; } @@ -1227,13 +1327,13 @@ static void handleTestTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { IdentifierLoc *Ident = AL.getArgAsIdent(0); StringRef Param = Ident->Ident->getName(); if (!TestTypestateAttr::ConvertStrToConsumedState(Param, TestState)) { - S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) - << AL.getName() << Param; + S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) << AL + << Param; return; } } else { - S.Diag(AL.getLoc(), diag::err_attribute_argument_type) << - AL.getName() << AANT_ArgumentIdentifier; + S.Diag(AL.getLoc(), diag::err_attribute_argument_type) + << AL << AANT_ArgumentIdentifier; return; } @@ -1261,7 +1361,7 @@ static void handlePackedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (BitfieldByteAligned) // The PS4 target needs to maintain ABI backwards compatibility. S.Diag(AL.getLoc(), diag::warn_attribute_ignored_for_field_of_type) - << AL.getName() << FD->getType(); + << AL << FD->getType(); else FD->addAttr(::new (S.Context) PackedAttr( AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); @@ -1275,7 +1375,7 @@ static void handlePackedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } } else - S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL.getName(); + S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL; } static bool checkIBOutletCommon(Sema &S, Decl *D, const ParsedAttr &AL) { @@ -1285,19 +1385,19 @@ static bool checkIBOutletCommon(Sema &S, Decl *D, const ParsedAttr &AL) { if (const auto *VD = dyn_cast<ObjCIvarDecl>(D)) { if (!VD->getType()->getAs<ObjCObjectPointerType>()) { S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type) - << AL.getName() << VD->getType() << 0; + << AL << VD->getType() << 0; return false; } } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) { if (!PD->getType()->getAs<ObjCObjectPointerType>()) { S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type) - << AL.getName() << PD->getType() << 1; + << AL << PD->getType() << 1; return false; } } else { - S.Diag(AL.getLoc(), diag::warn_attribute_iboutlet) << AL.getName(); + S.Diag(AL.getLoc(), diag::warn_attribute_iboutlet) << AL; return false; } @@ -1317,8 +1417,7 @@ static void handleIBOutletCollection(Sema &S, Decl *D, const ParsedAttr &AL) { // The iboutletcollection attribute can have zero or one arguments. if (AL.getNumArgs() > 1) { - S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) - << AL.getName() << 1; + S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1; return; } @@ -1390,10 +1489,10 @@ static bool attrNonNullArgCheck(Sema &S, QualType T, const ParsedAttr &AL, if (!S.isValidPointerAttrType(T)) { if (isReturnValue) S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only) - << AL.getName() << AttrParmRange << TypeRange; + << AL << AttrParmRange << TypeRange; else S.Diag(AL.getLoc(), diag::warn_attribute_pointers_only) - << AL.getName() << AttrParmRange << TypeRange << 0; + << AL << AttrParmRange << TypeRange << 0; return false; } return true; @@ -1486,7 +1585,7 @@ static void handleNoEscapeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { QualType T = cast<ParmVarDecl>(D)->getType(); if (!S.isValidPointerAttrType(T, /* RefOkay */ true)) { S.Diag(AL.getLoc(), diag::warn_attribute_pointers_only) - << AL.getName() << AL.getRange() << 0; + << AL << AL.getRange() << 0; return; } @@ -1579,7 +1678,7 @@ void Sema::AddAllocAlignAttr(SourceRange AttrRange, Decl *D, Expr *ParamExpr, QualType Ty = getFunctionOrMethodParamType(D, Idx.getASTIndex()); if (!Ty->isDependentType() && !Ty->isIntegralType(Context)) { - Diag(ParamExpr->getLocStart(), diag::err_attribute_integers_only) + Diag(ParamExpr->getBeginLoc(), diag::err_attribute_integers_only) << &TmpAttr << FuncDecl->getParamDecl(Idx.getASTIndex())->getSourceRange(); return; @@ -1611,7 +1710,7 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!AL.isArgIdent(0)) { S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) - << AL.getName() << 1 << AANT_ArgumentIdentifier; + << AL << 1 << AANT_ArgumentIdentifier; return; } @@ -1625,15 +1724,13 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) { case OwnershipAttr::Takes: case OwnershipAttr::Holds: if (AL.getNumArgs() < 2) { - S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) - << AL.getName() << 2; + S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) << AL << 2; return; } break; case OwnershipAttr::Returns: if (AL.getNumArgs() > 2) { - S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) - << AL.getName() << 1; + S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1; return; } break; @@ -1668,8 +1765,8 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) { break; } if (-1 != Err) { - S.Diag(AL.getLoc(), diag::err_ownership_type) << AL.getName() << Err - << Ex->getSourceRange(); + S.Diag(AL.getLoc(), diag::err_ownership_type) << AL << Err + << Ex->getSourceRange(); return; } @@ -1679,8 +1776,7 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // index. if (I->getOwnKind() != K && I->args_end() != std::find(I->args_begin(), I->args_end(), Idx)) { - S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) - << AL.getName() << I; + S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) << AL << I; return; } else if (K == OwnershipAttr::Returns && I->getOwnKind() == OwnershipAttr::Returns) { @@ -1710,8 +1806,7 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) { static void handleWeakRefAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // Check the attribute arguments. if (AL.getNumArgs() > 1) { - S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) - << AL.getName() << 1; + S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1; return; } @@ -1812,7 +1907,16 @@ static void handleAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } } - // FIXME: check if target symbol exists in current file + // Mark target used to prevent unneeded-internal-declaration warnings. + if (!S.LangOpts.CPlusPlus) { + // FIXME: demangle Str for C++, as the attribute refers to the mangled + // linkage name, not the pre-mangled identifier. + const DeclarationNameInfo target(&S.Context.Idents.get(Str), AL.getLoc()); + LookupResult LR(S, target, Sema::LookupOrdinaryName); + if (S.LookupQualifiedName(LR, S.getCurLexicalContext())) + for (NamedDecl *ND : LR) + ND->markUsed(S.Context); + } D->addAttr(::new (S.Context) AliasAttr(AL.getRange(), S.Context, Str, AL.getAttributeSpellingListIndex())); @@ -1846,11 +1950,19 @@ static void handleRestrictAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only) - << AL.getName() << getFunctionOrMethodResultSourceRange(D); + << AL << getFunctionOrMethodResultSourceRange(D); } static void handleCPUSpecificAttr(Sema &S, Decl *D, const ParsedAttr &AL) { FunctionDecl *FD = cast<FunctionDecl>(D); + + if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) { + if (MD->getParent()->isLambda()) { + S.Diag(AL.getLoc(), diag::err_attribute_dll_lambda) << AL; + return; + } + } + if (!checkAttributeAtLeastNumArgs(S, AL, 1)) return; @@ -1858,7 +1970,7 @@ static void handleCPUSpecificAttr(Sema &S, Decl *D, const ParsedAttr &AL) { for (unsigned ArgNo = 0; ArgNo < getNumAttributeArgs(AL); ++ArgNo) { if (!AL.isArgIdent(ArgNo)) { S.Diag(AL.getLoc(), diag::err_attribute_argument_type) - << AL.getName() << AANT_ArgumentIdentifier; + << AL << AANT_ArgumentIdentifier; return; } @@ -1896,18 +2008,16 @@ static void handleCPUSpecificAttr(Sema &S, Decl *D, const ParsedAttr &AL) { static void handleCommonAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (S.LangOpts.CPlusPlus) { S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang) - << AL.getName() << AttributeLangSupport::Cpp; + << AL << AttributeLangSupport::Cpp; return; } - if (CommonAttr *CA = S.mergeCommonAttr(D, AL.getRange(), AL.getName(), - AL.getAttributeSpellingListIndex())) + if (CommonAttr *CA = S.mergeCommonAttr(D, AL)) D->addAttr(CA); } static void handleNakedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (checkAttrMutualExclusion<DisableTailCallsAttr>(S, D, AL.getRange(), - AL.getName())) + if (checkAttrMutualExclusion<DisableTailCallsAttr>(S, D, AL)) return; if (AL.isDeclspecAttribute()) { @@ -1916,7 +2026,7 @@ static void handleNakedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (Arch != llvm::Triple::x86 && (Arch != llvm::Triple::arm && Arch != llvm::Triple::thumb)) { S.Diag(AL.getLoc(), diag::err_attribute_not_supported_on_arch) - << AL.getName() << Triple.getArchName(); + << AL << Triple.getArchName(); return; } } @@ -1930,7 +2040,7 @@ static void handleNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) { if (!isa<ObjCMethodDecl>(D)) { S.Diag(Attrs.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attrs.getName() << ExpectedFunctionOrMethod; + << Attrs << ExpectedFunctionOrMethod; return; } @@ -1957,7 +2067,7 @@ 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.getName(); + Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) << AL; AL.setInvalid(); return true; } @@ -1973,10 +2083,10 @@ static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &AL) { ValueDecl *VD = dyn_cast<ValueDecl>(D); if (!VD || (!VD->getType()->isBlockPointerType() && !VD->getType()->isFunctionPointerType())) { - S.Diag(AL.getLoc(), - AL.isCXX11Attribute() ? diag::err_attribute_wrong_decl_type - : diag::warn_attribute_wrong_decl_type) - << AL.getName() << ExpectedFunctionMethodOrBlock; + S.Diag(AL.getLoc(), AL.isCXX11Attribute() + ? diag::err_attribute_wrong_decl_type + : diag::warn_attribute_wrong_decl_type) + << AL << ExpectedFunctionMethodOrBlock; return; } } @@ -2065,7 +2175,7 @@ static void handleUnusedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // If this is spelled as the standard C++17 attribute, but not in C++17, warn // about using it as an extension. if (!S.getLangOpts().CPlusPlus17 && IsCXX17Attr) - S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL.getName(); + S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL; D->addAttr(::new (S.Context) UnusedAttr( AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); @@ -2108,7 +2218,7 @@ static void handleObjCSuppresProtocolAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!cast<ObjCProtocolDecl>(D)->isThisDeclarationADefinition()) { S.Diag(AL.getLoc(), diag::err_objc_attr_protocol_requires_definition) - << AL.getName() << AL.getRange(); + << AL << AL.getRange(); return; } @@ -2365,6 +2475,15 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getReplacementExpr())) Replacement = SE->getString(); + if (II->isStr("swift")) { + if (Introduced.isValid() || Obsoleted.isValid() || + (!IsUnavailable && !Deprecated.isValid())) { + S.Diag(AL.getLoc(), + diag::warn_availability_swift_unavailable_deprecated_only); + return; + } + } + AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, AL.getRange(), II, false/*Implicit*/, Introduced.Version, @@ -2506,8 +2625,7 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const ParsedAttr &AL, bool isTypeVisibility) { // Visibility attributes don't mean anything on a typedef. if (isa<TypedefNameDecl>(D)) { - S.Diag(AL.getRange().getBegin(), diag::warn_attribute_ignored) - << AL.getName(); + S.Diag(AL.getRange().getBegin(), diag::warn_attribute_ignored) << AL; return; } @@ -2517,7 +2635,7 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const ParsedAttr &AL, isa<ObjCInterfaceDecl>(D) || isa<NamespaceDecl>(D))) { S.Diag(AL.getRange().getBegin(), diag::err_attribute_wrong_decl_type) - << AL.getName() << ExpectedTypeOrNamespace; + << AL << ExpectedTypeOrNamespace; return; } @@ -2529,8 +2647,8 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const ParsedAttr &AL, VisibilityAttr::VisibilityType type; if (!VisibilityAttr::ConvertStrToVisibilityType(TypeStr, type)) { - S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported) - << AL.getName() << TypeStr; + S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported) << AL + << TypeStr; return; } @@ -2559,15 +2677,14 @@ static void handleObjCMethodFamilyAttr(Sema &S, Decl *D, const ParsedAttr &AL) { const auto *M = cast<ObjCMethodDecl>(D); if (!AL.isArgIdent(0)) { S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) - << AL.getName() << 1 << AANT_ArgumentIdentifier; + << AL << 1 << AANT_ArgumentIdentifier; return; } IdentifierLoc *IL = AL.getArgAsIdent(0); ObjCMethodFamilyAttr::FamilyKind F; if (!ObjCMethodFamilyAttr::ConvertStrToFamilyKind(IL->Ident->getName(), F)) { - S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) - << AL.getName() << IL->Ident; + S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL << IL->Ident; return; } @@ -2631,15 +2748,14 @@ static void handleObjCIndependentClass(Sema &S, Decl *D, const ParsedAttr &AL) { static void handleBlocksAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!AL.isArgIdent(0)) { S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) - << AL.getName() << 1 << AANT_ArgumentIdentifier; + << AL << 1 << AANT_ArgumentIdentifier; return; } IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; BlocksAttr::BlockType type; if (!BlocksAttr::ConvertStrToBlockType(II->getName(), type)) { - S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) - << AL.getName() << II; + S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II; return; } @@ -2656,8 +2772,7 @@ static void handleSentinelAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (E->isTypeDependent() || E->isValueDependent() || !E->isIntegerConstantExpr(Idx, S.Context)) { S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) - << AL.getName() << 1 << AANT_ArgumentIntegerConstant - << E->getSourceRange(); + << AL << 1 << AANT_ArgumentIntegerConstant << E->getSourceRange(); return; } @@ -2677,8 +2792,7 @@ static void handleSentinelAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (E->isTypeDependent() || E->isValueDependent() || !E->isIntegerConstantExpr(Idx, S.Context)) { S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) - << AL.getName() << 2 << AANT_ArgumentIntegerConstant - << E->getSourceRange(); + << AL << 2 << AANT_ArgumentIntegerConstant << E->getSourceRange(); return; } nullPos = Idx.getZExtValue(); @@ -2726,12 +2840,12 @@ static void handleSentinelAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } } else { S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) - << AL.getName() << ExpectedFunctionMethodOrBlock; + << AL << ExpectedFunctionMethodOrBlock; return; } } else { S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) - << AL.getName() << ExpectedFunctionMethodOrBlock; + << AL << ExpectedFunctionMethodOrBlock; return; } D->addAttr(::new (S.Context) @@ -2742,14 +2856,12 @@ static void handleSentinelAttr(Sema &S, Decl *D, const ParsedAttr &AL) { static void handleWarnUnusedResult(Sema &S, Decl *D, const ParsedAttr &AL) { if (D->getFunctionType() && D->getFunctionType()->getReturnType()->isVoidType()) { - S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method) - << AL.getName() << 0; + S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method) << AL << 0; return; } if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) if (MD->getReturnType()->isVoidType()) { - S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method) - << AL.getName() << 1; + S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method) << AL << 1; return; } @@ -2757,7 +2869,7 @@ static void handleWarnUnusedResult(Sema &S, Decl *D, const ParsedAttr &AL) { // about using it as an extension. if (!S.getLangOpts().CPlusPlus17 && AL.isCXX11Attribute() && !AL.getScopeName()) - S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL.getName(); + S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL; D->addAttr(::new (S.Context) WarnUnusedResultAttr(AL.getRange(), S.Context, @@ -2777,7 +2889,7 @@ static void handleWeakImportAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // Nothing to warn about here. } else S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) - << AL.getName() << ExpectedVariableOrFunction; + << AL << ExpectedVariableOrFunction; return; } @@ -2793,11 +2905,12 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { uint32_t WGSize[3]; for (unsigned i = 0; i < 3; ++i) { const Expr *E = AL.getArgAsExpr(i); - if (!checkUInt32Argument(S, AL, E, WGSize[i], i)) + if (!checkUInt32Argument(S, AL, E, WGSize[i], i, + /*StrictlyUnsigned=*/true)) return; if (WGSize[i] == 0) { S.Diag(AL.getLoc(), diag::err_attribute_argument_is_zero) - << AL.getName() << E->getSourceRange(); + << AL << E->getSourceRange(); return; } } @@ -2806,7 +2919,7 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { if (Existing && !(Existing->getXDim() == WGSize[0] && Existing->getYDim() == WGSize[1] && Existing->getZDim() == WGSize[2])) - S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL.getName(); + S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; D->addAttr(::new (S.Context) WorkGroupAttr(AL.getRange(), S.Context, WGSize[0], WGSize[1], WGSize[2], @@ -2821,14 +2934,14 @@ static void handleSubGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { return; if (SGSize == 0) { S.Diag(AL.getLoc(), diag::err_attribute_argument_is_zero) - << AL.getName() << E->getSourceRange(); + << AL << E->getSourceRange(); return; } OpenCLIntelReqdSubGroupSizeAttr *Existing = D->getAttr<OpenCLIntelReqdSubGroupSizeAttr>(); if (Existing && Existing->getSubGroupSize() != SGSize) - S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL.getName(); + S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; D->addAttr(::new (S.Context) OpenCLIntelReqdSubGroupSizeAttr( AL.getRange(), S.Context, SGSize, @@ -2837,8 +2950,7 @@ static void handleSubGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { static void handleVecTypeHint(Sema &S, Decl *D, const ParsedAttr &AL) { if (!AL.hasParsedType()) { - S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) - << AL.getName() << 1; + S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1; return; } @@ -2856,7 +2968,7 @@ static void handleVecTypeHint(Sema &S, Decl *D, const ParsedAttr &AL) { if (VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>()) { if (!S.Context.hasSameType(A->getTypeHint(), ParmType)) { - S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL.getName(); + S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; return; } } @@ -3030,7 +3142,7 @@ static void handleMinVectorWidthAttr(Sema &S, Decl *D, const ParsedAttr &AL) { MinVectorWidthAttr *Existing = D->getAttr<MinVectorWidthAttr>(); if (Existing && Existing->getVectorWidth() != VecWidth) { - S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL.getName(); + S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; return; } @@ -3100,7 +3212,7 @@ static void handleEnumExtensibilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!AL.isArgIdent(0)) { S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) - << AL.getName() << 0 << AANT_ArgumentIdentifier; + << AL << 0 << AANT_ArgumentIdentifier; return; } @@ -3108,8 +3220,7 @@ static void handleEnumExtensibilityAttr(Sema &S, Decl *D, IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; if (!EnumExtensibilityAttr::ConvertStrToKind(II->getName(), ExtensibilityKind)) { - S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) - << AL.getName() << II; + S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II; return; } @@ -3188,7 +3299,7 @@ static FormatAttrKind getFormatAttrKind(StringRef Format) { /// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html static void handleInitPriorityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!S.getLangOpts().CPlusPlus) { - S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL.getName(); + S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL; return; } @@ -3215,7 +3326,7 @@ static void handleInitPriorityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (prioritynum < 101 || prioritynum > 65535) { S.Diag(AL.getLoc(), diag::err_attribute_argument_outof_range) - << E->getSourceRange() << AL.getName() << 101 << 65535; + << E->getSourceRange() << AL << 101 << 65535; AL.setInvalid(); return; } @@ -3250,7 +3361,7 @@ FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range, static void handleFormatAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!AL.isArgIdent(0)) { S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) - << AL.getName() << 1 << AANT_ArgumentIdentifier; + << AL << 1 << AANT_ArgumentIdentifier; return; } @@ -3275,7 +3386,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (Kind == InvalidFormat) { S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) - << AL.getName() << II->getName(); + << AL << II->getName(); return; } @@ -3287,7 +3398,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (Idx < 1 || Idx > NumArgs) { S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) - << AL.getName() << 2 << IdxExpr->getSourceRange(); + << AL << 2 << IdxExpr->getSourceRange(); return; } @@ -3358,7 +3469,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // if 0 it disables parameter checking (to use with e.g. va_list) } else if (FirstArg != 0 && FirstArg != NumArgs) { S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) - << AL.getName() << 3 << FirstArgExpr->getSourceRange(); + << AL << 3 << FirstArgExpr->getSourceRange(); return; } @@ -3379,8 +3490,8 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { RD = dyn_cast<RecordDecl>(D); if (!RD || !RD->isUnion()) { - S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) - << AL.getName() << ExpectedUnion; + S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) << AL + << ExpectedUnion; return; } @@ -3513,8 +3624,7 @@ void Sema::AddAlignValueAttr(SourceRange AttrRange, Decl *D, Expr *E, static void handleAlignedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // check the attribute arguments. if (AL.getNumArgs() > 1) { - S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) - << AL.getName() << 1; + S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1; return; } @@ -3794,8 +3904,8 @@ static void handleModeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // This attribute isn't documented, but glibc uses it. It changes // the width of an int or unsigned int to the specified size. if (!AL.isArgIdent(0)) { - S.Diag(AL.getLoc(), diag::err_attribute_argument_type) << AL.getName() - << AANT_ArgumentIdentifier; + S.Diag(AL.getLoc(), diag::err_attribute_argument_type) + << AL << AANT_ArgumentIdentifier; return; } @@ -3968,26 +4078,55 @@ AlwaysInlineAttr *Sema::mergeAlwaysInlineAttr(Decl *D, SourceRange Range, AttrSpellingListIndex); } -CommonAttr *Sema::mergeCommonAttr(Decl *D, SourceRange Range, - IdentifierInfo *Ident, - unsigned AttrSpellingListIndex) { - if (checkAttrMutualExclusion<InternalLinkageAttr>(*this, D, Range, Ident)) +CommonAttr *Sema::mergeCommonAttr(Decl *D, const ParsedAttr &AL) { + if (checkAttrMutualExclusion<InternalLinkageAttr>(*this, D, AL)) + return nullptr; + + return ::new (Context) + CommonAttr(AL.getRange(), Context, AL.getAttributeSpellingListIndex()); +} + +CommonAttr *Sema::mergeCommonAttr(Decl *D, const CommonAttr &AL) { + if (checkAttrMutualExclusion<InternalLinkageAttr>(*this, D, AL)) return nullptr; - return ::new (Context) CommonAttr(Range, Context, AttrSpellingListIndex); + return ::new (Context) + CommonAttr(AL.getRange(), Context, AL.getSpellingListIndex()); } +InternalLinkageAttr *Sema::mergeInternalLinkageAttr(Decl *D, + const ParsedAttr &AL) { + if (const auto *VD = dyn_cast<VarDecl>(D)) { + // Attribute applies to Var but not any subclass of it (like ParmVar, + // ImplicitParm or VarTemplateSpecialization). + if (VD->getKind() != Decl::Var) { + Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) + << AL << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass + : ExpectedVariableOrFunction); + return nullptr; + } + // Attribute does not apply to non-static local variables. + if (VD->hasLocalStorage()) { + Diag(VD->getLocation(), diag::warn_internal_linkage_local_storage); + return nullptr; + } + } + + if (checkAttrMutualExclusion<CommonAttr>(*this, D, AL)) + return nullptr; + + return ::new (Context) InternalLinkageAttr( + AL.getRange(), Context, AL.getAttributeSpellingListIndex()); +} InternalLinkageAttr * -Sema::mergeInternalLinkageAttr(Decl *D, SourceRange Range, - IdentifierInfo *Ident, - unsigned AttrSpellingListIndex) { +Sema::mergeInternalLinkageAttr(Decl *D, const InternalLinkageAttr &AL) { if (const auto *VD = dyn_cast<VarDecl>(D)) { // Attribute applies to Var but not any subclass of it (like ParmVar, // ImplicitParm or VarTemplateSpecialization). if (VD->getKind() != Decl::Var) { - Diag(Range.getBegin(), diag::warn_attribute_wrong_decl_type) - << Ident << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass - : ExpectedVariableOrFunction); + Diag(AL.getLocation(), diag::warn_attribute_wrong_decl_type) + << &AL << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass + : ExpectedVariableOrFunction); return nullptr; } // Attribute does not apply to non-static local variables. @@ -3997,11 +4136,11 @@ Sema::mergeInternalLinkageAttr(Decl *D, SourceRange Range, } } - if (checkAttrMutualExclusion<CommonAttr>(*this, D, Range, Ident)) + if (checkAttrMutualExclusion<CommonAttr>(*this, D, AL)) return nullptr; return ::new (Context) - InternalLinkageAttr(Range, Context, AttrSpellingListIndex); + InternalLinkageAttr(AL.getRange(), Context, AL.getSpellingListIndex()); } MinSizeAttr *Sema::mergeMinSizeAttr(Decl *D, SourceRange Range, @@ -4039,8 +4178,7 @@ OptimizeNoneAttr *Sema::mergeOptimizeNoneAttr(Decl *D, SourceRange Range, } static void handleAlwaysInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (checkAttrMutualExclusion<NotTailCalledAttr>(S, D, AL.getRange(), - AL.getName())) + if (checkAttrMutualExclusion<NotTailCalledAttr>(S, D, AL)) return; if (AlwaysInlineAttr *Inline = S.mergeAlwaysInlineAttr( @@ -4062,8 +4200,7 @@ 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.getRange(), - AL.getName())) + if (checkAttrMutualExclusion<CUDASharedAttr>(S, D, AL)) return; const auto *VD = cast<VarDecl>(D); if (!VD->hasGlobalStorage()) { @@ -4075,13 +4212,12 @@ static void handleConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } static void handleSharedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, AL.getRange(), - AL.getName())) + if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, AL)) return; const auto *VD = cast<VarDecl>(D); // extern __shared__ is only allowed on arrays with no length (e.g. // "int x[]"). - if (!S.getLangOpts().CUDARelocatableDeviceCode && VD->hasExternalStorage() && + if (!S.getLangOpts().GPURelocatableDeviceCode && VD->hasExternalStorage() && !isa<IncompleteArrayType>(VD->getType())) { S.Diag(AL.getLoc(), diag::err_cuda_extern_shared) << VD; return; @@ -4095,10 +4231,8 @@ static void handleSharedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } static void handleGlobalAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (checkAttrMutualExclusion<CUDADeviceAttr>(S, D, AL.getRange(), - AL.getName()) || - checkAttrMutualExclusion<CUDAHostAttr>(S, D, AL.getRange(), - AL.getName())) { + if (checkAttrMutualExclusion<CUDADeviceAttr>(S, D, AL) || + checkAttrMutualExclusion<CUDAHostAttr>(S, D, AL)) { return; } const auto *FD = cast<FunctionDecl>(D); @@ -4112,15 +4246,15 @@ static void handleGlobalAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } if (const auto *Method = dyn_cast<CXXMethodDecl>(FD)) { if (Method->isInstance()) { - S.Diag(Method->getLocStart(), diag::err_kern_is_nonstatic_method) + S.Diag(Method->getBeginLoc(), diag::err_kern_is_nonstatic_method) << Method; return; } - S.Diag(Method->getLocStart(), diag::warn_kern_is_method) << Method; + S.Diag(Method->getBeginLoc(), diag::warn_kern_is_method) << Method; } // Only warn for "inline" when compiling for host, to cut down on noise. if (FD->isInlineSpecified() && !S.getLangOpts().CUDAIsDevice) - S.Diag(FD->getLocStart(), diag::warn_kern_is_inline) << FD; + S.Diag(FD->getBeginLoc(), diag::warn_kern_is_inline) << FD; D->addAttr(::new (S.Context) CUDAGlobalAttr(AL.getRange(), S.Context, @@ -4150,7 +4284,7 @@ static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!isa<ObjCMethodDecl>(D)) { S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) - << AL.getName() << ExpectedFunctionOrMethod; + << AL << ExpectedFunctionOrMethod; return; } @@ -4222,6 +4356,11 @@ static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) { AL.getAttributeSpellingListIndex())); return; } + case ParsedAttr::AT_AArch64VectorPcs: + D->addAttr(::new(S.Context) + AArch64VectorPcsAttr(AL.getRange(), S.Context, + AL.getAttributeSpellingListIndex())); + return; case ParsedAttr::AT_IntelOclBicc: D->addAttr(::new (S.Context) IntelOclBiccAttr(AL.getRange(), S.Context, @@ -4299,6 +4438,9 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC, case ParsedAttr::AT_VectorCall: CC = CC_X86VectorCall; break; + case ParsedAttr::AT_AArch64VectorPcs: + CC = CC_AArch64VectorCall; + break; case ParsedAttr::AT_RegCall: CC = CC_X86RegCall; break; @@ -4344,7 +4486,7 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC, TargetInfo::CallingConvCheckResult A = TI.checkCallingConvention(CC); if (A != TargetInfo::CCCR_OK) { if (A == TargetInfo::CCCR_Warning) - Diag(Attrs.getLoc(), diag::warn_cconv_ignored) << Attrs.getName(); + Diag(Attrs.getLoc(), diag::warn_cconv_ignored) << Attrs; // This convention is not valid for the target. Use the default function or // method calling convention. @@ -4559,7 +4701,7 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!AL.isArgIdent(0)) { S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) - << AL.getName() << /* arg num = */ 1 << AANT_ArgumentIdentifier; + << AL << /* arg num = */ 1 << AANT_ArgumentIdentifier; return; } @@ -4579,8 +4721,7 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D, unsigned ArgumentIdxAST = ArgumentIdx.getASTIndex(); if (ArgumentIdxAST >= getFunctionOrMethodNumParams(D) || !getFunctionOrMethodParamType(D, ArgumentIdxAST)->isPointerType()) - S.Diag(AL.getLoc(), diag::err_attribute_pointers_only) - << AL.getName() << 0; + S.Diag(AL.getLoc(), diag::err_attribute_pointers_only) << AL << 0; } D->addAttr(::new (S.Context) ArgumentWithTypeTagAttr( @@ -4592,7 +4733,7 @@ static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!AL.isArgIdent(0)) { S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) - << AL.getName() << 1 << AANT_ArgumentIdentifier; + << AL << 1 << AANT_ArgumentIdentifier; return; } @@ -4601,7 +4742,7 @@ static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D, if (!isa<VarDecl>(D)) { S.Diag(AL.getLoc(), diag::err_attribute_wrong_decl_type) - << AL.getName() << ExpectedVariable; + << AL << ExpectedVariable; return; } @@ -4635,58 +4776,84 @@ static void handleXRayLogArgsAttr(Sema &S, Decl *D, const ParsedAttr &AL) { //===----------------------------------------------------------------------===// // Checker-specific attribute handlers. //===----------------------------------------------------------------------===// - static bool isValidSubjectOfNSReturnsRetainedAttribute(QualType QT) { return QT->isDependentType() || QT->isObjCRetainableType(); } -static bool isValidSubjectOfNSAttribute(Sema &S, QualType QT) { +static bool isValidSubjectOfNSAttribute(QualType QT) { return QT->isDependentType() || QT->isObjCObjectPointerType() || - S.Context.isObjCNSObjectType(QT); + QT->isObjCNSObjectType(); } -static bool isValidSubjectOfCFAttribute(Sema &S, QualType QT) { +static bool isValidSubjectOfCFAttribute(QualType QT) { return QT->isDependentType() || QT->isPointerType() || - isValidSubjectOfNSAttribute(S, QT); + isValidSubjectOfNSAttribute(QT); } -static void handleNSConsumedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - S.AddNSConsumedAttr(AL.getRange(), D, AL.getAttributeSpellingListIndex(), - AL.getKind() == ParsedAttr::AT_NSConsumed, - /*template instantiation*/ false); +static bool isValidSubjectOfOSAttribute(QualType QT) { + if (QT->isDependentType()) + return true; + QualType PT = QT->getPointeeType(); + return !PT.isNull() && PT->getAsCXXRecordDecl() != nullptr; } -void Sema::AddNSConsumedAttr(SourceRange AttrRange, Decl *D, - unsigned SpellingIndex, bool IsNSConsumed, - bool IsTemplateInstantiation) { - const auto *Param = cast<ParmVarDecl>(D); - bool TypeOK; - - if (IsNSConsumed) - TypeOK = isValidSubjectOfNSAttribute(*this, Param->getType()); - else - TypeOK = isValidSubjectOfCFAttribute(*this, Param->getType()); +void Sema::AddXConsumedAttr(Decl *D, SourceRange SR, unsigned SpellingIndex, + RetainOwnershipKind K, + bool IsTemplateInstantiation) { + ValueDecl *VD = cast<ValueDecl>(D); + switch (K) { + case RetainOwnershipKind::OS: + handleSimpleAttributeOrDiagnose<OSConsumedAttr>( + *this, VD, SR, SpellingIndex, isValidSubjectOfOSAttribute(VD->getType()), + diag::warn_ns_attribute_wrong_parameter_type, + /*ExtraArgs=*/SR, "os_consumed", /*pointers*/ 1); + return; + case RetainOwnershipKind::NS: + handleSimpleAttributeOrDiagnose<NSConsumedAttr>( + *this, VD, SR, SpellingIndex, isValidSubjectOfNSAttribute(VD->getType()), - if (!TypeOK) { - // These attributes are normally just advisory, but in ARC, ns_consumed - // is significant. Allow non-dependent code to contain inappropriate - // attributes even in ARC, but require template instantiations to be - // set up correctly. - Diag(D->getLocStart(), (IsTemplateInstantiation && IsNSConsumed && - getLangOpts().ObjCAutoRefCount - ? diag::err_ns_attribute_wrong_parameter_type - : diag::warn_ns_attribute_wrong_parameter_type)) - << AttrRange << (IsNSConsumed ? "ns_consumed" : "cf_consumed") - << (IsNSConsumed ? /*objc pointers*/ 0 : /*cf pointers*/ 1); + // These attributes are normally just advisory, but in ARC, ns_consumed + // is significant. Allow non-dependent code to contain inappropriate + // attributes even in ARC, but require template instantiations to be + // set up correctly. + ((IsTemplateInstantiation && getLangOpts().ObjCAutoRefCount) + ? diag::err_ns_attribute_wrong_parameter_type + : diag::warn_ns_attribute_wrong_parameter_type), + /*ExtraArgs=*/SR, "ns_consumed", /*objc pointers*/ 0); + return; + case RetainOwnershipKind::CF: + handleSimpleAttributeOrDiagnose<CFConsumedAttr>( + *this, VD, SR, SpellingIndex, + isValidSubjectOfCFAttribute(VD->getType()), + diag::warn_ns_attribute_wrong_parameter_type, + /*ExtraArgs=*/SR, "cf_consumed", /*pointers*/1); return; } +} - if (IsNSConsumed) - D->addAttr(::new (Context) - NSConsumedAttr(AttrRange, Context, SpellingIndex)); - else - D->addAttr(::new (Context) - CFConsumedAttr(AttrRange, Context, SpellingIndex)); +static Sema::RetainOwnershipKind +parsedAttrToRetainOwnershipKind(const ParsedAttr &AL) { + switch (AL.getKind()) { + case ParsedAttr::AT_CFConsumed: + case ParsedAttr::AT_CFReturnsRetained: + case ParsedAttr::AT_CFReturnsNotRetained: + return Sema::RetainOwnershipKind::CF; + case ParsedAttr::AT_OSConsumesThis: + case ParsedAttr::AT_OSConsumed: + case ParsedAttr::AT_OSReturnsRetained: + case ParsedAttr::AT_OSReturnsNotRetained: + case ParsedAttr::AT_OSReturnsRetainedOnZero: + case ParsedAttr::AT_OSReturnsRetainedOnNonZero: + return Sema::RetainOwnershipKind::OS; + case ParsedAttr::AT_NSConsumesSelf: + case ParsedAttr::AT_NSConsumed: + case ParsedAttr::AT_NSReturnsRetained: + case ParsedAttr::AT_NSReturnsNotRetained: + case ParsedAttr::AT_NSReturnsAutoreleased: + return Sema::RetainOwnershipKind::NS; + default: + llvm_unreachable("Wrong argument supplied"); + } } bool Sema::checkNSReturnsRetainedReturnType(SourceLocation Loc, QualType QT) { @@ -4698,25 +4865,40 @@ bool Sema::checkNSReturnsRetainedReturnType(SourceLocation Loc, QualType QT) { return true; } -static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, +/// \return whether the parameter is a pointer to OSObject pointer. +static bool isValidOSObjectOutParameter(const Decl *D) { + const auto *PVD = dyn_cast<ParmVarDecl>(D); + if (!PVD) + return false; + QualType QT = PVD->getType(); + QualType PT = QT->getPointeeType(); + return !PT.isNull() && isValidSubjectOfOSAttribute(PT); +} + +static void handleXReturnsXRetainedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { QualType ReturnType; + Sema::RetainOwnershipKind K = parsedAttrToRetainOwnershipKind(AL); - if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) + if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) { ReturnType = MD->getReturnType(); - else if (S.getLangOpts().ObjCAutoRefCount && hasDeclarator(D) && - (AL.getKind() == ParsedAttr::AT_NSReturnsRetained)) + } else if (S.getLangOpts().ObjCAutoRefCount && hasDeclarator(D) && + (AL.getKind() == ParsedAttr::AT_NSReturnsRetained)) { return; // ignore: was handled as a type attribute - else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) + } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) { ReturnType = PD->getType(); - else if (const auto *FD = dyn_cast<FunctionDecl>(D)) + } else if (const auto *FD = dyn_cast<FunctionDecl>(D)) { ReturnType = FD->getReturnType(); - else if (const auto *Param = dyn_cast<ParmVarDecl>(D)) { + } else if (const auto *Param = dyn_cast<ParmVarDecl>(D)) { + // Attributes on parameters are used for out-parameters, + // passed as pointers-to-pointers. + unsigned DiagID = K == Sema::RetainOwnershipKind::CF + ? /*pointer-to-CF-pointer*/2 + : /*pointer-to-OSObject-pointer*/3; ReturnType = Param->getType()->getPointeeType(); if (ReturnType.isNull()) { - S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type) - << AL.getName() << /*pointer-to-CF*/2 - << AL.getRange(); + S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type) + << AL << DiagID << AL.getRange(); return; } } else if (AL.isUsedAsTypeAttr()) { @@ -4731,18 +4913,21 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, ExpectedDeclKind = ExpectedFunctionOrMethod; break; + case ParsedAttr::AT_OSReturnsRetained: + case ParsedAttr::AT_OSReturnsNotRetained: case ParsedAttr::AT_CFReturnsRetained: case ParsedAttr::AT_CFReturnsNotRetained: ExpectedDeclKind = ExpectedFunctionMethodOrParameter; break; } - S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type) - << AL.getRange() << AL.getName() << ExpectedDeclKind; + S.Diag(D->getBeginLoc(), diag::warn_attribute_wrong_decl_type) + << AL.getRange() << AL << ExpectedDeclKind; return; } bool TypeOK; bool Cf; + unsigned ParmDiagID = 2; // Pointer-to-CF-pointer switch (AL.getKind()) { default: llvm_unreachable("invalid ownership attribute"); case ParsedAttr::AT_NSReturnsRetained: @@ -4752,14 +4937,21 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, case ParsedAttr::AT_NSReturnsAutoreleased: case ParsedAttr::AT_NSReturnsNotRetained: - TypeOK = isValidSubjectOfNSAttribute(S, ReturnType); + TypeOK = isValidSubjectOfNSAttribute(ReturnType); Cf = false; break; case ParsedAttr::AT_CFReturnsRetained: case ParsedAttr::AT_CFReturnsNotRetained: - TypeOK = isValidSubjectOfCFAttribute(S, ReturnType); + TypeOK = isValidSubjectOfCFAttribute(ReturnType); + Cf = true; + break; + + case ParsedAttr::AT_OSReturnsRetained: + case ParsedAttr::AT_OSReturnsNotRetained: + TypeOK = isValidSubjectOfOSAttribute(ReturnType); Cf = true; + ParmDiagID = 3; // Pointer-to-OSObject-pointer break; } @@ -4768,9 +4960,8 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, return; if (isa<ParmVarDecl>(D)) { - S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type) - << AL.getName() << /*pointer-to-CF*/2 - << AL.getRange(); + S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type) + << AL << ParmDiagID << AL.getRange(); } else { // Needs to be kept in sync with warn_ns_attribute_wrong_return_type. enum : unsigned { @@ -4782,9 +4973,8 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, SubjectKind = Method; else if (isa<ObjCPropertyDecl>(D)) SubjectKind = Property; - S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type) - << AL.getName() << SubjectKind << Cf - << AL.getRange(); + S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type) + << AL << SubjectKind << Cf << AL.getRange(); } return; } @@ -4793,24 +4983,25 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, default: llvm_unreachable("invalid ownership attribute"); case ParsedAttr::AT_NSReturnsAutoreleased: - D->addAttr(::new (S.Context) NSReturnsAutoreleasedAttr( - AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); + handleSimpleAttribute<NSReturnsAutoreleasedAttr>(S, D, AL); return; case ParsedAttr::AT_CFReturnsNotRetained: - D->addAttr(::new (S.Context) CFReturnsNotRetainedAttr( - AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); + handleSimpleAttribute<CFReturnsNotRetainedAttr>(S, D, AL); return; case ParsedAttr::AT_NSReturnsNotRetained: - D->addAttr(::new (S.Context) NSReturnsNotRetainedAttr( - AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); + handleSimpleAttribute<NSReturnsNotRetainedAttr>(S, D, AL); return; case ParsedAttr::AT_CFReturnsRetained: - D->addAttr(::new (S.Context) CFReturnsRetainedAttr( - AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); + handleSimpleAttribute<CFReturnsRetainedAttr>(S, D, AL); return; case ParsedAttr::AT_NSReturnsRetained: - D->addAttr(::new (S.Context) NSReturnsRetainedAttr( - AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); + handleSimpleAttribute<NSReturnsRetainedAttr>(S, D, AL); + return; + case ParsedAttr::AT_OSReturnsRetained: + handleSimpleAttribute<OSReturnsRetainedAttr>(S, D, AL); + return; + case ParsedAttr::AT_OSReturnsNotRetained: + handleSimpleAttribute<OSReturnsNotRetainedAttr>(S, D, AL); return; }; } @@ -4829,11 +5020,10 @@ static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D, if (!resultType->isReferenceType() && (!resultType->isPointerType() || resultType->isObjCRetainableType())) { - S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type) - << SourceRange(loc) - << Attrs.getName() - << (isa<ObjCMethodDecl>(D) ? EP_ObjCMethod : EP_ObjCProperty) - << /*non-retainable pointer*/ 2; + S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type) + << SourceRange(loc) << Attrs + << (isa<ObjCMethodDecl>(D) ? EP_ObjCMethod : EP_ObjCProperty) + << /*non-retainable pointer*/ 2; // Drop the attribute. return; @@ -4849,14 +5039,14 @@ static void handleObjCRequiresSuperAttr(Sema &S, Decl *D, const DeclContext *DC = Method->getDeclContext(); if (const auto *PDecl = dyn_cast_or_null<ObjCProtocolDecl>(DC)) { - S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol) - << Attrs.getName() << 0; + S.Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol) << Attrs + << 0; S.Diag(PDecl->getLocation(), diag::note_protocol_decl); return; } if (Method->getMethodFamily() == OMF_dealloc) { - S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol) - << Attrs.getName() << 1; + S.Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol) << Attrs + << 1; return; } @@ -4868,15 +5058,14 @@ static void handleObjCBridgeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr; if (!Parm) { - S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << AL.getName() << 0; + S.Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0; return; } // Typedefs only allow objc_bridge(id) and have some additional checking. if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) { if (!Parm->Ident->isStr("id")) { - S.Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_id) - << AL.getName(); + S.Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_id) << AL; return; } @@ -4898,7 +5087,7 @@ static void handleObjCBridgeMutableAttr(Sema &S, Decl *D, IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr; if (!Parm) { - S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << AL.getName() << 0; + S.Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0; return; } @@ -4912,7 +5101,7 @@ static void handleObjCBridgeRelatedAttr(Sema &S, Decl *D, IdentifierInfo *RelatedClass = AL.isArgIdent(0) ? AL.getArgAsIdent(0)->Ident : nullptr; if (!RelatedClass) { - S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << AL.getName() << 0; + S.Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0; return; } IdentifierInfo *ClassMethod = @@ -4982,8 +5171,8 @@ static void handleObjCBoxable(Sema &S, Decl *D, const ParsedAttr &AL) { static void handleObjCOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (hasDeclarator(D)) return; - S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) - << AL.getRange() << AL.getName() << ExpectedVariable; + S.Diag(D->getBeginLoc(), diag::err_attribute_wrong_decl_type) + << AL.getRange() << AL << ExpectedVariable; } static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D, @@ -5047,7 +5236,7 @@ UuidAttr *Sema::mergeUuidAttr(Decl *D, SourceRange Range, static void handleUuidAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!S.LangOpts.CPlusPlus) { S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang) - << AL.getName() << AttributeLangSupport::C; + << AL << AttributeLangSupport::C; return; } @@ -5097,7 +5286,7 @@ static void handleUuidAttr(Sema &S, Decl *D, const ParsedAttr &AL) { static void handleMSInheritanceAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!S.LangOpts.CPlusPlus) { S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang) - << AL.getName() << AttributeLangSupport::C; + << AL << AttributeLangSupport::C; return; } MSInheritanceAttr *IA = S.mergeMSInheritanceAttr( @@ -5152,7 +5341,7 @@ static void handleAbiTagAttr(Sema &S, Decl *D, const ParsedAttr &AL) { return; // Store tags sorted and without duplicates. - llvm::sort(Tags.begin(), Tags.end()); + llvm::sort(Tags); Tags.erase(std::unique(Tags.begin(), Tags.end()), Tags.end()); D->addAttr(::new (S.Context) @@ -5163,8 +5352,7 @@ static void handleAbiTagAttr(Sema &S, Decl *D, const ParsedAttr &AL) { static void handleARMInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // Check the attribute arguments. if (AL.getNumArgs() > 1) { - S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) - << AL.getName() << 1; + S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1; return; } @@ -5178,8 +5366,8 @@ static void handleARMInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { ARMInterruptAttr::InterruptType Kind; if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) { - S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) - << AL.getName() << Str << ArgLoc; + S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << Str + << ArgLoc; return; } @@ -5193,8 +5381,8 @@ static void handleMSP430InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { return; if (!AL.isArgExpr(0)) { - S.Diag(AL.getLoc(), diag::err_attribute_argument_type) << AL.getName() - << AANT_ArgumentIntegerConstant; + S.Diag(AL.getLoc(), diag::err_attribute_argument_type) + << AL << AANT_ArgumentIntegerConstant; return; } @@ -5204,16 +5392,16 @@ static void handleMSP430InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { llvm::APSInt NumParams(32); if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) { S.Diag(AL.getLoc(), diag::err_attribute_argument_type) - << AL.getName() << AANT_ArgumentIntegerConstant - << NumParamsExpr->getSourceRange(); + << AL << AANT_ArgumentIntegerConstant + << NumParamsExpr->getSourceRange(); return; } unsigned Num = NumParams.getLimitedValue(255); if ((Num & 1) || Num > 30) { S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) - << AL.getName() << (int)NumParams.getSExtValue() - << NumParamsExpr->getSourceRange(); + << AL << (int)NumParams.getSExtValue() + << NumParamsExpr->getSourceRange(); return; } @@ -5226,8 +5414,7 @@ static void handleMSP430InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { static void handleMipsInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // Only one optional argument permitted. if (AL.getNumArgs() > 1) { - S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) - << AL.getName() << 1; + S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1; return; } @@ -5266,14 +5453,13 @@ static void handleMipsInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { return; } - if (checkAttrMutualExclusion<Mips16Attr>(S, D, AL.getRange(), - AL.getName())) + if (checkAttrMutualExclusion<Mips16Attr>(S, D, AL)) return; MipsInterruptAttr::InterruptType Kind; if (!MipsInterruptAttr::ConvertStrToInterruptType(Str, Kind)) { S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) - << AL.getName() << "'" + std::string(Str) + "'"; + << AL << "'" + std::string(Str) + "'"; return; } @@ -5292,7 +5478,7 @@ static void handleAnyX86InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { CXXMethodDecl::isStaticOverloadedOperator( cast<NamedDecl>(D)->getDeclName().getCXXOverloadedOperator())) { S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) - << AL.getName() << ExpectedFunctionWithProtoType; + << AL << ExpectedFunctionWithProtoType; return; } // Interrupt handler must have void return type. @@ -5308,7 +5494,7 @@ static void handleAnyX86InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // Interrupt handler must have 1 or 2 parameters. unsigned NumParams = getFunctionOrMethodNumParams(D); if (NumParams < 1 || NumParams > 2) { - S.Diag(D->getLocStart(), diag::err_anyx86_interrupt_attribute) + S.Diag(D->getBeginLoc(), diag::err_anyx86_interrupt_attribute) << (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86 ? 0 : 1) @@ -5421,8 +5607,8 @@ static void handleRISCVInterruptAttr(Sema &S, Decl *D, RISCVInterruptAttr::InterruptType Kind; if (!RISCVInterruptAttr::ConvertStrToInterruptType(Str, Kind)) { - S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) - << AL.getName() << Str << ArgLoc; + S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << Str + << ArgLoc; return; } @@ -5470,13 +5656,11 @@ static void handleAMDGPUFlatWorkGroupSizeAttr(Sema &S, Decl *D, return; if (Min == 0 && Max != 0) { - S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid) - << AL.getName() << 0; + S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid) << AL << 0; return; } if (Min > Max) { - S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid) - << AL.getName() << 1; + S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid) << AL << 1; return; } @@ -5499,13 +5683,11 @@ static void handleAMDGPUWavesPerEUAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } if (Min == 0 && Max != 0) { - S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid) - << AL.getName() << 0; + S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid) << AL << 0; return; } if (Max != 0 && Min > Max) { - S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid) - << AL.getName() << 1; + S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid) << AL << 1; return; } @@ -5552,7 +5734,7 @@ static void handleX86ForceAlignArgPointerAttr(Sema &S, Decl *D, // Attribute can only be applied to function types. if (!isa<FunctionDecl>(D)) { S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) - << AL.getName() << ExpectedFunction; + << AL << ExpectedFunction; return; } @@ -5568,12 +5750,17 @@ static void handleLayoutVersion(Sema &S, Decl *D, const ParsedAttr &AL) { return; // TODO: Investigate what happens with the next major version of MSVC. - if (Version != LangOptions::MSVC2015) { + if (Version != LangOptions::MSVC2015 / 100) { S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) - << AL.getName() << Version << VersionExpr->getSourceRange(); + << AL << Version << VersionExpr->getSourceRange(); return; } + // The attribute expects a "major" version number like 19, but new versions of + // MSVC have moved to updating the "minor", or less significant numbers, so we + // have to multiply by 100 now. + Version *= 100; + D->addAttr(::new (S.Context) LayoutVersionAttr(AL.getRange(), S.Context, Version, AL.getAttributeSpellingListIndex())); @@ -5608,8 +5795,7 @@ DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range, static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) { if (isa<ClassTemplatePartialSpecializationDecl>(D) && S.Context.getTargetInfo().getCXXABI().isMicrosoft()) { - S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored) - << A.getName(); + S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored) << A; return; } @@ -5618,7 +5804,7 @@ static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) { !S.Context.getTargetInfo().getCXXABI().isMicrosoft()) { // MinGW doesn't allow dllimport on inline functions. S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored_on_inline) - << A.getName(); + << A; return; } } @@ -5626,7 +5812,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() && MD->getParent()->isLambda()) { - S.Diag(A.getRange().getBegin(), diag::err_attribute_dll_lambda) << A.getName(); + S.Diag(A.getRange().getBegin(), diag::err_attribute_dll_lambda) << A; return; } } @@ -5788,10 +5974,8 @@ static void handleDeprecatedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { !S.checkStringLiteralArgumentAttr(AL, 1, Replacement)) return; - if (!S.getLangOpts().CPlusPlus14) - if (AL.isCXX11Attribute() && - !(AL.hasScope() && AL.getScopeName()->isStr("gnu"))) - S.Diag(AL.getLoc(), diag::ext_cxx14_attr) << AL.getName(); + if (!S.getLangOpts().CPlusPlus14 && AL.isCXX11Attribute() && !AL.isGNUScope()) + S.Diag(AL.getLoc(), diag::ext_cxx14_attr) << AL; D->addAttr(::new (S.Context) DeprecatedAttr(AL.getRange(), S.Context, Str, Replacement, @@ -5821,7 +6005,7 @@ static void handleNoSanitizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { S.Diag(LiteralLoc, diag::warn_unknown_sanitizer_ignored) << SanitizerName; else if (isGlobalVar(D) && SanitizerName != "address") S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) - << AL.getName() << ExpectedFunctionOrMethod; + << AL << ExpectedFunctionOrMethod; Sanitizers.push_back(SanitizerName); } @@ -5841,26 +6025,24 @@ static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D, .Case("no_sanitize_memory", "memory"); if (isGlobalVar(D) && SanitizerName != "address") S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) - << AL.getName() << ExpectedFunction; + << AL << ExpectedFunction; D->addAttr(::new (S.Context) NoSanitizeAttr(AL.getRange(), S.Context, &SanitizerName, 1, AL.getAttributeSpellingListIndex())); } static void handleInternalLinkageAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (InternalLinkageAttr *Internal = - S.mergeInternalLinkageAttr(D, AL.getRange(), AL.getName(), - AL.getAttributeSpellingListIndex())) + if (InternalLinkageAttr *Internal = S.mergeInternalLinkageAttr(D, AL)) D->addAttr(Internal); } static void handleOpenCLNoSVMAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (S.LangOpts.OpenCLVersion != 200) S.Diag(AL.getLoc(), diag::err_attribute_requires_opencl_version) - << AL.getName() << "2.0" << 0; + << AL << "2.0" << 0; else - S.Diag(AL.getLoc(), diag::warn_opencl_attr_deprecated_ignored) - << AL.getName() << "2.0"; + S.Diag(AL.getLoc(), diag::warn_opencl_attr_deprecated_ignored) << AL + << "2.0"; } /// Handles semantic checking for features that are common to all attributes, @@ -5912,10 +6094,16 @@ static void handleOpenCLAccessAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // Check if there is only one access qualifier. if (D->hasAttr<OpenCLAccessAttr>()) { - S.Diag(AL.getLoc(), diag::err_opencl_multiple_access_qualifiers) - << D->getSourceRange(); - D->setInvalidDecl(true); - return; + if (D->getAttr<OpenCLAccessAttr>()->getSemanticSpelling() == + AL.getSemanticSpelling()) { + S.Diag(AL.getLoc(), diag::warn_duplicate_declspec) + << AL.getName()->getName() << AL.getRange(); + } else { + S.Diag(AL.getLoc(), diag::err_opencl_multiple_access_qualifiers) + << D->getSourceRange(); + D->setInvalidDecl(true); + return; + } } // OpenCL v2.0 s6.6 - read_write can be used for image types to specify that an @@ -5928,7 +6116,7 @@ static void handleOpenCLAccessAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (AL.getName()->getName().find("read_write") != StringRef::npos) { if (S.getLangOpts().OpenCLVersion < 200 || DeclTy->isPipeType()) { S.Diag(AL.getLoc(), diag::err_opencl_invalid_read_write) - << AL.getName() << PDecl->getType() << DeclTy->isImageType(); + << AL << PDecl->getType() << DeclTy->isImageType(); D->setInvalidDecl(true); return; } @@ -5939,6 +6127,100 @@ static void handleOpenCLAccessAttr(Sema &S, Decl *D, const ParsedAttr &AL) { AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); } +static void handleDestroyAttr(Sema &S, Decl *D, const ParsedAttr &A) { + if (!cast<VarDecl>(D)->hasGlobalStorage()) { + S.Diag(D->getLocation(), diag::err_destroy_attr_on_non_static_var) + << (A.getKind() == ParsedAttr::AT_AlwaysDestroy); + return; + } + + if (A.getKind() == ParsedAttr::AT_AlwaysDestroy) + handleSimpleAttributeWithExclusions<AlwaysDestroyAttr, NoDestroyAttr>(S, D, A); + else + handleSimpleAttributeWithExclusions<NoDestroyAttr, AlwaysDestroyAttr>(S, D, A); +} + +static void handleUninitializedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + assert(cast<VarDecl>(D)->getStorageDuration() == SD_Automatic && + "uninitialized is only valid on automatic duration variables"); + unsigned Index = AL.getAttributeSpellingListIndex(); + D->addAttr(::new (S.Context) + UninitializedAttr(AL.getLoc(), S.Context, Index)); +} + +static bool tryMakeVariablePseudoStrong(Sema &S, VarDecl *VD, + bool DiagnoseFailure) { + QualType Ty = VD->getType(); + if (!Ty->isObjCRetainableType()) { + if (DiagnoseFailure) { + S.Diag(VD->getBeginLoc(), diag::warn_ignored_objc_externally_retained) + << 0; + } + return false; + } + + Qualifiers::ObjCLifetime LifetimeQual = Ty.getQualifiers().getObjCLifetime(); + + // Sema::inferObjCARCLifetime must run after processing decl attributes + // (because __block lowers to an attribute), so if the lifetime hasn't been + // explicitly specified, infer it locally now. + if (LifetimeQual == Qualifiers::OCL_None) + LifetimeQual = Ty->getObjCARCImplicitLifetime(); + + // The attributes only really makes sense for __strong variables; ignore any + // attempts to annotate a parameter with any other lifetime qualifier. + if (LifetimeQual != Qualifiers::OCL_Strong) { + if (DiagnoseFailure) { + S.Diag(VD->getBeginLoc(), diag::warn_ignored_objc_externally_retained) + << 1; + } + return false; + } + + // Tampering with the type of a VarDecl here is a bit of a hack, but we need + // to ensure that the variable is 'const' so that we can error on + // modification, which can otherwise over-release. + VD->setType(Ty.withConst()); + VD->setARCPseudoStrong(true); + return true; +} + +static void handleObjCExternallyRetainedAttr(Sema &S, Decl *D, + const ParsedAttr &AL) { + if (auto *VD = dyn_cast<VarDecl>(D)) { + assert(!isa<ParmVarDecl>(VD) && "should be diagnosed automatically"); + if (!VD->hasLocalStorage()) { + S.Diag(D->getBeginLoc(), diag::warn_ignored_objc_externally_retained) + << 0; + return; + } + + if (!tryMakeVariablePseudoStrong(S, VD, /*DiagnoseFailure=*/true)) + return; + + handleSimpleAttribute<ObjCExternallyRetainedAttr>(S, D, AL); + return; + } + + // If D is a function-like declaration (method, block, or function), then we + // make every parameter psuedo-strong. + for (unsigned I = 0, E = getFunctionOrMethodNumParams(D); I != E; ++I) { + auto *PVD = const_cast<ParmVarDecl *>(getFunctionOrMethodParam(D, I)); + QualType Ty = PVD->getType(); + + // If a user wrote a parameter with __strong explicitly, then assume they + // want "real" strong semantics for that parameter. This works because if + // the parameter was written with __strong, then the strong qualifier will + // be non-local. + if (Ty.getLocalUnqualifiedType().getQualifiers().getObjCLifetime() == + Qualifiers::OCL_Strong) + continue; + + tryMakeVariablePseudoStrong(S, PVD, /*DiagnoseFailure=*/false); + } + handleSimpleAttribute<ObjCExternallyRetainedAttr>(S, D, AL); +} + //===----------------------------------------------------------------------===// // Top Level Sema Entry Points //===----------------------------------------------------------------------===// @@ -5962,10 +6244,11 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, // though they were unknown attributes. if (AL.getKind() == ParsedAttr::UnknownAttribute || !AL.existsInTarget(S.Context.getTargetInfo())) { - S.Diag(AL.getLoc(), AL.isDeclspecAttribute() - ? diag::warn_unhandled_ms_attribute_ignored - : diag::warn_unknown_attribute_ignored) - << AL.getName(); + S.Diag(AL.getLoc(), + AL.isDeclspecAttribute() + ? (unsigned)diag::warn_unhandled_ms_attribute_ignored + : (unsigned)diag::warn_unknown_attribute_ignored) + << AL; return; } @@ -5980,7 +6263,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, break; } S.Diag(AL.getLoc(), diag::err_stmt_attribute_invalid_on_decl) - << AL.getName() << D->getLocation(); + << AL << D->getLocation(); break; case ParsedAttr::AT_Interrupt: handleInterruptAttr(S, D, AL); @@ -6259,17 +6542,37 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, break; case ParsedAttr::AT_CFConsumed: case ParsedAttr::AT_NSConsumed: - handleNSConsumedAttr(S, D, AL); + case ParsedAttr::AT_OSConsumed: + S.AddXConsumedAttr(D, AL.getRange(), AL.getAttributeSpellingListIndex(), + parsedAttrToRetainOwnershipKind(AL), + /*IsTemplateInstantiation=*/false); break; case ParsedAttr::AT_NSConsumesSelf: handleSimpleAttribute<NSConsumesSelfAttr>(S, D, AL); break; + case ParsedAttr::AT_OSConsumesThis: + handleSimpleAttribute<OSConsumesThisAttr>(S, D, AL); + break; + case ParsedAttr::AT_OSReturnsRetainedOnZero: + handleSimpleAttributeOrDiagnose<OSReturnsRetainedOnZeroAttr>( + S, D, AL, isValidOSObjectOutParameter(D), + diag::warn_ns_attribute_wrong_parameter_type, + /*Extra Args=*/AL, /*pointer-to-OSObject-pointer*/ 3, AL.getRange()); + break; + case ParsedAttr::AT_OSReturnsRetainedOnNonZero: + handleSimpleAttributeOrDiagnose<OSReturnsRetainedOnNonZeroAttr>( + S, D, AL, isValidOSObjectOutParameter(D), + diag::warn_ns_attribute_wrong_parameter_type, + /*Extra Args=*/AL, /*pointer-to-OSObject-poointer*/ 3, AL.getRange()); + break; case ParsedAttr::AT_NSReturnsAutoreleased: case ParsedAttr::AT_NSReturnsNotRetained: - case ParsedAttr::AT_CFReturnsNotRetained: case ParsedAttr::AT_NSReturnsRetained: + case ParsedAttr::AT_CFReturnsNotRetained: case ParsedAttr::AT_CFReturnsRetained: - handleNSReturnsRetainedAttr(S, D, AL); + case ParsedAttr::AT_OSReturnsNotRetained: + case ParsedAttr::AT_OSReturnsRetained: + handleXReturnsXRetainedAttr(S, D, AL); break; case ParsedAttr::AT_WorkGroupSizeHint: handleWorkGroupSize<WorkGroupSizeHintAttr>(S, D, AL); @@ -6295,6 +6598,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_Section: handleSectionAttr(S, D, AL); break; + case ParsedAttr::AT_SpeculativeLoadHardening: + handleSimpleAttribute<SpeculativeLoadHardeningAttr>(S, D, AL); + break; case ParsedAttr::AT_CodeSeg: handleCodeSegAttr(S, D, AL); break; @@ -6423,6 +6729,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_IntelOclBicc: case ParsedAttr::AT_PreserveMost: case ParsedAttr::AT_PreserveAll: + case ParsedAttr::AT_AArch64VectorPcs: handleCallConvAttr(S, D, AL); break; case ParsedAttr::AT_Suppress: @@ -6449,6 +6756,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_InternalLinkage: handleInternalLinkageAttr(S, D, AL); break; + case ParsedAttr::AT_ExcludeFromExplicitInstantiation: + handleSimpleAttribute<ExcludeFromExplicitInstantiationAttr>(S, D, AL); + break; case ParsedAttr::AT_LTOVisibilityPublic: handleSimpleAttribute<LTOVisibilityPublicAttr>(S, D, AL); break; @@ -6604,6 +6914,24 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_XRayLogArgs: handleXRayLogArgsAttr(S, D, AL); break; + + // Move semantics attribute. + case ParsedAttr::AT_Reinitializes: + handleSimpleAttribute<ReinitializesAttr>(S, D, AL); + break; + + case ParsedAttr::AT_AlwaysDestroy: + case ParsedAttr::AT_NoDestroy: + handleDestroyAttr(S, D, AL); + break; + + case ParsedAttr::AT_Uninitialized: + handleUninitializedAttr(S, D, AL); + break; + + case ParsedAttr::AT_ObjCExternallyRetained: + handleObjCExternallyRetainedAttr(S, D, AL); + break; } } @@ -6708,10 +7036,10 @@ static void checkUnusedDeclAttributes(Sema &S, const ParsedAttributesView &A) { if (AL.getKind() == ParsedAttr::UnknownAttribute) { S.Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) - << AL.getName() << AL.getRange(); + << AL << AL.getRange(); } else { - S.Diag(AL.getLoc(), diag::warn_attribute_not_on_decl) - << AL.getName() << AL.getRange(); + S.Diag(AL.getLoc(), diag::warn_attribute_not_on_decl) << AL + << AL.getRange(); } } } @@ -6942,8 +7270,12 @@ static const AvailabilityAttr *getAttrForPlatform(ASTContext &Context, /// \param D The declaration to check. /// \param Message If non-null, this will be populated with the message from /// the availability attribute that is selected. +/// \param ClassReceiver If we're checking the the method of a class message +/// send, the class. Otherwise nullptr. static std::pair<AvailabilityResult, const NamedDecl *> -ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, std::string *Message) { +ShouldDiagnoseAvailabilityOfDecl(Sema &S, const NamedDecl *D, + std::string *Message, + ObjCInterfaceDecl *ClassReceiver) { AvailabilityResult Result = D->getAvailability(Message); // For typedefs, if the typedef declaration appears available look @@ -6976,6 +7308,20 @@ ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, std::string *Message) { } } + // For +new, infer availability from -init. + if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) { + if (S.NSAPIObj && ClassReceiver) { + ObjCMethodDecl *Init = ClassReceiver->lookupInstanceMethod( + S.NSAPIObj->getInitSelector()); + if (Init && Result == AR_Available && MD->isClassMethod() && + MD->getSelector() == S.NSAPIObj->getNewSelector() && + MD->definedInNSObject(S.getASTContext())) { + Result = Init->getAvailability(Message); + D = Init; + } + } + } + return {Result, D}; } @@ -6983,9 +7329,10 @@ ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, std::string *Message) { /// whether we should emit a diagnostic for \c K and \c DeclVersion in /// the context of \c Ctx. For example, we should emit an unavailable diagnostic /// in a deprecated context, but not the other way around. -static bool ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K, - VersionTuple DeclVersion, - Decl *Ctx) { +static bool +ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K, + VersionTuple DeclVersion, Decl *Ctx, + const NamedDecl *OffendingDecl) { assert(K != AR_Available && "Expected an unavailable declaration here!"); // Checks if we should emit the availability diagnostic in the context of C. @@ -6994,9 +7341,22 @@ static bool ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K, if (const AvailabilityAttr *AA = getAttrForPlatform(S.Context, C)) if (AA->getIntroduced() >= DeclVersion) return true; - } else if (K == AR_Deprecated) + } else if (K == AR_Deprecated) { if (C->isDeprecated()) return true; + } else if (K == AR_Unavailable) { + // It is perfectly fine to refer to an 'unavailable' Objective-C method + // when it's actually defined and is referenced from within the + // @implementation itself. In this context, we interpret unavailable as a + // form of access control. + if (const auto *MD = dyn_cast<ObjCMethodDecl>(OffendingDecl)) { + if (const auto *Impl = dyn_cast<ObjCImplDecl>(C)) { + if (MD->getClassInterface() == Impl->getClassInterface() && + MD->isDefined()) + return true; + } + } + } if (C->isUnavailable()) return true; @@ -7078,13 +7438,13 @@ struct AttributeInsertion { StringRef Suffix; static AttributeInsertion createInsertionAfter(const NamedDecl *D) { - return {" ", D->getLocEnd(), ""}; + return {" ", D->getEndLoc(), ""}; } static AttributeInsertion createInsertionAfter(SourceLocation Loc) { return {" ", Loc, ""}; } static AttributeInsertion createInsertionBefore(const NamedDecl *D) { - return {"", D->getLocStart(), "\n"}; + return {"", D->getBeginLoc(), "\n"}; } }; @@ -7185,7 +7545,8 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K, if (const AvailabilityAttr *AA = getAttrForPlatform(S.Context, OffendingDecl)) DeclVersion = AA->getIntroduced(); - if (!ShouldDiagnoseAvailabilityInContext(S, K, DeclVersion, Ctx)) + if (!ShouldDiagnoseAvailabilityInContext(S, K, DeclVersion, Ctx, + OffendingDecl)) return; SourceLocation Loc = Locs.front(); @@ -7223,14 +7584,16 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K, unsigned Warning = UseNewWarning ? diag::warn_unguarded_availability_new : diag::warn_unguarded_availability; - S.Diag(Loc, Warning) - << OffendingDecl - << AvailabilityAttr::getPrettyPlatformName( - S.getASTContext().getTargetInfo().getPlatformName()) - << Introduced.getAsString(); + std::string PlatformName = AvailabilityAttr::getPrettyPlatformName( + S.getASTContext().getTargetInfo().getPlatformName()); - S.Diag(OffendingDecl->getLocation(), diag::note_availability_specified_here) - << OffendingDecl << /* partial */ 3; + S.Diag(Loc, Warning) << OffendingDecl << PlatformName + << Introduced.getAsString(); + + S.Diag(OffendingDecl->getLocation(), + diag::note_partial_availability_specified_here) + << OffendingDecl << PlatformName << Introduced.getAsString() + << S.Context.getTargetInfo().getPlatformMinVersion().getAsString(); if (const auto *Enclosing = findEnclosingDeclToAnnotate(Ctx)) { if (const auto *TD = dyn_cast<TagDecl>(Enclosing)) @@ -7423,6 +7786,7 @@ void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) { // for each of the different declarations. const DelayedDiagnosticPool *pool = &poppedPool; do { + bool AnyAccessFailures = false; for (DelayedDiagnosticPool::pool_iterator i = pool->pool_begin(), e = pool->pool_end(); i != e; ++i) { // This const_cast is a bit lame. Really, Triggered should be mutable. @@ -7439,7 +7803,14 @@ void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) { break; case DelayedDiagnostic::Access: + // Only produce one access control diagnostic for a structured binding + // declaration: we don't need to tell the user that all the fields are + // inaccessible one at a time. + if (AnyAccessFailures && isa<DecompositionDecl>(decl)) + continue; HandleDelayedAccessCheck(diag, decl); + if (diag.Triggered) + AnyAccessFailures = true; break; case DelayedDiagnostic::ForbiddenType: @@ -7564,7 +7935,8 @@ class DiagnoseUnguardedAvailability SmallVector<VersionTuple, 8> AvailabilityStack; SmallVector<const Stmt *, 16> StmtStack; - void DiagnoseDeclAvailability(NamedDecl *D, SourceRange Range); + void DiagnoseDeclAvailability(NamedDecl *D, SourceRange Range, + ObjCInterfaceDecl *ClassReceiver = nullptr); public: DiagnoseUnguardedAvailability(Sema &SemaRef, Decl *Ctx) @@ -7606,27 +7978,33 @@ public: } bool VisitObjCMessageExpr(ObjCMessageExpr *Msg) { - if (ObjCMethodDecl *D = Msg->getMethodDecl()) + if (ObjCMethodDecl *D = Msg->getMethodDecl()) { + ObjCInterfaceDecl *ID = nullptr; + QualType ReceiverTy = Msg->getClassReceiver(); + if (!ReceiverTy.isNull() && ReceiverTy->getAsObjCInterfaceType()) + ID = ReceiverTy->getAsObjCInterfaceType()->getInterface(); + DiagnoseDeclAvailability( - D, SourceRange(Msg->getSelectorStartLoc(), Msg->getLocEnd())); + D, SourceRange(Msg->getSelectorStartLoc(), Msg->getEndLoc()), ID); + } return true; } bool VisitDeclRefExpr(DeclRefExpr *DRE) { DiagnoseDeclAvailability(DRE->getDecl(), - SourceRange(DRE->getLocStart(), DRE->getLocEnd())); + SourceRange(DRE->getBeginLoc(), DRE->getEndLoc())); return true; } bool VisitMemberExpr(MemberExpr *ME) { DiagnoseDeclAvailability(ME->getMemberDecl(), - SourceRange(ME->getLocStart(), ME->getLocEnd())); + SourceRange(ME->getBeginLoc(), ME->getEndLoc())); return true; } bool VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *E) { - SemaRef.Diag(E->getLocStart(), diag::warn_at_available_unchecked_use) - << (!SemaRef.getLangOpts().ObjC1); + SemaRef.Diag(E->getBeginLoc(), diag::warn_at_available_unchecked_use) + << (!SemaRef.getLangOpts().ObjC); return true; } @@ -7634,11 +8012,11 @@ public: }; void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability( - NamedDecl *D, SourceRange Range) { + NamedDecl *D, SourceRange Range, ObjCInterfaceDecl *ReceiverClass) { AvailabilityResult Result; const NamedDecl *OffendingDecl; std::tie(Result, OffendingDecl) = - ShouldDiagnoseAvailabilityOfDecl(D, nullptr); + ShouldDiagnoseAvailabilityOfDecl(SemaRef, D, nullptr, ReceiverClass); if (Result != AR_Available) { // All other diagnostic kinds have already been handled in // DiagnoseAvailabilityOfDecl. @@ -7654,7 +8032,8 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability( // If the context of this function is less available than D, we should not // emit a diagnostic. - if (!ShouldDiagnoseAvailabilityInContext(SemaRef, Result, Introduced, Ctx)) + if (!ShouldDiagnoseAvailabilityInContext(SemaRef, Result, Introduced, Ctx, + OffendingDecl)) return; // We would like to emit the diagnostic even if -Wunguarded-availability is @@ -7668,21 +8047,24 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability( ? diag::warn_unguarded_availability_new : diag::warn_unguarded_availability; + std::string PlatformName = AvailabilityAttr::getPrettyPlatformName( + SemaRef.getASTContext().getTargetInfo().getPlatformName()); + SemaRef.Diag(Range.getBegin(), DiagKind) - << Range << D - << AvailabilityAttr::getPrettyPlatformName( - SemaRef.getASTContext().getTargetInfo().getPlatformName()) - << Introduced.getAsString(); + << Range << D << PlatformName << Introduced.getAsString(); SemaRef.Diag(OffendingDecl->getLocation(), - diag::note_availability_specified_here) - << OffendingDecl << /* partial */ 3; + diag::note_partial_availability_specified_here) + << OffendingDecl << PlatformName << Introduced.getAsString() + << SemaRef.Context.getTargetInfo() + .getPlatformMinVersion() + .getAsString(); auto FixitDiag = SemaRef.Diag(Range.getBegin(), diag::note_unguarded_available_silence) << Range << D - << (SemaRef.getLangOpts().ObjC1 ? /*@available*/ 0 - : /*__builtin_available*/ 1); + << (SemaRef.getLangOpts().ObjC ? /*@available*/ 0 + : /*__builtin_available*/ 1); // Find the statement which should be enclosed in the if @available check. if (StmtStack.empty()) @@ -7714,10 +8096,10 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability( const SourceManager &SM = SemaRef.getSourceManager(); SourceLocation IfInsertionLoc = - SM.getExpansionLoc(StmtOfUse->getLocStart()); + SM.getExpansionLoc(StmtOfUse->getBeginLoc()); SourceLocation StmtEndLoc = SM.getExpansionRange( - (LastStmtOfUse ? LastStmtOfUse : StmtOfUse)->getLocEnd()) + (LastStmtOfUse ? LastStmtOfUse : StmtOfUse)->getEndLoc()) .getEnd(); if (SM.getFileID(IfInsertionLoc) != SM.getFileID(StmtEndLoc)) return; @@ -7726,8 +8108,8 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability( const char *ExtraIndentation = " "; std::string FixItString; llvm::raw_string_ostream FixItOS(FixItString); - FixItOS << "if (" << (SemaRef.getLangOpts().ObjC1 ? "@available" - : "__builtin_available") + FixItOS << "if (" << (SemaRef.getLangOpts().ObjC ? "@available" + : "__builtin_available") << "(" << AvailabilityAttr::getPlatformNameSourceSpelling( SemaRef.getASTContext().getTargetInfo().getPlatformName()) @@ -7820,12 +8202,14 @@ void Sema::DiagnoseAvailabilityOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs, const ObjCInterfaceDecl *UnknownObjCClass, bool ObjCPropertyAccess, - bool AvoidPartialAvailabilityChecks) { + bool AvoidPartialAvailabilityChecks, + ObjCInterfaceDecl *ClassReceiver) { std::string Message; AvailabilityResult Result; const NamedDecl* OffendingDecl; // See if this declaration is unavailable, deprecated, or partial. - std::tie(Result, OffendingDecl) = ShouldDiagnoseAvailabilityOfDecl(D, &Message); + std::tie(Result, OffendingDecl) = + ShouldDiagnoseAvailabilityOfDecl(*this, D, &Message, ClassReceiver); if (Result == AR_Available) return; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 4cf3abdf5745f..43b289d8d0de1 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -94,17 +94,17 @@ namespace { // evaluated. Parameters of a function declared before a default // argument expression are in scope and can hide namespace and // class member names. - return S->Diag(DRE->getLocStart(), + return S->Diag(DRE->getBeginLoc(), diag::err_param_default_argument_references_param) - << Param->getDeclName() << DefaultArg->getSourceRange(); + << Param->getDeclName() << DefaultArg->getSourceRange(); } else if (VarDecl *VDecl = dyn_cast<VarDecl>(Decl)) { // C++ [dcl.fct.default]p7 // Local variables shall not be used in default argument // expressions. if (VDecl->isLocalVarDecl()) - return S->Diag(DRE->getLocStart(), + return S->Diag(DRE->getBeginLoc(), diag::err_param_default_argument_references_local) - << VDecl->getDeclName() << DefaultArg->getSourceRange(); + << VDecl->getDeclName() << DefaultArg->getSourceRange(); } return false; @@ -115,9 +115,9 @@ namespace { // C++ [dcl.fct.default]p8: // The keyword this shall not be used in a default argument of a // member function. - return S->Diag(ThisE->getLocStart(), + return S->Diag(ThisE->getBeginLoc(), diag::err_param_default_argument_references_this) - << ThisE->getSourceRange(); + << ThisE->getSourceRange(); } bool CheckDefaultArgumentVisitor::VisitPseudoObjectExpr(PseudoObjectExpr *POE) { @@ -144,8 +144,7 @@ namespace { if (Lambda->capture_begin() == Lambda->capture_end()) return false; - return S->Diag(Lambda->getLocStart(), - diag::err_lambda_capture_default_arg); + return S->Diag(Lambda->getBeginLoc(), diag::err_lambda_capture_default_arg); } } @@ -1108,7 +1107,7 @@ static bool checkTupleLikeDecomposition(Sema &S, // [dcl.decomp]p3: // The unqualified-id get is looked up in the scope of E by class member - // access lookup + // access lookup ... LookupResult MemberGet(S, GetDN, Src->getLocation(), Sema::LookupMemberName); bool UseMemberGet = false; if (S.isCompleteType(Src->getLocation(), DecompType)) { @@ -1116,7 +1115,20 @@ static bool checkTupleLikeDecomposition(Sema &S, S.LookupQualifiedName(MemberGet, RD); if (MemberGet.isAmbiguous()) return true; - UseMemberGet = !MemberGet.empty(); + // ... and if that finds at least one declaration that is a function + // template whose first template parameter is a non-type parameter ... + for (NamedDecl *D : MemberGet) { + if (FunctionTemplateDecl *FTD = + dyn_cast<FunctionTemplateDecl>(D->getUnderlyingDecl())) { + TemplateParameterList *TPL = FTD->getTemplateParameters(); + if (TPL->size() != 0 && + isa<NonTypeTemplateParmDecl>(TPL->getParam(0))) { + // ... the initializer is e.get<i>(). + UseMemberGet = true; + break; + } + } + } S.FilterAcceptableTemplateNames(MemberGet); } @@ -1193,7 +1205,7 @@ static bool checkTupleLikeDecomposition(Sema &S, E = Seq.Perform(S, Entity, Kind, Init); if (E.isInvalid()) return true; - E = S.ActOnFinishFullExpr(E.get(), Loc); + E = S.ActOnFinishFullExpr(E.get(), Loc, /*DiscardedValue*/ false); if (E.isInvalid()) return true; RefVD->setInit(E.get()); @@ -1215,16 +1227,16 @@ static bool checkTupleLikeDecomposition(Sema &S, /// Find the base class to decompose in a built-in decomposition of a class type. /// This base class search is, unfortunately, not quite like any other that we /// perform anywhere else in C++. -static const CXXRecordDecl *findDecomposableBaseClass(Sema &S, - SourceLocation Loc, - const CXXRecordDecl *RD, - CXXCastPath &BasePath) { +static DeclAccessPair findDecomposableBaseClass(Sema &S, SourceLocation Loc, + const CXXRecordDecl *RD, + CXXCastPath &BasePath) { auto BaseHasFields = [](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { return Specifier->getType()->getAsCXXRecordDecl()->hasDirectFields(); }; const CXXRecordDecl *ClassWithFields = nullptr; + AccessSpecifier AS = AS_public; if (RD->hasDirectFields()) // [dcl.decomp]p4: // Otherwise, all of E's non-static data members shall be public direct @@ -1237,7 +1249,7 @@ static const CXXRecordDecl *findDecomposableBaseClass(Sema &S, if (!RD->lookupInBases(BaseHasFields, Paths)) { // If no classes have fields, just decompose RD itself. (This will work // if and only if zero bindings were provided.) - return RD; + return DeclAccessPair::make(const_cast<CXXRecordDecl*>(RD), AS_public); } CXXBasePath *BestPath = nullptr; @@ -1250,7 +1262,7 @@ static const CXXRecordDecl *findDecomposableBaseClass(Sema &S, S.Diag(Loc, diag::err_decomp_decl_multiple_bases_with_members) << false << RD << BestPath->back().Base->getType() << P.back().Base->getType(); - return nullptr; + return DeclAccessPair(); } else if (P.Access < BestPath->Access) { BestPath = &P; } @@ -1261,23 +1273,13 @@ static const CXXRecordDecl *findDecomposableBaseClass(Sema &S, if (Paths.isAmbiguous(S.Context.getCanonicalType(BaseType))) { S.Diag(Loc, diag::err_decomp_decl_ambiguous_base) << RD << BaseType << S.getAmbiguousPathsDisplayString(Paths); - return nullptr; + return DeclAccessPair(); } - // ... public base class of E. - if (BestPath->Access != AS_public) { - S.Diag(Loc, diag::err_decomp_decl_non_public_base) - << RD << BaseType; - for (auto &BS : *BestPath) { - if (BS.Base->getAccessSpecifier() != AS_public) { - S.Diag(BS.Base->getLocStart(), diag::note_access_constrained_by_path) - << (BS.Base->getAccessSpecifier() == AS_protected) - << (BS.Base->getAccessSpecifierAsWritten() == AS_none); - break; - } - } - return nullptr; - } + // ... [accessible, implied by other rules] base class of E. + S.CheckBaseClassAccess(Loc, BaseType, S.Context.getRecordType(RD), + *BestPath, diag::err_decomp_decl_inaccessible_base); + AS = BestPath->Access; ClassWithFields = BaseType->getAsCXXRecordDecl(); S.BuildBasePathArray(Paths, BasePath); @@ -1290,17 +1292,19 @@ static const CXXRecordDecl *findDecomposableBaseClass(Sema &S, S.Diag(Loc, diag::err_decomp_decl_multiple_bases_with_members) << (ClassWithFields == RD) << RD << ClassWithFields << Paths.front().back().Base->getType(); - return nullptr; + return DeclAccessPair(); } - return ClassWithFields; + return DeclAccessPair::make(const_cast<CXXRecordDecl*>(ClassWithFields), AS); } static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings, ValueDecl *Src, QualType DecompType, - const CXXRecordDecl *RD) { + const CXXRecordDecl *OrigRD) { CXXCastPath BasePath; - RD = findDecomposableBaseClass(S, Src->getLocation(), RD, BasePath); + DeclAccessPair BasePair = + findDecomposableBaseClass(S, Src->getLocation(), OrigRD, BasePath); + const CXXRecordDecl *RD = cast_or_null<CXXRecordDecl>(BasePair.getDecl()); if (!RD) return true; QualType BaseType = S.Context.getQualifiedType(S.Context.getRecordType(RD), @@ -1317,7 +1321,8 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings, return true; }; - // all of E's non-static data members shall be public [...] members, + // all of E's non-static data members shall be [...] well-formed + // when named as e.name in the context of the structured binding, // E shall not have an anonymous union member, ... unsigned I = 0; for (auto *FD : RD->fields()) { @@ -1335,26 +1340,16 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings, if (I >= Bindings.size()) return DiagnoseBadNumberOfBindings(); auto *B = Bindings[I++]; - SourceLocation Loc = B->getLocation(); - if (FD->getAccess() != AS_public) { - S.Diag(Loc, diag::err_decomp_decl_non_public_member) << FD << DecompType; - // Determine whether the access specifier was explicit. - bool Implicit = true; - for (const auto *D : RD->decls()) { - if (declaresSameEntity(D, FD)) - break; - if (isa<AccessSpecDecl>(D)) { - Implicit = false; - break; - } - } - - S.Diag(FD->getLocation(), diag::note_access_natural) - << (FD->getAccess() == AS_protected) << Implicit; - return true; - } + // The field must be accessible in the context of the structured binding. + // We already checked that the base class is accessible. + // FIXME: Add 'const' to AccessedEntity's classes so we can remove the + // const_cast here. + S.CheckStructuredBindingMemberAccess( + Loc, const_cast<CXXRecordDecl *>(OrigRD), + DeclAccessPair::make(FD, CXXRecordDecl::MergeAccess( + BasePair.getAccess(), FD->getAccess()))); // Initialize the binding to Src.FD. ExprResult E = S.BuildDeclRefExpr(Src, DecompType, VK_LValue, Loc); @@ -1606,8 +1601,8 @@ bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD) { << isa<CXXConstructorDecl>(NewFD) << getRecordDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases(); for (const auto &I : RD->vbases()) - Diag(I.getLocStart(), - diag::note_constexpr_virtual_base_here) << I.getSourceRange(); + Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here) + << I.getSourceRange(); return false; } } @@ -1691,11 +1686,11 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl, case Decl::CXXRecord: // C++1y allows types to be defined, not just declared. if (cast<TagDecl>(DclIt)->isThisDeclarationADefinition()) - SemaRef.Diag(DS->getLocStart(), + SemaRef.Diag(DS->getBeginLoc(), SemaRef.getLangOpts().CPlusPlus14 - ? diag::warn_cxx11_compat_constexpr_type_definition - : diag::ext_constexpr_type_definition) - << isa<CXXConstructorDecl>(Dcl); + ? diag::warn_cxx11_compat_constexpr_type_definition + : diag::ext_constexpr_type_definition) + << isa<CXXConstructorDecl>(Dcl); continue; case Decl::EnumConstant: @@ -1746,12 +1741,12 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl, // These are disallowed in C++11 and permitted in C++1y. Allow them // everywhere as an extension. if (!Cxx1yLoc.isValid()) - Cxx1yLoc = DS->getLocStart(); + Cxx1yLoc = DS->getBeginLoc(); continue; default: - SemaRef.Diag(DS->getLocStart(), diag::err_constexpr_body_invalid_stmt) - << isa<CXXConstructorDecl>(Dcl); + SemaRef.Diag(DS->getBeginLoc(), diag::err_constexpr_body_invalid_stmt) + << isa<CXXConstructorDecl>(Dcl); return false; } } @@ -1808,7 +1803,7 @@ static void CheckConstexprCtorInitializer(Sema &SemaRef, static bool CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S, SmallVectorImpl<SourceLocation> &ReturnStmts, - SourceLocation &Cxx1yLoc) { + SourceLocation &Cxx1yLoc, SourceLocation &Cxx2aLoc) { // - its function-body shall be [...] a compound-statement that contains only switch (S->getStmtClass()) { case Stmt::NullStmtClass: @@ -1830,22 +1825,22 @@ CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S, if (isa<CXXConstructorDecl>(Dcl)) { // C++1y allows return statements in constexpr constructors. if (!Cxx1yLoc.isValid()) - Cxx1yLoc = S->getLocStart(); + Cxx1yLoc = S->getBeginLoc(); return true; } - ReturnStmts.push_back(S->getLocStart()); + ReturnStmts.push_back(S->getBeginLoc()); return true; case Stmt::CompoundStmtClass: { // C++1y allows compound-statements. if (!Cxx1yLoc.isValid()) - Cxx1yLoc = S->getLocStart(); + Cxx1yLoc = S->getBeginLoc(); CompoundStmt *CompStmt = cast<CompoundStmt>(S); for (auto *BodyIt : CompStmt->body()) { if (!CheckConstexprFunctionStmt(SemaRef, Dcl, BodyIt, ReturnStmts, - Cxx1yLoc)) + Cxx1yLoc, Cxx2aLoc)) return false; } return true; @@ -1853,21 +1848,21 @@ CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S, case Stmt::AttributedStmtClass: if (!Cxx1yLoc.isValid()) - Cxx1yLoc = S->getLocStart(); + Cxx1yLoc = S->getBeginLoc(); return true; case Stmt::IfStmtClass: { // C++1y allows if-statements. if (!Cxx1yLoc.isValid()) - Cxx1yLoc = S->getLocStart(); + Cxx1yLoc = S->getBeginLoc(); IfStmt *If = cast<IfStmt>(S); if (!CheckConstexprFunctionStmt(SemaRef, Dcl, If->getThen(), ReturnStmts, - Cxx1yLoc)) + Cxx1yLoc, Cxx2aLoc)) return false; if (If->getElse() && !CheckConstexprFunctionStmt(SemaRef, Dcl, If->getElse(), ReturnStmts, - Cxx1yLoc)) + Cxx1yLoc, Cxx2aLoc)) return false; return true; } @@ -1882,11 +1877,11 @@ CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S, if (!SemaRef.getLangOpts().CPlusPlus14) break; if (!Cxx1yLoc.isValid()) - Cxx1yLoc = S->getLocStart(); + Cxx1yLoc = S->getBeginLoc(); for (Stmt *SubStmt : S->children()) if (SubStmt && !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts, - Cxx1yLoc)) + Cxx1yLoc, Cxx2aLoc)) return false; return true; @@ -1897,12 +1892,32 @@ CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S, // C++1y allows switch-statements, and since they don't need variable // mutation, we can reasonably allow them in C++11 as an extension. if (!Cxx1yLoc.isValid()) - Cxx1yLoc = S->getLocStart(); + Cxx1yLoc = S->getBeginLoc(); for (Stmt *SubStmt : S->children()) if (SubStmt && !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts, - Cxx1yLoc)) + Cxx1yLoc, Cxx2aLoc)) + return false; + return true; + + case Stmt::CXXTryStmtClass: + if (Cxx2aLoc.isInvalid()) + Cxx2aLoc = S->getBeginLoc(); + for (Stmt *SubStmt : S->children()) { + if (SubStmt && + !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts, + Cxx1yLoc, Cxx2aLoc)) return false; + } + return true; + + case Stmt::CXXCatchStmtClass: + // Do not bother checking the language mode (already covered by the + // try block check). + if (!CheckConstexprFunctionStmt(SemaRef, Dcl, + cast<CXXCatchStmt>(S)->getHandlerBlock(), + ReturnStmts, Cxx1yLoc, Cxx2aLoc)) + return false; return true; default: @@ -1911,12 +1926,12 @@ CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S, // C++1y allows expression-statements. if (!Cxx1yLoc.isValid()) - Cxx1yLoc = S->getLocStart(); + Cxx1yLoc = S->getBeginLoc(); return true; } - SemaRef.Diag(S->getLocStart(), diag::err_constexpr_body_invalid_stmt) - << isa<CXXConstructorDecl>(Dcl); + SemaRef.Diag(S->getBeginLoc(), diag::err_constexpr_body_invalid_stmt) + << isa<CXXConstructorDecl>(Dcl); return false; } @@ -1925,6 +1940,8 @@ CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S, /// /// \return true if the body is OK, false if we have diagnosed a problem. bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { + SmallVector<SourceLocation, 4> ReturnStmts; + if (isa<CXXTryStmt>(Body)) { // C++11 [dcl.constexpr]p3: // The definition of a constexpr function shall satisfy the following @@ -1935,22 +1952,35 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { // C++11 [dcl.constexpr]p4: // In the definition of a constexpr constructor, [...] // - its function-body shall not be a function-try-block; - Diag(Body->getLocStart(), diag::err_constexpr_function_try_block) - << isa<CXXConstructorDecl>(Dcl); - return false; + // + // This restriction is lifted in C++2a, as long as inner statements also + // apply the general constexpr rules. + Diag(Body->getBeginLoc(), + !getLangOpts().CPlusPlus2a + ? diag::ext_constexpr_function_try_block_cxx2a + : diag::warn_cxx17_compat_constexpr_function_try_block) + << isa<CXXConstructorDecl>(Dcl); } - SmallVector<SourceLocation, 4> ReturnStmts; - // - its function-body shall be [...] a compound-statement that contains only // [... list of cases ...] - CompoundStmt *CompBody = cast<CompoundStmt>(Body); - SourceLocation Cxx1yLoc; - for (auto *BodyIt : CompBody->body()) { - if (!CheckConstexprFunctionStmt(*this, Dcl, BodyIt, ReturnStmts, Cxx1yLoc)) + // + // Note that walking the children here is enough to properly check for + // CompoundStmt and CXXTryStmt body. + SourceLocation Cxx1yLoc, Cxx2aLoc; + for (Stmt *SubStmt : Body->children()) { + if (SubStmt && + !CheckConstexprFunctionStmt(*this, Dcl, SubStmt, ReturnStmts, + Cxx1yLoc, Cxx2aLoc)) return false; } + if (Cxx2aLoc.isValid()) + Diag(Cxx2aLoc, + getLangOpts().CPlusPlus2a + ? diag::warn_cxx17_compat_constexpr_body_invalid_stmt + : diag::ext_constexpr_body_invalid_stmt_cxx2a) + << isa<CXXConstructorDecl>(Dcl); if (Cxx1yLoc.isValid()) Diag(Cxx1yLoc, getLangOpts().CPlusPlus14 @@ -2317,8 +2347,8 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, if (AL.isInvalid() || AL.getKind() == ParsedAttr::IgnoredAttribute) continue; Diag(AL.getLoc(), AL.getKind() == ParsedAttr::UnknownAttribute - ? diag::warn_unknown_attribute_ignored - : diag::err_base_specifier_attribute) + ? (unsigned)diag::warn_unknown_attribute_ignored + : (unsigned)diag::err_base_specifier_attribute) << AL.getName(); } @@ -2395,10 +2425,8 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, // C++ [class.mi]p3: // A class shall not be specified as a direct base class of a // derived class more than once. - Diag(Bases[idx]->getLocStart(), - diag::err_duplicate_base_class) - << KnownBase->getType() - << Bases[idx]->getSourceRange(); + Diag(Bases[idx]->getBeginLoc(), diag::err_duplicate_base_class) + << KnownBase->getType() << Bases[idx]->getSourceRange(); // Delete the duplicate base class specifier; we're going to // overwrite its pointer later. @@ -2421,9 +2449,9 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, KnownBase->getAccessSpecifier() != AS_public)) { // The Microsoft extension __interface does not permit bases that // are not themselves public interfaces. - Diag(KnownBase->getLocStart(), diag::err_invalid_base_in_interface) - << getRecordDiagFromTagKind(RD->getTagKind()) << RD - << RD->getSourceRange(); + Diag(KnownBase->getBeginLoc(), diag::err_invalid_base_in_interface) + << getRecordDiagFromTagKind(RD->getTagKind()) << RD + << RD->getSourceRange(); Invalid = true; } if (RD->hasAttr<WeakAttr>()) @@ -2457,9 +2485,9 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, (void)found; if (Paths.isAmbiguous(CanonicalBase)) - Diag(Bases[idx]->getLocStart (), diag::warn_inaccessible_base_class) - << BaseType << getAmbiguousPathsDisplayString(Paths) - << Bases[idx]->getSourceRange(); + Diag(Bases[idx]->getBeginLoc(), diag::warn_inaccessible_base_class) + << BaseType << getAmbiguousPathsDisplayString(Paths) + << Bases[idx]->getSourceRange(); else assert(Bases[idx]->isVirtual()); } @@ -2842,7 +2870,8 @@ static const ParsedAttr *getMSPropertyAttr(const ParsedAttributesView &list) { // Check if there is a field shadowing. void Sema::CheckShadowInheritedFields(const SourceLocation &Loc, DeclarationName FieldName, - const CXXRecordDecl *RD) { + const CXXRecordDecl *RD, + bool DeclIsField) { if (Diags.isIgnored(diag::warn_shadow_field, Loc)) return; @@ -2882,7 +2911,7 @@ void Sema::CheckShadowInheritedFields(const SourceLocation &Loc, if (AS_none != CXXRecordDecl::MergeAccess(P.Access, BaseField->getAccess())) { Diag(Loc, diag::warn_shadow_field) - << FieldName << RD << Base; + << FieldName << RD << Base << DeclIsField; Diag(BaseField->getLocation(), diag::note_shadow_field); Bases.erase(It); } @@ -2906,7 +2935,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, // For anonymous bitfields, the location should point to the type. if (Loc.isInvalid()) - Loc = D.getLocStart(); + Loc = D.getBeginLoc(); Expr *BitWidth = static_cast<Expr*>(BW); @@ -3144,17 +3173,17 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, if (auto *DG = dyn_cast<CXXDeductionGuideDecl>(NonTemplateMember)) { auto *TD = DG->getDeducedTemplate(); if (AS != TD->getAccess()) { - Diag(DG->getLocStart(), diag::err_deduction_guide_wrong_access); - Diag(TD->getLocStart(), diag::note_deduction_guide_template_access) - << TD->getAccess(); + Diag(DG->getBeginLoc(), diag::err_deduction_guide_wrong_access); + Diag(TD->getBeginLoc(), diag::note_deduction_guide_template_access) + << TD->getAccess(); const AccessSpecDecl *LastAccessSpec = nullptr; for (const auto *D : cast<CXXRecordDecl>(CurContext)->decls()) { if (const auto *AccessSpec = dyn_cast<AccessSpecDecl>(D)) LastAccessSpec = AccessSpec; } assert(LastAccessSpec && "differing access with no access specifier"); - Diag(LastAccessSpec->getLocStart(), diag::note_deduction_guide_access) - << AS; + Diag(LastAccessSpec->getBeginLoc(), diag::note_deduction_guide_access) + << AS; } } } @@ -3239,7 +3268,7 @@ namespace { ME = dyn_cast<MemberExpr>(ME->getBase()->IgnoreParenImpCasts()); } - // Binding a reference to an unintialized field is not an + // Binding a reference to an uninitialized field is not an // uninitialized use. if (CheckReferenceOnly && !ReferenceField) return true; @@ -3638,10 +3667,10 @@ void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D, InitializedEntity::InitializeMemberFromDefaultMemberInitializer(FD); InitializationKind Kind = FD->getInClassInitStyle() == ICIS_ListInit - ? InitializationKind::CreateDirectList(InitExpr->getLocStart(), - InitExpr->getLocStart(), - InitExpr->getLocEnd()) - : InitializationKind::CreateCopy(InitExpr->getLocStart(), InitLoc); + ? InitializationKind::CreateDirectList(InitExpr->getBeginLoc(), + InitExpr->getBeginLoc(), + InitExpr->getEndLoc()) + : InitializationKind::CreateCopy(InitExpr->getBeginLoc(), InitLoc); InitializationSequence Seq(*this, Entity, Kind, InitExpr); Init = Seq.Perform(*this, Entity, Kind, InitExpr); if (Init.isInvalid()) { @@ -3653,7 +3682,7 @@ void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D, // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. - Init = ActOnFinishFullExpr(Init.get(), InitLoc); + Init = ActOnFinishFullExpr(Init.get(), InitLoc, /*DiscardedValue*/ false); if (Init.isInvalid()) { FD->setInvalidDecl(); return; @@ -3737,8 +3766,7 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, ArrayRef<Expr *> Args, SourceLocation RParenLoc, SourceLocation EllipsisLoc) { - Expr *List = new (Context) ParenListExpr(Context, LParenLoc, - Args, RParenLoc); + Expr *List = ParenListExpr::Create(Context, LParenLoc, Args, RParenLoc); return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy, DS, IdLoc, List, EllipsisLoc); } @@ -3767,6 +3795,22 @@ private: } +ValueDecl *Sema::tryLookupCtorInitMemberDecl(CXXRecordDecl *ClassDecl, + CXXScopeSpec &SS, + ParsedType TemplateTypeTy, + IdentifierInfo *MemberOrBase) { + if (SS.getScopeRep() || TemplateTypeTy) + return nullptr; + DeclContext::lookup_result Result = ClassDecl->lookup(MemberOrBase); + if (Result.empty()) + return nullptr; + ValueDecl *Member; + if ((Member = dyn_cast<FieldDecl>(Result.front())) || + (Member = dyn_cast<IndirectFieldDecl>(Result.front()))) + return Member; + return nullptr; +} + /// Handle a C++ member initializer. MemInitResult Sema::BuildMemInitializer(Decl *ConstructorD, @@ -3810,21 +3854,16 @@ Sema::BuildMemInitializer(Decl *ConstructorD, // of a single identifier refers to the class member. A // mem-initializer-id for the hidden base class may be specified // using a qualified name. ] - if (!SS.getScopeRep() && !TemplateTypeTy) { - // Look for a member, first. - DeclContext::lookup_result Result = ClassDecl->lookup(MemberOrBase); - if (!Result.empty()) { - ValueDecl *Member; - if ((Member = dyn_cast<FieldDecl>(Result.front())) || - (Member = dyn_cast<IndirectFieldDecl>(Result.front()))) { - if (EllipsisLoc.isValid()) - Diag(EllipsisLoc, diag::err_pack_expansion_member_init) - << MemberOrBase - << SourceRange(IdLoc, Init->getSourceRange().getEnd()); - return BuildMemberInitializer(Member, Init, IdLoc); - } - } + // Look for a member, first. + if (ValueDecl *Member = tryLookupCtorInitMemberDecl( + ClassDecl, SS, TemplateTypeTy, MemberOrBase)) { + if (EllipsisLoc.isValid()) + Diag(EllipsisLoc, diag::err_pack_expansion_member_init) + << MemberOrBase + << SourceRange(IdLoc, Init->getSourceRange().getEnd()); + + return BuildMemberInitializer(Member, Init, IdLoc); } // It didn't name a member, so see if it names a class. QualType BaseType; @@ -3908,10 +3947,8 @@ Sema::BuildMemInitializer(Decl *ConstructorD, const CXXBaseSpecifier *BaseSpec = DirectBaseSpec ? DirectBaseSpec : VirtualBaseSpec; - Diag(BaseSpec->getLocStart(), - diag::note_base_class_specified_here) - << BaseSpec->getType() - << BaseSpec->getSourceRange(); + Diag(BaseSpec->getBeginLoc(), diag::note_base_class_specified_here) + << BaseSpec->getType() << BaseSpec->getSourceRange(); TyD = Type; } @@ -3990,7 +4027,7 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, nullptr); InitializationKind Kind = InitList ? InitializationKind::CreateDirectList( - IdLoc, Init->getLocStart(), Init->getLocEnd()) + IdLoc, Init->getBeginLoc(), Init->getEndLoc()) : InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(), InitRange.getEnd()); @@ -4003,7 +4040,8 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. - MemberInit = ActOnFinishFullExpr(MemberInit.get(), InitRange.getBegin()); + MemberInit = ActOnFinishFullExpr(MemberInit.get(), InitRange.getBegin(), + /*DiscardedValue*/ false); if (MemberInit.isInvalid()) return true; @@ -4043,7 +4081,7 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init, QualType(ClassDecl->getTypeForDecl(), 0)); InitializationKind Kind = InitList ? InitializationKind::CreateDirectList( - NameLoc, Init->getLocStart(), Init->getLocEnd()) + NameLoc, Init->getBeginLoc(), Init->getEndLoc()) : InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(), InitRange.getEnd()); InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args); @@ -4058,8 +4096,8 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init, // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. - DelegationInit = ActOnFinishFullExpr(DelegationInit.get(), - InitRange.getBegin()); + DelegationInit = ActOnFinishFullExpr( + DelegationInit.get(), InitRange.getBegin(), /*DiscardedValue*/ false); if (DelegationInit.isInvalid()) return true; @@ -4188,7 +4226,8 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. - BaseInit = ActOnFinishFullExpr(BaseInit.get(), InitRange.getBegin()); + BaseInit = ActOnFinishFullExpr(BaseInit.get(), InitRange.getBegin(), + /*DiscardedValue*/ false); if (BaseInit.isInvalid()) return true; @@ -4214,7 +4253,7 @@ static Expr *CastForMoving(Sema &SemaRef, Expr *E, QualType T = QualType()) { if (T.isNull()) T = E->getType(); QualType TargetType = SemaRef.BuildReferenceType( T, /*SpelledAsLValue*/false, SourceLocation(), DeclarationName()); - SourceLocation ExprLoc = E->getLocStart(); + SourceLocation ExprLoc = E->getBeginLoc(); TypeSourceInfo *TargetLoc = SemaRef.Context.getTrivialTypeSourceInfo( TargetType, ExprLoc); @@ -5171,10 +5210,9 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, assert(Dtor && "No dtor found for BaseClassDecl!"); // FIXME: caret should be on the start of the class name - CheckDestructorAccess(Base.getLocStart(), Dtor, + CheckDestructorAccess(Base.getBeginLoc(), Dtor, PDiag(diag::err_access_dtor_base) - << Base.getType() - << Base.getSourceRange(), + << Base.getType() << Base.getSourceRange(), Context.getTypeDeclType(ClassDecl)); MarkFunctionReferenced(Location, Dtor); @@ -5492,6 +5530,9 @@ static void ReferenceDllExportedMembers(Sema &S, CXXRecordDecl *Class) { // declaration. return; + if (S.Context.getTargetInfo().getTriple().isWindowsGNUEnvironment()) + S.MarkVTableUsed(Class->getLocation(), Class, true); + for (Decl *Member : Class->decls()) { // Defined static variables that are members of an exported base // class must be marked export too. @@ -5705,8 +5746,28 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { continue; if (!getDLLAttr(Member)) { - auto *NewAttr = - cast<InheritableAttr>(ClassAttr->clone(getASTContext())); + InheritableAttr *NewAttr = nullptr; + + // Do not export/import inline function when -fno-dllexport-inlines is + // passed. But add attribute for later local static var check. + if (!getLangOpts().DllExportInlines && MD && MD->isInlined() && + TSK != TSK_ExplicitInstantiationDeclaration && + TSK != TSK_ExplicitInstantiationDefinition) { + if (ClassExported) { + NewAttr = ::new (getASTContext()) + DLLExportStaticLocalAttr(ClassAttr->getRange(), + getASTContext(), + ClassAttr->getSpellingListIndex()); + } else { + NewAttr = ::new (getASTContext()) + DLLImportStaticLocalAttr(ClassAttr->getRange(), + getASTContext(), + ClassAttr->getSpellingListIndex()); + } + } else { + NewAttr = cast<InheritableAttr>(ClassAttr->clone(getASTContext())); + } + NewAttr->setInherited(true); Member->addAttr(NewAttr); @@ -5825,6 +5886,9 @@ static bool canPassInRegisters(Sema &S, CXXRecordDecl *D, if (D->isDependentType() || D->isInvalidDecl()) return false; + if (D->hasAttr<TrivialABIAttr>()) + return true; + // Clang <= 4 used the pre-C++11 rule, which ignores move operations. // The PS4 platform ABI follows the behavior of Clang 3.2. if (CCK == TargetInfo::CCK_ClangABI4OrPS4) @@ -6450,20 +6514,29 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { // copy operation can take a non-const reference) as an implicit // declaration, and // -- not have default arguments. + // C++2a changes the second bullet to instead delete the function if it's + // defaulted on its first declaration, unless it's "an assignment operator, + // and its return type differs or its parameter type is not a reference". + bool DeleteOnTypeMismatch = getLangOpts().CPlusPlus2a && First; + bool ShouldDeleteForTypeMismatch = false; unsigned ExpectedParams = 1; if (CSM == CXXDefaultConstructor || CSM == CXXDestructor) ExpectedParams = 0; if (MD->getNumParams() != ExpectedParams) { - // This also checks for default arguments: a copy or move constructor with a + // This checks for default arguments: a copy or move constructor with a // default argument is classified as a default constructor, and assignment // operations and destructors can't have default arguments. Diag(MD->getLocation(), diag::err_defaulted_special_member_params) << CSM << MD->getSourceRange(); HadError = true; } else if (MD->isVariadic()) { - Diag(MD->getLocation(), diag::err_defaulted_special_member_variadic) - << CSM << MD->getSourceRange(); - HadError = true; + if (DeleteOnTypeMismatch) + ShouldDeleteForTypeMismatch = true; + else { + Diag(MD->getLocation(), diag::err_defaulted_special_member_variadic) + << CSM << MD->getSourceRange(); + HadError = true; + } } const FunctionProtoType *Type = MD->getType()->getAs<FunctionProtoType>(); @@ -6478,8 +6551,11 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { if (CSM == CXXCopyAssignment || CSM == CXXMoveAssignment) { // Check for return type matching. ReturnType = Type->getReturnType(); - QualType ExpectedReturnType = - Context.getLValueReferenceType(Context.getTypeDeclType(RD)); + + QualType DeclType = Context.getTypeDeclType(RD); + DeclType = Context.getAddrSpaceQualType(DeclType, MD->getTypeQualifiers().getAddressSpace()); + QualType ExpectedReturnType = Context.getLValueReferenceType(DeclType); + if (!Context.hasSameType(ReturnType, ExpectedReturnType)) { Diag(MD->getLocation(), diag::err_defaulted_special_member_return_type) << (CSM == CXXMoveAssignment) << ExpectedReturnType; @@ -6487,10 +6563,14 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { } // A defaulted special member cannot have cv-qualifiers. - if (Type->getTypeQuals()) { - Diag(MD->getLocation(), diag::err_defaulted_special_member_quals) - << (CSM == CXXMoveAssignment) << getLangOpts().CPlusPlus14; - HadError = true; + if (Type->getTypeQuals().hasConst() || Type->getTypeQuals().hasVolatile()) { + if (DeleteOnTypeMismatch) + ShouldDeleteForTypeMismatch = true; + else { + Diag(MD->getLocation(), diag::err_defaulted_special_member_quals) + << (CSM == CXXMoveAssignment) << getLangOpts().CPlusPlus14; + HadError = true; + } } } @@ -6503,23 +6583,30 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { HasConstParam = ReferentType.isConstQualified(); if (ReferentType.isVolatileQualified()) { - Diag(MD->getLocation(), - diag::err_defaulted_special_member_volatile_param) << CSM; - HadError = true; + if (DeleteOnTypeMismatch) + ShouldDeleteForTypeMismatch = true; + else { + Diag(MD->getLocation(), + diag::err_defaulted_special_member_volatile_param) << CSM; + HadError = true; + } } if (HasConstParam && !CanHaveConstParam) { - if (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment) { + if (DeleteOnTypeMismatch) + ShouldDeleteForTypeMismatch = true; + else if (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment) { Diag(MD->getLocation(), diag::err_defaulted_special_member_copy_const_param) << (CSM == CXXCopyAssignment); // FIXME: Explain why this special member can't be const. + HadError = true; } else { Diag(MD->getLocation(), diag::err_defaulted_special_member_move_const_param) << (CSM == CXXMoveAssignment); + HadError = true; } - HadError = true; } } else if (ExpectedParams) { // A copy assignment operator can take its argument by value, but a @@ -6542,7 +6629,7 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { : isa<CXXConstructorDecl>(MD)) && MD->isConstexpr() && !Constexpr && MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { - Diag(MD->getLocStart(), diag::err_incorrect_defaulted_constexpr) << CSM; + Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr) << CSM; // FIXME: Explain why the special member can't be constexpr. HadError = true; } @@ -6556,7 +6643,7 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { // If the exception specification needs to be instantiated, do so now, // before we clobber it with an EST_Unevaluated specification below. if (Type->getExceptionSpecType() == EST_Uninstantiated) { - InstantiateExceptionSpec(MD->getLocStart(), MD); + InstantiateExceptionSpec(MD->getBeginLoc(), MD); Type = MD->getType()->getAs<FunctionProtoType>(); } DelayedDefaultedMemberExceptionSpecs.push_back(std::make_pair(MD, Type)); @@ -6581,14 +6668,27 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { EPI)); } - if (ShouldDeleteSpecialMember(MD, CSM)) { + if (ShouldDeleteForTypeMismatch || ShouldDeleteSpecialMember(MD, CSM)) { if (First) { SetDeclDeleted(MD, MD->getLocation()); + if (!inTemplateInstantiation() && !HadError) { + Diag(MD->getLocation(), diag::warn_defaulted_method_deleted) << CSM; + if (ShouldDeleteForTypeMismatch) { + Diag(MD->getLocation(), diag::note_deleted_type_mismatch) << CSM; + } else { + ShouldDeleteSpecialMember(MD, CSM, nullptr, /*Diagnose*/true); + } + } + if (ShouldDeleteForTypeMismatch && !HadError) { + Diag(MD->getLocation(), + diag::warn_cxx17_compat_defaulted_method_type_mismatch) << CSM; + } } else { // C++11 [dcl.fct.def.default]p4: // [For a] user-provided explicitly-defaulted function [...] if such a // function is implicitly defined as deleted, the program is ill-formed. Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) << CSM; + assert(!ShouldDeleteForTypeMismatch && "deleted non-first decl"); ShouldDeleteSpecialMember(MD, CSM, nullptr, /*Diagnose*/true); HadError = true; } @@ -6628,20 +6728,27 @@ void Sema::CheckExplicitlyDefaultedMemberExceptionSpec( } void Sema::CheckDelayedMemberExceptionSpecs() { - decltype(DelayedExceptionSpecChecks) Checks; - decltype(DelayedDefaultedMemberExceptionSpecs) Specs; + decltype(DelayedOverridingExceptionSpecChecks) Overriding; + decltype(DelayedEquivalentExceptionSpecChecks) Equivalent; + decltype(DelayedDefaultedMemberExceptionSpecs) Defaulted; - std::swap(Checks, DelayedExceptionSpecChecks); - std::swap(Specs, DelayedDefaultedMemberExceptionSpecs); + std::swap(Overriding, DelayedOverridingExceptionSpecChecks); + std::swap(Equivalent, DelayedEquivalentExceptionSpecChecks); + std::swap(Defaulted, DelayedDefaultedMemberExceptionSpecs); // Perform any deferred checking of exception specifications for virtual // destructors. - for (auto &Check : Checks) + for (auto &Check : Overriding) CheckOverridingFunctionExceptionSpec(Check.first, Check.second); + // Perform any deferred checking of exception specifications for befriended + // special members. + for (auto &Check : Equivalent) + CheckEquivalentExceptionSpec(Check.second, Check.first); + // Check that any explicitly-defaulted methods have exception specifications // compatible with their implicit exception specifications. - for (auto &Spec : Specs) + for (auto &Spec : Defaulted) CheckExplicitlyDefaultedMemberExceptionSpec(Spec.first, Spec.second); } @@ -6858,10 +6965,10 @@ bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall( << Field << DiagKind << IsDtorCallInCtor; } else { CXXBaseSpecifier *Base = Subobj.get<CXXBaseSpecifier*>(); - S.Diag(Base->getLocStart(), + S.Diag(Base->getBeginLoc(), diag::note_deleted_special_member_class_subobject) - << getEffectiveCSM() << MD->getParent() << /*IsField*/false - << Base->getType() << DiagKind << IsDtorCallInCtor; + << getEffectiveCSM() << MD->getParent() << /*IsField*/ false + << Base->getType() << DiagKind << IsDtorCallInCtor; } if (DiagKind == 1) @@ -6930,10 +7037,10 @@ bool SpecialMemberDeletionInfo::shouldDeleteForBase(CXXBaseSpecifier *Base) { // FIXME: Check that the base has a usable destructor! Sink this into // shouldDeleteForClassSubobject. if (BaseCtor->isDeleted() && Diagnose) { - S.Diag(Base->getLocStart(), + S.Diag(Base->getBeginLoc(), diag::note_deleted_special_member_class_subobject) - << getEffectiveCSM() << MD->getParent() << /*IsField*/false - << Base->getType() << /*Deleted*/1 << /*IsDtorCallInCtor*/false; + << getEffectiveCSM() << MD->getParent() << /*IsField*/ false + << Base->getType() << /*Deleted*/ 1 << /*IsDtorCallInCtor*/ false; S.NoteDeletedFunction(BaseCtor); } return BaseCtor->isDeleted(); @@ -7080,7 +7187,8 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, // The closure type associated with a lambda-expression has a // deleted (8.4.3) default constructor and a deleted copy // assignment operator. - if (RD->isLambda() && + // C++2a adds back these operators if the lambda has no capture-default. + if (RD->isLambda() && !RD->lambdaIsDefaultConstructibleAndAssignable() && (CSM == CXXDefaultConstructor || CSM == CXXCopyAssignment)) { if (Diagnose) Diag(RD->getLocation(), diag::note_lambda_decl); @@ -7180,8 +7288,17 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, if (getLangOpts().CUDA) { // We should delete the special member in CUDA mode if target inference // failed. - return inferCUDATargetForImplicitSpecialMember(RD, CSM, MD, SMI.ConstArg, - Diagnose); + // For inherited constructors (non-null ICI), CSM may be passed so that MD + // is treated as certain special member, which may not reflect what special + // member MD really is. However inferCUDATargetForImplicitSpecialMember + // expects CSM to match MD, therefore recalculate CSM. + assert(ICI || CSM == getSpecialMember(MD)); + auto RealCSM = CSM; + if (ICI) + RealCSM = getSpecialMember(MD); + + return inferCUDATargetForImplicitSpecialMember(RD, RealCSM, MD, + SMI.ConstArg, Diagnose); } return false; @@ -7544,7 +7661,7 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, // -- all the direct base classes have trivial [default constructors or // destructors] for (const auto &BI : RD->bases()) - if (!checkTrivialSubobjectCall(*this, BI.getLocStart(), BI.getType(), + if (!checkTrivialSubobjectCall(*this, BI.getBeginLoc(), BI.getType(), ConstArg, CSM, TSK_BaseClass, TAH, Diagnose)) return false; @@ -7584,14 +7701,14 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, // member in all bases is trivial, so vbases must all be direct. CXXBaseSpecifier &BS = *RD->vbases_begin(); assert(BS.isVirtual()); - Diag(BS.getLocStart(), diag::note_nontrivial_has_virtual) << RD << 1; + Diag(BS.getBeginLoc(), diag::note_nontrivial_has_virtual) << RD << 1; return false; } // Must have a virtual method. for (const auto *MI : RD->methods()) { if (MI->isVirtual()) { - SourceLocation MLoc = MI->getLocStart(); + SourceLocation MLoc = MI->getBeginLoc(); Diag(MLoc, diag::note_nontrivial_has_virtual) << RD << 0; return false; } @@ -7612,7 +7729,7 @@ struct FindHiddenVirtualMethod { SmallVector<CXXMethodDecl *, 8> OverloadedMethods; private: - /// Check whether any most overriden method from MD in Methods + /// Check whether any most overridden method from MD in Methods static bool CheckMostOverridenMethods( const CXXMethodDecl *MD, const llvm::SmallPtrSetImpl<const CXXMethodDecl *> &Methods) { @@ -7696,7 +7813,7 @@ void Sema::FindHiddenVirtualMethods(CXXMethodDecl *MD, FHVM.Method = MD; FHVM.S = this; - // Keep the base methods that were overriden or introduced in the subclass + // Keep the base methods that were overridden or introduced in the subclass // by 'using' in a set. A base method not in this set is hidden. CXXRecordDecl *DC = MD->getParent(); DeclContext::lookup_result R = DC->lookup(MD->getDeclName()); @@ -8063,16 +8180,12 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, } DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); - if (FTI.TypeQuals != 0) { - if (FTI.TypeQuals & Qualifiers::Const) - Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor) - << "const" << SourceRange(D.getIdentifierLoc()); - if (FTI.TypeQuals & Qualifiers::Volatile) - Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor) - << "volatile" << SourceRange(D.getIdentifierLoc()); - if (FTI.TypeQuals & Qualifiers::Restrict) - Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor) - << "restrict" << SourceRange(D.getIdentifierLoc()); + if (FTI.hasMethodTypeQualifiers()) { + FTI.MethodQualifiers->forEachQualifier( + [&](DeclSpec::TQ TypeQual, StringRef QualName, SourceLocation SL) { + Diag(SL, diag::err_invalid_qualified_constructor) + << QualName << SourceRange(SL); + }); D.setInvalidType(); } @@ -8093,7 +8206,7 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, return R; FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo(); - EPI.TypeQuals = 0; + EPI.TypeQuals = Qualifiers(); EPI.RefQualifier = RQ_None; return Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), EPI); @@ -8179,6 +8292,7 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) { } } + DiagnoseUseOfDecl(OperatorDelete, Loc); MarkFunctionReferenced(Loc, OperatorDelete); Destructor->setOperatorDelete(OperatorDelete, ThisArg); } @@ -8252,16 +8366,12 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, } DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); - if (FTI.TypeQuals != 0 && !D.isInvalidType()) { - if (FTI.TypeQuals & Qualifiers::Const) - Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor) - << "const" << SourceRange(D.getIdentifierLoc()); - if (FTI.TypeQuals & Qualifiers::Volatile) - Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor) - << "volatile" << SourceRange(D.getIdentifierLoc()); - if (FTI.TypeQuals & Qualifiers::Restrict) - Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor) - << "restrict" << SourceRange(D.getIdentifierLoc()); + if (FTI.hasMethodTypeQualifiers() && !D.isInvalidType()) { + FTI.MethodQualifiers->forEachQualifier( + [&](DeclSpec::TQ TypeQual, StringRef QualName, SourceLocation SL) { + Diag(SL, diag::err_invalid_qualified_destructor) + << QualName << SourceRange(SL); + }); D.setInvalidType(); } @@ -8299,7 +8409,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, const FunctionProtoType *Proto = R->getAs<FunctionProtoType>(); FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo(); EPI.Variadic = false; - EPI.TypeQuals = 0; + EPI.TypeQuals = Qualifiers(); EPI.RefQualifier = RQ_None; return Context.getFunctionType(Context.VoidTy, None, EPI); } @@ -8437,7 +8547,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, // If we can provide a correct fix-it hint, do so. if (After.isInvalid() && ConvTSI) { SourceLocation InsertLoc = - getLocForEndOfToken(ConvTSI->getTypeLoc().getLocEnd()); + getLocForEndOfToken(ConvTSI->getTypeLoc().getEndLoc()); DB << FixItHint::CreateInsertion(InsertLoc, " ") << FixItHint::CreateInsertionFromRange( InsertLoc, CharSourceRange::getTokenRange(Before)) @@ -8627,13 +8737,13 @@ void Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R, if (Chunk.Kind == DeclaratorChunk::Paren) continue; if (Chunk.Kind != DeclaratorChunk::Function || FoundFunction) { - Diag(D.getDeclSpec().getLocStart(), - diag::err_deduction_guide_with_complex_decl) - << D.getSourceRange(); + Diag(D.getDeclSpec().getBeginLoc(), + diag::err_deduction_guide_with_complex_decl) + << D.getSourceRange(); break; } if (!Chunk.Fun.hasTrailingReturnType()) { - Diag(D.getName().getLocStart(), + Diag(D.getName().getBeginLoc(), diag::err_deduction_guide_no_trailing_return_type); break; } @@ -8665,10 +8775,11 @@ void Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R, } if (!AcceptableReturnType) { - Diag(TSI->getTypeLoc().getLocStart(), + Diag(TSI->getTypeLoc().getBeginLoc(), diag::err_deduction_guide_bad_trailing_return_type) - << GuidedTemplate << TSI->getType() << MightInstantiateToSpecialization - << TSI->getTypeLoc().getSourceRange(); + << GuidedTemplate << TSI->getType() + << MightInstantiateToSpecialization + << TSI->getTypeLoc().getSourceRange(); } // Keep going to check that we don't have any inner declarator pieces (we @@ -9349,7 +9460,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS, assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); if (SS.isEmpty()) { - Diag(Name.getLocStart(), diag::err_using_requires_qualname); + Diag(Name.getBeginLoc(), diag::err_using_requires_qualname); return nullptr; } @@ -9364,24 +9475,23 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS, case UnqualifiedIdKind::IK_ConstructorName: case UnqualifiedIdKind::IK_ConstructorTemplateId: // C++11 inheriting constructors. - Diag(Name.getLocStart(), - getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_using_decl_constructor : - diag::err_using_decl_constructor) - << SS.getRange(); + Diag(Name.getBeginLoc(), + getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_using_decl_constructor + : diag::err_using_decl_constructor) + << SS.getRange(); if (getLangOpts().CPlusPlus11) break; return nullptr; case UnqualifiedIdKind::IK_DestructorName: - Diag(Name.getLocStart(), diag::err_using_decl_destructor) - << SS.getRange(); + Diag(Name.getBeginLoc(), diag::err_using_decl_destructor) << SS.getRange(); return nullptr; case UnqualifiedIdKind::IK_TemplateId: - Diag(Name.getLocStart(), diag::err_using_decl_template_id) - << SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc); + Diag(Name.getBeginLoc(), diag::err_using_decl_template_id) + << SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc); return nullptr; case UnqualifiedIdKind::IK_DeductionGuideName: @@ -9395,10 +9505,10 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS, // Warn about access declarations. if (UsingLoc.isInvalid()) { - Diag(Name.getLocStart(), - getLangOpts().CPlusPlus11 ? diag::err_access_decl - : diag::warn_access_decl_deprecated) - << FixItHint::CreateInsertion(SS.getRange().getBegin(), "using "); + Diag(Name.getBeginLoc(), getLangOpts().CPlusPlus11 + ? diag::err_access_decl + : diag::warn_access_decl_deprecated) + << FixItHint::CreateInsertion(SS.getRange().getBegin(), "using "); } if (EllipsisLoc.isInvalid()) { @@ -10230,8 +10340,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, " = "); } else { // Convert 'using X::Y;' to 'typedef X::Y Y;'. - SourceLocation InsertLoc = - getLocForEndOfToken(NameInfo.getLocEnd()); + SourceLocation InsertLoc = getLocForEndOfToken(NameInfo.getEndLoc()); Diag(InsertLoc, diag::note_using_decl_class_member_workaround) << 1 // typedef declaration << FixItHint::CreateReplacement(UsingLoc, "typedef") @@ -10472,7 +10581,8 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, AccessSpecifier AS, OldDecl->getTemplateParameters(), /*Complain=*/true, TPL_TemplateMatch)) - OldTemplateParams = OldDecl->getTemplateParameters(); + OldTemplateParams = + OldDecl->getMostRecentDecl()->getTemplateParameters(); else Invalid = true; @@ -10679,19 +10789,48 @@ void SpecialMemberExceptionSpecInfo::visitSubobjectCall( ExceptSpec.CalledDecl(getSubobjectLoc(Subobj), MD); } +namespace { +/// RAII object to register a special member as being currently declared. +struct ComputingExceptionSpec { + Sema &S; + + ComputingExceptionSpec(Sema &S, CXXMethodDecl *MD, SourceLocation Loc) + : S(S) { + Sema::CodeSynthesisContext Ctx; + Ctx.Kind = Sema::CodeSynthesisContext::ExceptionSpecEvaluation; + Ctx.PointOfInstantiation = Loc; + Ctx.Entity = MD; + S.pushCodeSynthesisContext(Ctx); + } + ~ComputingExceptionSpec() { + S.popCodeSynthesisContext(); + } +}; +} + static Sema::ImplicitExceptionSpecification ComputeDefaultedSpecialMemberExceptionSpec( Sema &S, SourceLocation Loc, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM, Sema::InheritedConstructorInfo *ICI) { + ComputingExceptionSpec CES(S, MD, Loc); + CXXRecordDecl *ClassDecl = MD->getParent(); // C++ [except.spec]p14: // An implicitly declared special member function (Clause 12) shall have an // exception-specification. [...] - SpecialMemberExceptionSpecInfo Info(S, MD, CSM, ICI, Loc); + SpecialMemberExceptionSpecInfo Info(S, MD, CSM, ICI, MD->getLocation()); if (ClassDecl->isInvalidDecl()) return Info.ExceptSpec; + // FIXME: If this diagnostic fires, we're probably missing a check for + // attempting to resolve an exception specification before it's known + // at a higher level. + if (S.RequireCompleteType(MD->getLocation(), + S.Context.getRecordType(ClassDecl), + diag::err_exception_spec_incomplete_type)) + return Info.ExceptSpec; + // C++1z [except.spec]p7: // [Look for exceptions thrown by] a constructor selected [...] to // initialize a potentially constructed subobject, @@ -10774,6 +10913,22 @@ void Sema::CheckImplicitSpecialMemberDeclaration(Scope *S, FunctionDecl *FD) { CheckFunctionDeclaration(S, FD, R, /*IsMemberSpecialization*/false); } +void Sema::setupImplicitSpecialMemberType(CXXMethodDecl *SpecialMem, + QualType ResultTy, + ArrayRef<QualType> Args) { + // Build an exception specification pointing back at this constructor. + FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, SpecialMem); + + if (getLangOpts().OpenCLCPlusPlus) { + // OpenCL: Implicitly defaulted special member are of the generic address + // space. + EPI.TypeQuals.addAddressSpace(LangAS::opencl_generic); + } + + auto QT = Context.getFunctionType(ResultTy, Args, EPI); + SpecialMem->setType(QT); +} + CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( CXXRecordDecl *ClassDecl) { // C++ [class.ctor]p5: @@ -10814,9 +10969,7 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( /* Diagnose */ false); } - // Build an exception specification pointing back at this constructor. - FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, DefaultCon); - DefaultCon->setType(Context.getFunctionType(Context.VoidTy, None, EPI)); + setupImplicitSpecialMemberType(DefaultCon, Context.VoidTy, None); // We don't need to use SpecialMemberIsTrivial here; triviality for default // constructors is easy to compute. @@ -10866,8 +11019,8 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, return; } - SourceLocation Loc = Constructor->getLocEnd().isValid() - ? Constructor->getLocEnd() + SourceLocation Loc = Constructor->getEndLoc().isValid() + ? Constructor->getEndLoc() : Constructor->getLocation(); Constructor->setBody(new (Context) CompoundStmt(Loc)); Constructor->markUsed(Context); @@ -11087,9 +11240,7 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { /* Diagnose */ false); } - // Build an exception specification pointing back at this destructor. - FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, Destructor); - Destructor->setType(Context.getFunctionType(Context.VoidTy, None, EPI)); + setupImplicitSpecialMemberType(Destructor, Context.VoidTy, None); // We don't need to use SpecialMemberIsTrivial here; triviality for // destructors is easy to compute. @@ -11149,8 +11300,8 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, return; } - SourceLocation Loc = Destructor->getLocEnd().isValid() - ? Destructor->getLocEnd() + SourceLocation Loc = Destructor->getEndLoc().isValid() + ? Destructor->getEndLoc() : Destructor->getLocation(); Destructor->setBody(new (Context) CompoundStmt(Loc)); Destructor->markUsed(Context); @@ -11166,8 +11317,9 @@ void Sema::ActOnFinishCXXMemberDecls() { // If the context is an invalid C++ class, just suppress these checks. if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(CurContext)) { if (Record->isInvalidDecl()) { + DelayedOverridingExceptionSpecChecks.clear(); + DelayedEquivalentExceptionSpecChecks.clear(); DelayedDefaultedMemberExceptionSpecs.clear(); - DelayedExceptionSpecChecks.clear(); return; } checkForMultipleExportedDefaultConstructors(*this, Record); @@ -11189,11 +11341,13 @@ void Sema::referenceDLLExportedClassMethods() { } } -void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, - CXXDestructorDecl *Destructor) { +void Sema::AdjustDestructorExceptionSpec(CXXDestructorDecl *Destructor) { assert(getLangOpts().CPlusPlus11 && "adjusting dtor exception specs was introduced in c++11"); + if (Destructor->isDependentContext()) + return; + // C++11 [class.dtor]p3: // A declaration of a destructor that does not have an exception- // specification is implicitly considered to have the same exception- @@ -11660,6 +11814,10 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { bool Const = ClassDecl->implicitCopyAssignmentHasConstParam(); if (Const) ArgType = ArgType.withConst(); + + if (Context.getLangOpts().OpenCLCPlusPlus) + ArgType = Context.getAddrSpaceQualType(ArgType, LangAS::opencl_generic); + ArgType = Context.getLValueReferenceType(ArgType); bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, @@ -11686,10 +11844,7 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { /* Diagnose */ false); } - // Build an exception specification pointing back at this member. - FunctionProtoType::ExtProtoInfo EPI = - getImplicitMethodEPI(*this, CopyAssignment); - CopyAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI)); + setupImplicitSpecialMemberType(CopyAssignment, RetType, ArgType); // Add the parameter to the operator. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment, @@ -11821,8 +11976,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, } // Our location for everything implicitly-generated. - SourceLocation Loc = CopyAssignOperator->getLocEnd().isValid() - ? CopyAssignOperator->getLocEnd() + SourceLocation Loc = CopyAssignOperator->getEndLoc().isValid() + ? CopyAssignOperator->getEndLoc() : CopyAssignOperator->getLocation(); // Builds a DeclRefExpr for the "other" object. @@ -11853,7 +12008,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, // Dereference "this". DerefBuilder DerefThis(This); CastBuilder To(DerefThis, - Context.getCVRQualifiedType( + Context.getQualifiedType( BaseType, CopyAssignOperator->getTypeQualifiers()), VK_LValue, BasePath); @@ -12100,14 +12255,14 @@ static void checkMoveAssignmentForRepeatedMove(Sema &S, CXXRecordDecl *Class, if (Existing && Existing != &BI) { S.Diag(CurrentLocation, diag::warn_vbase_moved_multiple_times) << Class << Base; - S.Diag(Existing->getLocStart(), diag::note_vbase_moved_here) - << (Base->getCanonicalDecl() == - Existing->getType()->getAsCXXRecordDecl()->getCanonicalDecl()) - << Base << Existing->getType() << Existing->getSourceRange(); - S.Diag(BI.getLocStart(), diag::note_vbase_moved_here) - << (Base->getCanonicalDecl() == - BI.getType()->getAsCXXRecordDecl()->getCanonicalDecl()) - << Base << BI.getType() << BaseSpec->getSourceRange(); + S.Diag(Existing->getBeginLoc(), diag::note_vbase_moved_here) + << (Base->getCanonicalDecl() == + Existing->getType()->getAsCXXRecordDecl()->getCanonicalDecl()) + << Base << Existing->getType() << Existing->getSourceRange(); + S.Diag(BI.getBeginLoc(), diag::note_vbase_moved_here) + << (Base->getCanonicalDecl() == + BI.getType()->getAsCXXRecordDecl()->getCanonicalDecl()) + << Base << BI.getType() << BaseSpec->getSourceRange(); // Only diagnose each vbase once. Existing = nullptr; @@ -12173,12 +12328,10 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, ParmVarDecl *Other = MoveAssignOperator->getParamDecl(0); QualType OtherRefType = Other->getType()-> getAs<RValueReferenceType>()->getPointeeType(); - assert(!OtherRefType.getQualifiers() && - "Bad argument type of defaulted move assignment"); // Our location for everything implicitly-generated. - SourceLocation Loc = MoveAssignOperator->getLocEnd().isValid() - ? MoveAssignOperator->getLocEnd() + SourceLocation Loc = MoveAssignOperator->getEndLoc().isValid() + ? MoveAssignOperator->getEndLoc() : MoveAssignOperator->getLocation(); // Builds a reference to the "other" object. @@ -12220,7 +12373,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, // Implicitly cast "this" to the appropriately-qualified base type. CastBuilder To(DerefThis, - Context.getCVRQualifiedType( + Context.getQualifiedType( BaseType, MoveAssignOperator->getTypeQualifiers()), VK_LValue, BasePath); @@ -12356,6 +12509,10 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( bool Const = ClassDecl->implicitCopyConstructorHasConstParam(); if (Const) ArgType = ArgType.withConst(); + + if (Context.getLangOpts().OpenCLCPlusPlus) + ArgType = Context.getAddrSpaceQualType(ArgType, LangAS::opencl_generic); + ArgType = Context.getLValueReferenceType(ArgType); bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, @@ -12384,11 +12541,7 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( /* Diagnose */ false); } - // Build an exception specification pointing back at this member. - FunctionProtoType::ExtProtoInfo EPI = - getImplicitMethodEPI(*this, CopyConstructor); - CopyConstructor->setType( - Context.getFunctionType(Context.VoidTy, ArgType, EPI)); + setupImplicitSpecialMemberType(CopyConstructor, Context.VoidTy, ArgType); // Add the parameter to the constructor. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor, @@ -12462,8 +12615,8 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, if (SetCtorInitializers(CopyConstructor, /*AnyErrors=*/false)) { CopyConstructor->setInvalidDecl(); } else { - SourceLocation Loc = CopyConstructor->getLocEnd().isValid() - ? CopyConstructor->getLocEnd() + SourceLocation Loc = CopyConstructor->getEndLoc().isValid() + ? CopyConstructor->getEndLoc() : CopyConstructor->getLocation(); Sema::CompoundScopeRAII CompoundScope(*this); CopyConstructor->setBody( @@ -12485,7 +12638,11 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( return nullptr; QualType ClassType = Context.getTypeDeclType(ClassDecl); - QualType ArgType = Context.getRValueReferenceType(ClassType); + + QualType ArgType = ClassType; + if (Context.getLangOpts().OpenCLCPlusPlus) + ArgType = Context.getAddrSpaceQualType(ClassType, LangAS::opencl_generic); + ArgType = Context.getRValueReferenceType(ArgType); bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, CXXMoveConstructor, @@ -12514,11 +12671,7 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( /* Diagnose */ false); } - // Build an exception specification pointing back at this member. - FunctionProtoType::ExtProtoInfo EPI = - getImplicitMethodEPI(*this, MoveConstructor); - MoveConstructor->setType( - Context.getFunctionType(Context.VoidTy, ArgType, EPI)); + setupImplicitSpecialMemberType(MoveConstructor, Context.VoidTy, ArgType); // Add the parameter to the constructor. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveConstructor, @@ -12585,8 +12738,8 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation, if (SetCtorInitializers(MoveConstructor, /*AnyErrors=*/false)) { MoveConstructor->setInvalidDecl(); } else { - SourceLocation Loc = MoveConstructor->getLocEnd().isValid() - ? MoveConstructor->getLocEnd() + SourceLocation Loc = MoveConstructor->getEndLoc().isValid() + ? MoveConstructor->getEndLoc() : MoveConstructor->getLocation(); Sema::CompoundScopeRAII CompoundScope(*this); MoveConstructor->setBody(ActOnCompoundStmt( @@ -12889,7 +13042,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { RecordDecl *OutermostClass = ParentRD->getOuterLexicalRecordContext(); Diag(Loc, diag::err_in_class_initializer_not_yet_parsed) << OutermostClass << Field; - Diag(Field->getLocEnd(), diag::note_in_class_initializer_not_yet_parsed); + Diag(Field->getEndLoc(), diag::note_in_class_initializer_not_yet_parsed); // Recover by marking the field invalid, unless we're in a SFINAE context. if (!isSFINAEContext()) Field->setInvalidDecl(); @@ -12904,6 +13057,9 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { if (ClassDecl->hasIrrelevantDestructor()) return; if (ClassDecl->isDependentContext()) return; + if (VD->isNoDestroy(getASTContext())) + return; + CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl); MarkFunctionReferenced(VD->getLocation(), Destructor); CheckDestructorAccess(VD->getLocation(), Destructor, @@ -13123,7 +13279,8 @@ CheckOperatorDeleteDeclaration(Sema &SemaRef, FunctionDecl *FnDecl) { // C++ P0722: // A destroying operator delete shall be a usual deallocation function. if (MD && !MD->getParent()->isDependentContext() && - MD->isDestroyingOperatorDelete() && !MD->isUsualDeallocationFunction()) { + MD->isDestroyingOperatorDelete() && + !SemaRef.isUsualDeallocationFunction(MD)) { SemaRef.Diag(MD->getLocation(), diag::err_destroying_operator_delete_not_usual); return true; @@ -13601,7 +13758,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, // Only the non-fragile NeXT runtime currently supports C++ catches // of ObjC types, and no runtime supports catching ObjC types by value. - if (!Invalid && getLangOpts().ObjC1) { + if (!Invalid && getLangOpts().ObjC) { QualType T = ExDeclType; if (const ReferenceType *RT = T->getAs<ReferenceType>()) T = RT->getPointeeType(); @@ -13711,10 +13868,8 @@ Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { Invalid = true; } - VarDecl *ExDecl = BuildExceptionDeclaration(S, TInfo, - D.getLocStart(), - D.getIdentifierLoc(), - D.getIdentifier()); + VarDecl *ExDecl = BuildExceptionDeclaration( + S, TInfo, D.getBeginLoc(), D.getIdentifierLoc(), D.getIdentifier()); if (Invalid) ExDecl->setInvalidDecl(); @@ -13755,6 +13910,8 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc, ExprResult Converted = PerformContextuallyConvertToBool(AssertExpr); if (Converted.isInvalid()) Failed = true; + else + Converted = ConstantExpr::Create(Context, Converted.get()); llvm::APSInt Cond; if (!Failed && VerifyIntegerConstantExpression(Converted.get(), &Cond, @@ -13771,9 +13928,9 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc, Expr *InnerCond = nullptr; std::string InnerCondDescription; std::tie(InnerCond, InnerCondDescription) = - findFailedBooleanCondition(Converted.get(), - /*AllowTopLevelCond=*/false); - if (InnerCond) { + findFailedBooleanCondition(Converted.get()); + if (InnerCond && !isa<CXXBoolLiteralExpr>(InnerCond) + && !isa<IntegerLiteral>(InnerCond)) { Diag(StaticAssertLoc, diag::err_static_assert_requirement_failed) << InnerCondDescription << !AssertMessage << Msg.str() << InnerCond->getSourceRange(); @@ -13870,7 +14027,7 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart, // cv-qualified) class type, that class is declared as a friend; otherwise, // the friend declaration is ignored. return FriendDecl::Create(Context, CurContext, - TSInfo->getTypeLoc().getLocStart(), TSInfo, + TSInfo->getTypeLoc().getBeginLoc(), TSInfo, FriendLoc); } @@ -14012,11 +14169,34 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, /// template <> template \<class T> friend class A<int>::B; Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, MultiTemplateParamsArg TempParams) { - SourceLocation Loc = DS.getLocStart(); + SourceLocation Loc = DS.getBeginLoc(); assert(DS.isFriendSpecified()); assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified); + // C++ [class.friend]p3: + // A friend declaration that does not declare a function shall have one of + // the following forms: + // friend elaborated-type-specifier ; + // friend simple-type-specifier ; + // friend typename-specifier ; + // + // Any declaration with a type qualifier does not have that form. (It's + // legal to specify a qualified type as a friend, you just can't write the + // keywords.) + if (DS.getTypeQualifiers()) { + if (DS.getTypeQualifiers() & DeclSpec::TQ_const) + Diag(DS.getConstSpecLoc(), diag::err_friend_decl_spec) << "const"; + if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile) + Diag(DS.getVolatileSpecLoc(), diag::err_friend_decl_spec) << "volatile"; + if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict) + Diag(DS.getRestrictSpecLoc(), diag::err_friend_decl_spec) << "restrict"; + if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic) + Diag(DS.getAtomicSpecLoc(), diag::err_friend_decl_spec) << "_Atomic"; + if (DS.getTypeQualifiers() & DeclSpec::TQ_unaligned) + Diag(DS.getUnalignedSpecLoc(), diag::err_friend_decl_spec) << "__unaligned"; + } + // Try to convert the decl specifier to a type. This works for // friend templates because ActOnTag never produces a ClassTemplateDecl // for a TUK_Friend. @@ -14123,8 +14303,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, CXXScopeSpec &SS = D.getCXXScopeSpec(); DeclarationNameInfo NameInfo = GetNameForDeclarator(D); - DeclarationName Name = NameInfo.getName(); - assert(Name); + assert(NameInfo.getName()); // Check for unexpanded parameter packs. if (DiagnoseUnexpandedParameterPack(Loc, TInfo, UPPC_FriendDeclaration) || @@ -14243,25 +14422,6 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, LookupQualifiedName(Previous, DC); - // Ignore things found implicitly in the wrong scope. - // TODO: better diagnostics for this case. Suggesting the right - // qualified scope would be nice... - LookupResult::Filter F = Previous.makeFilter(); - while (F.hasNext()) { - NamedDecl *D = F.next(); - if (!DC->InEnclosingNamespaceSetOf( - D->getDeclContext()->getRedeclContext())) - F.erase(); - } - F.done(); - - if (Previous.empty()) { - D.setInvalidType(); - Diag(Loc, diag::err_qualified_friend_not_found) - << Name << TInfo->getType(); - return nullptr; - } - // C++ [class.friend]p1: A friend of a class is a function or // class that is not a member of the class . . . if (DC->Equals(CurContext)) @@ -14275,6 +14435,10 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, // A function can be defined in a friend declaration of a class if and // only if the class is a non-local class (9.8), the function name is // unqualified, and the function has namespace scope. + // + // FIXME: We should only do this if the scope specifier names the + // innermost enclosing namespace; otherwise the fixit changes the + // meaning of the code. SemaDiagnosticBuilder DB = Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def); @@ -14532,8 +14696,8 @@ static void SearchForReturnInStmt(Sema &Self, Stmt *S) { if (!SubStmt) continue; if (isa<ReturnStmt>(SubStmt)) - Self.Diag(SubStmt->getLocStart(), - diag::err_return_in_constructor_handler); + Self.Diag(SubStmt->getBeginLoc(), + diag::err_return_in_constructor_handler); if (!isa<Expr>(SubStmt)) SearchForReturnInStmt(Self, SubStmt); } @@ -14834,6 +14998,15 @@ void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class, if (!Class->isDynamicClass() || Class->isDependentContext() || CurContext->isDependentContext() || isUnevaluatedContext()) return; + // Do not mark as used if compiling for the device outside of the target + // region. + if (LangOpts.OpenMP && LangOpts.OpenMPIsDevice && + !isInOpenMPDeclareTargetContext() && + !isInOpenMPTargetExecutionDirective()) { + if (!DefinitionRequired) + MarkVirtualMembersReferenced(Loc, Class); + return; + } // Try to insert this class into the map. LoadExternalVTableUses(); @@ -15439,10 +15612,11 @@ MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record, if (PrevDecl && !isDeclInScope(PrevDecl, Record, S)) PrevDecl = nullptr; - SourceLocation TSSL = D.getLocStart(); - const ParsedAttr::PropertyData &Data = MSPropertyAttr.getPropertyData(); - MSPropertyDecl *NewPD = MSPropertyDecl::Create( - Context, Record, Loc, II, T, TInfo, TSSL, Data.GetterId, Data.SetterId); + SourceLocation TSSL = D.getBeginLoc(); + MSPropertyDecl *NewPD = + MSPropertyDecl::Create(Context, Record, Loc, II, T, TInfo, TSSL, + MSPropertyAttr.getPropertyDataGetter(), + MSPropertyAttr.getPropertyDataSetter()); ProcessDeclAttributes(TUScope, NewPD, D); NewPD->setAccess(AS); diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 595cc76cd4a31..3746bdad0358c 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -363,6 +363,8 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { assert((getCurMethodDecl() == nullptr) && "Methodparsing confused"); ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D); + PushExpressionEvaluationContext(ExprEvalContexts.back().Context); + // If we don't have a valid method decl, simply return. if (!MDecl) return; @@ -653,7 +655,7 @@ ActOnSuperClassOfClassInterface(Scope *S, } IDecl->setSuperClass(SuperClassTInfo); - IDecl->setEndOfDefinitionLoc(SuperClassTInfo->getTypeLoc().getLocEnd()); + IDecl->setEndOfDefinitionLoc(SuperClassTInfo->getTypeLoc().getEndLoc()); } } @@ -717,21 +719,22 @@ DeclResult Sema::actOnObjCTypeParam(Scope *S, if (auto attr = qual.getAs<AttributedTypeLoc>()) { rangeToRemove = attr.getLocalSourceRange(); if (attr.getTypePtr()->getImmediateNullability()) { - Diag(attr.getLocStart(), + Diag(attr.getBeginLoc(), diag::err_objc_type_param_bound_explicit_nullability) - << paramName << typeBound - << FixItHint::CreateRemoval(rangeToRemove); + << paramName << typeBound + << FixItHint::CreateRemoval(rangeToRemove); diagnosed = true; } } } if (!diagnosed) { - Diag(qual ? qual.getLocStart() - : typeBoundInfo->getTypeLoc().getLocStart(), - diag::err_objc_type_param_bound_qualified) - << paramName << typeBound << typeBound.getQualifiers().getAsString() - << FixItHint::CreateRemoval(rangeToRemove); + Diag(qual ? qual.getBeginLoc() + : typeBoundInfo->getTypeLoc().getBeginLoc(), + diag::err_objc_type_param_bound_qualified) + << paramName << typeBound + << typeBound.getQualifiers().getAsString() + << FixItHint::CreateRemoval(rangeToRemove); } // If the type bound has qualifiers other than CVR, we need to strip @@ -828,7 +831,7 @@ static bool checkTypeParamListConsistency(Sema &S, if (newTypeParams->size() > prevTypeParams->size()) { diagLoc = newTypeParams->begin()[prevTypeParams->size()]->getLocation(); } else { - diagLoc = S.getLocForEndOfToken(newTypeParams->back()->getLocEnd()); + diagLoc = S.getLocForEndOfToken(newTypeParams->back()->getEndLoc()); } S.Diag(diagLoc, diag::err_objc_type_param_arity_mismatch) @@ -865,7 +868,7 @@ static bool checkTypeParamListConsistency(Sema &S, // Diagnose the conflict and update the second declaration. SourceLocation diagLoc = newTypeParam->getVarianceLoc(); if (diagLoc.isInvalid()) - diagLoc = newTypeParam->getLocStart(); + diagLoc = newTypeParam->getBeginLoc(); auto diag = S.Diag(diagLoc, diag::err_objc_type_param_variance_conflict) @@ -886,7 +889,7 @@ static bool checkTypeParamListConsistency(Sema &S, : "__contravariant"; if (newTypeParam->getVariance() == ObjCTypeParamVariance::Invariant) { - diag << FixItHint::CreateInsertion(newTypeParam->getLocStart(), + diag << FixItHint::CreateInsertion(newTypeParam->getBeginLoc(), (newVarianceStr + " ").str()); } else { diag << FixItHint::CreateReplacement(newTypeParam->getVarianceLoc(), @@ -2164,9 +2167,10 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, } else if (ImplIvar->isBitField() && ClsIvar->isBitField() && ImplIvar->getBitWidthValue(Context) != ClsIvar->getBitWidthValue(Context)) { - Diag(ImplIvar->getBitWidth()->getLocStart(), - diag::err_conflicting_ivar_bitwidth) << ImplIvar->getIdentifier(); - Diag(ClsIvar->getBitWidth()->getLocStart(), + Diag(ImplIvar->getBitWidth()->getBeginLoc(), + diag::err_conflicting_ivar_bitwidth) + << ImplIvar->getIdentifier(); + Diag(ClsIvar->getBitWidth()->getBeginLoc(), diag::note_previous_definition); } // Make sure the names are identical. @@ -2206,7 +2210,7 @@ static void WarnUndefinedMethod(Sema &S, SourceLocation ImpLoc, } // Issue a note to the original declaration. - SourceLocation MethodLoc = method->getLocStart(); + SourceLocation MethodLoc = method->getBeginLoc(); if (MethodLoc.isValid()) S.Diag(MethodLoc, diag::note_method_declared_at) << method; } @@ -2880,7 +2884,7 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap, IMPDecl, PI, IncompleteImpl, false, WarnCategoryMethodImpl); - // FIXME. For now, we are not checking for extact match of methods + // FIXME. For now, we are not checking for exact match of methods // in category implementation and its primary class's super class. if (!WarnCategoryMethodImpl && I->getSuperClass()) MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, @@ -3580,12 +3584,12 @@ void Sema::DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl<ObjCMethodDecl*> & else Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R; - Diag(Methods[0]->getLocStart(), + Diag(Methods[0]->getBeginLoc(), issueError ? diag::note_possibility : diag::note_using) - << Methods[0]->getSourceRange(); + << Methods[0]->getSourceRange(); for (unsigned I = 1, N = Methods.size(); I != N; ++I) { - Diag(Methods[I]->getLocStart(), diag::note_also_found) - << Methods[I]->getSourceRange(); + Diag(Methods[I]->getBeginLoc(), diag::note_also_found) + << Methods[I]->getSourceRange(); } } } @@ -4351,7 +4355,7 @@ void Sema::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, // Propagate down the 'related result type' bit from overridden methods. if (RTC != Sema::RTC_Incompatible && overridden->hasRelatedResultType()) - ObjCMethod->SetRelatedResultType(); + ObjCMethod->setRelatedResultType(); // Then merge the declarations. mergeObjCMethodDecls(ObjCMethod, overridden); @@ -4485,7 +4489,7 @@ static void checkObjCMethodX86VectorTypes(Sema &SemaRef, QualType T; for (const ParmVarDecl *P : Method->parameters()) { if (P->getType()->isVectorType()) { - Loc = P->getLocStart(); + Loc = P->getBeginLoc(); T = P->getType(); break; } @@ -4746,7 +4750,7 @@ Decl *Sema::ActOnMethodDeclaration( if (InferRelatedResultType && !ObjCMethod->getReturnType()->isObjCIndependentClassType()) - ObjCMethod->SetRelatedResultType(); + ObjCMethod->setRelatedResultType(); } if (MethodDefinition && diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp index 134c76ef28c62..e0850feaffc66 100644 --- a/lib/Sema/SemaExceptionSpec.cpp +++ b/lib/Sema/SemaExceptionSpec.cpp @@ -64,7 +64,7 @@ bool Sema::isLibstdcxxEagerExceptionSpecHack(const Declarator &D) { } // Only apply this hack within a system header. - if (!Context.getSourceManager().isInSystemHeader(D.getLocStart())) + if (!Context.getSourceManager().isInSystemHeader(D.getBeginLoc())) return false; return llvm::StringSwitch<bool>(RD->getIdentifier()->getName()) @@ -230,6 +230,16 @@ Sema::UpdateExceptionSpec(FunctionDecl *FD, Context.adjustExceptionSpec(Redecl, ESI); } +static bool exceptionSpecNotKnownYet(const FunctionDecl *FD) { + auto *MD = dyn_cast<CXXMethodDecl>(FD); + if (!MD) + return false; + + auto EST = MD->getType()->castAs<FunctionProtoType>()->getExceptionSpecType(); + return EST == EST_Unparsed || + (EST == EST_Unevaluated && MD->getParent()->isBeingDefined()); +} + static bool CheckEquivalentExceptionSpecImpl( Sema &S, const PartialDiagnostic &DiagID, const PartialDiagnostic &NoteID, const FunctionProtoType *Old, SourceLocation OldLoc, @@ -278,6 +288,14 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { ReturnValueOnError = false; } + // If we're befriending a member function of a class that's currently being + // defined, we might not be able to work out its exception specification yet. + // If not, defer the check until later. + if (exceptionSpecNotKnownYet(Old) || exceptionSpecNotKnownYet(New)) { + DelayedEquivalentExceptionSpecChecks.push_back({New, Old}); + return false; + } + // Check the types as written: they must match before any exception // specification adjustment is applied. if (!CheckEquivalentExceptionSpecImpl( @@ -904,26 +922,21 @@ bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New, if (New->getType()->castAs<FunctionProtoType>()->getExceptionSpecType() == EST_Unparsed) return false; - if (getLangOpts().CPlusPlus11 && isa<CXXDestructorDecl>(New)) { - // Don't check uninstantiated template destructors at all. We can only - // synthesize correct specs after the template is instantiated. - if (New->getParent()->isDependentType()) - return false; - if (New->getParent()->isBeingDefined()) { - // The destructor might be updated once the definition is finished. So - // remember it and check later. - DelayedExceptionSpecChecks.push_back(std::make_pair(New, Old)); - return false; - } - } - // If the old exception specification hasn't been parsed yet, remember that - // we need to perform this check when we get to the end of the outermost + + // Don't check uninstantiated template destructors at all. We can only + // synthesize correct specs after the template is instantiated. + if (isa<CXXDestructorDecl>(New) && New->getParent()->isDependentType()) + return false; + + // If the old exception specification hasn't been parsed yet, or the new + // exception specification can't be computed yet, remember that we need to + // perform this check when we get to the end of the outermost // lexically-surrounding class. - if (Old->getType()->castAs<FunctionProtoType>()->getExceptionSpecType() == - EST_Unparsed) { - DelayedExceptionSpecChecks.push_back(std::make_pair(New, Old)); + if (exceptionSpecNotKnownYet(Old) || exceptionSpecNotKnownYet(New)) { + DelayedOverridingExceptionSpecChecks.push_back({New, Old}); return false; } + unsigned DiagID = diag::err_override_exception_spec; if (getLangOpts().MicrosoftExt) DiagID = diag::ext_override_exception_spec; @@ -992,7 +1005,7 @@ static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, const Decl *D) { if (!FT) return CT_Can; - FT = S.ResolveExceptionSpec(E->getLocStart(), FT); + FT = S.ResolveExceptionSpec(E->getBeginLoc(), FT); if (!FT) return CT_Can; @@ -1038,6 +1051,9 @@ CanThrowResult Sema::canThrow(const Expr *E) { // [Can throw] if in a potentially-evaluated context the expression would // contain: switch (E->getStmtClass()) { + case Expr::ConstantExprClass: + return canThrow(cast<ConstantExpr>(E)->getSubExpr()); + case Expr::CXXThrowExprClass: // - a potentially evaluated throw-expression return CT_Can; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 3dc6fb151cb7c..d5416d4d057c7 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -26,6 +26,7 @@ #include "clang/AST/ExprOpenMP.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/TypeLoc.h" +#include "clang/Basic/FixedPoint.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -65,6 +66,12 @@ bool Sema::CanUseDecl(NamedDecl *D, bool TreatUnavailableAsInvalid) { if (getLangOpts().CPlusPlus14 && FD->getReturnType()->isUndeducedType() && DeduceReturnType(FD, SourceLocation(), /*Diagnose*/ false)) return false; + + // See if this is an aligned allocation/deallocation function that is + // unavailable. + if (TreatUnavailableAsInvalid && + isUnavailableAlignedAllocationFunction(*FD)) + return false; } // See if this function is unavailable. @@ -114,7 +121,7 @@ void Sema::NoteDeletedFunction(FunctionDecl *Decl) { return NoteDeletedInheritingConstructor(Ctor); Diag(Decl->getLocation(), diag::note_availability_specified_here) - << Decl << true; + << Decl << 1; } /// Determine whether a FunctionDecl was ever declared with an @@ -205,7 +212,8 @@ void Sema::MaybeSuggestAddingStaticToDecl(const FunctionDecl *Cur) { bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs, const ObjCInterfaceDecl *UnknownObjCClass, bool ObjCPropertyAccess, - bool AvoidPartialAvailabilityChecks) { + bool AvoidPartialAvailabilityChecks, + ObjCInterfaceDecl *ClassReceiver) { SourceLocation Loc = Locs.front(); if (getLangOpts().CPlusPlus && isa<FunctionDecl>(D)) { // If there were any diagnostics suppressed by template argument deduction, @@ -226,6 +234,8 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs, // The function 'main' shall not be used within a program. if (cast<FunctionDecl>(D)->isMain()) Diag(Loc, diag::ext_main_used); + + diagnoseUnavailableAlignedAllocation(*cast<FunctionDecl>(D), Loc); } // See if this is an auto-typed variable whose initializer we are parsing. @@ -264,6 +274,17 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs, return true; } + if (auto *MD = dyn_cast<CXXMethodDecl>(D)) { + // Lambdas are only default-constructible or assignable in C++2a onwards. + if (MD->getParent()->isLambda() && + ((isa<CXXConstructorDecl>(MD) && + cast<CXXConstructorDecl>(MD)->isDefaultConstructor()) || + MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator())) { + Diag(Loc, diag::warn_cxx17_compat_lambda_def_ctor_assign) + << !isa<CXXConstructorDecl>(MD); + } + } + auto getReferencedObjCProp = [](const NamedDecl *D) -> const ObjCPropertyDecl * { if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) @@ -291,7 +312,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs, } DiagnoseAvailabilityOfDecl(D, Locs, UnknownObjCClass, ObjCPropertyAccess, - AvoidPartialAvailabilityChecks); + AvoidPartialAvailabilityChecks, ClassReceiver); DiagnoseUnusedOfDecl(*this, D, Loc); @@ -386,8 +407,7 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, // or 'NULL' if those are actually defined in the context. Only use // 'nil' for ObjC methods, where it's much more likely that the // variadic arguments form a list of object pointers. - SourceLocation MissingNilLoc - = getLocForEndOfToken(sentinelExpr->getLocEnd()); + SourceLocation MissingNilLoc = getLocForEndOfToken(sentinelExpr->getEndLoc()); std::string NullValue; if (calleeType == CT_Method && PP.isMacroDefined("nil")) NullValue = "nil"; @@ -501,12 +521,13 @@ static void DiagnoseDirectIsaAccess(Sema &S, const ObjCIvarRefExpr *OIRE, &S.Context.Idents.get("object_setClass"), SourceLocation(), S.LookupOrdinaryName); if (ObjectSetClass) { - SourceLocation RHSLocEnd = S.getLocForEndOfToken(RHS->getLocEnd()); - S.Diag(OIRE->getExprLoc(), diag::warn_objc_isa_assign) << - FixItHint::CreateInsertion(OIRE->getLocStart(), "object_setClass(") << - FixItHint::CreateReplacement(SourceRange(OIRE->getOpLoc(), - AssignLoc), ",") << - FixItHint::CreateInsertion(RHSLocEnd, ")"); + SourceLocation RHSLocEnd = S.getLocForEndOfToken(RHS->getEndLoc()); + S.Diag(OIRE->getExprLoc(), diag::warn_objc_isa_assign) + << FixItHint::CreateInsertion(OIRE->getBeginLoc(), + "object_setClass(") + << FixItHint::CreateReplacement( + SourceRange(OIRE->getOpLoc(), AssignLoc), ",") + << FixItHint::CreateInsertion(RHSLocEnd, ")"); } else S.Diag(OIRE->getLocation(), diag::warn_objc_isa_assign); @@ -516,11 +537,11 @@ static void DiagnoseDirectIsaAccess(Sema &S, const ObjCIvarRefExpr *OIRE, &S.Context.Idents.get("object_getClass"), SourceLocation(), S.LookupOrdinaryName); if (ObjectGetClass) - S.Diag(OIRE->getExprLoc(), diag::warn_objc_isa_use) << - FixItHint::CreateInsertion(OIRE->getLocStart(), "object_getClass(") << - FixItHint::CreateReplacement( - SourceRange(OIRE->getOpLoc(), - OIRE->getLocEnd()), ")"); + S.Diag(OIRE->getExprLoc(), diag::warn_objc_isa_use) + << FixItHint::CreateInsertion(OIRE->getBeginLoc(), + "object_getClass(") + << FixItHint::CreateReplacement( + SourceRange(OIRE->getOpLoc(), OIRE->getEndLoc()), ")"); else S.Diag(OIRE->getLocation(), diag::warn_objc_isa_use); } @@ -575,10 +596,10 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { &Context.Idents.get("object_getClass"), SourceLocation(), LookupOrdinaryName); if (ObjectGetClass) - Diag(E->getExprLoc(), diag::warn_objc_isa_use) << - FixItHint::CreateInsertion(OISA->getLocStart(), "object_getClass(") << - FixItHint::CreateReplacement( - SourceRange(OISA->getOpLoc(), OISA->getIsaMemberLoc()), ")"); + Diag(E->getExprLoc(), diag::warn_objc_isa_use) + << FixItHint::CreateInsertion(OISA->getBeginLoc(), "object_getClass(") + << FixItHint::CreateReplacement( + SourceRange(OISA->getOpLoc(), OISA->getIsaMemberLoc()), ")"); else Diag(E->getExprLoc(), diag::warn_objc_isa_use); } @@ -717,20 +738,33 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) { return ExprError(); E = Res.get(); + QualType ScalarTy = Ty; + unsigned NumElts = 0; + if (const ExtVectorType *VecTy = Ty->getAs<ExtVectorType>()) { + NumElts = VecTy->getNumElements(); + ScalarTy = VecTy->getElementType(); + } + // If this is a 'float' or '__fp16' (CVR qualified or typedef) // promote to double. // Note that default argument promotion applies only to float (and // half/fp16); it does not apply to _Float16. - const BuiltinType *BTy = Ty->getAs<BuiltinType>(); + const BuiltinType *BTy = ScalarTy->getAs<BuiltinType>(); if (BTy && (BTy->getKind() == BuiltinType::Half || BTy->getKind() == BuiltinType::Float)) { if (getLangOpts().OpenCL && !getOpenCLOptions().isEnabled("cl_khr_fp64")) { - if (BTy->getKind() == BuiltinType::Half) { - E = ImpCastExprToType(E, Context.FloatTy, CK_FloatingCast).get(); - } + if (BTy->getKind() == BuiltinType::Half) { + QualType Ty = Context.FloatTy; + if (NumElts != 0) + Ty = Context.getExtVectorType(Ty, NumElts); + E = ImpCastExprToType(E, Ty, CK_FloatingCast).get(); + } } else { - E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).get(); + QualType Ty = Context.DoubleTy; + if (NumElts != 0) + Ty = Context.getExtVectorType(Ty, NumElts); + E = ImpCastExprToType(E, Ty, CK_FloatingCast).get(); } } @@ -819,40 +853,38 @@ void Sema::checkVariadicArgument(const Expr *E, VariadicCallType CT) { switch (VAK) { case VAK_ValidInCXX11: DiagRuntimeBehavior( - E->getLocStart(), nullptr, - PDiag(diag::warn_cxx98_compat_pass_non_pod_arg_to_vararg) - << Ty << CT); + E->getBeginLoc(), nullptr, + PDiag(diag::warn_cxx98_compat_pass_non_pod_arg_to_vararg) << Ty << CT); LLVM_FALLTHROUGH; case VAK_Valid: if (Ty->isRecordType()) { // This is unlikely to be what the user intended. If the class has a // 'c_str' member function, the user probably meant to call that. - DiagRuntimeBehavior(E->getLocStart(), nullptr, + DiagRuntimeBehavior(E->getBeginLoc(), nullptr, PDiag(diag::warn_pass_class_arg_to_vararg) - << Ty << CT << hasCStrMethod(E) << ".c_str()"); + << Ty << CT << hasCStrMethod(E) << ".c_str()"); } break; case VAK_Undefined: case VAK_MSVCUndefined: - DiagRuntimeBehavior( - E->getLocStart(), nullptr, - PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg) - << getLangOpts().CPlusPlus11 << Ty << CT); + DiagRuntimeBehavior(E->getBeginLoc(), nullptr, + PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg) + << getLangOpts().CPlusPlus11 << Ty << CT); break; case VAK_Invalid: if (Ty.isDestructedType() == QualType::DK_nontrivial_c_struct) - Diag(E->getLocStart(), - diag::err_cannot_pass_non_trivial_c_struct_to_vararg) << Ty << CT; + Diag(E->getBeginLoc(), + diag::err_cannot_pass_non_trivial_c_struct_to_vararg) + << Ty << CT; else if (Ty->isObjCObjectType()) - DiagRuntimeBehavior( - E->getLocStart(), nullptr, - PDiag(diag::err_cannot_pass_objc_interface_to_vararg) - << Ty << CT); + DiagRuntimeBehavior(E->getBeginLoc(), nullptr, + PDiag(diag::err_cannot_pass_objc_interface_to_vararg) + << Ty << CT); else - Diag(E->getLocStart(), diag::err_cannot_pass_to_vararg) - << isa<InitListExpr>(E) << Ty << CT; + Diag(E->getBeginLoc(), diag::err_cannot_pass_to_vararg) + << isa<InitListExpr>(E) << Ty << CT; break; } } @@ -890,20 +922,19 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, SourceLocation TemplateKWLoc; UnqualifiedId Name; Name.setIdentifier(PP.getIdentifierInfo("__builtin_trap"), - E->getLocStart()); + E->getBeginLoc()); ExprResult TrapFn = ActOnIdExpression(TUScope, SS, TemplateKWLoc, Name, true, false); if (TrapFn.isInvalid()) return ExprError(); - ExprResult Call = ActOnCallExpr(TUScope, TrapFn.get(), - E->getLocStart(), None, - E->getLocEnd()); + ExprResult Call = ActOnCallExpr(TUScope, TrapFn.get(), E->getBeginLoc(), + None, E->getEndLoc()); if (Call.isInvalid()) return ExprError(); - ExprResult Comma = ActOnBinOp(TUScope, E->getLocStart(), tok::comma, - Call.get(), E); + ExprResult Comma = + ActOnBinOp(TUScope, E->getBeginLoc(), tok::comma, Call.get(), E); if (Comma.isInvalid()) return ExprError(); return Comma.get(); @@ -1436,9 +1467,9 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc, // We strip parens here because the controlling expression is typically // parenthesized in macro definitions. ControllingExpr = ControllingExpr->IgnoreParens(); - Diag(ControllingExpr->getLocStart(), diag::err_generic_sel_multi_match) - << ControllingExpr->getSourceRange() << ControllingExpr->getType() - << (unsigned) CompatIndices.size(); + Diag(ControllingExpr->getBeginLoc(), diag::err_generic_sel_multi_match) + << ControllingExpr->getSourceRange() << ControllingExpr->getType() + << (unsigned)CompatIndices.size(); for (unsigned I : CompatIndices) { Diag(Types[I]->getTypeLoc().getBeginLoc(), diag::note_compat_assoc) @@ -1455,8 +1486,8 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc, // We strip parens here because the controlling expression is typically // parenthesized in macro definitions. ControllingExpr = ControllingExpr->IgnoreParens(); - Diag(ControllingExpr->getLocStart(), diag::err_generic_sel_no_match) - << ControllingExpr->getSourceRange() << ControllingExpr->getType(); + Diag(ControllingExpr->getBeginLoc(), diag::err_generic_sel_no_match) + << ControllingExpr->getSourceRange() << ControllingExpr->getType(); return ExprError(); } @@ -1549,6 +1580,32 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) { CharTy = Context.UnsignedCharTy; } + // Warn on initializing an array of char from a u8 string literal; this + // becomes ill-formed in C++2a. + if (getLangOpts().CPlusPlus && !getLangOpts().CPlusPlus2a && + !getLangOpts().Char8 && Kind == StringLiteral::UTF8) { + Diag(StringTokLocs.front(), diag::warn_cxx2a_compat_utf8_string); + + // Create removals for all 'u8' prefixes in the string literal(s). This + // ensures C++2a compatibility (but may change the program behavior when + // built by non-Clang compilers for which the execution character set is + // not always UTF-8). + auto RemovalDiag = PDiag(diag::note_cxx2a_compat_utf8_string_remove_u8); + SourceLocation RemovalDiagLoc; + for (const Token &Tok : StringToks) { + if (Tok.getKind() == tok::utf8_string_literal) { + if (RemovalDiagLoc.isInvalid()) + RemovalDiagLoc = Tok.getLocation(); + RemovalDiag << FixItHint::CreateRemoval(CharSourceRange::getCharRange( + Tok.getLocation(), + Lexer::AdvanceToTokenCharacter(Tok.getLocation(), 2, + getSourceManager(), getLangOpts()))); + } + } + Diag(RemovalDiagLoc, RemovalDiag); + } + + QualType CharTyConst = CharTy; // A C++ string literal has a const-qualified element type (C++ 2.13.4p1). if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings) @@ -1681,7 +1738,7 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, if (getLangOpts().ObjCWeak && isa<VarDecl>(D) && Ty.getObjCLifetime() == Qualifiers::OCL_Weak && !isUnevaluatedContext() && - !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getLocStart())) + !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getBeginLoc())) getCurFunction()->recordUseOfWeak(E); FieldDecl *FD = dyn_cast<FieldDecl>(D); @@ -2528,7 +2585,7 @@ Sema::PerformObjectMemberConversion(Expr *From, if (Method->isStatic()) return From; - DestType = Method->getThisType(Context); + DestType = Method->getThisType(); DestRecordType = DestType->getPointeeType(); if (FromType->getAs<PointerType>()) { @@ -3026,7 +3083,7 @@ static void ConvertUTF8ToWideString(unsigned CharByteWidth, StringRef Source, } ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc, - PredefinedExpr::IdentType IT) { + PredefinedExpr::IdentKind IK) { // Pick the current block, lambda, captured statement or function. Decl *currentDecl = nullptr; if (const BlockScopeInfo *BSI = getCurBlock()) @@ -3050,11 +3107,11 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc, else { // Pre-defined identifiers are of type char[x], where x is the length of // the string. - auto Str = PredefinedExpr::ComputeName(IT, currentDecl); + auto Str = PredefinedExpr::ComputeName(IK, currentDecl); unsigned Length = Str.length(); llvm::APInt LengthI(32, Length + 1); - if (IT == PredefinedExpr::LFunction || IT == PredefinedExpr::LFuncSig) { + if (IK == PredefinedExpr::LFunction || IK == PredefinedExpr::LFuncSig) { ResTy = Context.adjustStringLiteralBaseType(Context.WideCharTy.withConst()); SmallString<32> RawChars; @@ -3073,24 +3130,24 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc, } } - return new (Context) PredefinedExpr(Loc, ResTy, IT, SL); + return PredefinedExpr::Create(Context, Loc, ResTy, IK, SL); } ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { - PredefinedExpr::IdentType IT; + PredefinedExpr::IdentKind IK; switch (Kind) { default: llvm_unreachable("Unknown simple primary expr!"); - case tok::kw___func__: IT = PredefinedExpr::Func; break; // [C99 6.4.2.2] - case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break; - case tok::kw___FUNCDNAME__: IT = PredefinedExpr::FuncDName; break; // [MS] - case tok::kw___FUNCSIG__: IT = PredefinedExpr::FuncSig; break; // [MS] - case tok::kw_L__FUNCTION__: IT = PredefinedExpr::LFunction; break; // [MS] - case tok::kw_L__FUNCSIG__: IT = PredefinedExpr::LFuncSig; break; // [MS] - case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break; + case tok::kw___func__: IK = PredefinedExpr::Func; break; // [C99 6.4.2.2] + case tok::kw___FUNCTION__: IK = PredefinedExpr::Function; break; + case tok::kw___FUNCDNAME__: IK = PredefinedExpr::FuncDName; break; // [MS] + case tok::kw___FUNCSIG__: IK = PredefinedExpr::FuncSig; break; // [MS] + case tok::kw_L__FUNCTION__: IK = PredefinedExpr::LFunction; break; // [MS] + case tok::kw_L__FUNCSIG__: IK = PredefinedExpr::LFuncSig; break; // [MS] + case tok::kw___PRETTY_FUNCTION__: IK = PredefinedExpr::PrettyFunction; break; } - return BuildPredefinedExpr(Loc, IT); + return BuildPredefinedExpr(Loc, IK); } ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) { @@ -3363,16 +3420,14 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { bool isSigned = !Literal.isUnsigned; unsigned scale = Context.getFixedPointScale(Ty); - unsigned ibits = Context.getFixedPointIBits(Ty); unsigned bit_width = Context.getTypeInfo(Ty).Width; llvm::APInt Val(bit_width, 0, isSigned); bool Overflowed = Literal.GetFixedPointValue(Val, scale); + bool ValIsZero = Val.isNullValue() && !Overflowed; - // Do not use bit_width since some types may have padding like _Fract or - // unsigned _Accums if PaddingOnUnsignedFixedPoint is set. - auto MaxVal = llvm::APInt::getMaxValue(ibits + scale).zextOrSelf(bit_width); - if (Literal.isFract && Val == MaxVal + 1) + auto MaxVal = Context.getFixedPointMax(Ty).getValue(); + if (Literal.isFract && Val == MaxVal + 1 && !ValIsZero) // Clause 6.4.4 - The value of a constant shall be in the range of // representable values for its type, with exception for constants of a // fract type with a value of exactly 1; such a constant shall denote @@ -3588,7 +3643,8 @@ static bool CheckExtensionTraitOperandType(Sema &S, QualType T, // C99 6.5.3.4p1: if (T->isFunctionType() && - (TraitKind == UETT_SizeOf || TraitKind == UETT_AlignOf)) { + (TraitKind == UETT_SizeOf || TraitKind == UETT_AlignOf || + TraitKind == UETT_PreferredAlignOf)) { // sizeof(function)/alignof(function) is allowed as an extension. S.Diag(Loc, diag::ext_sizeof_alignof_function_type) << TraitKind << ArgRange; @@ -3666,7 +3722,7 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E, // the expression to be complete. 'sizeof' requires the expression's type to // be complete (and will attempt to complete it if it's an array of unknown // bound). - if (ExprKind == UETT_AlignOf) { + if (ExprKind == UETT_AlignOf || ExprKind == UETT_PreferredAlignOf) { if (RequireCompleteType(E->getExprLoc(), Context.getBaseElementType(E->getType()), diag::err_sizeof_alignof_incomplete_type, ExprKind, @@ -3690,7 +3746,8 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E, // The operand for sizeof and alignof is in an unevaluated expression context, // so side effects could result in unintended consequences. - if ((ExprKind == UETT_SizeOf || ExprKind == UETT_AlignOf) && + if ((ExprKind == UETT_SizeOf || ExprKind == UETT_AlignOf || + ExprKind == UETT_PreferredAlignOf) && !inTemplateInstantiation() && E->HasSideEffects(Context, false)) Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context); @@ -3759,7 +3816,8 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType, // C11 6.5.3.4/3, C++11 [expr.alignof]p3: // When alignof or _Alignof is applied to an array type, the result // is the alignment of the element type. - if (ExprKind == UETT_AlignOf || ExprKind == UETT_OpenMPRequiredSimdAlign) + if (ExprKind == UETT_AlignOf || ExprKind == UETT_PreferredAlignOf || + ExprKind == UETT_OpenMPRequiredSimdAlign) ExprType = Context.getBaseElementType(ExprType); if (ExprKind == UETT_VecStep) @@ -3788,7 +3846,7 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType, return false; } -static bool CheckAlignOfExpr(Sema &S, Expr *E) { +static bool CheckAlignOfExpr(Sema &S, Expr *E, UnaryExprOrTypeTrait ExprKind) { E = E->IgnoreParens(); // Cannot know anything else if the expression is dependent. @@ -3842,7 +3900,7 @@ static bool CheckAlignOfExpr(Sema &S, Expr *E) { return false; } - return S.CheckUnaryExprOrTypeTraitOperand(E, UETT_AlignOf); + return S.CheckUnaryExprOrTypeTraitOperand(E, ExprKind); } bool Sema::CheckVecStepExpr(Expr *E) { @@ -4038,8 +4096,8 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc, bool isInvalid = false; if (E->isTypeDependent()) { // Delay type-checking for type-dependent expressions. - } else if (ExprKind == UETT_AlignOf) { - isInvalid = CheckAlignOfExpr(*this, E); + } else if (ExprKind == UETT_AlignOf || ExprKind == UETT_PreferredAlignOf) { + isInvalid = CheckAlignOfExpr(*this, E, ExprKind); } else if (ExprKind == UETT_VecStep) { isInvalid = CheckVecStepExpr(E); } else if (ExprKind == UETT_OpenMPRequiredSimdAlign) { @@ -4238,7 +4296,57 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc, return CreateOverloadedArraySubscriptExpr(lbLoc, rbLoc, base, idx); } - return CreateBuiltinArraySubscriptExpr(base, lbLoc, idx, rbLoc); + ExprResult Res = CreateBuiltinArraySubscriptExpr(base, lbLoc, idx, rbLoc); + + if (!Res.isInvalid() && isa<ArraySubscriptExpr>(Res.get())) + CheckSubscriptAccessOfNoDeref(cast<ArraySubscriptExpr>(Res.get())); + + return Res; +} + +void Sema::CheckAddressOfNoDeref(const Expr *E) { + ExpressionEvaluationContextRecord &LastRecord = ExprEvalContexts.back(); + const Expr *StrippedExpr = E->IgnoreParenImpCasts(); + + // For expressions like `&(*s).b`, the base is recorded and what should be + // checked. + const MemberExpr *Member = nullptr; + while ((Member = dyn_cast<MemberExpr>(StrippedExpr)) && !Member->isArrow()) + StrippedExpr = Member->getBase()->IgnoreParenImpCasts(); + + LastRecord.PossibleDerefs.erase(StrippedExpr); +} + +void Sema::CheckSubscriptAccessOfNoDeref(const ArraySubscriptExpr *E) { + QualType ResultTy = E->getType(); + ExpressionEvaluationContextRecord &LastRecord = ExprEvalContexts.back(); + + // Bail if the element is an array since it is not memory access. + if (isa<ArrayType>(ResultTy)) + return; + + if (ResultTy->hasAttr(attr::NoDeref)) { + LastRecord.PossibleDerefs.insert(E); + return; + } + + // Check if the base type is a pointer to a member access of a struct + // marked with noderef. + const Expr *Base = E->getBase(); + QualType BaseTy = Base->getType(); + if (!(isa<ArrayType>(BaseTy) || isa<PointerType>(BaseTy))) + // Not a pointer access + return; + + const MemberExpr *Member = nullptr; + while ((Member = dyn_cast<MemberExpr>(Base->IgnoreParenCasts())) && + Member->isArrow()) + Base = Member->getBase(); + + if (const auto *Ptr = dyn_cast<PointerType>(Base->getType())) { + if (Ptr->getPointeeType()->hasAttr(attr::NoDeref)) + LastRecord.PossibleDerefs.insert(E); + } } ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc, @@ -4339,10 +4447,11 @@ ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc, return ExprError(); if (LowerBound && !OriginalTy->isAnyPointerType()) { - llvm::APSInt LowerBoundValue; - if (LowerBound->EvaluateAsInt(LowerBoundValue, Context)) { + Expr::EvalResult Result; + if (LowerBound->EvaluateAsInt(Result, Context)) { // OpenMP 4.5, [2.4 Array Sections] // The array section must be a subset of the original array. + llvm::APSInt LowerBoundValue = Result.Val.getInt(); if (LowerBoundValue.isNegative()) { Diag(LowerBound->getExprLoc(), diag::err_omp_section_not_subset_of_array) << LowerBound->getSourceRange(); @@ -4352,10 +4461,11 @@ ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc, } if (Length) { - llvm::APSInt LengthValue; - if (Length->EvaluateAsInt(LengthValue, Context)) { + Expr::EvalResult Result; + if (Length->EvaluateAsInt(Result, Context)) { // OpenMP 4.5, [2.4 Array Sections] // The length must evaluate to non-negative integers. + llvm::APSInt LengthValue = Result.Val.getInt(); if (LengthValue.isNegative()) { Diag(Length->getExprLoc(), diag::err_omp_section_length_negative) << LengthValue.toString(/*Radix=*/10, /*Signed=*/true) @@ -4488,8 +4598,8 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, // wasn't promoted because of the C90 rule that doesn't // allow promoting non-lvalue arrays. Warn, then // force the promotion here. - Diag(LHSExp->getLocStart(), diag::ext_subscript_non_lvalue) << - LHSExp->getSourceRange(); + Diag(LHSExp->getBeginLoc(), diag::ext_subscript_non_lvalue) + << LHSExp->getSourceRange(); LHSExp = ImpCastExprToType(LHSExp, Context.getArrayDecayedType(LHSTy), CK_ArrayToPointerDecay).get(); LHSTy = LHSExp->getType(); @@ -4499,8 +4609,8 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, ResultType = LHSTy->getAs<PointerType>()->getPointeeType(); } else if (RHSTy->isArrayType()) { // Same as previous, except for 123[f().a] case - Diag(RHSExp->getLocStart(), diag::ext_subscript_non_lvalue) << - RHSExp->getSourceRange(); + Diag(RHSExp->getBeginLoc(), diag::ext_subscript_non_lvalue) + << RHSExp->getSourceRange(); RHSExp = ImpCastExprToType(RHSExp, Context.getArrayDecayedType(RHSTy), CK_ArrayToPointerDecay).get(); RHSTy = RHSExp->getType(); @@ -4527,8 +4637,8 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, // type. Note that Functions are not objects, and that (in C99 parlance) // incomplete types are not object types. if (ResultType->isFunctionType()) { - Diag(BaseExpr->getLocStart(), diag::err_subscript_function_type) - << ResultType << BaseExpr->getSourceRange(); + Diag(BaseExpr->getBeginLoc(), diag::err_subscript_function_type) + << ResultType << BaseExpr->getSourceRange(); return ExprError(); } @@ -4594,7 +4704,7 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, if (Inst.isInvalid()) return true; if (Inst.isAlreadyInstantiating()) { - Diag(Param->getLocStart(), diag::err_recursive_default_argument) << FD; + Diag(Param->getBeginLoc(), diag::err_recursive_default_argument) << FD; Param->setInvalidDecl(); return true; } @@ -4616,9 +4726,9 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, // Check the expression as an initializer for the parameter. InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, Param); - InitializationKind Kind - = InitializationKind::CreateCopy(Param->getLocation(), - /*FIXME:EqualLoc*/UninstExpr->getLocStart()); + InitializationKind Kind = InitializationKind::CreateCopy( + Param->getLocation(), + /*FIXME:EqualLoc*/ UninstExpr->getBeginLoc()); Expr *ResultE = Result.getAs<Expr>(); InitializationSequence InitSeq(*this, Entity, Kind, ResultE); @@ -4626,8 +4736,9 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, if (Result.isInvalid()) return true; - Result = ActOnFinishFullExpr(Result.getAs<Expr>(), - Param->getOuterLocStart()); + Result = + ActOnFinishFullExpr(Result.getAs<Expr>(), Param->getOuterLocStart(), + /*DiscardedValue*/ false); if (Result.isInvalid()) return true; @@ -4640,7 +4751,7 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, // If the default argument expression is not set yet, we are building it now. if (!Param->hasInit()) { - Diag(Param->getLocStart(), diag::err_recursive_default_argument) << FD; + Diag(Param->getBeginLoc(), diag::err_recursive_default_argument) << FD; Param->setInvalidDecl(); return true; } @@ -4725,7 +4836,7 @@ static TypoCorrection TryTypoCorrectionForCall(Sema &S, Expr *Fn, ArrayRef<Expr *> Args) { MemberExpr *ME = dyn_cast<MemberExpr>(Fn); DeclarationName FuncName = FDecl->getDeclName(); - SourceLocation NameLoc = ME ? ME->getMemberLoc() : Fn->getLocStart(); + SourceLocation NameLoc = ME ? ME->getMemberLoc() : Fn->getBeginLoc(); if (TypoCorrection Corrected = S.CorrectTypo( DeclarationNameInfo(FuncName, NameLoc), Sema::LookupOrdinaryName, @@ -4816,12 +4927,14 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, // Emit the location of the prototype. if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig) - Diag(FDecl->getLocStart(), diag::note_callee_decl) - << FDecl; + Diag(FDecl->getBeginLoc(), diag::note_callee_decl) << FDecl; return true; } - Call->setNumArgs(Context, NumParams); + // We reserve space for the default arguments when we create + // the call expression, before calling ConvertArgumentsForCall. + assert((Call->getNumArgs() == NumParams) && + "We should have reserved space for the default arguments before!"); } // If too many are passed and not variadic, error on the extras and drop @@ -4839,39 +4952,38 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, << TC.getCorrectionRange()); } else if (NumParams == 1 && FDecl && FDecl->getParamDecl(0)->getDeclName()) - Diag(Args[NumParams]->getLocStart(), + Diag(Args[NumParams]->getBeginLoc(), MinArgs == NumParams ? diag::err_typecheck_call_too_many_args_one : diag::err_typecheck_call_too_many_args_at_most_one) << FnKind << FDecl->getParamDecl(0) << static_cast<unsigned>(Args.size()) << Fn->getSourceRange() - << SourceRange(Args[NumParams]->getLocStart(), - Args.back()->getLocEnd()); + << SourceRange(Args[NumParams]->getBeginLoc(), + Args.back()->getEndLoc()); else - Diag(Args[NumParams]->getLocStart(), + Diag(Args[NumParams]->getBeginLoc(), MinArgs == NumParams ? diag::err_typecheck_call_too_many_args : diag::err_typecheck_call_too_many_args_at_most) << FnKind << NumParams << static_cast<unsigned>(Args.size()) << Fn->getSourceRange() - << SourceRange(Args[NumParams]->getLocStart(), - Args.back()->getLocEnd()); + << SourceRange(Args[NumParams]->getBeginLoc(), + Args.back()->getEndLoc()); // Emit the location of the prototype. if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig) - Diag(FDecl->getLocStart(), diag::note_callee_decl) - << FDecl; + Diag(FDecl->getBeginLoc(), diag::note_callee_decl) << FDecl; // This deletes the extra arguments. - Call->setNumArgs(Context, NumParams); + Call->shrinkNumArgs(NumParams); return true; } } SmallVector<Expr *, 8> AllArgs; VariadicCallType CallType = getVariadicCallType(FDecl, Proto, Fn); - Invalid = GatherArgumentsForCall(Call->getLocStart(), FDecl, - Proto, 0, Args, AllArgs, CallType); + Invalid = GatherArgumentsForCall(Call->getBeginLoc(), FDecl, Proto, 0, Args, + AllArgs, CallType); if (Invalid) return true; unsigned TotalNumArgs = AllArgs.size(); @@ -4899,8 +5011,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl, if (ArgIx < Args.size()) { Arg = Args[ArgIx++]; - if (RequireCompleteType(Arg->getLocStart(), - ProtoArgType, + if (RequireCompleteType(Arg->getBeginLoc(), ProtoArgType, diag::err_call_incomplete_argument, Arg)) return true; @@ -5058,6 +5169,9 @@ static bool isPlaceholderToRemoveAsArg(QualType type) { #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ case BuiltinType::Id: #include "clang/Basic/OpenCLImageTypes.def" +#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ + case BuiltinType::Id: +#include "clang/Basic/OpenCLExtensionTypes.def" #define PLACEHOLDER_TYPE(ID, SINGLETON_ID) #define BUILTIN_TYPE(ID, SINGLETON_ID) case BuiltinType::ID: #include "clang/AST/BuiltinTypes.def" @@ -5153,10 +5267,13 @@ static FunctionDecl *rewriteBuiltinFunctionDecl(Sema *Sema, ASTContext &Context, continue; } + QualType PointeeType = ParamType->getPointeeType(); + if (PointeeType.getQualifiers().hasAddressSpace()) + continue; + NeedsNewDecl = true; LangAS AS = ArgType->getPointeeType().getAddressSpace(); - QualType PointeeType = ParamType->getPointeeType(); PointeeType = Context.getAddrSpaceQualType(PointeeType, AS); OverloadParams.push_back(Context.getPointerType(PointeeType)); } @@ -5205,7 +5322,7 @@ static void checkDirectCallValidity(Sema &S, const Expr *Fn, return; if (const EnableIfAttr *Attr = S.CheckEnableIf(Callee, ArgExprs, true)) { - S.Diag(Fn->getLocStart(), + S.Diag(Fn->getBeginLoc(), isa<CXXMethodDecl>(Callee) ? diag::err_ovl_no_viable_member_function_in_call : diag::err_ovl_no_viable_function_in_call) @@ -5317,14 +5434,14 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, if (isa<CXXPseudoDestructorExpr>(Fn)) { if (!ArgExprs.empty()) { // Pseudo-destructor calls should not have any arguments. - Diag(Fn->getLocStart(), diag::err_pseudo_dtor_call_with_args) + Diag(Fn->getBeginLoc(), diag::err_pseudo_dtor_call_with_args) << FixItHint::CreateRemoval( - SourceRange(ArgExprs.front()->getLocStart(), - ArgExprs.back()->getLocEnd())); + SourceRange(ArgExprs.front()->getBeginLoc(), + ArgExprs.back()->getEndLoc())); } - return new (Context) - CallExpr(Context, Fn, None, Context.VoidTy, VK_RValue, RParenLoc); + return CallExpr::Create(Context, Fn, /*Args=*/{}, Context.VoidTy, + VK_RValue, RParenLoc); } if (Fn->getType() == Context.PseudoObjectTy) { ExprResult result = CheckPlaceholderExpr(Fn); @@ -5334,25 +5451,19 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, // Determine whether this is a dependent call inside a C++ template, // in which case we won't do any semantic analysis now. - bool Dependent = false; - if (Fn->isTypeDependent()) - Dependent = true; - else if (Expr::hasAnyTypeDependentArguments(ArgExprs)) - Dependent = true; - - if (Dependent) { + if (Fn->isTypeDependent() || Expr::hasAnyTypeDependentArguments(ArgExprs)) { if (ExecConfig) { - return new (Context) CUDAKernelCallExpr( + return CUDAKernelCallExpr::Create( Context, Fn, cast<CallExpr>(ExecConfig), ArgExprs, Context.DependentTy, VK_RValue, RParenLoc); } else { - tryImplicitlyCaptureThisIfImplicitMemberFunctionAccessWithDependentArgs( + tryImplicitlyCaptureThisIfImplicitMemberFunctionAccessWithDependentArgs( *this, dyn_cast<UnresolvedMemberExpr>(Fn->IgnoreParens()), - Fn->getLocStart()); + Fn->getBeginLoc()); - return new (Context) CallExpr( - Context, Fn, ArgExprs, Context.DependentTy, VK_RValue, RParenLoc); + return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy, + VK_RValue, RParenLoc); } } @@ -5380,8 +5491,8 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, // We aren't supposed to apply this logic if there's an '&' involved. if (!find.HasFormOfMemberPointer) { if (Expr::hasAnyTypeDependentArguments(ArgExprs)) - return new (Context) CallExpr( - Context, Fn, ArgExprs, Context.DependentTy, VK_RValue, RParenLoc); + return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy, + VK_RValue, RParenLoc); OverloadExpr *ovl = find.Expression; if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(ovl)) return BuildOverloadedCallExpr( @@ -5430,9 +5541,8 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, NDecl = cast<MemberExpr>(NakedFn)->getMemberDecl(); if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(NDecl)) { - if (CallingNDeclIndirectly && - !checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true, - Fn->getLocStart())) + if (CallingNDeclIndirectly && !checkAddressOfFunctionIsAvailable( + FD, /*Complain=*/true, Fn->getBeginLoc())) return ExprError(); if (getLangOpts().OpenCL && checkOpenCLDisabledDecl(*FD, *Fn)) @@ -5484,12 +5594,11 @@ ExprResult Sema::ActOnConvertVectorExpr(Expr *E, ParsedType ParsedDestTy, /// block-pointer type. /// /// \param NDecl the declaration being called, if available -ExprResult -Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, - SourceLocation LParenLoc, - ArrayRef<Expr *> Args, - SourceLocation RParenLoc, - Expr *Config, bool IsExecConfig) { +ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, + SourceLocation LParenLoc, + ArrayRef<Expr *> Args, + SourceLocation RParenLoc, Expr *Config, + bool IsExecConfig, ADLCallKind UsesADL) { FunctionDecl *FDecl = dyn_cast_or_null<FunctionDecl>(NDecl); unsigned BuiltinID = (FDecl ? FDecl->getBuiltinID() : 0); @@ -5514,28 +5623,71 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, // We special-case function promotion here because we only allow promoting // builtin functions to function pointers in the callee of a call. ExprResult Result; + QualType ResultTy; if (BuiltinID && Fn->getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn)) { - Result = ImpCastExprToType(Fn, Context.getPointerType(FDecl->getType()), - CK_BuiltinFnToFnPtr).get(); + // Extract the return type from the (builtin) function pointer type. + // FIXME Several builtins still have setType in + // Sema::CheckBuiltinFunctionCall. One should review their definitions in + // Builtins.def to ensure they are correct before removing setType calls. + QualType FnPtrTy = Context.getPointerType(FDecl->getType()); + Result = ImpCastExprToType(Fn, FnPtrTy, CK_BuiltinFnToFnPtr).get(); + ResultTy = FDecl->getCallResultType(); } else { Result = CallExprUnaryConversions(Fn); + ResultTy = Context.BoolTy; } if (Result.isInvalid()) return ExprError(); Fn = Result.get(); - // Make the call expr early, before semantic checks. This guarantees cleanup - // of arguments and function on error. + // Check for a valid function type, but only if it is not a builtin which + // requires custom type checking. These will be handled by + // CheckBuiltinFunctionCall below just after creation of the call expression. + const FunctionType *FuncT = nullptr; + if (!BuiltinID || !Context.BuiltinInfo.hasCustomTypechecking(BuiltinID)) { + retry: + if (const PointerType *PT = Fn->getType()->getAs<PointerType>()) { + // C99 6.5.2.2p1 - "The expression that denotes the called function shall + // have type pointer to function". + FuncT = PT->getPointeeType()->getAs<FunctionType>(); + if (!FuncT) + return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function) + << Fn->getType() << Fn->getSourceRange()); + } else if (const BlockPointerType *BPT = + Fn->getType()->getAs<BlockPointerType>()) { + FuncT = BPT->getPointeeType()->castAs<FunctionType>(); + } else { + // Handle calls to expressions of unknown-any type. + if (Fn->getType() == Context.UnknownAnyTy) { + ExprResult rewrite = rebuildUnknownAnyFunction(*this, Fn); + if (rewrite.isInvalid()) return ExprError(); + Fn = rewrite.get(); + goto retry; + } + + return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function) + << Fn->getType() << Fn->getSourceRange()); + } + } + + // Get the number of parameters in the function prototype, if any. + // We will allocate space for max(Args.size(), NumParams) arguments + // in the call expression. + const auto *Proto = dyn_cast_or_null<FunctionProtoType>(FuncT); + unsigned NumParams = Proto ? Proto->getNumParams() : 0; + CallExpr *TheCall; - if (Config) - TheCall = new (Context) CUDAKernelCallExpr(Context, Fn, - cast<CallExpr>(Config), Args, - Context.BoolTy, VK_RValue, - RParenLoc); - else - TheCall = new (Context) CallExpr(Context, Fn, Args, Context.BoolTy, - VK_RValue, RParenLoc); + 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); + } else { + TheCall = CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue, + RParenLoc, NumParams, UsesADL); + } if (!getLangOpts().CPlusPlus) { // C cannot always handle TypoExpr nodes in builtin calls and direct @@ -5546,39 +5698,16 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, if (!Result.isUsable()) return ExprError(); TheCall = dyn_cast<CallExpr>(Result.get()); if (!TheCall) return Result; - Args = llvm::makeArrayRef(TheCall->getArgs(), TheCall->getNumArgs()); + // TheCall at this point has max(Args.size(), NumParams) arguments, + // with extra arguments nulled. We don't want to introduce nulled + // arguments in Args and so we only take the first Args.size() arguments. + Args = llvm::makeArrayRef(TheCall->getArgs(), Args.size()); } - // Bail out early if calling a builtin with custom typechecking. + // Bail out early if calling a builtin with custom type checking. if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID)) return CheckBuiltinFunctionCall(FDecl, BuiltinID, TheCall); - retry: - const FunctionType *FuncT; - if (const PointerType *PT = Fn->getType()->getAs<PointerType>()) { - // C99 6.5.2.2p1 - "The expression that denotes the called function shall - // have type pointer to function". - FuncT = PT->getPointeeType()->getAs<FunctionType>(); - if (!FuncT) - return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function) - << Fn->getType() << Fn->getSourceRange()); - } else if (const BlockPointerType *BPT = - Fn->getType()->getAs<BlockPointerType>()) { - FuncT = BPT->getPointeeType()->castAs<FunctionType>(); - } else { - // Handle calls to expressions of unknown-any type. - if (Fn->getType() == Context.UnknownAnyTy) { - ExprResult rewrite = rebuildUnknownAnyFunction(*this, Fn); - if (rewrite.isInvalid()) return ExprError(); - Fn = rewrite.get(); - TheCall->setCallee(Fn); - goto retry; - } - - return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function) - << Fn->getType() << Fn->getSourceRange()); - } - if (getLangOpts().CUDA) { if (Config) { // CUDA: Kernel calls must be to global functions @@ -5599,7 +5728,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, } // Check for a valid return type - if (CheckCallReturnType(FuncT->getReturnType(), Fn->getLocStart(), TheCall, + if (CheckCallReturnType(FuncT->getReturnType(), Fn->getBeginLoc(), TheCall, FDecl)) return ExprError(); @@ -5607,7 +5736,6 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, TheCall->setType(FuncT->getCallResultType(Context)); TheCall->setValueKind(Expr::getValueKindForType(FuncT->getReturnType())); - const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FuncT); if (Proto) { if (ConvertArgumentsForCall(TheCall, Fn, FDecl, Proto, Args, RParenLoc, IsExecConfig)) @@ -5655,8 +5783,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, Arg = ArgE.getAs<Expr>(); } - if (RequireCompleteType(Arg->getLocStart(), - Arg->getType(), + if (RequireCompleteType(Arg->getBeginLoc(), Arg->getType(), diag::err_call_incomplete_argument, Arg)) return ExprError(); @@ -5739,13 +5866,6 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, LiteralExpr = Result.get(); bool isFileScope = !CurContext->isFunctionOrMethod(); - if (isFileScope && - !LiteralExpr->isTypeDependent() && - !LiteralExpr->isValueDependent() && - !literalType->isDependentType()) { // 6.5.2.5p3 - if (CheckForConstantInitializer(LiteralExpr, literalType)) - return ExprError(); - } // In C, compound literals are l-values for some reason. // For GCC compatibility, in C++, file-scope array compound literals with @@ -5770,9 +5890,32 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, ? VK_RValue : VK_LValue; - return MaybeBindToTemporary( - new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType, - VK, LiteralExpr, isFileScope)); + if (isFileScope) + if (auto ILE = dyn_cast<InitListExpr>(LiteralExpr)) + for (unsigned i = 0, j = ILE->getNumInits(); i != j; i++) { + Expr *Init = ILE->getInit(i); + ILE->setInit(i, ConstantExpr::Create(Context, Init)); + } + + Expr *E = new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType, + VK, LiteralExpr, isFileScope); + if (isFileScope) { + if (!LiteralExpr->isTypeDependent() && + !LiteralExpr->isValueDependent() && + !literalType->isDependentType()) // C99 6.5.2.5p3 + if (CheckForConstantInitializer(LiteralExpr, literalType)) + return ExprError(); + } else if (literalType.getAddressSpace() != LangAS::opencl_private && + literalType.getAddressSpace() != LangAS::Default) { + // Embedded-C extensions to C99 6.5.2.5: + // "If the compound literal occurs inside the body of a function, the + // type name shall not be qualified by an address-space qualifier." + Diag(LParenLoc, diag::err_compound_literal_with_address_space) + << SourceRange(LParenLoc, LiteralExpr->getSourceRange().getEnd()); + return ExprError(); + } + + return MaybeBindToTemporary(E); } ExprResult @@ -5854,6 +5997,8 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) { LangAS DestAS = DestTy->getPointeeType().getAddressSpace(); if (SrcAS != DestAS) return CK_AddressSpaceConversion; + if (Context.hasCvrSimilarType(SrcTy, DestTy)) + return CK_NoOp; return CK_BitCast; } case Type::STK_BlockPointer: @@ -5874,10 +6019,33 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) { case Type::STK_FloatingComplex: case Type::STK_IntegralComplex: case Type::STK_MemberPointer: + case Type::STK_FixedPoint: llvm_unreachable("illegal cast from pointer"); } llvm_unreachable("Should have returned before this"); + case Type::STK_FixedPoint: + switch (DestTy->getScalarTypeKind()) { + case Type::STK_FixedPoint: + return CK_FixedPointCast; + case Type::STK_Bool: + return CK_FixedPointToBoolean; + case Type::STK_Integral: + case Type::STK_Floating: + case Type::STK_IntegralComplex: + case Type::STK_FloatingComplex: + Diag(Src.get()->getExprLoc(), + diag::err_unimplemented_conversion_with_fixed_point_type) + << DestTy; + return CK_IntegralCast; + case Type::STK_CPointer: + case Type::STK_ObjCObjectPointer: + case Type::STK_BlockPointer: + case Type::STK_MemberPointer: + llvm_unreachable("illegal cast to pointer type"); + } + llvm_unreachable("Should have returned before this"); + case Type::STK_Bool: // casting from bool is like casting from an integer case Type::STK_Integral: switch (DestTy->getScalarTypeKind()) { @@ -5906,6 +6074,11 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) { return CK_FloatingRealToComplex; 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; } llvm_unreachable("Should have returned before this"); @@ -5933,6 +6106,11 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) { llvm_unreachable("valid float->pointer cast?"); 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; } llvm_unreachable("Should have returned before this"); @@ -5962,6 +6140,11 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) { llvm_unreachable("valid complex float->pointer cast?"); 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; } llvm_unreachable("Should have returned before this"); @@ -5991,6 +6174,11 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) { llvm_unreachable("valid complex int->pointer cast?"); 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; } llvm_unreachable("Should have returned before this"); } @@ -6323,8 +6511,7 @@ Sema::MaybeConvertParenListExprToParenExpr(Scope *S, Expr *OrigExpr) { ExprResult Sema::ActOnParenListExpr(SourceLocation L, SourceLocation R, MultiExprArg Val) { - Expr *expr = new (Context) ParenListExpr(Context, L, Val, R); - return expr; + return ParenListExpr::Create(Context, L, Val, R); } /// Emit a specialized diagnostic when one expression is a null pointer @@ -6394,11 +6581,11 @@ static QualType checkConditionalVoidType(Sema &S, ExprResult &LHS, Expr *RHSExpr = RHS.get(); if (!LHSExpr->getType()->isVoidType()) - S.Diag(RHSExpr->getLocStart(), diag::ext_typecheck_cond_one_void) - << RHSExpr->getSourceRange(); + S.Diag(RHSExpr->getBeginLoc(), diag::ext_typecheck_cond_one_void) + << RHSExpr->getSourceRange(); if (!RHSExpr->getType()->isVoidType()) - S.Diag(LHSExpr->getLocStart(), diag::ext_typecheck_cond_one_void) - << LHSExpr->getSourceRange(); + S.Diag(LHSExpr->getBeginLoc(), diag::ext_typecheck_cond_one_void) + << LHSExpr->getSourceRange(); LHS = S.ImpCastExprToType(LHS.get(), S.Context.VoidTy, CK_ToVoid); RHS = S.ImpCastExprToType(RHS.get(), S.Context.VoidTy, CK_ToVoid); return S.Context.VoidTy; @@ -6458,20 +6645,18 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS, LangAS ResultAddrSpace = LangAS::Default; LangAS LAddrSpace = lhQual.getAddressSpace(); LangAS RAddrSpace = rhQual.getAddressSpace(); - if (S.getLangOpts().OpenCL) { - // OpenCL v1.1 s6.5 - Conversion between pointers to distinct address - // spaces is disallowed. - if (lhQual.isAddressSpaceSupersetOf(rhQual)) - ResultAddrSpace = LAddrSpace; - else if (rhQual.isAddressSpaceSupersetOf(lhQual)) - ResultAddrSpace = RAddrSpace; - else { - S.Diag(Loc, - diag::err_typecheck_op_on_nonoverlapping_address_space_pointers) - << LHSTy << RHSTy << 2 << LHS.get()->getSourceRange() - << RHS.get()->getSourceRange(); - return QualType(); - } + + // OpenCL v1.1 s6.5 - Conversion between pointers to distinct address + // spaces is disallowed. + if (lhQual.isAddressSpaceSupersetOf(rhQual)) + ResultAddrSpace = LAddrSpace; + else if (rhQual.isAddressSpaceSupersetOf(lhQual)) + ResultAddrSpace = RAddrSpace; + else { + S.Diag(Loc, diag::err_typecheck_op_on_nonoverlapping_address_space_pointers) + << LHSTy << RHSTy << 2 << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + return QualType(); } unsigned MergedCVRQual = lhQual.getCVRQualifiers() | rhQual.getCVRQualifiers(); @@ -6489,16 +6674,12 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS, // Thus for conditional operator we merge CVR and address space unqualified // pointees and if there is a composite type we return a pointer to it with // merged qualifiers. - if (S.getLangOpts().OpenCL) { - LHSCastKind = LAddrSpace == ResultAddrSpace - ? CK_BitCast - : CK_AddressSpaceConversion; - RHSCastKind = RAddrSpace == ResultAddrSpace - ? CK_BitCast - : CK_AddressSpaceConversion; - lhQual.removeAddressSpace(); - rhQual.removeAddressSpace(); - } + LHSCastKind = + LAddrSpace == ResultAddrSpace ? CK_BitCast : CK_AddressSpaceConversion; + RHSCastKind = + RAddrSpace == ResultAddrSpace ? CK_BitCast : CK_AddressSpaceConversion; + lhQual.removeAddressSpace(); + rhQual.removeAddressSpace(); lhptee = S.Context.getQualifiedType(lhptee.getUnqualifiedType(), lhQual); rhptee = S.Context.getQualifiedType(rhptee.getUnqualifiedType(), rhQual); @@ -6514,6 +6695,7 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS, S.Context.getAddrSpaceQualType(S.Context.VoidTy, ResultAddrSpace)); LHS = S.ImpCastExprToType(LHS.get(), incompatTy, LHSCastKind); RHS = S.ImpCastExprToType(RHS.get(), incompatTy, RHSCastKind); + // FIXME: For OpenCL the warning emission and cast to void* leaves a room // for casts between types with incompatible address space qualifiers. // For the following code the compiler produces casts between global and @@ -6524,6 +6706,7 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS, S.Diag(Loc, diag::ext_typecheck_cond_incompatible_pointers) << LHSTy << RHSTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + return incompatTy; } @@ -7219,14 +7402,15 @@ static void DiagnoseConditionalPrecedence(Sema &Self, << Condition->getSourceRange() << BinaryOperator::getOpcodeStr(CondOpcode); - SuggestParentheses(Self, OpLoc, - Self.PDiag(diag::note_precedence_silence) - << BinaryOperator::getOpcodeStr(CondOpcode), - SourceRange(Condition->getLocStart(), Condition->getLocEnd())); + SuggestParentheses( + Self, OpLoc, + Self.PDiag(diag::note_precedence_silence) + << BinaryOperator::getOpcodeStr(CondOpcode), + SourceRange(Condition->getBeginLoc(), Condition->getEndLoc())); SuggestParentheses(Self, OpLoc, - Self.PDiag(diag::note_precedence_conditional_first), - SourceRange(CondRHS->getLocStart(), RHSExpr->getLocEnd())); + Self.PDiag(diag::note_precedence_conditional_first), + SourceRange(CondRHS->getBeginLoc(), RHSExpr->getEndLoc())); } /// Compute the nullability of a conditional expression. @@ -7757,7 +7941,12 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, if (isa<PointerType>(RHSType)) { LangAS AddrSpaceL = LHSPointer->getPointeeType().getAddressSpace(); LangAS AddrSpaceR = RHSType->getPointeeType().getAddressSpace(); - Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast; + if (AddrSpaceL != AddrSpaceR) + Kind = CK_AddressSpaceConversion; + else if (Context.hasCvrSimilarType(RHSType, LHSType)) + Kind = CK_NoOp; + else + Kind = CK_BitCast; return checkPointerTypesForAssignment(*this, LHSType, RHSType); } @@ -7825,7 +8014,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, } // id -> T^ - if (getLangOpts().ObjC1 && RHSType->isObjCIdType()) { + if (getLangOpts().ObjC && RHSType->isObjCIdType()) { Kind = CK_AnyPointerToBlockPointerCast; return Compatible; } @@ -8029,6 +8218,17 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS, ExprResult LocalRHS = CallerRHS; ExprResult &RHS = ConvertRHS ? CallerRHS : LocalRHS; + if (const auto *LHSPtrType = LHSType->getAs<PointerType>()) { + if (const auto *RHSPtrType = RHS.get()->getType()->getAs<PointerType>()) { + if (RHSPtrType->getPointeeType()->hasAttr(attr::NoDeref) && + !LHSPtrType->getPointeeType()->hasAttr(attr::NoDeref)) { + Diag(RHS.get()->getExprLoc(), + diag::warn_noderef_to_dereferenceable_pointer) + << RHS.get()->getSourceRange(); + } + } + } + if (getLangOpts().CPlusPlus) { if (!LHSType->isRecordType() && !LHSType->isAtomicType()) { // C++ 5.17p3: If the left operand is not of class type, the @@ -8092,6 +8292,13 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS, return Compatible; } + // OpenCL queue_t type assignment. + if (LHSType->isQueueT() && RHS.get()->isNullPointerConstant( + Context, Expr::NPC_ValueDependentIsNull)) { + RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer); + return Compatible; + } + // This check seems unnatural, however it is necessary to ensure the proper // conversion of functions/arrays. If the conversion were done for all // DeclExpr's (created by ActOnIdExpression), it would mess up the unary @@ -8104,16 +8311,6 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS, if (RHS.isInvalid()) return Incompatible; } - - Expr *PRE = RHS.get()->IgnoreParenCasts(); - if (Diagnose && isa<ObjCProtocolExpr>(PRE)) { - ObjCProtocolDecl *PDecl = cast<ObjCProtocolExpr>(PRE)->getProtocol(); - if (PDecl && !PDecl->hasDefinition()) { - Diag(PRE->getExprLoc(), diag::warn_atprotocol_protocol) << PDecl; - Diag(PDecl->getLocation(), diag::note_entity_declared_at) << PDecl; - } - } - CastKind Kind; Sema::AssignConvertType result = CheckAssignmentConstraints(LHSType, RHS, Kind, ConvertRHS); @@ -8137,8 +8334,8 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS, if (!Diagnose) return Incompatible; } - if (getLangOpts().ObjC1 && - (CheckObjCBridgeRelatedConversions(E->getLocStart(), LHSType, + if (getLangOpts().ObjC && + (CheckObjCBridgeRelatedConversions(E->getBeginLoc(), LHSType, E->getType(), E, Diagnose) || ConversionToObjCStringLiteralCheck(LHSType, E, Diagnose))) { if (!Diagnose) @@ -8152,6 +8349,7 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS, if (ConvertRHS) RHS = ImpCastExprToType(E, Ty, Kind); } + return result; } @@ -8314,8 +8512,8 @@ static bool canConvertIntToOtherIntTy(Sema &S, ExprResult *Int, // Reject cases where the value of the Int is unknown as that would // possibly cause truncation, but accept cases where the scalar can be // demoted without loss of precision. - llvm::APSInt Result; - bool CstInt = Int->get()->EvaluateAsInt(Result, S.Context); + Expr::EvalResult EVResult; + bool CstInt = Int->get()->EvaluateAsInt(EVResult, S.Context); int Order = S.Context.getIntegerTypeOrder(OtherIntTy, IntTy); bool IntSigned = IntTy->hasSignedIntegerRepresentation(); bool OtherIntSigned = OtherIntTy->hasSignedIntegerRepresentation(); @@ -8323,6 +8521,7 @@ static bool canConvertIntToOtherIntTy(Sema &S, ExprResult *Int, if (CstInt) { // If the scalar is constant and is of a higher order and has more active // bits that the vector element type, reject it. + llvm::APSInt Result = EVResult.Val.getInt(); unsigned NumBits = IntSigned ? (Result.isNegative() ? Result.getMinSignedBits() : Result.getActiveBits()) @@ -8350,8 +8549,9 @@ static bool canConvertIntTyToFloatTy(Sema &S, ExprResult *Int, // Determine if the integer constant can be expressed as a floating point // number of the appropriate type. - llvm::APSInt Result; - bool CstInt = Int->get()->EvaluateAsInt(Result, S.Context); + Expr::EvalResult EVResult; + bool CstInt = Int->get()->EvaluateAsInt(EVResult, S.Context); + uint64_t Bits = 0; if (CstInt) { // Reject constants that would be truncated if they were converted to @@ -8359,6 +8559,7 @@ static bool canConvertIntTyToFloatTy(Sema &S, ExprResult *Int, // FIXME: Ideally the conversion to an APFloat and from an APFloat // could be avoided if there was a convertFromAPInt method // which could signal back if implicit truncation occurred. + llvm::APSInt Result = EVResult.Val.getInt(); llvm::APFloat Float(S.Context.getFloatTypeSemantics(FloatTy)); Float.convertFromAPInt(Result, IntTy->hasSignedIntegerRepresentation(), llvm::APFloat::rmTowardZero); @@ -8668,13 +8869,40 @@ static void checkArithmeticNull(Sema &S, ExprResult &LHS, ExprResult &RHS, << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); } +static void DiagnoseDivisionSizeofPointer(Sema &S, Expr *LHS, Expr *RHS, + SourceLocation Loc) { + const auto *LUE = dyn_cast<UnaryExprOrTypeTraitExpr>(LHS); + const auto *RUE = dyn_cast<UnaryExprOrTypeTraitExpr>(RHS); + if (!LUE || !RUE) + return; + if (LUE->getKind() != UETT_SizeOf || LUE->isArgumentType() || + RUE->getKind() != UETT_SizeOf) + return; + + QualType LHSTy = LUE->getArgumentExpr()->IgnoreParens()->getType(); + QualType RHSTy; + + if (RUE->isArgumentType()) + RHSTy = RUE->getArgumentType(); + else + RHSTy = RUE->getArgumentExpr()->IgnoreParens()->getType(); + + if (!LHSTy->isPointerType() || RHSTy->isPointerType()) + return; + if (LHSTy->getPointeeType() != RHSTy) + return; + + S.Diag(Loc, diag::warn_division_sizeof_ptr) << LHS << LHS->getSourceRange(); +} + static void DiagnoseBadDivideOrRemainderValues(Sema& S, ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsDiv) { // Check for division/remainder by zero. - llvm::APSInt RHSValue; + Expr::EvalResult RHSValue; if (!RHS.get()->isValueDependent() && - RHS.get()->EvaluateAsInt(RHSValue, S.Context) && RHSValue == 0) + RHS.get()->EvaluateAsInt(RHSValue, S.Context) && + RHSValue.Val.getInt() == 0) S.DiagRuntimeBehavior(Loc, RHS.get(), S.PDiag(diag::warn_remainder_division_by_zero) << IsDiv << RHS.get()->getSourceRange()); @@ -8698,8 +8926,10 @@ QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS, if (compType.isNull() || !compType->isArithmeticType()) return InvalidOperands(Loc, LHS, RHS); - if (IsDiv) + if (IsDiv) { DiagnoseBadDivideOrRemainderValues(*this, LHS, RHS, Loc, IsDiv); + DiagnoseDivisionSizeofPointer(*this, LHS.get(), RHS.get(), Loc); + } return compType; } @@ -8914,24 +9144,15 @@ static void diagnoseStringPlusInt(Sema &Self, SourceLocation OpLoc, if (!IsStringPlusInt || IndexExpr->isValueDependent()) return; - llvm::APSInt index; - if (IndexExpr->EvaluateAsInt(index, Self.getASTContext())) { - unsigned StrLenWithNull = StrExpr->getLength() + 1; - if (index.isNonNegative() && - index <= llvm::APSInt(llvm::APInt(index.getBitWidth(), StrLenWithNull), - index.isUnsigned())) - return; - } - - SourceRange DiagRange(LHSExpr->getLocStart(), RHSExpr->getLocEnd()); + SourceRange DiagRange(LHSExpr->getBeginLoc(), RHSExpr->getEndLoc()); Self.Diag(OpLoc, diag::warn_string_plus_int) << DiagRange << IndexExpr->IgnoreImpCasts()->getType(); // Only print a fixit for "str" + int, not for int + "str". if (IndexExpr == RHSExpr) { - SourceLocation EndLoc = Self.getLocForEndOfToken(RHSExpr->getLocEnd()); + SourceLocation EndLoc = Self.getLocForEndOfToken(RHSExpr->getEndLoc()); Self.Diag(OpLoc, diag::note_string_plus_scalar_silence) - << FixItHint::CreateInsertion(LHSExpr->getLocStart(), "&") + << FixItHint::CreateInsertion(LHSExpr->getBeginLoc(), "&") << FixItHint::CreateReplacement(SourceRange(OpLoc), "[") << FixItHint::CreateInsertion(EndLoc, "]"); } else @@ -8964,7 +9185,7 @@ static void diagnoseStringPlusChar(Sema &Self, SourceLocation OpLoc, return; ASTContext &Ctx = Self.getASTContext(); - SourceRange DiagRange(LHSExpr->getLocStart(), RHSExpr->getLocEnd()); + SourceRange DiagRange(LHSExpr->getBeginLoc(), RHSExpr->getEndLoc()); const QualType CharType = CharExpr->getType(); if (!CharType->isAnyCharacterType() && @@ -8979,9 +9200,9 @@ static void diagnoseStringPlusChar(Sema &Self, SourceLocation OpLoc, // Only print a fixit for str + char, not for char + str. if (isa<CharacterLiteral>(RHSExpr->IgnoreImpCasts())) { - SourceLocation EndLoc = Self.getLocForEndOfToken(RHSExpr->getLocEnd()); + SourceLocation EndLoc = Self.getLocForEndOfToken(RHSExpr->getEndLoc()); Self.Diag(OpLoc, diag::note_string_plus_scalar_silence) - << FixItHint::CreateInsertion(LHSExpr->getLocStart(), "&") + << FixItHint::CreateInsertion(LHSExpr->getBeginLoc(), "&") << FixItHint::CreateReplacement(SourceRange(OpLoc), "[") << FixItHint::CreateInsertion(EndLoc, "]"); } else { @@ -9059,10 +9280,11 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS, if (PExp->IgnoreParenCasts()->isNullPointerConstant( Context, Expr::NPC_ValueDependentIsNotNull)) { // In C++ adding zero to a null pointer is defined. - llvm::APSInt KnownVal; + Expr::EvalResult KnownVal; if (!getLangOpts().CPlusPlus || (!IExp->isValueDependent() && - (!IExp->EvaluateAsInt(KnownVal, Context) || KnownVal != 0))) { + (!IExp->EvaluateAsInt(KnownVal, Context) || + KnownVal.Val.getInt() != 0))) { // Check the conditions to see if this is the 'p = nullptr + n' idiom. bool IsGNUIdiom = BinaryOperator::isNullPointerArithmeticExtension( Context, BO_Add, PExp, IExp); @@ -9137,10 +9359,11 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS, if (LHS.get()->IgnoreParenCasts()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) { // In C++ adding zero to a null pointer is defined. - llvm::APSInt KnownVal; + Expr::EvalResult KnownVal; if (!getLangOpts().CPlusPlus || (!RHS.get()->isValueDependent() && - (!RHS.get()->EvaluateAsInt(KnownVal, Context) || KnownVal != 0))) { + (!RHS.get()->EvaluateAsInt(KnownVal, Context) || + KnownVal.Val.getInt() != 0))) { diagnoseArithmeticOnNullPointer(*this, Loc, LHS.get(), false); } } @@ -9216,11 +9439,12 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS, if (S.getLangOpts().OpenCL) return; - llvm::APSInt Right; // Check right/shifter operand + Expr::EvalResult RHSResult; if (RHS.get()->isValueDependent() || - !RHS.get()->EvaluateAsInt(Right, S.Context)) + !RHS.get()->EvaluateAsInt(RHSResult, S.Context)) return; + llvm::APSInt Right = RHSResult.Val.getInt(); if (Right.isNegative()) { S.DiagRuntimeBehavior(Loc, RHS.get(), @@ -9243,11 +9467,12 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS, // according to C++ has undefined behavior ([expr.shift] 5.8/2). Unsigned // integers have defined behavior modulo one more than the maximum value // representable in the result type, so never warn for those. - llvm::APSInt Left; + Expr::EvalResult LHSResult; if (LHS.get()->isValueDependent() || LHSType->hasUnsignedIntegerRepresentation() || - !LHS.get()->EvaluateAsInt(Left, S.Context)) + !LHS.get()->EvaluateAsInt(LHSResult, S.Context)) return; + llvm::APSInt Left = LHSResult.Val.getInt(); // If LHS does not have a signed type and non-negative value // then, the behavior is undefined. Warn about it. @@ -9653,8 +9878,8 @@ static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc, if (BinaryOperator::isEqualityOp(Opc) && hasIsEqualMethod(S, LHS.get(), RHS.get())) { - SourceLocation Start = LHS.get()->getLocStart(); - SourceLocation End = S.getLocForEndOfToken(RHS.get()->getLocEnd()); + SourceLocation Start = LHS.get()->getBeginLoc(); + SourceLocation End = S.getLocForEndOfToken(RHS.get()->getEndLoc()); CharSourceRange OpRange = CharSourceRange::getCharRange(Loc, S.getLocForEndOfToken(Loc)); @@ -9686,8 +9911,8 @@ static void diagnoseLogicalNotOnLHSofCheck(Sema &S, ExprResult &LHS, << Loc << IsBitwiseOp; // First note suggest !(x < y) - SourceLocation FirstOpen = SubExpr->getLocStart(); - SourceLocation FirstClose = RHS.get()->getLocEnd(); + SourceLocation FirstOpen = SubExpr->getBeginLoc(); + SourceLocation FirstClose = RHS.get()->getEndLoc(); FirstClose = S.getLocForEndOfToken(FirstClose); if (FirstClose.isInvalid()) FirstOpen = SourceLocation(); @@ -9697,8 +9922,8 @@ static void diagnoseLogicalNotOnLHSofCheck(Sema &S, ExprResult &LHS, << FixItHint::CreateInsertion(FirstClose, ")"); // Second note suggests (!x) < y - SourceLocation SecondOpen = LHS.get()->getLocStart(); - SourceLocation SecondClose = LHS.get()->getLocEnd(); + SourceLocation SecondOpen = LHS.get()->getBeginLoc(); + SourceLocation SecondClose = LHS.get()->getEndLoc(); SecondClose = S.getLocForEndOfToken(SecondClose); if (SecondClose.isInvalid()) SecondOpen = SourceLocation(); @@ -9734,7 +9959,7 @@ static void diagnoseTautologicalComparison(Sema &S, SourceLocation Loc, QualType RHSType = RHS->getType(); if (LHSType->hasFloatingRepresentation() || (LHSType->isBlockPointerType() && !BinaryOperator::isEqualityOp(Opc)) || - LHS->getLocStart().isMacroID() || RHS->getLocStart().isMacroID() || + LHS->getBeginLoc().isMacroID() || RHS->getBeginLoc().isMacroID() || S.inTemplateInstantiation()) return; @@ -9888,7 +10113,7 @@ static bool checkThreeWayNarrowingConversion(Sema &S, QualType ToType, Expr *E, case NK_Constant_Narrowing: // Implicit conversion to a narrower type, and the value is not a constant // expression. - S.Diag(E->getLocStart(), diag::err_spaceship_argument_narrowing) + S.Diag(E->getBeginLoc(), diag::err_spaceship_argument_narrowing) << /*Constant*/ 1 << PreNarrowingValue.getAsString(S.Context, PreNarrowingType) << ToType; return true; @@ -9897,7 +10122,7 @@ static bool checkThreeWayNarrowingConversion(Sema &S, QualType ToType, Expr *E, // Implicit conversion to a narrower type, and the value is not a constant // expression. case NK_Type_Narrowing: - S.Diag(E->getLocStart(), diag::err_spaceship_argument_narrowing) + S.Diag(E->getBeginLoc(), diag::err_spaceship_argument_narrowing) << /*Constant*/ 0 << FromType << ToType; // TODO: It's not a constant expression, but what if the user intended it // to be? Can we produce notes to help them figure out why it isn't? @@ -9972,9 +10197,9 @@ static QualType checkArithmeticOrEnumeralThreeWayCompare(Sema &S, assert(Type->isArithmeticType() || Type->isEnumeralType()); bool HasNarrowing = checkThreeWayNarrowingConversion( - S, Type, LHS.get(), LHSType, LHS.get()->getLocStart()); - HasNarrowing |= checkThreeWayNarrowingConversion( - S, Type, RHS.get(), RHSType, RHS.get()->getLocStart()); + S, Type, LHS.get(), LHSType, LHS.get()->getBeginLoc()); + HasNarrowing |= checkThreeWayNarrowingConversion(S, Type, RHS.get(), RHSType, + RHS.get()->getBeginLoc()); if (HasNarrowing) return QualType(); @@ -10439,6 +10664,14 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, } if (getLangOpts().OpenCLVersion >= 200) { + if (LHSType->isClkEventT() && RHSType->isClkEventT()) { + return computeResultTy(); + } + + if (LHSType->isQueueT() && RHSType->isQueueT()) { + return computeResultTy(); + } + if (LHSIsNull && RHSType->isQueueT()) { LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer); return computeResultTy(); @@ -10609,8 +10842,9 @@ inline QualType Sema::CheckLogicalOperands(ExprResult &LHS, ExprResult &RHS, // that isn't 0 or 1 (which indicate a potential logical operation that // happened to fold to true/false) then warn. // Parens on the RHS are ignored. - llvm::APSInt Result; - if (RHS.get()->EvaluateAsInt(Result, Context)) + Expr::EvalResult EVResult; + if (RHS.get()->EvaluateAsInt(EVResult, Context)) { + llvm::APSInt Result = EVResult.Val.getInt(); if ((getLangOpts().Bool && !RHS.get()->getType()->isBooleanType() && !RHS.get()->getExprLoc().isMacroID()) || (Result != 0 && Result != 1)) { @@ -10627,9 +10861,10 @@ inline QualType Sema::CheckLogicalOperands(ExprResult &LHS, ExprResult &RHS, // Suggest replacing "Foo() && kNonZero" with "Foo()" Diag(Loc, diag::note_logical_instead_of_bitwise_remove_constant) << FixItHint::CreateRemoval( - SourceRange(getLocForEndOfToken(LHS.get()->getLocEnd()), - RHS.get()->getLocEnd())); + SourceRange(getLocForEndOfToken(LHS.get()->getEndLoc()), + RHS.get()->getEndLoc())); } + } } if (!Context.getLangOpts().CPlusPlus) { @@ -10880,30 +11115,38 @@ static void DiagnoseRecursiveConstFields(Sema &S, const ValueDecl *VD, const RecordType *Ty, SourceLocation Loc, SourceRange Range, OriginalExprKind OEK, - bool &DiagnosticEmitted, - bool IsNested = false) { + bool &DiagnosticEmitted) { + std::vector<const RecordType *> RecordTypeList; + RecordTypeList.push_back(Ty); + unsigned NextToCheckIndex = 0; // We walk the record hierarchy breadth-first to ensure that we print // diagnostics in field nesting order. - // First, check every field for constness. - for (const FieldDecl *Field : Ty->getDecl()->fields()) { - if (Field->getType().isConstQualified()) { - if (!DiagnosticEmitted) { - S.Diag(Loc, diag::err_typecheck_assign_const) - << Range << NestedConstMember << OEK << VD - << IsNested << Field; - DiagnosticEmitted = true; + while (RecordTypeList.size() > NextToCheckIndex) { + bool IsNested = NextToCheckIndex > 0; + for (const FieldDecl *Field : + RecordTypeList[NextToCheckIndex]->getDecl()->fields()) { + // First, check every field for constness. + QualType FieldTy = Field->getType(); + if (FieldTy.isConstQualified()) { + if (!DiagnosticEmitted) { + S.Diag(Loc, diag::err_typecheck_assign_const) + << Range << NestedConstMember << OEK << VD + << IsNested << Field; + DiagnosticEmitted = true; + } + S.Diag(Field->getLocation(), diag::note_typecheck_assign_const) + << NestedConstMember << IsNested << Field + << FieldTy << Field->getSourceRange(); + } + + // Then we append it to the list to check next in order. + FieldTy = FieldTy.getCanonicalType(); + if (const auto *FieldRecTy = FieldTy->getAs<RecordType>()) { + if (llvm::find(RecordTypeList, FieldRecTy) == RecordTypeList.end()) + RecordTypeList.push_back(FieldRecTy); } - S.Diag(Field->getLocation(), diag::note_typecheck_assign_const) - << NestedConstMember << IsNested << Field - << Field->getType() << Field->getSourceRange(); } - } - // Then, recurse. - for (const FieldDecl *Field : Ty->getDecl()->fields()) { - QualType FTy = Field->getType(); - if (const RecordType *FieldRecTy = FTy->getAs<RecordType>()) - DiagnoseRecursiveConstFields(S, VD, FieldRecTy, Loc, Range, - OEK, DiagnosticEmitted, true); + ++NextToCheckIndex; } } @@ -10971,17 +11214,23 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { if (var->isARCPseudoStrong() && (!var->getTypeSourceInfo() || !var->getTypeSourceInfo()->getType().isConstQualified())) { - // There are two pseudo-strong cases: + // There are three pseudo-strong cases: // - self ObjCMethodDecl *method = S.getCurMethodDecl(); - if (method && var == method->getSelfDecl()) + if (method && var == method->getSelfDecl()) { DiagID = method->isClassMethod() ? diag::err_typecheck_arc_assign_self_class_method : diag::err_typecheck_arc_assign_self; + // - Objective-C externally_retained attribute. + } else if (var->hasAttr<ObjCExternallyRetainedAttr>() || + isa<ParmVarDecl>(var)) { + DiagID = diag::err_typecheck_arc_assign_externally_retained; + // - fast enumeration variables - else + } else { DiagID = diag::err_typecheck_arr_assign_enumeration; + } SourceRange Assign; if (Loc != OrigLoc) @@ -11150,15 +11399,14 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(RHSCheck)) RHSCheck = ICE->getSubExpr(); if (UnaryOperator *UO = dyn_cast<UnaryOperator>(RHSCheck)) { - if ((UO->getOpcode() == UO_Plus || - UO->getOpcode() == UO_Minus) && + if ((UO->getOpcode() == UO_Plus || UO->getOpcode() == UO_Minus) && Loc.isFileID() && UO->getOperatorLoc().isFileID() && // Only if the two operators are exactly adjacent. Loc.getLocWithOffset(1) == UO->getOperatorLoc() && // And there is a space or other character before the subexpr of the // unary +/-. We don't want to warn on "x=-1". - Loc.getLocWithOffset(2) != UO->getSubExpr()->getLocStart() && - UO->getSubExpr()->getLocStart().isFileID()) { + Loc.getLocWithOffset(2) != UO->getSubExpr()->getBeginLoc() && + UO->getSubExpr()->getBeginLoc().isFileID()) { Diag(Loc, diag::warn_not_compound_assign) << (UO->getOpcode() == UO_Plus ? "+" : "-") << SourceRange(UO->getOperatorLoc(), UO->getOperatorLoc()); @@ -11188,7 +11436,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, // For ObjCWeak only, we do not warn if the assign is to a non-weak // variable, which will be valid for the current autorelease scope. if (!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, - RHS.get()->getLocStart())) + RHS.get()->getBeginLoc())) getCurFunction()->markSafeWeakUse(RHS.get()); } else if (getLangOpts().ObjCAutoRefCount || getLangOpts().ObjCWeak) { @@ -11225,6 +11473,12 @@ static bool IgnoreCommaOperand(const Expr *E) { if (CE->getCastKind() == CK_ToVoid) { return true; } + + // static_cast<void> on a dependent type will not show up as CK_ToVoid. + if (CE->getCastKind() == CK_Dependent && E->getType()->isVoidType() && + CE->getSubExpr()->getType()->isDependentType()) { + return true; + } } return false; @@ -11248,8 +11502,11 @@ void Sema::DiagnoseCommaOperator(const Expr *LHS, SourceLocation Loc) { // The whitelisted locations are the initialization and increment portions // of a for loop. The additional checks are on the condition of // if statements, do/while loops, and for loops. + // Differences in scope flags for C89 mode requires the extra logic. const unsigned ForIncrementFlags = - Scope::ControlScope | Scope::ContinueScope | Scope::BreakScope; + getLangOpts().C99 || getLangOpts().CPlusPlus + ? Scope::ControlScope | Scope::ContinueScope | Scope::BreakScope + : Scope::ContinueScope | Scope::BreakScope; const unsigned ForInitFlags = Scope::ControlScope | Scope::DeclScope; const unsigned ScopeFlags = getCurScope()->getFlags(); if ((ScopeFlags & ForIncrementFlags) == ForIncrementFlags || @@ -11269,12 +11526,12 @@ void Sema::DiagnoseCommaOperator(const Expr *LHS, SourceLocation Loc) { return; Diag(Loc, diag::warn_comma_operator); - Diag(LHS->getLocStart(), diag::note_cast_to_void) + Diag(LHS->getBeginLoc(), diag::note_cast_to_void) << LHS->getSourceRange() - << FixItHint::CreateInsertion(LHS->getLocStart(), + << FixItHint::CreateInsertion(LHS->getBeginLoc(), LangOpts.CPlusPlus ? "static_cast<void>(" : "(void)(") - << FixItHint::CreateInsertion(PP.getLocForEndOfToken(LHS->getLocEnd()), + << FixItHint::CreateInsertion(PP.getLocForEndOfToken(LHS->getEndLoc()), ")"); } @@ -11551,7 +11808,7 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { if (auto *FD = dyn_cast_or_null<FunctionDecl>(dcl)) if (!checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true, - op->getLocStart())) + op->getBeginLoc())) return QualType(); Expr::LValueClassification lval = op->ClassifyLValue(Context); @@ -11877,7 +12134,7 @@ static void DiagnoseSelfAssignment(Sema &S, Expr *LHSExpr, Expr *RHSExpr, /// is usually indicative of introspection within the Objective-C pointer. static void checkObjCPointerIntrospection(Sema &S, ExprResult &L, ExprResult &R, SourceLocation OpLoc) { - if (!S.getLangOpts().ObjC1) + if (!S.getLangOpts().ObjC) return; const Expr *ObjCPointerExpr = nullptr, *OtherExpr = nullptr; @@ -12006,7 +12263,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, // The meaning of x = {v} [...] is that of x = T(v) [...]. The meaning // of x = {} is x = T(). InitializationKind Kind = InitializationKind::CreateDirectList( - RHSExpr->getLocStart(), RHSExpr->getLocStart(), RHSExpr->getLocEnd()); + RHSExpr->getBeginLoc(), RHSExpr->getBeginLoc(), RHSExpr->getEndLoc()); InitializedEntity Entity = InitializedEntity::InitializeTemporary(LHSExpr->getType()); InitializationSequence InitSeq(*this, Entity, Kind, RHSExpr); @@ -12035,7 +12292,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, // OpenCLC v2.0 s6.13.11.1 allows atomic variables to be initialized by // the ATOMIC_VAR_INIT macro. if (LHSTy->isAtomicType() || RHSTy->isAtomicType()) { - SourceRange SR(LHSExpr->getLocStart(), RHSExpr->getLocEnd()); + SourceRange SR(LHSExpr->getBeginLoc(), RHSExpr->getEndLoc()); if (BO_Assign == Opc) Diag(OpLoc, diag::err_opencl_atomic_init) << 0 << SR; else @@ -12197,11 +12454,13 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, &Context.Idents.get("object_setClass"), SourceLocation(), LookupOrdinaryName); if (ObjectSetClass && isa<ObjCIsaExpr>(LHS.get())) { - SourceLocation RHSLocEnd = getLocForEndOfToken(RHS.get()->getLocEnd()); - Diag(LHS.get()->getExprLoc(), diag::warn_objc_isa_assign) << - FixItHint::CreateInsertion(LHS.get()->getLocStart(), "object_setClass(") << - FixItHint::CreateReplacement(SourceRange(OISA->getOpLoc(), OpLoc), ",") << - FixItHint::CreateInsertion(RHSLocEnd, ")"); + SourceLocation RHSLocEnd = getLocForEndOfToken(RHS.get()->getEndLoc()); + Diag(LHS.get()->getExprLoc(), diag::warn_objc_isa_assign) + << FixItHint::CreateInsertion(LHS.get()->getBeginLoc(), + "object_setClass(") + << FixItHint::CreateReplacement(SourceRange(OISA->getOpLoc(), OpLoc), + ",") + << FixItHint::CreateInsertion(RHSLocEnd, ")"); } else Diag(LHS.get()->getExprLoc(), diag::warn_objc_isa_assign); @@ -12258,13 +12517,14 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc, if (isLeftBitwise || isRightBitwise) return; - SourceRange DiagRange = isLeftComp ? SourceRange(LHSExpr->getLocStart(), - OpLoc) - : SourceRange(OpLoc, RHSExpr->getLocEnd()); + SourceRange DiagRange = isLeftComp + ? SourceRange(LHSExpr->getBeginLoc(), OpLoc) + : SourceRange(OpLoc, RHSExpr->getEndLoc()); StringRef OpStr = isLeftComp ? LHSBO->getOpcodeStr() : RHSBO->getOpcodeStr(); - SourceRange ParensRange = isLeftComp ? - SourceRange(LHSBO->getRHS()->getLocStart(), RHSExpr->getLocEnd()) - : SourceRange(LHSExpr->getLocStart(), RHSBO->getLHS()->getLocEnd()); + SourceRange ParensRange = + isLeftComp + ? SourceRange(LHSBO->getRHS()->getBeginLoc(), RHSExpr->getEndLoc()) + : SourceRange(LHSExpr->getBeginLoc(), RHSBO->getLHS()->getEndLoc()); Self.Diag(OpLoc, diag::warn_precedence_bitwise_rel) << DiagRange << BinaryOperator::getOpcodeStr(Opc) << OpStr; @@ -12398,10 +12658,9 @@ static void DiagnoseShiftCompare(Sema &S, SourceLocation OpLoc, S.PDiag(diag::note_precedence_silence) << (Kind == OO_LessLess ? "<<" : ">>"), OCE->getSourceRange()); - SuggestParentheses(S, OpLoc, - S.PDiag(diag::note_evaluate_comparison_first), - SourceRange(OCE->getArg(1)->getLocStart(), - RHSExpr->getLocEnd())); + SuggestParentheses( + S, OpLoc, S.PDiag(diag::note_evaluate_comparison_first), + SourceRange(OCE->getArg(1)->getBeginLoc(), RHSExpr->getEndLoc())); } /// DiagnoseBinOpPrecedence - Emit warnings for expressions with tricky @@ -12643,6 +12902,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, break; case UO_AddrOf: resultType = CheckAddressOfOperand(Input, OpLoc); + CheckAddressOfNoDeref(InputExpr); RecordModifiableNonNullParam(*this, InputExpr); break; case UO_Deref: { @@ -12807,6 +13067,11 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, auto *UO = new (Context) UnaryOperator(Input.get(), Opc, resultType, VK, OK, OpLoc, CanOverflow); + + if (Opc == UO_Deref && UO->getType()->hasAttr(attr::NoDeref) && + !isa<ArrayType>(UO->getType().getDesugaredType(Context))) + ExprEvalContexts.back().PossibleDerefs.insert(UO); + // Convert the result back to a half vector. if (ConvertHalfVec) return convertVector(UO, Context.HalfTy, *this); @@ -13071,9 +13336,9 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, // FIXME: An integral constant expression? if (!Idx->isTypeDependent() && !Idx->isValueDependent() && !Idx->getType()->isIntegerType()) - return ExprError(Diag(Idx->getLocStart(), - diag::err_typecheck_subscript_not_integer) - << Idx->getSourceRange()); + return ExprError( + Diag(Idx->getBeginLoc(), diag::err_typecheck_subscript_not_integer) + << Idx->getSourceRange()); // Record this array index. Comps.push_back(OffsetOfNode(OC.LocStart, Exprs.size(), OC.LocEnd)); @@ -13294,7 +13559,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo, // Drop the parameters. FunctionProtoType::ExtProtoInfo EPI; EPI.HasTrailingReturn = false; - EPI.TypeQuals |= DeclSpec::TQ_const; + EPI.TypeQuals.addConst(); T = Context.getFunctionType(Context.DependentTy, None, EPI); Sig = Context.getTrivialTypeSourceInfo(T); } @@ -13365,7 +13630,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo, } else if (const FunctionProtoType *Fn = T->getAs<FunctionProtoType>()) { for (const auto &I : Fn->param_types()) { ParmVarDecl *Param = BuildParmVarDeclForTypedef( - CurBlock->TheDecl, ParamInfo.getLocStart(), I); + CurBlock->TheDecl, ParamInfo.getBeginLoc(), I); Params.push_back(Param); } } @@ -13421,6 +13686,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, PopExpressionEvaluationContext(); BlockScopeInfo *BSI = cast<BlockScopeInfo>(FunctionScopes.back()); + BlockDecl *BD = BSI->TheDecl; if (BSI->HasImplicitReturnType) deduceClosureReturnType(*BSI); @@ -13431,7 +13697,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, if (!BSI->ReturnType.isNull()) RetTy = BSI->ReturnType; - bool NoReturn = BSI->TheDecl->hasAttr<NoReturnAttr>(); + bool NoReturn = BD->hasAttr<NoReturnAttr>(); QualType BlockTy; // Set the captured variables on the block. @@ -13444,7 +13710,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, Cap.isNested(), Cap.getInitExpr()); Captures.push_back(NewCap); } - BSI->TheDecl->setCaptures(Context, Captures, BSI->CXXThisCaptureIndex != 0); + BD->setCaptures(Context, Captures, BSI->CXXThisCaptureIndex != 0); // If the user wrote a function type in some form, try to use that. if (!BSI->FunctionType.isNull()) { @@ -13469,7 +13735,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, } else { const FunctionProtoType *FPT = cast<FunctionProtoType>(FTy); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); - EPI.TypeQuals = 0; // FIXME: silently? + EPI.TypeQuals = Qualifiers(); EPI.ExtInfo = Ext; BlockTy = Context.getFunctionType(RetTy, FPT->getParamTypes(), EPI); } @@ -13481,7 +13747,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, BlockTy = Context.getFunctionType(RetTy, None, EPI); } - DiagnoseUnusedParameters(BSI->TheDecl->parameters()); + DiagnoseUnusedParameters(BD->parameters()); BlockTy = Context.getBlockPointerType(BlockTy); // If needed, diagnose invalid gotos and switches in the block. @@ -13489,19 +13755,19 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, !PP.isCodeCompletionEnabled()) DiagnoseInvalidJumps(cast<CompoundStmt>(Body)); - BSI->TheDecl->setBody(cast<CompoundStmt>(Body)); + BD->setBody(cast<CompoundStmt>(Body)); if (Body && getCurFunction()->HasPotentialAvailabilityViolations) - DiagnoseUnguardedAvailabilityViolations(BSI->TheDecl); + DiagnoseUnguardedAvailabilityViolations(BD); // Try to apply the named return value optimization. We have to check again // if we can do this, though, because blocks keep return statements around // to deduce an implicit return type. if (getLangOpts().CPlusPlus && RetTy->isRecordType() && - !BSI->TheDecl->isDependentContext()) + !BD->isDependentContext()) computeNRVO(Body, BSI); - BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy); + BlockExpr *Result = new (Context) BlockExpr(BD, BlockTy); AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy(); PopFunctionScopeInfo(&WP, Result->getBlockDecl(), Result); @@ -13523,6 +13789,9 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, } } + if (getCurFunction()) + getCurFunction()->addBlock(BD); + return Result; } @@ -13544,7 +13813,7 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, if (const FunctionDecl *F = dyn_cast<FunctionDecl>(CurContext)) { CUDAFunctionTarget T = IdentifyCUDATarget(F); if (T == CFT_Global || T == CFT_Device || T == CFT_HostDevice) - return ExprError(Diag(E->getLocStart(), diag::err_va_arg_in_device)); + return ExprError(Diag(E->getBeginLoc(), diag::err_va_arg_in_device)); } } @@ -13594,9 +13863,10 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, if (!IsMS && !E->isTypeDependent() && !Context.hasSameType(VaListType, E->getType())) - return ExprError(Diag(E->getLocStart(), - diag::err_first_argument_to_va_arg_not_of_type_va_list) - << OrigExpr->getType() << E->getSourceRange()); + return ExprError( + Diag(E->getBeginLoc(), + diag::err_first_argument_to_va_arg_not_of_type_va_list) + << OrigExpr->getType() << E->getSourceRange()); if (!TInfo->getType()->isDependentType()) { if (RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), TInfo->getType(), @@ -13661,7 +13931,7 @@ ExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) { bool Sema::ConversionToObjCStringLiteralCheck(QualType DstType, Expr *&Exp, bool Diagnose) { - if (!getLangOpts().ObjC1) + if (!getLangOpts().ObjC) return false; const ObjCObjectPointerType *PT = DstType->getAs<ObjCObjectPointerType>(); @@ -13687,9 +13957,9 @@ bool Sema::ConversionToObjCStringLiteralCheck(QualType DstType, Expr *&Exp, if (!SL || !SL->isAscii()) return false; if (Diagnose) { - Diag(SL->getLocStart(), diag::err_missing_atsign_prefix) - << FixItHint::CreateInsertion(SL->getLocStart(), "@"); - Exp = BuildObjCStringLiteral(SL->getLocStart(), SL).get(); + Diag(SL->getBeginLoc(), diag::err_missing_atsign_prefix) + << FixItHint::CreateInsertion(SL->getBeginLoc(), "@"); + Exp = BuildObjCStringLiteral(SL->getBeginLoc(), SL).get(); } return true; } @@ -13710,7 +13980,7 @@ static bool maybeDiagnoseAssignmentToFunction(Sema &S, QualType DstType, return !S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true, - SrcExpr->getLocStart()); + SrcExpr->getBeginLoc()); } bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, @@ -13963,7 +14233,7 @@ ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, VerifyICEDiagnoser &Diagnoser, bool AllowFold) { - SourceLocation DiagLoc = E->getLocStart(); + SourceLocation DiagLoc = E->getBeginLoc(); if (getLangOpts().CPlusPlus11) { // C++11 [expr.const]p5: @@ -14030,11 +14300,14 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, return ExprError(); } + if (!isa<ConstantExpr>(E)) + E = ConstantExpr::Create(Context, E); + // Circumvent ICE checking in C++11 to avoid evaluating the expression twice // in the non-ICE case. if (!getLangOpts().CPlusPlus11 && E->isIntegerConstantExpr(Context)) { if (Result) - *Result = E->EvaluateKnownConstInt(Context); + *Result = E->EvaluateKnownConstIntCheckOverflow(Context); return E; } @@ -14165,6 +14438,51 @@ Sema::PushExpressionEvaluationContext( PushExpressionEvaluationContext(NewContext, ClosureContextDecl, ExprContext); } +namespace { + +const DeclRefExpr *CheckPossibleDeref(Sema &S, const Expr *PossibleDeref) { + PossibleDeref = PossibleDeref->IgnoreParenImpCasts(); + if (const auto *E = dyn_cast<UnaryOperator>(PossibleDeref)) { + if (E->getOpcode() == UO_Deref) + return CheckPossibleDeref(S, E->getSubExpr()); + } else if (const auto *E = dyn_cast<ArraySubscriptExpr>(PossibleDeref)) { + return CheckPossibleDeref(S, E->getBase()); + } else if (const auto *E = dyn_cast<MemberExpr>(PossibleDeref)) { + return CheckPossibleDeref(S, E->getBase()); + } else if (const auto E = dyn_cast<DeclRefExpr>(PossibleDeref)) { + QualType Inner; + QualType Ty = E->getType(); + if (const auto *Ptr = Ty->getAs<PointerType>()) + Inner = Ptr->getPointeeType(); + else if (const auto *Arr = S.Context.getAsArrayType(Ty)) + Inner = Arr->getElementType(); + else + return nullptr; + + if (Inner->hasAttr(attr::NoDeref)) + return E; + } + return nullptr; +} + +} // namespace + +void Sema::WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec) { + for (const Expr *E : Rec.PossibleDerefs) { + const DeclRefExpr *DeclRef = CheckPossibleDeref(*this, E); + if (DeclRef) { + const ValueDecl *Decl = DeclRef->getDecl(); + Diag(E->getExprLoc(), diag::warn_dereference_of_noderef_type) + << Decl->getName() << E->getSourceRange(); + Diag(Decl->getLocation(), diag::note_previous_decl) << Decl->getName(); + } else { + Diag(E->getExprLoc(), diag::warn_dereference_of_noderef_type_no_decl) + << E->getSourceRange(); + } + } + Rec.PossibleDerefs.clear(); +} + void Sema::PopExpressionEvaluationContext() { ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back(); unsigned NumTypos = Rec.NumTypos; @@ -14193,7 +14511,7 @@ void Sema::PopExpressionEvaluationContext() { llvm_unreachable("Couldn't infer lambda error message."); for (const auto *L : Rec.Lambdas) - Diag(L->getLocStart(), D); + Diag(L->getBeginLoc(), D); } else { // Mark the capture expressions odr-used. This was deferred // during lambda expression creation. @@ -14204,6 +14522,8 @@ void Sema::PopExpressionEvaluationContext() { } } + WarnOnPendingNoDerefs(Rec); + // When are coming out of an unevaluated context, clear out any // temporaries that we may have created as part of the evaluation of // the expression in that context: they aren't relevant because they @@ -14224,11 +14544,8 @@ void Sema::PopExpressionEvaluationContext() { // Pop the current expression evaluation context off the stack. ExprEvalContexts.pop_back(); - if (!ExprEvalContexts.empty()) - ExprEvalContexts.back().NumTypos += NumTypos; - else - assert(NumTypos == 0 && "There are outstanding typos after popping the " - "last ExpressionEvaluationContextRecord"); + // The global expression evaluation context record is never popped. + ExprEvalContexts.back().NumTypos += NumTypos; } void Sema::DiscardCleanupsInEvaluationContext() { @@ -14240,6 +14557,10 @@ void Sema::DiscardCleanupsInEvaluationContext() { } ExprResult Sema::HandleExprEvaluationContextForTypeof(Expr *E) { + ExprResult Result = CheckPlaceholderExpr(E); + if (Result.isInvalid()) + return ExprError(); + E = Result.get(); if (!E->getType()->isVariablyModifiedType()) return E; return TransformToPotentiallyEvaluated(E); @@ -14641,8 +14962,10 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var, Expr *CopyExpr = nullptr; bool ByRef = false; - // Blocks are not allowed to capture arrays. - if (CaptureType->isArrayType()) { + // Blocks are not allowed to capture arrays, excepting OpenCL. + // OpenCL v2.0 s1.12.5 (revision 40): arrays are captured by reference + // (decayed to pointers). + if (!S.getLangOpts().OpenCL && CaptureType->isArrayType()) { if (BuildAndDiagnose) { S.Diag(Loc, diag::err_ref_array_type); S.Diag(Var->getLocation(), diag::note_previous_decl) @@ -14665,15 +14988,15 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var, // Warn about implicitly autoreleasing indirect parameters captured by blocks. if (const auto *PT = CaptureType->getAs<PointerType>()) { // This function finds out whether there is an AttributedType of kind - // attr_objc_ownership in Ty. The existence of AttributedType of kind - // attr_objc_ownership implies __autoreleasing was explicitly specified + // attr::ObjCOwnership in Ty. The existence of AttributedType of kind + // attr::ObjCOwnership implies __autoreleasing was explicitly specified // rather than being added implicitly by the compiler. auto IsObjCOwnershipAttributedType = [](QualType Ty) { while (const auto *AttrTy = Ty->getAs<AttributedType>()) { - if (AttrTy->getAttrKind() == AttributedType::attr_objc_ownership) + if (AttrTy->getAttrKind() == attr::ObjCOwnership) return true; - // Peel off AttributedTypes that are not of kind objc_ownership. + // Peel off AttributedTypes that are not of kind ObjCOwnership. Ty = AttrTy->getModifiedType(); } @@ -14722,9 +15045,8 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var, // According to the blocks spec, the capture of a variable from // the stack requires a const copy constructor. This is not true // of the copy/move done to move a __block variable to the heap. - Expr *DeclRef = new (S.Context) DeclRefExpr(Var, Nested, - DeclRefType.withConst(), - VK_LValue, Loc); + Expr *DeclRef = new (S.Context) DeclRefExpr( + S.Context, Var, Nested, DeclRefType.withConst(), VK_LValue, Loc); ExprResult Result = S.PerformCopyInitialization( @@ -14800,8 +15122,8 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI, if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP) S.setOpenMPCaptureKind(Field, Var, RSI->OpenMPLevel); - CopyExpr = new (S.Context) DeclRefExpr(Var, RefersToCapturedVariable, - DeclRefType, VK_LValue, Loc); + CopyExpr = new (S.Context) DeclRefExpr( + S.Context, Var, RefersToCapturedVariable, DeclRefType, VK_LValue, Loc); Var->setReferenced(true); Var->markUsed(S.Context); } @@ -14828,6 +15150,21 @@ static void addAsFieldToClosureType(Sema &S, LambdaScopeInfo *LSI, = FieldDecl::Create(S.Context, Lambda, Loc, Loc, nullptr, FieldType, S.Context.getTrivialTypeSourceInfo(FieldType, Loc), nullptr, false, ICIS_NoInit); + // If the variable being captured has an invalid type, mark the lambda class + // as invalid as well. + if (!FieldType->isDependentType()) { + if (S.RequireCompleteType(Loc, FieldType, diag::err_field_incomplete)) { + Lambda->setInvalidDecl(); + Field->setInvalidDecl(); + } else { + NamedDecl *Def; + FieldType->isIncompleteType(&Def); + if (Def && Def->isInvalidDecl()) { + Lambda->setInvalidDecl(); + Field->setInvalidDecl(); + } + } + } Field->setImplicit(true); Field->setAccess(AS_private); Lambda->addDecl(Field); @@ -15023,7 +15360,7 @@ bool Sema::tryCaptureVariable( Diag(ExprLoc, diag::err_lambda_impcap) << Var->getDeclName(); Diag(Var->getLocation(), diag::note_previous_decl) << Var->getDeclName(); - Diag(LSI->Lambda->getLocStart(), diag::note_lambda_decl); + Diag(LSI->Lambda->getBeginLoc(), diag::note_lambda_decl); } else diagnoseUncapturableValueReference(*this, ExprLoc, Var, DC); } @@ -15077,7 +15414,7 @@ bool Sema::tryCaptureVariable( Diag(Var->getLocation(), diag::note_previous_decl) << Var->getDeclName(); if (cast<LambdaScopeInfo>(CSI)->Lambda) - Diag(cast<LambdaScopeInfo>(CSI)->Lambda->getLocStart(), + Diag(cast<LambdaScopeInfo>(CSI)->Lambda->getBeginLoc(), diag::note_lambda_decl); // FIXME: If we error out because an outer lambda can not implicitly // capture a variable that an inner lambda explicitly captures, we @@ -15435,8 +15772,8 @@ void Sema::MarkMemberReferenced(MemberExpr *E) { if (Method->isPure()) MightBeOdrUse = false; } - SourceLocation Loc = E->getMemberLoc().isValid() ? - E->getMemberLoc() : E->getLocStart(); + SourceLocation Loc = + E->getMemberLoc().isValid() ? E->getMemberLoc() : E->getBeginLoc(); MarkExprReferenced(*this, Loc, E->getMemberDecl(), E, MightBeOdrUse); } @@ -15532,34 +15869,34 @@ namespace { } void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { - S.MarkFunctionReferenced(E->getLocStart(), - const_cast<CXXDestructorDecl*>(E->getTemporary()->getDestructor())); + S.MarkFunctionReferenced( + E->getBeginLoc(), + const_cast<CXXDestructorDecl *>(E->getTemporary()->getDestructor())); Visit(E->getSubExpr()); } void VisitCXXNewExpr(CXXNewExpr *E) { if (E->getOperatorNew()) - S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorNew()); + S.MarkFunctionReferenced(E->getBeginLoc(), E->getOperatorNew()); if (E->getOperatorDelete()) - S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorDelete()); + S.MarkFunctionReferenced(E->getBeginLoc(), E->getOperatorDelete()); Inherited::VisitCXXNewExpr(E); } void VisitCXXDeleteExpr(CXXDeleteExpr *E) { if (E->getOperatorDelete()) - S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorDelete()); + S.MarkFunctionReferenced(E->getBeginLoc(), E->getOperatorDelete()); QualType Destroyed = S.Context.getBaseElementType(E->getDestroyedType()); if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) { CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl()); - S.MarkFunctionReferenced(E->getLocStart(), - S.LookupDestructor(Record)); + S.MarkFunctionReferenced(E->getBeginLoc(), S.LookupDestructor(Record)); } Inherited::VisitCXXDeleteExpr(E); } void VisitCXXConstructExpr(CXXConstructExpr *E) { - S.MarkFunctionReferenced(E->getLocStart(), E->getConstructor()); + S.MarkFunctionReferenced(E->getBeginLoc(), E->getConstructor()); Inherited::VisitCXXConstructExpr(E); } @@ -15730,7 +16067,7 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) { Diag(Loc, diagnostic) << E->getSourceRange(); - SourceLocation Open = E->getLocStart(); + SourceLocation Open = E->getBeginLoc(); SourceLocation Close = getLocForEndOfToken(E->getSourceRange().getEnd()); Diag(Loc, diag::note_condition_assign_silence) << FixItHint::CreateInsertion(Open, "(") @@ -15748,7 +16085,7 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) { /// that the user intended an assignment used as condition. void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *ParenE) { // Don't warn if the parens came from a macro. - SourceLocation parenLoc = ParenE->getLocStart(); + SourceLocation parenLoc = ParenE->getBeginLoc(); if (parenLoc.isInvalid() || parenLoc.isMacroID()) return; // Don't warn for dependent expressions. @@ -16211,7 +16548,7 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) { DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E); if (DRE && Proto && Proto->getParamTypes().empty() && Proto->isVariadic()) { SourceLocation Loc = FD->getLocation(); - FunctionDecl *NewFD = FunctionDecl::Create(FD->getASTContext(), + FunctionDecl *NewFD = FunctionDecl::Create(S.Context, FD->getDeclContext(), Loc, Loc, FD->getNameInfo().getName(), DestType, FD->getTypeSourceInfo(), @@ -16439,25 +16776,29 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { auto *FD = cast<FunctionDecl>(DRE->getDecl()); if (FD->getBuiltinID() == Builtin::BI__noop) { E = ImpCastExprToType(E, Context.getPointerType(FD->getType()), - CK_BuiltinFnToFnPtr).get(); - return new (Context) CallExpr(Context, E, None, Context.IntTy, - VK_RValue, SourceLocation()); + CK_BuiltinFnToFnPtr) + .get(); + return CallExpr::Create(Context, E, /*Args=*/{}, Context.IntTy, + VK_RValue, SourceLocation()); } } - Diag(E->getLocStart(), diag::err_builtin_fn_use); + Diag(E->getBeginLoc(), diag::err_builtin_fn_use); return ExprError(); } // Expressions of unknown type. case BuiltinType::OMPArraySection: - Diag(E->getLocStart(), diag::err_omp_array_section_use); + Diag(E->getBeginLoc(), diag::err_omp_array_section_use); return ExprError(); // Everything else should be impossible. #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ case BuiltinType::Id: #include "clang/Basic/OpenCLImageTypes.def" +#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ + case BuiltinType::Id: +#include "clang/Basic/OpenCLExtensionTypes.def" #define BUILTIN_TYPE(Id, SingletonId) case BuiltinType::Id: #define PLACEHOLDER_TYPE(Id, SingletonId) #include "clang/AST/BuiltinTypes.def" diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index a1168fa34d56b..8c89a3cee3dbb 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -113,9 +113,15 @@ ParsedType Sema::getConstructorName(IdentifierInfo &II, break; } } - if (!InjectedClassName && CurClass->isInvalidDecl()) + if (!InjectedClassName) { + if (!CurClass->isInvalidDecl()) { + // FIXME: RequireCompleteDeclContext doesn't check dependent contexts + // properly. Work around it here for now. + Diag(SS.getLastQualifierNameLoc(), + diag::err_incomplete_nested_name_spec) << CurClass << SS.getRange(); + } return ParsedType(); - assert(InjectedClassName && "couldn't find injected class name"); + } QualType T = Context.getTypeDeclType(InjectedClassName); DiagnoseUseOfDecl(InjectedClassName, NameLoc); @@ -413,8 +419,8 @@ bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS, // namespace scope. Therefore, this unqualified-id cannot name anything. // Reject it early, because we have no AST representation for this in the // case where the scope is dependent. - Diag(Name.getLocStart(), diag::err_literal_operator_id_outside_namespace) - << SS.getScopeRep(); + Diag(Name.getBeginLoc(), diag::err_literal_operator_id_outside_namespace) + << SS.getScopeRep(); return true; case NestedNameSpecifier::Global: @@ -1058,7 +1064,7 @@ QualType Sema::getCurrentThisType() { if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC)) { if (method && method->isInstance()) - ThisTy = method->getThisType(Context); + ThisTy = method->getThisType(); } if (ThisTy.isNull() && isLambdaCallOperator(CurContext) && @@ -1088,7 +1094,7 @@ QualType Sema::getCurrentThisType() { Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S, Decl *ContextDecl, - unsigned CXXThisTypeQuals, + Qualifiers CXXThisTypeQuals, bool Enabled) : S(S), OldCXXThisTypeOverride(S.CXXThisTypeOverride), Enabled(false) { @@ -1101,11 +1107,10 @@ Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S, else Record = cast<CXXRecordDecl>(ContextDecl); - // We care only for CVR qualifiers here, so cut everything else. - CXXThisTypeQuals &= Qualifiers::FastMask; - S.CXXThisTypeOverride - = S.Context.getPointerType( - S.Context.getRecordType(Record).withCVRQualifiers(CXXThisTypeQuals)); + QualType T = S.Context.getRecordType(Record); + T = S.getASTContext().getQualifiedType(T, CXXThisTypeQuals); + + S.CXXThisTypeOverride = S.Context.getPointerType(T); this->Enabled = true; } @@ -1442,11 +1447,33 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, return Result; } +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; + + SmallVector<const FunctionDecl*, 4> PreventedBy; + bool Result = Method->isUsualDeallocationFunction(PreventedBy); + + if (Result || !getLangOpts().CUDA || PreventedBy.empty()) + return Result; + + // In case of CUDA, return true if none of the 1-argument deallocator + // functions are actually callable. + return llvm::none_of(PreventedBy, [&](const FunctionDecl *FD) { + assert(FD->getNumParams() == 1 && + "Only single-operand functions should be in PreventedBy"); + return IdentifyCUDAPreference(Caller, FD) >= CFP_HostDevice; + }); +} + /// Determine whether the given function is a non-placement /// deallocation function. static bool isNonPlacementDeallocationFunction(Sema &S, FunctionDecl *FD) { if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD)) - return Method->isUsualDeallocationFunction(); + return S.isUsualDeallocationFunction(Method); if (FD->getOverloadedOperator() != OO_Delete && FD->getOverloadedOperator() != OO_Array_Delete) @@ -1484,11 +1511,19 @@ namespace { Destroying = true; ++NumBaseParams; } - if (FD->getNumParams() == NumBaseParams + 2) - HasAlignValT = HasSizeT = true; - else if (FD->getNumParams() == NumBaseParams + 1) { - HasSizeT = FD->getParamDecl(NumBaseParams)->getType()->isIntegerType(); - HasAlignValT = !HasSizeT; + + if (NumBaseParams < FD->getNumParams() && + S.Context.hasSameUnqualifiedType( + FD->getParamDecl(NumBaseParams)->getType(), + S.Context.getSizeType())) { + ++NumBaseParams; + HasSizeT = true; + } + + if (NumBaseParams < FD->getNumParams() && + FD->getParamDecl(NumBaseParams)->getType()->isAlignValT()) { + ++NumBaseParams; + HasAlignValT = true; } // In CUDA, determine how much we'd like / dislike to call this. @@ -1692,15 +1727,9 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, if (ParenListExpr *List = dyn_cast_or_null<ParenListExpr>(Initializer)) DirectInitRange = List->getSourceRange(); - return BuildCXXNew(SourceRange(StartLoc, D.getLocEnd()), UseGlobal, - PlacementLParen, - PlacementArgs, - PlacementRParen, - TypeIdParens, - AllocType, - TInfo, - ArraySize, - DirectInitRange, + return BuildCXXNew(SourceRange(StartLoc, D.getEndLoc()), UseGlobal, + PlacementLParen, PlacementArgs, PlacementRParen, + TypeIdParens, AllocType, TInfo, ArraySize, DirectInitRange, Initializer); } @@ -1723,28 +1752,33 @@ static bool isLegalArrayNewInitializer(CXXNewExpr::InitializationStyle Style, return false; } -// Emit a diagnostic if an aligned allocation/deallocation function that is not -// implemented in the standard library is selected. -static void diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD, - SourceLocation Loc, bool IsDelete, - Sema &S) { - if (!S.getLangOpts().AlignedAllocationUnavailable) - return; - - // Return if there is a definition. +bool +Sema::isUnavailableAlignedAllocationFunction(const FunctionDecl &FD) const { + if (!getLangOpts().AlignedAllocationUnavailable) + return false; if (FD.isDefined()) - return; - + return false; bool IsAligned = false; - if (FD.isReplaceableGlobalAllocationFunction(&IsAligned) && IsAligned) { - const llvm::Triple &T = S.getASTContext().getTargetInfo().getTriple(); + if (FD.isReplaceableGlobalAllocationFunction(&IsAligned) && IsAligned) + return true; + return false; +} + +// Emit a diagnostic if an aligned allocation/deallocation function that is not +// implemented in the standard library is selected. +void Sema::diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD, + SourceLocation Loc) { + if (isUnavailableAlignedAllocationFunction(FD)) { + const llvm::Triple &T = getASTContext().getTargetInfo().getTriple(); StringRef OSName = AvailabilityAttr::getPlatformNameSourceSpelling( - S.getASTContext().getTargetInfo().getPlatformName()); + getASTContext().getTargetInfo().getPlatformName()); - S.Diag(Loc, diag::warn_aligned_allocation_unavailable) - << IsDelete << FD.getType().getAsString() << OSName - << alignedAllocMinVersion(T.getOS()).getAsString(); - S.Diag(Loc, diag::note_silence_unligned_allocation_unavailable); + 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(); + Diag(Loc, diag::note_silence_aligned_allocation_unavailable); } } @@ -1787,20 +1821,21 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, // A new-expression that creates an object of type T initializes that // object as follows: InitializationKind Kind - // - If the new-initializer is omitted, the object is default- - // initialized (8.5); if no initialization is performed, - // the object has indeterminate value - = initStyle == CXXNewExpr::NoInit - ? InitializationKind::CreateDefault(TypeRange.getBegin()) - // - Otherwise, the new-initializer is interpreted according to the - // initialization rules of 8.5 for direct-initialization. - : initStyle == CXXNewExpr::ListInit - ? InitializationKind::CreateDirectList(TypeRange.getBegin(), - Initializer->getLocStart(), - Initializer->getLocEnd()) - : InitializationKind::CreateDirect(TypeRange.getBegin(), - DirectInitRange.getBegin(), - DirectInitRange.getEnd()); + // - If the new-initializer is omitted, the object is default- + // initialized (8.5); if no initialization is performed, + // the object has indeterminate value + = initStyle == CXXNewExpr::NoInit + ? InitializationKind::CreateDefault(TypeRange.getBegin()) + // - Otherwise, the new-initializer is interpreted according to + // the + // initialization rules of 8.5 for direct-initialization. + : initStyle == CXXNewExpr::ListInit + ? InitializationKind::CreateDirectList( + TypeRange.getBegin(), Initializer->getBeginLoc(), + Initializer->getEndLoc()) + : InitializationKind::CreateDirect(TypeRange.getBegin(), + DirectInitRange.getBegin(), + DirectInitRange.getEnd()); // C++11 [dcl.spec.auto]p6. Deduce the type which 'auto' stands in for. auto *Deduced = AllocType->getContainedDeducedType(); @@ -1831,19 +1866,18 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, << AllocType << TypeRange); if (NumInits > 1) { Expr *FirstBad = Inits[1]; - return ExprError(Diag(FirstBad->getLocStart(), + return ExprError(Diag(FirstBad->getBeginLoc(), diag::err_auto_new_ctor_multiple_expressions) << AllocType << TypeRange); } if (Braced && !getLangOpts().CPlusPlus17) - Diag(Initializer->getLocStart(), diag::ext_auto_new_list_init) + Diag(Initializer->getBeginLoc(), diag::ext_auto_new_list_init) << AllocType << TypeRange; - Expr *Deduce = Inits[0]; QualType DeducedType; - if (DeduceAutoType(AllocTypeInfo, Deduce, DeducedType) == DAR_Failed) + if (DeduceAutoType(AllocTypeInfo, Inits[0], DeducedType) == DAR_Failed) return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure) - << AllocType << Deduce->getType() - << TypeRange << Deduce->getSourceRange()); + << AllocType << Inits[0]->getType() + << TypeRange << Inits[0]->getSourceRange()); if (DeducedType.isNull()) return ExprError(); AllocType = DeducedType; @@ -1983,7 +2017,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, // C++14 onwards, because Value is always unsigned here! if (ArraySize->isIntegerConstantExpr(Value, Context)) { if (Value.isSigned() && Value.isNegative()) { - return ExprError(Diag(ArraySize->getLocStart(), + return ExprError(Diag(ArraySize->getBeginLoc(), diag::err_typecheck_negative_array_size) << ArraySize->getSourceRange()); } @@ -1992,19 +2026,18 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, unsigned ActiveSizeBits = ConstantArrayType::getNumAddressingBits(Context, AllocType, Value); if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) - return ExprError(Diag(ArraySize->getLocStart(), - diag::err_array_too_large) - << Value.toString(10) - << ArraySize->getSourceRange()); + return ExprError( + Diag(ArraySize->getBeginLoc(), diag::err_array_too_large) + << Value.toString(10) << ArraySize->getSourceRange()); } KnownArraySize = Value.getZExtValue(); } else if (TypeIdParens.isValid()) { // Can't have dynamic array size when the type-id is in parentheses. - Diag(ArraySize->getLocStart(), diag::ext_new_paren_array_nonconst) - << ArraySize->getSourceRange() - << FixItHint::CreateRemoval(TypeIdParens.getBegin()) - << FixItHint::CreateRemoval(TypeIdParens.getEnd()); + Diag(ArraySize->getBeginLoc(), diag::ext_new_paren_array_nonconst) + << ArraySize->getSourceRange() + << FixItHint::CreateRemoval(TypeIdParens.getBegin()) + << FixItHint::CreateRemoval(TypeIdParens.getEnd()); TypeIdParens = SourceRange(); } @@ -2066,8 +2099,8 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, // global operator new. if (PlacementArgs.empty() && !PassAlignment && (OperatorNew->isImplicit() || - (OperatorNew->getLocStart().isValid() && - getSourceManager().isInSystemHeader(OperatorNew->getLocStart())))) { + (OperatorNew->getBeginLoc().isValid() && + getSourceManager().isInSystemHeader(OperatorNew->getBeginLoc())))) { if (Alignment > NewAlignment) Diag(StartLoc, diag::warn_overaligned_type) << AllocType @@ -2080,8 +2113,8 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, // Initializer lists are also allowed, in C++11. Rely on the parser for the // dialect distinction. if (ArraySize && !isLegalArrayNewInitializer(initStyle, Initializer)) { - SourceRange InitRange(Inits[0]->getLocStart(), - Inits[NumInits - 1]->getLocEnd()); + SourceRange InitRange(Inits[0]->getBeginLoc(), + Inits[NumInits - 1]->getEndLoc()); Diag(StartLoc, diag::err_new_array_init_args) << InitRange; return ExprError(); } @@ -2128,13 +2161,11 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, if (DiagnoseUseOfDecl(OperatorNew, StartLoc)) return ExprError(); MarkFunctionReferenced(StartLoc, OperatorNew); - diagnoseUnavailableAlignedAllocation(*OperatorNew, StartLoc, false, *this); } if (OperatorDelete) { if (DiagnoseUseOfDecl(OperatorDelete, StartLoc)) return ExprError(); MarkFunctionReferenced(StartLoc, OperatorDelete); - diagnoseUnavailableAlignedAllocation(*OperatorDelete, StartLoc, true, *this); } // C++0x [expr.new]p17: @@ -2155,11 +2186,11 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, } } - return new (Context) - CXXNewExpr(Context, UseGlobal, OperatorNew, OperatorDelete, PassAlignment, - UsualArrayDeleteWantsSize, PlacementArgs, TypeIdParens, - ArraySize, initStyle, Initializer, ResultType, AllocTypeInfo, - Range, DirectInitRange); + return CXXNewExpr::Create(Context, UseGlobal, OperatorNew, OperatorDelete, + PassAlignment, UsualArrayDeleteWantsSize, + PlacementArgs, TypeIdParens, ArraySize, initStyle, + Initializer, ResultType, AllocTypeInfo, Range, + DirectInitRange); } /// Checks that a type is suitable as the allocated type @@ -2587,8 +2618,8 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, if (IsSizedDelete) { SourceRange R = PlaceArgs.empty() ? SourceRange() - : SourceRange(PlaceArgs.front()->getLocStart(), - PlaceArgs.back()->getLocEnd()); + : SourceRange(PlaceArgs.front()->getBeginLoc(), + PlaceArgs.back()->getEndLoc()); Diag(StartLoc, diag::err_placement_new_non_placement_delete) << R; if (!OperatorDelete->isImplicit()) Diag(OperatorDelete->getLocation(), diag::note_previous_decl) @@ -2794,9 +2825,10 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, // Global allocation functions should always be visible. Alloc->setVisibleDespiteOwningModule(); - // Implicit sized deallocation functions always have default visibility. - Alloc->addAttr( - VisibilityAttr::CreateImplicit(Context, VisibilityAttr::Default)); + Alloc->addAttr(VisibilityAttr::CreateImplicit( + Context, LangOpts.GlobalAllocationFunctionVisibilityHidden + ? VisibilityAttr::Hidden + : VisibilityAttr::Default)); llvm::SmallVector<ParmVarDecl *, 3> ParamDecls; for (QualType T : Params) { @@ -3156,12 +3188,12 @@ void Sema::AnalyzeDeleteExprMismatch(const CXXDeleteExpr *DE) { switch (Detector.analyzeDeleteExpr(DE)) { case MismatchingNewDeleteDetector::VarInitMismatches: case MismatchingNewDeleteDetector::MemberInitMismatches: { - DiagnoseMismatchedNewDelete(*this, DE->getLocStart(), Detector); + DiagnoseMismatchedNewDelete(*this, DE->getBeginLoc(), Detector); break; } case MismatchingNewDeleteDetector::AnalyzeLater: { DeleteExprs[Detector.Field].push_back( - std::make_pair(DE->getLocStart(), DE->isArrayForm())); + std::make_pair(DE->getBeginLoc(), DE->isArrayForm())); break; } case MismatchingNewDeleteDetector::NoMismatch: @@ -3280,10 +3312,10 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, if (Pointee.getAddressSpace() != LangAS::Default && !getLangOpts().OpenCLCPlusPlus) - return Diag(Ex.get()->getLocStart(), + return Diag(Ex.get()->getBeginLoc(), diag::err_address_space_qualified_delete) - << Pointee.getUnqualifiedType() - << Pointee.getQualifiers().getAddressSpaceAttributePrintValue(); + << Pointee.getUnqualifiedType() + << Pointee.getQualifiers().getAddressSpaceAttributePrintValue(); CXXRecordDecl *PointeeRD = nullptr; if (Pointee->isVoidType() && !isSFINAEContext()) { @@ -3383,8 +3415,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, } } - diagnoseUnavailableAlignedAllocation(*OperatorDelete, StartLoc, true, - *this); + DiagnoseUseOfDecl(OperatorDelete, StartLoc); // Convert the operand to the type of the first parameter of operator // delete. This is only necessary if we selected a destroying operator @@ -3421,7 +3452,7 @@ static bool resolveBuiltinNewDeleteOverload(Sema &S, CallExpr *TheCall, DeclarationName NewName = S.Context.DeclarationNames.getCXXOperatorName( IsDelete ? OO_Delete : OO_New); - LookupResult R(S, NewName, TheCall->getLocStart(), Sema::LookupOrdinaryName); + LookupResult R(S, NewName, TheCall->getBeginLoc(), Sema::LookupOrdinaryName); S.LookupQualifiedName(R, S.Context.getTranslationUnitDecl()); assert(!R.empty() && "implicitly declared allocation functions not found"); assert(!R.isAmbiguous() && "global allocation functions are ambiguous"); @@ -3517,13 +3548,16 @@ Sema::SemaBuiltinOperatorNewDeleteOverloaded(ExprResult TheCallResult, return ExprError(); assert(OperatorNewOrDelete && "should be found"); + DiagnoseUseOfDecl(OperatorNewOrDelete, TheCall->getExprLoc()); + MarkFunctionReferenced(TheCall->getExprLoc(), OperatorNewOrDelete); + TheCall->setType(OperatorNewOrDelete->getReturnType()); for (unsigned i = 0; i != TheCall->getNumArgs(); ++i) { QualType ParamTy = OperatorNewOrDelete->getParamDecl(i)->getType(); InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, ParamTy, false); ExprResult Arg = PerformCopyInitialization( - Entity, TheCall->getArg(i)->getLocStart(), TheCall->getArg(i)); + Entity, TheCall->getArg(i)->getBeginLoc(), TheCall->getArg(i)); if (Arg.isInvalid()) return ExprError(); TheCall->setArg(i, Arg.get()); @@ -3561,7 +3595,7 @@ void Sema::CheckVirtualDtorCall(CXXDestructorDecl *dtor, SourceLocation Loc, if (getSourceManager().isInSystemHeader(PointeeRD->getLocation())) return; - QualType ClassType = dtor->getThisType(Context)->getPointeeType(); + QualType ClassType = dtor->getThisType()->getPointeeType(); if (PointeeRD->isAbstract()) { // If the class is abstract, we warn by default, because we're // sure the code has undefined behavior. @@ -3811,14 +3845,10 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, From = Res.get(); } - ExprResult CastArg - = BuildCXXCastArgument(*this, - From->getLocStart(), - ToType.getNonReferenceType(), - CastKind, cast<CXXMethodDecl>(FD), - ICS.UserDefined.FoundConversionFunction, - ICS.UserDefined.HadMultipleCandidates, - From); + ExprResult CastArg = BuildCXXCastArgument( + *this, From->getBeginLoc(), ToType.getNonReferenceType(), CastKind, + cast<CXXMethodDecl>(FD), ICS.UserDefined.FoundConversionFunction, + ICS.UserDefined.HadMultipleCandidates, From); if (CastArg.isInvalid()) return ExprError(); @@ -3906,7 +3936,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, if (!Fn) return ExprError(); - if (DiagnoseUseOfDecl(Fn, From->getLocStart())) + if (DiagnoseUseOfDecl(Fn, From->getBeginLoc())) return ExprError(); From = FixOverloadedFunctionReference(From, Found, Fn); @@ -4045,15 +4075,15 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, if (SCS.IncompatibleObjC && Action != AA_Casting) { // Diagnose incompatible Objective-C conversions if (Action == AA_Initializing || Action == AA_Assigning) - Diag(From->getLocStart(), + Diag(From->getBeginLoc(), diag::ext_typecheck_convert_incompatible_pointer) - << ToType << From->getType() << Action - << From->getSourceRange() << 0; + << ToType << From->getType() << Action << From->getSourceRange() + << 0; else - Diag(From->getLocStart(), + Diag(From->getBeginLoc(), diag::ext_typecheck_convert_incompatible_pointer) - << From->getType() << ToType << Action - << From->getSourceRange() << 0; + << From->getType() << ToType << Action << From->getSourceRange() + << 0; if (From->getType()->isObjCObjectPointerType() && ToType->isObjCObjectPointerType()) @@ -4062,13 +4092,11 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, !CheckObjCARCUnavailableWeakConversion(ToType, From->getType())) { if (Action == AA_Initializing) - Diag(From->getLocStart(), - diag::err_arc_weak_unavailable_assign); + Diag(From->getBeginLoc(), diag::err_arc_weak_unavailable_assign); else - Diag(From->getLocStart(), - diag::err_arc_convesion_of_weak_unavailable) - << (Action == AA_Casting) << From->getType() << ToType - << From->getSourceRange(); + Diag(From->getBeginLoc(), diag::err_arc_convesion_of_weak_unavailable) + << (Action == AA_Casting) << From->getType() << ToType + << From->getSourceRange(); } CastKind Kind; @@ -4124,12 +4152,9 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, case ICK_Derived_To_Base: { CXXCastPath BasePath; - if (CheckDerivedToBaseConversion(From->getType(), - ToType.getNonReferenceType(), - From->getLocStart(), - From->getSourceRange(), - &BasePath, - CStyle)) + if (CheckDerivedToBaseConversion( + From->getType(), ToType.getNonReferenceType(), From->getBeginLoc(), + From->getSourceRange(), &BasePath, CStyle)) return ExprError(); From = ImpCastExprToType(From, ToType.getNonReferenceType(), @@ -4223,14 +4248,9 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, } case ICK_Zero_Event_Conversion: - From = ImpCastExprToType(From, ToType, - CK_ZeroToOCLEvent, - From->getValueKind()).get(); - break; - case ICK_Zero_Queue_Conversion: From = ImpCastExprToType(From, ToType, - CK_ZeroToOCLQueue, + CK_ZeroToOCLOpaqueType, From->getValueKind()).get(); break; @@ -4263,17 +4283,32 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, case ICK_Qualification: { // The qualification keeps the category of the inner expression, unless the // target type isn't a reference. - ExprValueKind VK = ToType->isReferenceType() ? - From->getValueKind() : VK_RValue; - From = ImpCastExprToType(From, ToType.getNonLValueExprType(Context), - CK_NoOp, VK, /*BasePath=*/nullptr, CCK).get(); + ExprValueKind VK = + ToType->isReferenceType() ? From->getValueKind() : VK_RValue; + + CastKind CK = CK_NoOp; + + if (ToType->isReferenceType() && + ToType->getPointeeType().getAddressSpace() != + From->getType().getAddressSpace()) + CK = CK_AddressSpaceConversion; + + if (ToType->isPointerType() && + ToType->getPointeeType().getAddressSpace() != + From->getType()->getPointeeType().getAddressSpace()) + CK = CK_AddressSpaceConversion; + + From = ImpCastExprToType(From, ToType.getNonLValueExprType(Context), CK, VK, + /*BasePath=*/nullptr, CCK) + .get(); if (SCS.DeprecatedStringLiteralToCharPtr && !getLangOpts().WritableStrings) { - Diag(From->getLocStart(), getLangOpts().CPlusPlus11 - ? diag::ext_deprecated_string_literal_conversion - : diag::warn_deprecated_string_literal_conversion) - << ToType.getNonReferenceType(); + Diag(From->getBeginLoc(), + getLangOpts().CPlusPlus11 + ? diag::ext_deprecated_string_literal_conversion + : diag::warn_deprecated_string_literal_conversion) + << ToType.getNonReferenceType(); } break; @@ -4296,7 +4331,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, // _Nullable type to a _Nonnull one, complain. if (!isCast(CCK)) diagnoseNullableToNonnullConversion(ToType, InitialFromType, - From->getLocStart()); + From->getBeginLoc()); return From; } @@ -4926,7 +4961,7 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, if (ArgTy->isObjectType() || ArgTy->isFunctionType()) ArgTy = S.Context.getRValueReferenceType(ArgTy); OpaqueArgExprs.push_back( - OpaqueValueExpr(Args[I]->getTypeLoc().getLocStart(), + OpaqueValueExpr(Args[I]->getTypeLoc().getBeginLoc(), ArgTy.getNonLValueExprType(S.Context), Expr::getValueKindForType(ArgTy))); } @@ -5421,10 +5456,10 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS, } CXXCastPath BasePath; - if (CheckDerivedToBaseConversion(LHSType, Class, Loc, - SourceRange(LHS.get()->getLocStart(), - RHS.get()->getLocEnd()), - &BasePath)) + if (CheckDerivedToBaseConversion( + LHSType, Class, Loc, + SourceRange(LHS.get()->getBeginLoc(), RHS.get()->getEndLoc()), + &BasePath)) return QualType(); // Cast LHS to type of use. @@ -5518,8 +5553,8 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To, HaveConversion = false; ToType = To->getType(); - InitializationKind Kind = InitializationKind::CreateCopy(To->getLocStart(), - SourceLocation()); + InitializationKind Kind = + InitializationKind::CreateCopy(To->getBeginLoc(), SourceLocation()); // C++11 5.16p3 // The process for determining whether an operand expression E1 of type T1 // can be converted to match an operand expression E2 of type T2 is defined @@ -5664,8 +5699,8 @@ static bool FindConditionalOverload(Sema &Self, ExprResult &LHS, ExprResult &RHS /// TryClassUnification. static bool ConvertForConditional(Sema &Self, ExprResult &E, QualType T) { InitializedEntity Entity = InitializedEntity::InitializeTemporary(T); - InitializationKind Kind = InitializationKind::CreateCopy(E.get()->getLocStart(), - SourceLocation()); + InitializationKind Kind = + InitializationKind::CreateCopy(E.get()->getBeginLoc(), SourceLocation()); Expr *Arg = E.get(); InitializationSequence InitSeq(Self, Entity, Kind, Arg); ExprResult Result = InitSeq.Perform(Self, Entity, Kind, Arg); @@ -6515,6 +6550,11 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) { ExpressionEvaluationContextRecord::EK_Decltype && "not in a decltype expression"); + ExprResult Result = CheckPlaceholderExpr(E); + if (Result.isInvalid()) + return ExprError(); + E = Result.get(); + // C++11 [expr.call]p11: // If a function call is a prvalue of object type, // -- if the function call is either @@ -6571,8 +6611,7 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) { continue; if (CheckCallReturnType(Call->getCallReturnType(Context), - Call->getLocStart(), - Call, Call->getDirectCallee())) + Call->getBeginLoc(), Call, Call->getDirectCallee())) return ExprError(); } @@ -6707,7 +6746,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, << BaseType << Base->getSourceRange(); CallExpr *CE = dyn_cast<CallExpr>(Base); if (Decl *CD = (CE ? CE->getCalleeDecl() : nullptr)) { - Diag(CD->getLocStart(), + Diag(CD->getBeginLoc(), diag::note_member_reference_arrow_from_operator_arrow); } } @@ -7162,9 +7201,8 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, ExprValueKind VK = Expr::getValueKindForType(ResultType); ResultType = ResultType.getNonLValueExprType(Context); - CXXMemberCallExpr *CE = - new (Context) CXXMemberCallExpr(Context, ME, None, ResultType, VK, - Exp.get()->getLocEnd()); + CXXMemberCallExpr *CE = CXXMemberCallExpr::Create( + Context, ME, /*Args=*/{}, ResultType, VK, Exp.get()->getEndLoc()); if (CheckFunctionCall(Method, CE, Method->getType()->castAs<FunctionProtoType>())) @@ -7752,41 +7790,24 @@ Sema::CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl, ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC, bool DiscardedValue, - bool IsConstexpr, - bool IsLambdaInitCaptureInitializer) { + bool IsConstexpr) { ExprResult FullExpr = FE; if (!FullExpr.get()) return ExprError(); - // If we are an init-expression in a lambdas init-capture, we should not - // diagnose an unexpanded pack now (will be diagnosed once lambda-expr - // containing full-expression is done). - // template<class ... Ts> void test(Ts ... t) { - // test([&a(t)]() { <-- (t) is an init-expr that shouldn't be diagnosed now. - // return a; - // }() ...); - // } - // FIXME: This is a hack. It would be better if we pushed the lambda scope - // when we parse the lambda introducer, and teach capturing (but not - // unexpanded pack detection) to walk over LambdaScopeInfos which don't have a - // corresponding class yet (that is, have LambdaScopeInfo either represent a - // lambda where we've entered the introducer but not the body, or represent a - // lambda where we've entered the body, depending on where the - // parser/instantiation has got to). - if (!IsLambdaInitCaptureInitializer && - DiagnoseUnexpandedParameterPack(FullExpr.get())) + if (DiagnoseUnexpandedParameterPack(FullExpr.get())) return ExprError(); - // Top-level expressions default to 'id' when we're in a debugger. - if (DiscardedValue && getLangOpts().DebuggerCastResultToId && - FullExpr.get()->getType() == Context.UnknownAnyTy) { - FullExpr = forceUnknownAnyToType(FullExpr.get(), Context.getObjCIdType()); - if (FullExpr.isInvalid()) - return ExprError(); - } - if (DiscardedValue) { + // Top-level expressions default to 'id' when we're in a debugger. + if (getLangOpts().DebuggerCastResultToId && + FullExpr.get()->getType() == Context.UnknownAnyTy) { + FullExpr = forceUnknownAnyToType(FullExpr.get(), Context.getObjCIdType()); + if (FullExpr.isInvalid()) + return ExprError(); + } + FullExpr = CheckPlaceholderExpr(FullExpr.get()); if (FullExpr.isInvalid()) return ExprError(); @@ -7794,6 +7815,8 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC, FullExpr = IgnoredValueConversions(FullExpr.get()); if (FullExpr.isInvalid()) return ExprError(); + + DiagnoseUnusedExprResult(FullExpr.get()); } FullExpr = CorrectDelayedTyposInExpr(FullExpr.get()); diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp index e6d2b5068fd56..b2b21ba9eefa0 100644 --- a/lib/Sema/SemaExprMember.cpp +++ b/lib/Sema/SemaExprMember.cpp @@ -496,7 +496,7 @@ Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType, // allows this, while still reporting an error if T is a struct pointer. if (!IsArrow) { const PointerType *PT = BaseType->getAs<PointerType>(); - if (PT && (!getLangOpts().ObjC1 || + if (PT && (!getLangOpts().ObjC || PT->getPointeeType()->isRecordType())) { assert(BaseExpr && "cannot happen with implicit member accesses"); Diag(OpLoc, diag::err_typecheck_member_reference_struct_union) @@ -1708,9 +1708,31 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, } ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl}; - return BuildMemberReferenceExpr(Base, Base->getType(), OpLoc, IsArrow, SS, - TemplateKWLoc, FirstQualifierInScope, - NameInfo, TemplateArgs, S, &ExtraArgs); + ExprResult Res = BuildMemberReferenceExpr( + Base, Base->getType(), OpLoc, IsArrow, SS, TemplateKWLoc, + FirstQualifierInScope, NameInfo, TemplateArgs, S, &ExtraArgs); + + if (!Res.isInvalid() && isa<MemberExpr>(Res.get())) + CheckMemberAccessOfNoDeref(cast<MemberExpr>(Res.get())); + + return Res; +} + +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)) + return; + + if (E->isArrow()) { + if (const auto *Ptr = dyn_cast<PointerType>( + E->getBase()->getType().getDesugaredType(Context))) { + if (Ptr->getPointeeType()->hasAttr(attr::NoDeref)) + ExprEvalContexts.back().PossibleDerefs.insert(E); + } + } } ExprResult diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index b291fc8691d50..ed780efd4cf30 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -50,8 +50,8 @@ ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, // ObjC strings can't be wide or UTF. if (!S->isAscii()) { - Diag(S->getLocStart(), diag::err_cfstring_literal_not_string_constant) - << S->getSourceRange(); + Diag(S->getBeginLoc(), diag::err_cfstring_literal_not_string_constant) + << S->getSourceRange(); return true; } @@ -107,8 +107,8 @@ ExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){ } else { // If there is no NSConstantString interface defined then treat this // as error and recover from it. - Diag(S->getLocStart(), diag::err_no_nsconstant_string_class) << NSIdent - << S->getSourceRange(); + Diag(S->getBeginLoc(), diag::err_no_nsconstant_string_class) + << NSIdent << S->getSourceRange(); Ty = Context.getObjCIdType(); } } else { @@ -399,9 +399,8 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element, InitializedEntity Entity = InitializedEntity::InitializeParameter(S.Context, T, /*Consumed=*/false); - InitializationKind Kind - = InitializationKind::CreateCopy(Element->getLocStart(), - SourceLocation()); + InitializationKind Kind = InitializationKind::CreateCopy( + Element->getBeginLoc(), SourceLocation()); InitializationSequence Seq(S, Entity, Kind, Element); if (!Seq.Failed()) return Seq.Perform(S, Entity, Kind, Element); @@ -432,12 +431,12 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element, isa<ObjCBoolLiteralExpr>(OrigElement)) ? 2 : 3; - S.Diag(OrigElement->getLocStart(), diag::err_box_literal_collection) - << Which << OrigElement->getSourceRange() - << FixItHint::CreateInsertion(OrigElement->getLocStart(), "@"); + S.Diag(OrigElement->getBeginLoc(), diag::err_box_literal_collection) + << Which << OrigElement->getSourceRange() + << FixItHint::CreateInsertion(OrigElement->getBeginLoc(), "@"); - Result = S.BuildObjCNumericLiteral(OrigElement->getLocStart(), - OrigElement); + Result = + S.BuildObjCNumericLiteral(OrigElement->getBeginLoc(), OrigElement); if (Result.isInvalid()) return ExprError(); @@ -448,11 +447,11 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element, // If this is potentially an Objective-C string literal, add the '@'. else if (StringLiteral *String = dyn_cast<StringLiteral>(OrigElement)) { if (String->isAscii()) { - S.Diag(OrigElement->getLocStart(), diag::err_box_literal_collection) - << 0 << OrigElement->getSourceRange() - << FixItHint::CreateInsertion(OrigElement->getLocStart(), "@"); + S.Diag(OrigElement->getBeginLoc(), diag::err_box_literal_collection) + << 0 << OrigElement->getSourceRange() + << FixItHint::CreateInsertion(OrigElement->getBeginLoc(), "@"); - Result = S.BuildObjCStringLiteral(OrigElement->getLocStart(), String); + Result = S.BuildObjCStringLiteral(OrigElement->getBeginLoc(), String); if (Result.isInvalid()) return ExprError(); @@ -462,8 +461,8 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element, } if (!Recovered) { - S.Diag(Element->getLocStart(), diag::err_invalid_collection_element) - << Element->getType(); + S.Diag(Element->getBeginLoc(), diag::err_invalid_collection_element) + << Element->getType(); return ExprError(); } } @@ -481,9 +480,9 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element, break; } if (!hasMacro) - S.Diag(Element->getLocStart(), + S.Diag(Element->getBeginLoc(), diag::warn_concatenated_nsarray_literal) - << Element->getType(); + << Element->getType(); } } } @@ -491,9 +490,9 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element, // Make sure that the element has the type that the container factory // function expects. return S.PerformCopyInitialization( - InitializedEntity::InitializeParameter(S.Context, T, - /*Consumed=*/false), - Element->getLocStart(), Element); + InitializedEntity::InitializeParameter(S.Context, T, + /*Consumed=*/false), + Element->getBeginLoc(), Element); } ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { @@ -1034,8 +1033,8 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, !Element.Value->containsUnexpandedParameterPack()) { Diag(Element.EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) - << SourceRange(Element.Key->getLocStart(), - Element.Value->getLocEnd()); + << SourceRange(Element.Key->getBeginLoc(), + Element.Value->getEndLoc()); return ExprError(); } @@ -1228,8 +1227,12 @@ ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId, Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId; return true; } - if (PDecl->hasDefinition()) + if (!PDecl->hasDefinition()) { + Diag(ProtoLoc, diag::err_atprotocol_protocol) << PDecl; + Diag(PDecl->getLocation(), diag::note_entity_declared_at) << PDecl; + } else { PDecl = PDecl->getDefinition(); + } QualType Ty = Context.getObjCProtoType(); if (Ty.isNull()) @@ -1343,7 +1346,8 @@ static QualType getBaseMessageSendResultType(Sema &S, return transferNullability(ReceiverType); } -QualType Sema::getMessageSendResultType(QualType ReceiverType, +QualType Sema::getMessageSendResultType(const Expr *Receiver, + QualType ReceiverType, ObjCMethodDecl *Method, bool isClassMessage, bool isSuperMessage) { @@ -1354,8 +1358,33 @@ QualType Sema::getMessageSendResultType(QualType ReceiverType, isSuperMessage); // If this is a class message, ignore the nullability of the receiver. - if (isClassMessage) + if (isClassMessage) { + // In a class method, class messages to 'self' that return instancetype can + // be typed as the current class. We can safely do this in ARC because self + // can't be reassigned, and we do it unsafely outside of ARC because in + // practice people never reassign self in class methods and there's some + // virtue in not being aggressively pedantic. + if (Receiver && Receiver->isObjCSelfExpr()) { + assert(ReceiverType->isObjCClassType() && "expected a Class self"); + QualType T = Method->getSendResultType(ReceiverType); + AttributedType::stripOuterNullability(T); + if (T == Context.getObjCInstanceType()) { + const ObjCMethodDecl *MD = cast<ObjCMethodDecl>( + cast<ImplicitParamDecl>( + cast<DeclRefExpr>(Receiver->IgnoreParenImpCasts())->getDecl()) + ->getDeclContext()); + assert(MD->isClassMethod() && "expected a class method"); + QualType NewResultType = Context.getObjCObjectPointerType( + Context.getObjCInterfaceType(MD->getClassInterface())); + if (auto Nullability = resultType->getNullability(Context)) + NewResultType = Context.getAttributedType( + AttributedType::getNullabilityAttrKind(*Nullability), + NewResultType, NewResultType); + return NewResultType; + } + } return resultType; + } // There is nothing left to do if the result type cannot have a nullability // specifier. @@ -1502,15 +1531,12 @@ void Sema::EmitRelatedResultTypeNote(const Expr *E) { << MsgSend->getType(); } -bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, - MultiExprArg Args, - Selector Sel, - ArrayRef<SourceLocation> SelectorLocs, - ObjCMethodDecl *Method, - bool isClassMessage, bool isSuperMessage, - SourceLocation lbrac, SourceLocation rbrac, - SourceRange RecRange, - QualType &ReturnType, ExprValueKind &VK) { +bool Sema::CheckMessageArgumentTypes( + const Expr *Receiver, QualType ReceiverType, MultiExprArg Args, + Selector Sel, ArrayRef<SourceLocation> SelectorLocs, ObjCMethodDecl *Method, + bool isClassMessage, bool isSuperMessage, SourceLocation lbrac, + SourceLocation rbrac, SourceRange RecRange, QualType &ReturnType, + ExprValueKind &VK) { SourceLocation SelLoc; if (!SelectorLocs.empty() && SelectorLocs.front().isValid()) SelLoc = SelectorLocs.front(); @@ -1587,8 +1613,8 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, return false; } - ReturnType = getMessageSendResultType(ReceiverType, Method, isClassMessage, - isSuperMessage); + ReturnType = getMessageSendResultType(Receiver, ReceiverType, Method, + isClassMessage, isSuperMessage); VK = Expr::getValueKindForType(Method->getReturnType()); unsigned NumNamedArgs = Sel.getNumArgs(); @@ -1693,12 +1719,12 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, } else { // Check for extra arguments to non-variadic methods. if (Args.size() != NumNamedArgs) { - Diag(Args[NumNamedArgs]->getLocStart(), + Diag(Args[NumNamedArgs]->getBeginLoc(), diag::err_typecheck_call_too_many_args) - << 2 /*method*/ << NumNamedArgs << static_cast<unsigned>(Args.size()) - << Method->getSourceRange() - << SourceRange(Args[NumNamedArgs]->getLocStart(), - Args.back()->getLocEnd()); + << 2 /*method*/ << NumNamedArgs << static_cast<unsigned>(Args.size()) + << Method->getSourceRange() + << SourceRange(Args[NumNamedArgs]->getBeginLoc(), + Args.back()->getEndLoc()); } } @@ -2323,7 +2349,7 @@ static void checkFoundationAPI(Sema &S, SourceLocation Loc, << (!Ret->isRecordType() ? /*Vector*/ 2 : Ret->isUnionType() ? /*Union*/ 1 : /*Struct*/ 0); - S.Diag(ImpliedMethod->getLocStart(), + S.Diag(ImpliedMethod->getBeginLoc(), diag::note_objc_unsafe_perform_selector_method_declared_here) << ImpliedMethod->getSelector() << Ret; } @@ -2468,7 +2494,8 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, if (!Method) Method = Class->lookupPrivateClassMethod(Sel); - if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs)) + if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs, + nullptr, false, false, Class)) return ExprError(); } @@ -2478,12 +2505,10 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, unsigned NumArgs = ArgsIn.size(); Expr **Args = ArgsIn.data(); - if (CheckMessageArgumentTypes(ReceiverType, MultiExprArg(Args, NumArgs), - Sel, SelectorLocs, - Method, true, - SuperLoc.isValid(), LBracLoc, RBracLoc, - SourceRange(), - ReturnType, VK)) + if (CheckMessageArgumentTypes(/*Receiver=*/nullptr, ReceiverType, + MultiExprArg(Args, NumArgs), Sel, SelectorLocs, + Method, true, SuperLoc.isValid(), LBracLoc, + RBracLoc, SourceRange(), ReturnType, VK)) return ExprError(); if (Method && !Method->getReturnType()->isVoidType() && @@ -2582,7 +2607,7 @@ static bool isMethodDeclaredInRootProtocol(Sema &S, const ObjCMethodDecl *M) { return false; const IdentifierInfo *II = S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject); if (const auto *RootClass = dyn_cast_or_null<ObjCInterfaceDecl>( - S.LookupSingleName(S.TUScope, II, Protocol->getLocStart(), + S.LookupSingleName(S.TUScope, II, Protocol->getBeginLoc(), Sema::LookupOrdinaryName))) { for (const ObjCProtocolDecl *P : RootClass->all_referenced_protocols()) { if (P->getCanonicalDecl() == Protocol->getCanonicalDecl()) @@ -2635,7 +2660,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, "use it instead."); // The location of the receiver. - SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart(); + SourceLocation Loc = SuperLoc.isValid() ? SuperLoc : Receiver->getBeginLoc(); SourceRange RecRange = SuperLoc.isValid()? SuperLoc : Receiver->getSourceRange(); ArrayRef<SourceLocation> SelectorSlotLocs; @@ -2781,14 +2806,19 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, } else { if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) { + // FIXME: Is this correct? Why are we assuming that a message to + // Class will call a method in the current interface? + // First check the public methods in the class interface. Method = ClassDecl->lookupClassMethod(Sel); if (!Method) Method = ClassDecl->lookupPrivateClassMethod(Sel); + + if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs, nullptr, + false, false, ClassDecl)) + return ExprError(); } - if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs)) - return ExprError(); } if (!Method) { // If not messaging 'self', look for any factory method named 'Sel'. @@ -2856,8 +2886,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, return ExprError(); forwardClass = OCIType->getInterfaceDecl(); - Diag(Receiver ? Receiver->getLocStart() - : SuperLoc, diag::note_receiver_is_id); + Diag(Receiver ? Receiver->getBeginLoc() : SuperLoc, + diag::note_receiver_is_id); Method = nullptr; } else { Method = ClassDecl->lookupInstanceMethod(Sel); @@ -2973,9 +3003,9 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, ExprValueKind VK = VK_RValue; bool ClassMessage = (ReceiverType->isObjCClassType() || ReceiverType->isObjCQualifiedClassType()); - if (CheckMessageArgumentTypes(ReceiverType, MultiExprArg(Args, NumArgs), - Sel, SelectorLocs, Method, - ClassMessage, SuperLoc.isValid(), + if (CheckMessageArgumentTypes(Receiver, ReceiverType, + MultiExprArg(Args, NumArgs), Sel, SelectorLocs, + Method, ClassMessage, SuperLoc.isValid(), LBracLoc, RBracLoc, RecRange, ReturnType, VK)) return ExprError(); @@ -3131,7 +3161,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak; if (!IsWeak && Sel.isUnarySelector()) IsWeak = ReturnType.getObjCLifetime() & Qualifiers::OCL_Weak; - if (IsWeak && + if (IsWeak && !isUnevaluatedContext() && !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, LBracLoc)) getCurFunction()->recordUseOfWeak(Result, Prop); } @@ -3776,8 +3806,8 @@ static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr, (CastClass && CastClass->isSuperClassOf(ExprClass))) return true; if (warn) - S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge) - << T << Target->getName() << castType->getPointeeType(); + S.Diag(castExpr->getBeginLoc(), diag::warn_objc_invalid_bridge) + << T << Target->getName() << castType->getPointeeType(); return false; } else if (castType->isObjCIdType() || (S.Context.ObjCObjectAdoptsQTypeProtocols( @@ -3788,20 +3818,21 @@ static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr, return true; else { if (warn) { - S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge) - << T << Target->getName() << castType; - S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); - S.Diag(Target->getLocStart(), diag::note_declared_at); + S.Diag(castExpr->getBeginLoc(), diag::warn_objc_invalid_bridge) + << T << Target->getName() << castType; + S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at); + S.Diag(Target->getBeginLoc(), diag::note_declared_at); } return false; } } } else if (!castType->isObjCIdType()) { - S.Diag(castExpr->getLocStart(), diag::err_objc_cf_bridged_not_interface) - << castExpr->getType() << Parm; - S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); + S.Diag(castExpr->getBeginLoc(), + diag::err_objc_cf_bridged_not_interface) + << castExpr->getType() << Parm; + S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at); if (Target) - S.Diag(Target->getLocStart(), diag::note_declared_at); + S.Diag(Target->getBeginLoc(), diag::note_declared_at); } return true; } @@ -3841,9 +3872,10 @@ static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr, (ExprClass && CastClass->isSuperClassOf(ExprClass))) return true; if (warn) { - S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf) - << castExpr->getType()->getPointeeType() << T; - S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); + S.Diag(castExpr->getBeginLoc(), + diag::warn_objc_invalid_bridge_to_cf) + << castExpr->getType()->getPointeeType() << T; + S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at); } return false; } else if (castExpr->getType()->isObjCIdType() || @@ -3855,20 +3887,22 @@ static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr, return true; else { if (warn) { - S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf) - << castExpr->getType() << castType; - S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); - S.Diag(Target->getLocStart(), diag::note_declared_at); + S.Diag(castExpr->getBeginLoc(), + diag::warn_objc_invalid_bridge_to_cf) + << castExpr->getType() << castType; + S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at); + S.Diag(Target->getBeginLoc(), diag::note_declared_at); } return false; } } } - S.Diag(castExpr->getLocStart(), diag::err_objc_ns_bridged_invalid_cfobject) - << castExpr->getType() << castType; - S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); + S.Diag(castExpr->getBeginLoc(), + diag::err_objc_ns_bridged_invalid_cfobject) + << castExpr->getType() << castType; + S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at); if (Target) - S.Diag(Target->getLocStart(), diag::note_declared_at); + S.Diag(Target->getBeginLoc(), diag::note_declared_at); return true; } return false; @@ -3879,7 +3913,7 @@ static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr, } void Sema::CheckTollFreeBridgeCast(QualType castType, Expr *castExpr) { - if (!getLangOpts().ObjC1) + if (!getLangOpts().ObjC) return; // warn in presence of __bridge casting to or from a toll free bridge cast. ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExpr->getType()); @@ -3945,13 +3979,13 @@ void Sema::CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr) { ARCConversionTypeClass castExprACTC = classifyTypeForARCConversion(castType); if (srcExprACTC != ACTC_retainable || castExprACTC != ACTC_coreFoundation) return; - CheckObjCBridgeRelatedConversions(castExpr->getLocStart(), - castType, SrcType, castExpr); + CheckObjCBridgeRelatedConversions(castExpr->getBeginLoc(), castType, SrcType, + castExpr); } bool Sema::CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr, CastKind &Kind) { - if (!getLangOpts().ObjC1) + if (!getLangOpts().ObjC) return false; ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExpr->getType()); @@ -3991,7 +4025,7 @@ bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc, if (Diagnose) { Diag(Loc, diag::err_objc_bridged_related_invalid_class) << RCId << SrcType << DestType; - Diag(TDNDecl->getLocStart(), diag::note_declared_at); + Diag(TDNDecl->getBeginLoc(), diag::note_declared_at); } return false; } @@ -4002,9 +4036,9 @@ bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc, if (Diagnose) { Diag(Loc, diag::err_objc_bridged_related_invalid_class_name) << RCId << SrcType << DestType; - Diag(TDNDecl->getLocStart(), diag::note_declared_at); + Diag(TDNDecl->getBeginLoc(), diag::note_declared_at); if (Target) - Diag(Target->getLocStart(), diag::note_declared_at); + Diag(Target->getBeginLoc(), diag::note_declared_at); } return false; } @@ -4017,7 +4051,7 @@ bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc, if (Diagnose) { Diag(Loc, diag::err_objc_bridged_related_known_method) << SrcType << DestType << Sel << false; - Diag(TDNDecl->getLocStart(), diag::note_declared_at); + Diag(TDNDecl->getBeginLoc(), diag::note_declared_at); } return false; } @@ -4031,7 +4065,7 @@ bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc, if (Diagnose) { Diag(Loc, diag::err_objc_bridged_related_known_method) << SrcType << DestType << Sel << true; - Diag(TDNDecl->getLocStart(), diag::note_declared_at); + Diag(TDNDecl->getBeginLoc(), diag::note_declared_at); } return false; } @@ -4067,14 +4101,16 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc, ExpressionString += RelatedClass->getNameAsString(); ExpressionString += " "; ExpressionString += ClassMethod->getSelector().getAsString(); - SourceLocation SrcExprEndLoc = getLocForEndOfToken(SrcExpr->getLocEnd()); + SourceLocation SrcExprEndLoc = + getLocForEndOfToken(SrcExpr->getEndLoc()); // Provide a fixit: [RelatedClass ClassMethod SrcExpr] Diag(Loc, diag::err_objc_bridged_related_known_method) - << SrcType << DestType << ClassMethod->getSelector() << false - << FixItHint::CreateInsertion(SrcExpr->getLocStart(), ExpressionString) - << FixItHint::CreateInsertion(SrcExprEndLoc, "]"); - Diag(RelatedClass->getLocStart(), diag::note_declared_at); - Diag(TDNDecl->getLocStart(), diag::note_declared_at); + << SrcType << DestType << ClassMethod->getSelector() << false + << FixItHint::CreateInsertion(SrcExpr->getBeginLoc(), + ExpressionString) + << FixItHint::CreateInsertion(SrcExprEndLoc, "]"); + Diag(RelatedClass->getBeginLoc(), diag::note_declared_at); + Diag(TDNDecl->getBeginLoc(), diag::note_declared_at); QualType receiverType = Context.getObjCInterfaceType(RelatedClass); // Argument. @@ -4094,7 +4130,7 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc, if (Diagnose) { std::string ExpressionString; SourceLocation SrcExprEndLoc = - getLocForEndOfToken(SrcExpr->getLocEnd()); + getLocForEndOfToken(SrcExpr->getEndLoc()); if (InstanceMethod->isPropertyAccessor()) if (const ObjCPropertyDecl *PDecl = InstanceMethod->findPropertyDecl()) { @@ -4113,11 +4149,11 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc, Diag(Loc, diag::err_objc_bridged_related_known_method) << SrcType << DestType << InstanceMethod->getSelector() << true - << FixItHint::CreateInsertion(SrcExpr->getLocStart(), "[") + << FixItHint::CreateInsertion(SrcExpr->getBeginLoc(), "[") << FixItHint::CreateInsertion(SrcExprEndLoc, ExpressionString); } - Diag(RelatedClass->getLocStart(), diag::note_declared_at); - Diag(TDNDecl->getLocStart(), diag::note_declared_at); + Diag(RelatedClass->getBeginLoc(), diag::note_declared_at); + Diag(TDNDecl->getBeginLoc(), diag::note_declared_at); ExprResult msg = BuildInstanceMessageImplicit(SrcExpr, SrcType, diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index f006a677b6789..10c0c6bf33b35 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -194,15 +194,15 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT, // [dcl.init.string]p2 if (StrLength > CAT->getSize().getZExtValue()) - S.Diag(Str->getLocStart(), + S.Diag(Str->getBeginLoc(), diag::err_initializer_string_for_char_array_too_long) - << Str->getSourceRange(); + << Str->getSourceRange(); } else { // C99 6.7.8p14. if (StrLength-1 > CAT->getSize().getZExtValue()) - S.Diag(Str->getLocStart(), + S.Diag(Str->getBeginLoc(), diag::ext_initializer_string_for_char_array_too_long) - << Str->getSourceRange(); + << Str->getSourceRange(); } // Set the type to the actual size that we are initializing. If we have @@ -518,10 +518,10 @@ void InitListChecker::FillInEmptyInitForBase( if (!ILE->getInit(Init)) { ExprResult BaseInit = - FillWithNoInit ? new (SemaRef.Context) NoInitExpr(Base.getType()) - : PerformEmptyInit(SemaRef, ILE->getLocEnd(), BaseEntity, - /*VerifyOnly*/ false, - TreatUnavailableAsInvalid); + FillWithNoInit + ? new (SemaRef.Context) NoInitExpr(Base.getType()) + : PerformEmptyInit(SemaRef, ILE->getEndLoc(), BaseEntity, + /*VerifyOnly*/ false, TreatUnavailableAsInvalid); if (BaseInit.isInvalid()) { hadError = true; return; @@ -545,7 +545,7 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field, InitListExpr *ILE, bool &RequiresSecondPass, bool FillWithNoInit) { - SourceLocation Loc = ILE->getLocEnd(); + SourceLocation Loc = ILE->getEndLoc(); unsigned NumInits = ILE->getNumInits(); InitializedEntity MemberEntity = InitializedEntity::InitializeMember(Field, &ParentEntity); @@ -765,10 +765,9 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity, if (FillWithNoInit) Filler = new (SemaRef.Context) NoInitExpr(ElementType); else { - ExprResult ElementInit = PerformEmptyInit(SemaRef, ILE->getLocEnd(), - ElementEntity, - /*VerifyOnly*/false, - TreatUnavailableAsInvalid); + ExprResult ElementInit = + PerformEmptyInit(SemaRef, ILE->getEndLoc(), ElementEntity, + /*VerifyOnly*/ false, TreatUnavailableAsInvalid); if (ElementInit.isInvalid()) { hadError = true; return; @@ -917,7 +916,7 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity, if (maxElements == 0) { if (!VerifyOnly) - SemaRef.Diag(ParentIList->getInit(Index)->getLocStart(), + SemaRef.Diag(ParentIList->getInit(Index)->getBeginLoc(), diag::err_implicit_empty_initializer); ++Index; hadError = true; @@ -925,11 +924,10 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity, } // Build a structured initializer list corresponding to this subobject. - InitListExpr *StructuredSubobjectInitList - = getStructuredSubobjectInit(ParentIList, Index, T, StructuredList, - StructuredIndex, - SourceRange(ParentIList->getInit(Index)->getLocStart(), - ParentIList->getSourceRange().getEnd())); + InitListExpr *StructuredSubobjectInitList = getStructuredSubobjectInit( + ParentIList, Index, T, StructuredList, StructuredIndex, + SourceRange(ParentIList->getInit(Index)->getBeginLoc(), + ParentIList->getSourceRange().getEnd())); unsigned StructuredSubobjectInitIndex = 0; // Check the element types and build the structural subobject. @@ -956,16 +954,24 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity, if ((T->isArrayType() || T->isRecordType()) && !ParentIList->isIdiomaticZeroInitializer(SemaRef.getLangOpts()) && !isIdiomaticBraceElisionEntity(Entity)) { - SemaRef.Diag(StructuredSubobjectInitList->getLocStart(), + SemaRef.Diag(StructuredSubobjectInitList->getBeginLoc(), diag::warn_missing_braces) << StructuredSubobjectInitList->getSourceRange() << FixItHint::CreateInsertion( - StructuredSubobjectInitList->getLocStart(), "{") + StructuredSubobjectInitList->getBeginLoc(), "{") << FixItHint::CreateInsertion( SemaRef.getLocForEndOfToken( - StructuredSubobjectInitList->getLocEnd()), + StructuredSubobjectInitList->getEndLoc()), "}"); } + + // Warn if this type won't be an aggregate in future versions of C++. + auto *CXXRD = T->getAsCXXRecordDecl(); + if (CXXRD && CXXRD->hasUserDeclaredConstructor()) { + SemaRef.Diag(StructuredSubobjectInitList->getBeginLoc(), + diag::warn_cxx2a_compat_aggregate_init_with_ctors) + << StructuredSubobjectInitList->getSourceRange() << T; + } } } @@ -1080,8 +1086,8 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity, hadError = true; } // Special-case - SemaRef.Diag(IList->getInit(Index)->getLocStart(), DK) - << IList->getInit(Index)->getSourceRange(); + SemaRef.Diag(IList->getInit(Index)->getBeginLoc(), DK) + << IList->getInit(Index)->getSourceRange(); } else if (!T->isIncompleteType()) { // Don't complain for incomplete types, since we'll get an error // elsewhere @@ -1103,14 +1109,35 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity, hadError = true; } - SemaRef.Diag(IList->getInit(Index)->getLocStart(), DK) - << initKind << IList->getInit(Index)->getSourceRange(); + SemaRef.Diag(IList->getInit(Index)->getBeginLoc(), DK) + << initKind << IList->getInit(Index)->getSourceRange(); } } - if (!VerifyOnly && T->isScalarType() && - IList->getNumInits() == 1 && !isa<InitListExpr>(IList->getInit(0))) - warnBracedScalarInit(SemaRef, Entity, IList->getSourceRange()); + if (!VerifyOnly) { + if (T->isScalarType() && IList->getNumInits() == 1 && + !isa<InitListExpr>(IList->getInit(0))) + warnBracedScalarInit(SemaRef, Entity, IList->getSourceRange()); + + // Warn if this is a class type that won't be an aggregate in future + // versions of C++. + auto *CXXRD = T->getAsCXXRecordDecl(); + if (CXXRD && CXXRD->hasUserDeclaredConstructor()) { + // Don't warn if there's an equivalent default constructor that would be + // used instead. + bool HasEquivCtor = false; + if (IList->getNumInits() == 0) { + auto *CD = SemaRef.LookupDefaultConstructor(CXXRD); + HasEquivCtor = CD && !CD->isDeleted(); + } + + if (!HasEquivCtor) { + SemaRef.Diag(IList->getBeginLoc(), + diag::warn_cxx2a_compat_aggregate_init_with_ctors) + << IList->getSourceRange() << T; + } + } + } } void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity, @@ -1155,21 +1182,24 @@ void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity, // This type is invalid, issue a diagnostic. ++Index; if (!VerifyOnly) - SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type) - << DeclType; + SemaRef.Diag(IList->getBeginLoc(), diag::err_illegal_initializer_type) + << DeclType; hadError = true; } else if (DeclType->isReferenceType()) { CheckReferenceType(Entity, IList, DeclType, Index, StructuredList, StructuredIndex); } else if (DeclType->isObjCObjectType()) { if (!VerifyOnly) - SemaRef.Diag(IList->getLocStart(), diag::err_init_objc_class) - << DeclType; + SemaRef.Diag(IList->getBeginLoc(), diag::err_init_objc_class) << DeclType; hadError = true; + } else if (DeclType->isOCLIntelSubgroupAVCType()) { + // Checks for scalar type are sufficient for these types too. + CheckScalarType(Entity, IList, DeclType, Index, StructuredList, + StructuredIndex); } else { if (!VerifyOnly) - SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type) - << DeclType; + SemaRef.Diag(IList->getBeginLoc(), diag::err_illegal_initializer_type) + << DeclType; hadError = true; } } @@ -1232,7 +1262,7 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, // FIXME: Better EqualLoc? InitializationKind Kind = - InitializationKind::CreateCopy(expr->getLocStart(), SourceLocation()); + InitializationKind::CreateCopy(expr->getBeginLoc(), SourceLocation()); InitializationSequence Seq(SemaRef, Entity, Kind, expr, /*TopLevelOfInitList*/ true); @@ -1356,8 +1386,8 @@ void InitListChecker::CheckComplexType(const InitializedEntity &Entity, // This is an extension in C. (The builtin _Complex type does not exist // in the C++ standard.) if (!SemaRef.getLangOpts().CPlusPlus && !VerifyOnly) - SemaRef.Diag(IList->getLocStart(), diag::ext_complex_component_init) - << IList->getSourceRange(); + SemaRef.Diag(IList->getBeginLoc(), diag::ext_complex_component_init) + << IList->getSourceRange(); // Initialize the complex number. QualType elementType = DeclType->getAs<ComplexType>()->getElementType(); @@ -1378,11 +1408,11 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity, unsigned &StructuredIndex) { if (Index >= IList->getNumInits()) { if (!VerifyOnly) - SemaRef.Diag(IList->getLocStart(), - SemaRef.getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_empty_scalar_initializer : - diag::err_empty_scalar_initializer) - << IList->getSourceRange(); + SemaRef.Diag(IList->getBeginLoc(), + SemaRef.getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_empty_scalar_initializer + : diag::err_empty_scalar_initializer) + << IList->getSourceRange(); hadError = !SemaRef.getLangOpts().CPlusPlus11; ++Index; ++StructuredIndex; @@ -1394,18 +1424,17 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity, // FIXME: This is invalid, and accepting it causes overload resolution // to pick the wrong overload in some corner cases. if (!VerifyOnly) - SemaRef.Diag(SubIList->getLocStart(), + SemaRef.Diag(SubIList->getBeginLoc(), diag::ext_many_braces_around_scalar_init) - << SubIList->getSourceRange(); + << SubIList->getSourceRange(); CheckScalarType(Entity, SubIList, DeclType, Index, StructuredList, StructuredIndex); return; } else if (isa<DesignatedInitExpr>(expr)) { if (!VerifyOnly) - SemaRef.Diag(expr->getLocStart(), - diag::err_designator_for_scalar_init) - << DeclType << expr->getSourceRange(); + SemaRef.Diag(expr->getBeginLoc(), diag::err_designator_for_scalar_init) + << DeclType << expr->getSourceRange(); hadError = true; ++Index; ++StructuredIndex; @@ -1420,8 +1449,8 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity, } ExprResult Result = - SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(), expr, - /*TopLevelOfInitList=*/true); + SemaRef.PerformCopyInitialization(Entity, expr->getBeginLoc(), expr, + /*TopLevelOfInitList=*/true); Expr *ResultExpr = nullptr; @@ -1453,10 +1482,9 @@ void InitListChecker::CheckReferenceType(const InitializedEntity &Entity, // so that we know the location (or decl) of the "current object" being // initialized. if (!VerifyOnly) - SemaRef.Diag(IList->getLocStart(), - diag::err_init_reference_member_uninitialized) - << DeclType - << IList->getSourceRange(); + SemaRef.Diag(IList->getBeginLoc(), + diag::err_init_reference_member_uninitialized) + << DeclType << IList->getSourceRange(); hadError = true; ++Index; ++StructuredIndex; @@ -1466,8 +1494,8 @@ void InitListChecker::CheckReferenceType(const InitializedEntity &Entity, Expr *expr = IList->getInit(Index); if (isa<InitListExpr>(expr) && !SemaRef.getLangOpts().CPlusPlus11) { if (!VerifyOnly) - SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list) - << DeclType << IList->getSourceRange(); + SemaRef.Diag(IList->getBeginLoc(), diag::err_init_non_aggr_init_list) + << DeclType << IList->getSourceRange(); hadError = true; ++Index; ++StructuredIndex; @@ -1482,7 +1510,7 @@ void InitListChecker::CheckReferenceType(const InitializedEntity &Entity, } ExprResult Result = - SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(), expr, + SemaRef.PerformCopyInitialization(Entity, expr->getBeginLoc(), expr, /*TopLevelOfInitList=*/true); if (Result.isInvalid()) @@ -1513,7 +1541,7 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity, if (VerifyOnly) CheckEmptyInitializable( InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity), - IList->getLocEnd()); + IList->getEndLoc()); return; } @@ -1529,9 +1557,9 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity, return; } - ExprResult Result = - SemaRef.PerformCopyInitialization(Entity, Init->getLocStart(), Init, - /*TopLevelOfInitList=*/true); + ExprResult Result = + SemaRef.PerformCopyInitialization(Entity, Init->getBeginLoc(), Init, + /*TopLevelOfInitList=*/true); Expr *ResultExpr = nullptr; if (Result.isInvalid()) @@ -1560,7 +1588,7 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity, // Don't attempt to go past the end of the init list if (Index >= IList->getNumInits()) { if (VerifyOnly) - CheckEmptyInitializable(ElementEntity, IList->getLocEnd()); + CheckEmptyInitializable(ElementEntity, IList->getEndLoc()); break; } @@ -1586,7 +1614,7 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity, // // Because of this, explicitly call out that it is non-portable. // - SemaRef.Diag(IList->getLocStart(), + SemaRef.Diag(IList->getBeginLoc(), diag::warn_neon_vector_initializer_non_portable); const char *typeCode; @@ -1601,11 +1629,11 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity, else llvm_unreachable("Invalid element type!"); - SemaRef.Diag(IList->getLocStart(), - SemaRef.Context.getTypeSize(VT) > 64 ? - diag::note_neon_vector_initializer_non_portable_q : - diag::note_neon_vector_initializer_non_portable) - << typeCode << typeSize; + SemaRef.Diag(IList->getBeginLoc(), + SemaRef.Context.getTypeSize(VT) > 64 + ? diag::note_neon_vector_initializer_non_portable_q + : diag::note_neon_vector_initializer_non_portable) + << typeCode << typeSize; } return; @@ -1646,9 +1674,9 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity, // OpenCL requires all elements to be initialized. if (numEltsInit != maxElements) { if (!VerifyOnly) - SemaRef.Diag(IList->getLocStart(), + SemaRef.Diag(IList->getBeginLoc(), diag::err_vector_incorrect_num_initializers) - << (numEltsInit < maxElements) << maxElements << numEltsInit; + << (numEltsInit < maxElements) << maxElements << numEltsInit; hadError = true; } } @@ -1686,9 +1714,9 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity, // earlier, but I don't know where clang accepts VLAs (gcc accepts // them in all sorts of strange places). if (!VerifyOnly) - SemaRef.Diag(VAT->getSizeExpr()->getLocStart(), - diag::err_variable_object_no_init) - << VAT->getSizeExpr()->getSourceRange(); + SemaRef.Diag(VAT->getSizeExpr()->getBeginLoc(), + diag::err_variable_object_no_init) + << VAT->getSizeExpr()->getSourceRange(); hadError = true; ++Index; ++StructuredIndex; @@ -1765,8 +1793,7 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity, if (maxElements == Zero && !Entity.isVariableLengthArrayNew()) { // Sizing an array implicitly to zero is not allowed by ISO C, // but is supported by GNU. - SemaRef.Diag(IList->getLocStart(), - diag::ext_typecheck_zero_array_size); + SemaRef.Diag(IList->getBeginLoc(), diag::ext_typecheck_zero_array_size); } DeclType = SemaRef.Context.getConstantArrayType(elementType, maxElements, @@ -1780,9 +1807,9 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity, // FIXME: This needs to detect holes left by designated initializers too. if ((maxElementsKnown && elementIndex < maxElements) || Entity.isVariableLengthArrayNew()) - CheckEmptyInitializable(InitializedEntity::InitializeElement( - SemaRef.Context, 0, Entity), - IList->getLocEnd()); + CheckEmptyInitializable( + InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity), + IList->getEndLoc()); } } @@ -1815,9 +1842,8 @@ bool InitListChecker::CheckFlexibleArrayInit(const InitializedEntity &Entity, } if (!VerifyOnly) { - SemaRef.Diag(InitExpr->getLocStart(), - FlexArrayDiag) - << InitExpr->getLocStart(); + SemaRef.Diag(InitExpr->getBeginLoc(), FlexArrayDiag) + << InitExpr->getBeginLoc(); SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member) << Field; } @@ -1825,6 +1851,30 @@ bool InitListChecker::CheckFlexibleArrayInit(const InitializedEntity &Entity, return FlexArrayDiag != diag::ext_flexible_array_init; } +/// Check if the type of a class element has an accessible destructor. +/// +/// Aggregate initialization requires a class element's destructor be +/// accessible per 11.6.1 [dcl.init.aggr]: +/// +/// The destructor for each element of class type is potentially invoked +/// (15.4 [class.dtor]) from the context where the aggregate initialization +/// occurs. +static bool hasAccessibleDestructor(QualType ElementType, SourceLocation Loc, + Sema &SemaRef) { + auto *CXXRD = ElementType->getAsCXXRecordDecl(); + if (!CXXRD) + return false; + + CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(CXXRD); + SemaRef.CheckDestructorAccess(Loc, Destructor, + SemaRef.PDiag(diag::err_access_dtor_temp) + << ElementType); + SemaRef.MarkFunctionReferenced(Loc, Destructor); + if (SemaRef.DiagnoseUseOfDecl(Destructor, Loc)) + return true; + return false; +} + void InitListChecker::CheckStructUnionTypes( const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, CXXRecordDecl::base_class_range Bases, RecordDecl::field_iterator Field, @@ -1845,6 +1895,15 @@ void InitListChecker::CheckStructUnionTypes( if (DeclType->isUnionType() && IList->getNumInits() == 0) { RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl(); + if (!VerifyOnly) + for (FieldDecl *FD : RD->fields()) { + QualType ET = SemaRef.Context.getBaseElementType(FD->getType()); + if (hasAccessibleDestructor(ET, IList->getEndLoc(), SemaRef)) { + hadError = true; + return; + } + } + // If there's a default initializer, use it. if (isa<CXXRecordDecl>(RD) && cast<CXXRecordDecl>(RD)->hasInClassInitializer()) { if (VerifyOnly) @@ -1867,7 +1926,7 @@ void InitListChecker::CheckStructUnionTypes( if (VerifyOnly) CheckEmptyInitializable( InitializedEntity::InitializeMember(*Field, &Entity), - IList->getLocEnd()); + IList->getEndLoc()); else StructuredList->setInitializedFieldInUnion(*Field); break; @@ -1881,13 +1940,13 @@ void InitListChecker::CheckStructUnionTypes( // If we have any base classes, they are initialized prior to the fields. for (auto &Base : Bases) { Expr *Init = Index < IList->getNumInits() ? IList->getInit(Index) : nullptr; - SourceLocation InitLoc = Init ? Init->getLocStart() : IList->getLocEnd(); // Designated inits always initialize fields, so if we see one, all // remaining base classes have no explicit initializer. if (Init && isa<DesignatedInitExpr>(Init)) Init = nullptr; + SourceLocation InitLoc = Init ? Init->getBeginLoc() : IList->getEndLoc(); InitializedEntity BaseEntity = InitializedEntity::InitializeBase( SemaRef.Context, &Base, false, &Entity); if (Init) { @@ -1897,6 +1956,12 @@ void InitListChecker::CheckStructUnionTypes( } else if (VerifyOnly) { CheckEmptyInitializable(BaseEntity, InitLoc); } + + if (!VerifyOnly) + if (hasAccessibleDestructor(Base.getType(), InitLoc, SemaRef)) { + hadError = true; + return; + } } // If structDecl is a forward declaration, this loop won't do @@ -1907,9 +1972,11 @@ void InitListChecker::CheckStructUnionTypes( RecordDecl::field_iterator FieldEnd = RD->field_end(); bool CheckForMissingFields = !IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts()); + bool HasDesignatedInit = false; while (Index < IList->getNumInits()) { Expr *Init = IList->getInit(Index); + SourceLocation InitLoc = Init->getBeginLoc(); if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Init)) { // If we're not the subobject that matches up with the '{' for @@ -1918,6 +1985,8 @@ void InitListChecker::CheckStructUnionTypes( if (!SubobjectIsDesignatorContext) return; + HasDesignatedInit = true; + // Handle this designated initializer. Field will be updated to // the next field that we'll be initializing. if (CheckDesignatedInitializer(Entity, IList, DIE, 0, @@ -1925,6 +1994,17 @@ void InitListChecker::CheckStructUnionTypes( StructuredList, StructuredIndex, true, TopLevelObject)) hadError = true; + else if (!VerifyOnly) { + // Find the field named by the designated initializer. + RecordDecl::field_iterator F = RD->field_begin(); + while (std::next(F) != Field) + ++F; + QualType ET = SemaRef.Context.getBaseElementType(F->getType()); + if (hasAccessibleDestructor(ET, InitLoc, SemaRef)) { + hadError = true; + return; + } + } InitializedSomething = true; @@ -1958,8 +2038,8 @@ void InitListChecker::CheckStructUnionTypes( if (VerifyOnly) InvalidUse = !SemaRef.CanUseDecl(*Field, TreatUnavailableAsInvalid); else - InvalidUse = SemaRef.DiagnoseUseOfDecl(*Field, - IList->getInit(Index)->getLocStart()); + InvalidUse = SemaRef.DiagnoseUseOfDecl( + *Field, IList->getInit(Index)->getBeginLoc()); if (InvalidUse) { ++Index; ++Field; @@ -1967,6 +2047,14 @@ void InitListChecker::CheckStructUnionTypes( continue; } + if (!VerifyOnly) { + QualType ET = SemaRef.Context.getBaseElementType(Field->getType()); + if (hasAccessibleDestructor(ET, InitLoc, SemaRef)) { + hadError = true; + return; + } + } + InitializedEntity MemberEntity = InitializedEntity::InitializeMember(*Field, &Entity); CheckSubElementType(MemberEntity, IList, Field->getType(), Index, @@ -2005,7 +2093,22 @@ void InitListChecker::CheckStructUnionTypes( if (!Field->isUnnamedBitfield() && !Field->hasInClassInitializer()) CheckEmptyInitializable( InitializedEntity::InitializeMember(*Field, &Entity), - IList->getLocEnd()); + IList->getEndLoc()); + } + } + + // Check that the types of the remaining fields have accessible destructors. + if (!VerifyOnly) { + // If the initializer expression has a designated initializer, check the + // elements for which a designated initializer is not provided too. + RecordDecl::field_iterator I = HasDesignatedInit ? RD->field_begin() + : Field; + for (RecordDecl::field_iterator E = RD->field_end(); I != E; ++I) { + QualType ET = SemaRef.Context.getBaseElementType(I->getType()); + if (hasAccessibleDestructor(ET, IList->getEndLoc(), SemaRef)) { + hadError = true; + return; + } } } @@ -2182,11 +2285,9 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, ExistingInit = StructuredList->getArrayFiller(); if (!ExistingInit) - StructuredList = - getStructuredSubobjectInit(IList, Index, CurrentObjectType, - StructuredList, StructuredIndex, - SourceRange(D->getLocStart(), - DIE->getLocEnd())); + StructuredList = getStructuredSubobjectInit( + IList, Index, CurrentObjectType, StructuredList, StructuredIndex, + SourceRange(D->getBeginLoc(), DIE->getEndLoc())); else if (InitListExpr *Result = dyn_cast<InitListExpr>(ExistingInit)) StructuredList = Result; else { @@ -2194,10 +2295,9 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, dyn_cast<DesignatedInitUpdateExpr>(ExistingInit)) StructuredList = E->getUpdater(); else { - DesignatedInitUpdateExpr *DIUE = - new (SemaRef.Context) DesignatedInitUpdateExpr(SemaRef.Context, - D->getLocStart(), ExistingInit, - DIE->getLocEnd()); + DesignatedInitUpdateExpr *DIUE = new (SemaRef.Context) + DesignatedInitUpdateExpr(SemaRef.Context, D->getBeginLoc(), + ExistingInit, DIE->getEndLoc()); StructuredList->updateInit(SemaRef.Context, StructuredIndex, DIUE); StructuredList = DIUE->getUpdater(); } @@ -2222,14 +2322,13 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, // Here, xs[0].a == 0 and xs[0].b == 3, since the second, // designated initializer re-initializes the whole // subobject [0], overwriting previous initializers. - SemaRef.Diag(D->getLocStart(), + SemaRef.Diag(D->getBeginLoc(), diag::warn_subobject_initializer_overrides) - << SourceRange(D->getLocStart(), DIE->getLocEnd()); + << SourceRange(D->getBeginLoc(), DIE->getEndLoc()); - SemaRef.Diag(ExistingInit->getLocStart(), + SemaRef.Diag(ExistingInit->getBeginLoc(), diag::note_previous_initializer) - << /*FIXME:has side effects=*/0 - << ExistingInit->getSourceRange(); + << /*FIXME:has side effects=*/0 << ExistingInit->getSourceRange(); } } } @@ -2350,10 +2449,10 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, SemaRef.Diag(D->getFieldLoc(), diag::warn_initializer_overrides) << D->getSourceRange(); - SemaRef.Diag(ExistingInit->getLocStart(), + SemaRef.Diag(ExistingInit->getBeginLoc(), diag::note_previous_initializer) - << /*FIXME:has side effects=*/0 - << ExistingInit->getSourceRange(); + << /*FIXME:has side effects=*/0 + << ExistingInit->getSourceRange(); } // remove existing initializer @@ -2395,10 +2494,9 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, if (!VerifyOnly) { DesignatedInitExpr::Designator *NextD = DIE->getDesignator(DesigIdx + 1); - SemaRef.Diag(NextD->getLocStart(), - diag::err_designator_into_flexible_array_member) - << SourceRange(NextD->getLocStart(), - DIE->getLocEnd()); + SemaRef.Diag(NextD->getBeginLoc(), + diag::err_designator_into_flexible_array_member) + << SourceRange(NextD->getBeginLoc(), DIE->getEndLoc()); SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member) << *Field; } @@ -2409,9 +2507,9 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, !isa<StringLiteral>(DIE->getInit())) { // The initializer is not an initializer list. if (!VerifyOnly) { - SemaRef.Diag(DIE->getInit()->getLocStart(), - diag::err_flexible_array_init_needs_braces) - << DIE->getInit()->getSourceRange(); + SemaRef.Diag(DIE->getInit()->getBeginLoc(), + diag::err_flexible_array_init_needs_braces) + << DIE->getInit()->getSourceRange(); SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member) << *Field; } @@ -2553,10 +2651,10 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, DesignatedEndIndex.setIsUnsigned(MaxElements.isUnsigned()); if (DesignatedEndIndex >= MaxElements) { if (!VerifyOnly) - SemaRef.Diag(IndexExpr->getLocStart(), - diag::err_array_designator_too_large) - << DesignatedEndIndex.toString(10) << MaxElements.toString(10) - << IndexExpr->getSourceRange(); + SemaRef.Diag(IndexExpr->getBeginLoc(), + diag::err_array_designator_too_large) + << DesignatedEndIndex.toString(10) << MaxElements.toString(10) + << IndexExpr->getSourceRange(); ++Index; return true; } @@ -2728,10 +2826,8 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index, SemaRef.Diag(InitRange.getBegin(), diag::warn_subobject_initializer_overrides) << InitRange; - SemaRef.Diag(ExistingInit->getLocStart(), - diag::note_previous_initializer) - << /*FIXME:has side effects=*/0 - << ExistingInit->getSourceRange(); + SemaRef.Diag(ExistingInit->getBeginLoc(), diag::note_previous_initializer) + << /*FIXME:has side effects=*/0 << ExistingInit->getSourceRange(); } InitListExpr *Result @@ -2810,14 +2906,11 @@ void InitListChecker::UpdateStructuredListElement(InitListExpr *StructuredList, // There is an overwrite taking place because the first braced initializer // list "{ .a = 2 }' already provides value for .p.b (which is zero). if (PrevInit->getSourceRange().isValid()) { - SemaRef.Diag(expr->getLocStart(), - diag::warn_initializer_overrides) - << expr->getSourceRange(); + SemaRef.Diag(expr->getBeginLoc(), diag::warn_initializer_overrides) + << expr->getSourceRange(); - SemaRef.Diag(PrevInit->getLocStart(), - diag::note_previous_initializer) - << /*FIXME:has side effects=*/0 - << PrevInit->getSourceRange(); + SemaRef.Diag(PrevInit->getBeginLoc(), diag::note_previous_initializer) + << /*FIXME:has side effects=*/0 << PrevInit->getSourceRange(); } } @@ -2833,7 +2926,7 @@ void InitListChecker::UpdateStructuredListElement(InitListExpr *StructuredList, /// value of the constant expression. static ExprResult CheckArrayDesignatorExpr(Sema &S, Expr *Index, llvm::APSInt &Value) { - SourceLocation Loc = Index->getLocStart(); + SourceLocation Loc = Index->getBeginLoc(); // Make sure this is an integer constant expression. ExprResult Result = S.VerifyIntegerConstantExpression(Index, &Value); @@ -2941,8 +3034,8 @@ ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, Init.getAs<Expr>()); if (!getLangOpts().C99) - Diag(DIE->getLocStart(), diag::ext_designated_init) - << DIE->getSourceRange(); + Diag(DIE->getBeginLoc(), diag::ext_designated_init) + << DIE->getSourceRange(); return DIE; } @@ -3172,8 +3265,7 @@ void InitializationSequence::Step::Destroy() { case SK_StdInitializerList: case SK_StdInitializerListConstructorCall: case SK_OCLSamplerInit: - case SK_OCLZeroEvent: - case SK_OCLZeroQueue: + case SK_OCLZeroOpaqueType: break; case SK_ConversionSequence: @@ -3459,16 +3551,9 @@ void InitializationSequence::AddOCLSamplerInitStep(QualType T) { Steps.push_back(S); } -void InitializationSequence::AddOCLZeroEventStep(QualType T) { +void InitializationSequence::AddOCLZeroOpaqueTypeStep(QualType T) { Step S; - S.Kind = SK_OCLZeroEvent; - S.Type = T; - Steps.push_back(S); -} - -void InitializationSequence::AddOCLZeroQueueStep(QualType T) { - Step S; - S.Kind = SK_OCLZeroQueue; + S.Kind = SK_OCLZeroOpaqueType; S.Type = T; Steps.push_back(S); } @@ -3507,11 +3592,11 @@ maybeRecoverWithZeroInitialization(Sema &S, InitializationSequence &Sequence, return false; VarDecl *VD = cast<VarDecl>(Entity.getDecl()); - if (VD->getInit() || VD->getLocEnd().isMacroID()) + if (VD->getInit() || VD->getEndLoc().isMacroID()) return false; QualType VariableTy = VD->getType().getCanonicalType(); - SourceLocation Loc = S.getLocForEndOfToken(VD->getLocEnd()); + SourceLocation Loc = S.getLocForEndOfToken(VD->getEndLoc()); std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc); if (!Init.empty()) { Sequence.AddZeroInitializationStep(Entity.getType()); @@ -3583,7 +3668,7 @@ static bool TryInitializerListConstruction(Sema &S, InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary(ArrayType); InitializationKind Kind = InitializationKind::CreateDirectList( - List->getExprLoc(), List->getLocStart(), List->getLocEnd()); + List->getExprLoc(), List->getBeginLoc(), List->getEndLoc()); TryListInitialization(S, HiddenArray, Kind, List, Sequence, TreatUnavailableAsInvalid); if (Sequence) @@ -3974,7 +4059,7 @@ static void TryReferenceListInitialization(Sema &S, T1, Sequence)) return; - SourceLocation DeclLoc = Initializer->getLocStart(); + SourceLocation DeclLoc = Initializer->getBeginLoc(); bool dummy1, dummy2, dummy3; Sema::ReferenceCompareResult RefRelationship = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, dummy1, @@ -4031,7 +4116,7 @@ static void TryListInitialization(Sema &S, } if (DestType->isRecordType() && - !S.isCompleteType(InitList->getLocStart(), DestType)) { + !S.isCompleteType(InitList->getBeginLoc(), DestType)) { Sequence.setIncompleteTypeFailure(DestType); return; } @@ -4051,7 +4136,7 @@ static void TryListInitialization(Sema &S, if (DestType->isRecordType()) { QualType InitType = InitList->getInit(0)->getType(); if (S.Context.hasSameUnqualifiedType(InitType, DestType) || - S.IsDerivedFrom(InitList->getLocStart(), InitType, DestType)) { + S.IsDerivedFrom(InitList->getBeginLoc(), InitType, DestType)) { Expr *InitListAsExpr = InitList; TryConstructorInitialization(S, Entity, Kind, InitListAsExpr, DestType, DestType, Sequence, @@ -4218,9 +4303,8 @@ static OverloadingResult TryRefInitWithConversionFunction( bool DerivedToBase; bool ObjCConversion; bool ObjCLifetimeConversion; - assert(!S.CompareReferenceRelationship(Initializer->getLocStart(), - T1, T2, DerivedToBase, - ObjCConversion, + assert(!S.CompareReferenceRelationship(Initializer->getBeginLoc(), T1, T2, + DerivedToBase, ObjCConversion, ObjCLifetimeConversion) && "Must have incompatible references when binding via conversion"); (void)DerivedToBase; @@ -4313,7 +4397,7 @@ static OverloadingResult TryRefInitWithConversionFunction( if (T2RecordType && T2RecordType->getDecl()->isInvalidDecl()) return OR_No_Viable_Function; - SourceLocation DeclLoc = Initializer->getLocStart(); + SourceLocation DeclLoc = Initializer->getBeginLoc(); // Perform overload resolution. If it fails, return the failed result. OverloadCandidateSet::iterator Best; @@ -4439,7 +4523,7 @@ static void TryReferenceInitializationCore(Sema &S, Qualifiers T2Quals, InitializationSequence &Sequence) { QualType DestType = Entity.getType(); - SourceLocation DeclLoc = Initializer->getLocStart(); + SourceLocation DeclLoc = Initializer->getBeginLoc(); // Compute some basic properties of the types and the initializer. bool isLValueRef = DestType->isLValueReferenceType(); bool isRValueRef = !isLValueRef; @@ -4585,11 +4669,22 @@ static void TryReferenceInitializationCore(Sema &S, // If the converted initializer is a prvalue, its type T4 is adjusted // to type "cv1 T4" and the temporary materialization conversion is // applied. + // Postpone address space conversions to after the temporary materialization + // conversion to allow creating temporaries in the alloca address space. + auto AS1 = T1Quals.getAddressSpace(); + auto AS2 = T2Quals.getAddressSpace(); + T1Quals.removeAddressSpace(); + T2Quals.removeAddressSpace(); QualType cv1T4 = S.Context.getQualifiedType(cv2T2, T1Quals); if (T1Quals != T2Quals) Sequence.AddQualificationConversionStep(cv1T4, ValueKind); Sequence.AddReferenceBindingStep(cv1T4, ValueKind == VK_RValue); ValueKind = isLValueRef ? VK_LValue : VK_XValue; + if (AS1 != AS2) { + T1Quals.addAddressSpace(AS1); + QualType cv1AST4 = S.Context.getQualifiedType(cv2T2, T1Quals); + Sequence.AddQualificationConversionStep(cv1AST4, ValueKind); + } // In any case, the reference is bound to the resulting glvalue (or to // an appropriate base class subobject). @@ -4867,7 +4962,7 @@ static void TryUserDefinedConversion(Sema &S, } } - SourceLocation DeclLoc = Initializer->getLocStart(); + SourceLocation DeclLoc = Initializer->getBeginLoc(); if (const RecordType *SourceRecordType = SourceType->getAs<RecordType>()) { // The type we're converting from is a class type, enumerate its conversion @@ -5172,39 +5267,51 @@ static bool TryOCLSamplerInitialization(Sema &S, return true; } -// -// OpenCL 1.2 spec, s6.12.10 -// -// The event argument can also be used to associate the -// async_work_group_copy with a previous async copy allowing -// an event to be shared by multiple async copies; otherwise -// event should be zero. -// -static bool TryOCLZeroEventInitialization(Sema &S, - InitializationSequence &Sequence, - QualType DestType, - Expr *Initializer) { - if (!S.getLangOpts().OpenCL || !DestType->isEventT() || - !Initializer->isIntegerConstantExpr(S.getASTContext()) || - (Initializer->EvaluateKnownConstInt(S.getASTContext()) != 0)) - return false; - - Sequence.AddOCLZeroEventStep(DestType); - return true; +static bool IsZeroInitializer(Expr *Initializer, Sema &S) { + return Initializer->isIntegerConstantExpr(S.getASTContext()) && + (Initializer->EvaluateKnownConstInt(S.getASTContext()) == 0); } -static bool TryOCLZeroQueueInitialization(Sema &S, - InitializationSequence &Sequence, - QualType DestType, - Expr *Initializer) { - if (!S.getLangOpts().OpenCL || S.getLangOpts().OpenCLVersion < 200 || - !DestType->isQueueT() || - !Initializer->isIntegerConstantExpr(S.getASTContext()) || - (Initializer->EvaluateKnownConstInt(S.getASTContext()) != 0)) +static bool TryOCLZeroOpaqueTypeInitialization(Sema &S, + InitializationSequence &Sequence, + QualType DestType, + Expr *Initializer) { + if (!S.getLangOpts().OpenCL) return false; - Sequence.AddOCLZeroQueueStep(DestType); - return true; + // + // OpenCL 1.2 spec, s6.12.10 + // + // The event argument can also be used to associate the + // async_work_group_copy with a previous async copy allowing + // an event to be shared by multiple async copies; otherwise + // event should be zero. + // + if (DestType->isEventT() || DestType->isQueueT()) { + if (!IsZeroInitializer(Initializer, S)) + return false; + + Sequence.AddOCLZeroOpaqueTypeStep(DestType); + return true; + } + + // We should allow zero initialization for all types defined in the + // cl_intel_device_side_avc_motion_estimation extension, except + // intel_sub_group_avc_mce_payload_t and intel_sub_group_avc_mce_result_t. + if (S.getOpenCLOptions().isEnabled( + "cl_intel_device_side_avc_motion_estimation") && + DestType->isOCLIntelSubgroupAVCType()) { + if (DestType->isOCLIntelSubgroupAVCMcePayloadType() || + DestType->isOCLIntelSubgroupAVCMceResultType()) + return false; + if (!IsZeroInitializer(Initializer, S)) + return false; + + Sequence.AddOCLZeroOpaqueTypeStep(DestType); + return true; + } + + return false; } InitializationSequence::InitializationSequence(Sema &S, @@ -5309,8 +5416,8 @@ void InitializationSequence::InitializeFrom(Sema &S, Expr *Initializer = nullptr; if (Args.size() == 1) { Initializer = Args[0]; - if (S.getLangOpts().ObjC1) { - if (S.CheckObjCBridgeRelatedConversions(Initializer->getLocStart(), + if (S.getLangOpts().ObjC) { + if (S.CheckObjCBridgeRelatedConversions(Initializer->getBeginLoc(), DestType, Initializer->getType(), Initializer) || S.ConversionToObjCStringLiteralCheck(DestType, Initializer)) @@ -5431,7 +5538,8 @@ void InitializationSequence::InitializeFrom(Sema &S, // array from a compound literal that creates an array of the same // type, so long as the initializer has no side effects. if (!S.getLangOpts().CPlusPlus && Initializer && - isa<CompoundLiteralExpr>(Initializer->IgnoreParens()) && + (isa<ConstantExpr>(Initializer->IgnoreParens()) || + isa<CompoundLiteralExpr>(Initializer->IgnoreParens())) && Initializer->getType()->isArrayType()) { const ArrayType *SourceAT = Context.getAsArrayType(Initializer->getType()); @@ -5478,12 +5586,9 @@ void InitializationSequence::InitializeFrom(Sema &S, if (TryOCLSamplerInitialization(S, *this, DestType, Initializer)) return; - if (TryOCLZeroEventInitialization(S, *this, DestType, Initializer)) + if (TryOCLZeroOpaqueTypeInitialization(S, *this, DestType, Initializer)) return; - if (TryOCLZeroQueueInitialization(S, *this, DestType, Initializer)) - return; - // Handle initialization in C AddCAssignmentStep(DestType); MaybeProduceObjCObject(S, *this, Entity); @@ -5501,7 +5606,7 @@ void InitializationSequence::InitializeFrom(Sema &S, if (Kind.getKind() == InitializationKind::IK_Direct || (Kind.getKind() == InitializationKind::IK_Copy && (Context.hasSameUnqualifiedType(SourceType, DestType) || - S.IsDerivedFrom(Initializer->getLocStart(), SourceType, DestType)))) + S.IsDerivedFrom(Initializer->getBeginLoc(), SourceType, DestType)))) TryConstructorInitialization(S, Entity, Kind, Args, DestType, DestType, *this); // - Otherwise (i.e., for the remaining copy-initialization cases), @@ -5535,7 +5640,7 @@ void InitializationSequence::InitializeFrom(Sema &S, bool NeedAtomicConversion = false; if (const AtomicType *Atomic = DestType->getAs<AtomicType>()) { if (Context.hasSameUnqualifiedType(SourceType, Atomic->getValueType()) || - S.IsDerivedFrom(Initializer->getLocStart(), SourceType, + S.IsDerivedFrom(Initializer->getBeginLoc(), SourceType, Atomic->getValueType())) { DestType = Atomic->getValueType(); NeedAtomicConversion = true; @@ -5758,7 +5863,7 @@ static SourceLocation getInitializationLoc(const InitializedEntity &Entity, case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_CompoundLiteralInit: case InitializedEntity::EK_RelatedResult: - return Initializer->getLocStart(); + return Initializer->getBeginLoc(); } llvm_unreachable("missed an InitializedEntity kind?"); } @@ -6092,7 +6197,10 @@ PerformConstructorInitialization(Sema &S, TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo(); if (!TSInfo) TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc); - SourceRange ParenOrBraceRange = Kind.getParenOrBraceRange(); + SourceRange ParenOrBraceRange = + (Kind.getKind() == InitializationKind::IK_DirectList) + ? SourceRange(LBraceLoc, RBraceLoc) + : Kind.getParenOrBraceRange(); if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>( Step.Function.FoundDecl.getDecl())) { @@ -6102,7 +6210,7 @@ PerformConstructorInitialization(Sema &S, } S.MarkFunctionReferenced(Loc, Constructor); - CurInit = new (S.Context) CXXTemporaryObjectExpr( + CurInit = CXXTemporaryObjectExpr::Create( S.Context, Constructor, Entity.getType().getNonLValueExprType(S.Context), TSInfo, ConstructorArgs, ParenOrBraceRange, HadMultipleCandidates, @@ -6353,7 +6461,7 @@ static bool isVarOnPath(IndirectLocalPath &Path, VarDecl *VD) { } static bool pathContainsInit(IndirectLocalPath &Path) { - return std::any_of(Path.begin(), Path.end(), [=](IndirectLocalPathEntry E) { + return llvm::any_of(Path, [=](IndirectLocalPathEntry E) { return E.Kind == IndirectLocalPathEntry::DefaultInit || E.Kind == IndirectLocalPathEntry::VarInit; }); @@ -6371,10 +6479,14 @@ static bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) { const TypeSourceInfo *TSI = FD->getTypeSourceInfo(); if (!TSI) return false; + // Don't declare this variable in the second operand of the for-statement; + // GCC miscompiles that by ending its lifetime before evaluating the + // third operand. See gcc.gnu.org/PR86769. + AttributedTypeLoc ATL; for (TypeLoc TL = TSI->getTypeLoc(); - auto ATL = TL.getAsAdjusted<AttributedTypeLoc>(); + (ATL = TL.getAsAdjusted<AttributedTypeLoc>()); TL = ATL.getModifiedLoc()) { - if (ATL.getAttrKind() == AttributedType::attr_lifetimebound) + if (ATL.getAttrAs<LifetimeBoundAttr>()) return true; } return false; @@ -6437,8 +6549,8 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, do { Old = Init; - if (auto *EWC = dyn_cast<ExprWithCleanups>(Init)) - Init = EWC->getSubExpr(); + if (auto *FE = dyn_cast<FullExpr>(Init)) + Init = FE->getSubExpr(); if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) { // If this is just redundant braces around an initializer, step over it. @@ -6561,8 +6673,8 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, Init = DIE->getExpr(); } - if (auto *EWC = dyn_cast<ExprWithCleanups>(Init)) - Init = EWC->getSubExpr(); + if (auto *FE = dyn_cast<FullExpr>(Init)) + Init = FE->getSubExpr(); // Dig out the expression which constructs the extended temporary. Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments()); @@ -6694,6 +6806,20 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, return; } + // The lifetime of an init-capture is that of the closure object constructed + // by a lambda-expression. + if (auto *LE = dyn_cast<LambdaExpr>(Init)) { + for (Expr *E : LE->capture_inits()) { + if (!E) + continue; + if (E->isGLValue()) + visitLocalsRetainedByReferenceBinding(Path, E, RK_ReferenceBinding, + Visit); + else + visitLocalsRetainedByInitializer(Path, E, Visit, true); + } + } + if (isa<CallExpr>(Init) || isa<CXXConstructExpr>(Init)) return visitLifetimeBoundArguments(Path, Init, Visit); @@ -6938,6 +7064,10 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, } else if (isa<BlockExpr>(L)) { Diag(DiagLoc, diag::err_ret_local_block) << DiagRange; } else if (isa<AddrLabelExpr>(L)) { + // Don't warn when returning a label from a statement expression. + // Leaving the scope doesn't end its lifetime. + if (LK == LK_StmtExprResult) + return false; Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange; } else { Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref) @@ -7063,18 +7193,18 @@ static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr, return; } - S.Diag(CE->getLocStart(), DiagID); + S.Diag(CE->getBeginLoc(), DiagID); // Get all the locations for a fix-it. Don't emit the fix-it if any location // is within a macro. - SourceLocation CallBegin = CE->getCallee()->getLocStart(); + SourceLocation CallBegin = CE->getCallee()->getBeginLoc(); if (CallBegin.isMacroID()) return; SourceLocation RParen = CE->getRParenLoc(); if (RParen.isMacroID()) return; SourceLocation LParen; - SourceLocation ArgLoc = Arg->getLocStart(); + SourceLocation ArgLoc = Arg->getBeginLoc(); // Special testing for the argument location. Since the fix-it needs the // location right before the argument, the argument location can be in a @@ -7089,7 +7219,7 @@ static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr, LParen = ArgLoc.getLocWithOffset(-1); - S.Diag(CE->getLocStart(), diag::note_remove_move) + S.Diag(CE->getBeginLoc(), diag::note_remove_move) << FixItHint::CreateRemoval(SourceRange(CallBegin, LParen)) << FixItHint::CreateRemoval(SourceRange(RParen, RParen)); } @@ -7142,12 +7272,20 @@ ExprResult Sema::TemporaryMaterializationConversion(Expr *E) { return CreateMaterializeTemporaryExpr(E->getType(), E, false); } -ExprResult -InitializationSequence::Perform(Sema &S, - const InitializedEntity &Entity, - const InitializationKind &Kind, - MultiExprArg Args, - QualType *ResultType) { +ExprResult Sema::PerformQualificationConversion(Expr *E, QualType Ty, + ExprValueKind VK, + CheckedConversionKind CCK) { + CastKind CK = (Ty.getAddressSpace() != E->getType().getAddressSpace()) + ? CK_AddressSpaceConversion + : CK_NoOp; + return ImpCastExprToType(E, Ty, CK, VK, /*BasePath=*/nullptr, CCK); +} + +ExprResult InitializationSequence::Perform(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + MultiExprArg Args, + QualType *ResultType) { if (Failed()) { Diagnose(S, Entity, Kind, Args); return ExprError(); @@ -7231,8 +7369,8 @@ InitializationSequence::Perform(Sema &S, // from an initializer list. For parameters, we produce a better warning // elsewhere. Expr *Init = Args[0]; - S.Diag(Init->getLocStart(), diag::warn_cxx98_compat_reference_list_init) - << Init->getSourceRange(); + S.Diag(Init->getBeginLoc(), diag::warn_cxx98_compat_reference_list_init) + << Init->getSourceRange(); } // OpenCL v2.0 s6.13.11.1. atomic variables can be initialized in global scope @@ -7244,8 +7382,9 @@ InitializationSequence::Perform(Sema &S, if (S.getLangOpts().OpenCLVersion >= 200 && ETy->isAtomicType() && !HasGlobalAS && Entity.getKind() == InitializedEntity::EK_Variable && Args.size() > 0) { - S.Diag(Args[0]->getLocStart(), diag::err_opencl_atomic_init) << 1 << - SourceRange(Entity.getDecl()->getLocStart(), Args[0]->getLocEnd()); + S.Diag(Args[0]->getBeginLoc(), diag::err_opencl_atomic_init) + << 1 + << SourceRange(Entity.getDecl()->getBeginLoc(), Args[0]->getEndLoc()); return ExprError(); } @@ -7296,8 +7435,7 @@ InitializationSequence::Perform(Sema &S, case SK_ProduceObjCObject: case SK_StdInitializerList: case SK_OCLSamplerInit: - case SK_OCLZeroEvent: - case SK_OCLZeroQueue: { + case SK_OCLZeroOpaqueType: { assert(Args.size() == 1); CurInit = Args[0]; if (!CurInit.get()) return ExprError(); @@ -7361,10 +7499,9 @@ InitializationSequence::Perform(Sema &S, // Casts to inaccessible base classes are allowed with C-style casts. bool IgnoreBaseAccess = Kind.isCStyleOrFunctionalCast(); - if (S.CheckDerivedToBaseConversion(SourceType, Step->Type, - CurInit.get()->getLocStart(), - CurInit.get()->getSourceRange(), - &BasePath, IgnoreBaseAccess)) + if (S.CheckDerivedToBaseConversion( + SourceType, Step->Type, CurInit.get()->getBeginLoc(), + CurInit.get()->getSourceRange(), &BasePath, IgnoreBaseAccess)) return ExprError(); ExprValueKind VK = @@ -7393,7 +7530,7 @@ InitializationSequence::Perform(Sema &S, if (auto *DRE = dyn_cast<DeclRefExpr>(CurInit.get()->IgnoreParens())) { if (auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl())) { if (!S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true, - DRE->getLocStart())) + DRE->getBeginLoc())) return ExprError(); } } @@ -7454,7 +7591,7 @@ InitializationSequence::Perform(Sema &S, if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Fn)) { // Build a call to the selected constructor. SmallVector<Expr*, 8> ConstructorArgs; - SourceLocation Loc = CurInit.get()->getLocStart(); + SourceLocation Loc = CurInit.get()->getBeginLoc(); // Determine the arguments required to actually perform the constructor // call. @@ -7521,10 +7658,10 @@ InitializationSequence::Perform(Sema &S, if (const RecordType *Record = T->getAs<RecordType>()) { CXXDestructorDecl *Destructor = S.LookupDestructor(cast<CXXRecordDecl>(Record->getDecl())); - S.CheckDestructorAccess(CurInit.get()->getLocStart(), Destructor, + S.CheckDestructorAccess(CurInit.get()->getBeginLoc(), Destructor, S.PDiag(diag::err_access_dtor_temp) << T); - S.MarkFunctionReferenced(CurInit.get()->getLocStart(), Destructor); - if (S.DiagnoseUseOfDecl(Destructor, CurInit.get()->getLocStart())) + S.MarkFunctionReferenced(CurInit.get()->getBeginLoc(), Destructor); + if (S.DiagnoseUseOfDecl(Destructor, CurInit.get()->getBeginLoc())) return ExprError(); } } @@ -7536,12 +7673,11 @@ InitializationSequence::Perform(Sema &S, case SK_QualificationConversionRValue: { // Perform a qualification conversion; these can never go wrong. ExprValueKind VK = - Step->Kind == SK_QualificationConversionLValue ? - VK_LValue : - (Step->Kind == SK_QualificationConversionXValue ? - VK_XValue : - VK_RValue); - CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type, CK_NoOp, VK); + Step->Kind == SK_QualificationConversionLValue + ? VK_LValue + : (Step->Kind == SK_QualificationConversionXValue ? VK_XValue + : VK_RValue); + CurInit = S.PerformQualificationConversion(CurInit.get(), Step->Type, VK); break; } @@ -7562,6 +7698,18 @@ InitializationSequence::Perform(Sema &S, case SK_ConversionSequence: case SK_ConversionSequenceNoNarrowing: { + if (const auto *FromPtrType = + CurInit.get()->getType()->getAs<PointerType>()) { + if (const auto *ToPtrType = Step->Type->getAs<PointerType>()) { + if (FromPtrType->getPointeeType()->hasAttr(attr::NoDeref) && + !ToPtrType->getPointeeType()->hasAttr(attr::NoDeref)) { + S.Diag(CurInit.get()->getExprLoc(), + diag::warn_noderef_to_dereferenceable_pointer) + << CurInit.get()->getSourceRange(); + } + } + } + Sema::CheckedConversionKind CCK = Kind.isCStyleCast()? Sema::CCK_CStyleCast : Kind.isFunctionalCast()? Sema::CCK_FunctionalCast @@ -7728,6 +7876,7 @@ InitializationSequence::Perform(Sema &S, case SK_CAssignment: { QualType SourceType = CurInit.get()->getType(); + // Save off the initial CurInit in case we need to emit a diagnostic ExprResult InitialCurInit = CurInit; ExprResult Result = CurInit; @@ -7863,7 +8012,7 @@ InitializationSequence::Perform(Sema &S, } case SK_OCLSamplerInit: { - // Sampler initialzation have 5 cases: + // Sampler initialization have 5 cases: // 1. function argument passing // 1a. argument is a file-scope variable // 1b. argument is a function-scope variable @@ -7925,8 +8074,9 @@ InitializationSequence::Perform(Sema &S, break; } - llvm::APSInt Result; - Init->EvaluateAsInt(Result, S.Context); + Expr::EvalResult EVResult; + Init->EvaluateAsInt(EVResult, S.Context); + llvm::APSInt Result = EVResult.Val.getInt(); const uint64_t SamplerValue = Result.getLimitedValue(); // 32-bit value of sampler's initializer is interpreted as // bit-field with the following structure: @@ -7936,7 +8086,9 @@ InitializationSequence::Perform(Sema &S, // defined in SPIR spec v1.2 and also opencl-c.h unsigned AddressingMode = (0x0E & SamplerValue) >> 1; unsigned FilterMode = (0x30 & SamplerValue) >> 4; - if (FilterMode != 1 && FilterMode != 2) + if (FilterMode != 1 && FilterMode != 2 && + !S.getOpenCLOptions().isEnabled( + "cl_intel_device_side_avc_motion_estimation")) S.Diag(Kind.getLocation(), diag::warn_sampler_initializer_invalid_bits) << "Filter Mode"; @@ -7952,21 +8104,13 @@ InitializationSequence::Perform(Sema &S, CK_IntToOCLSampler); break; } - case SK_OCLZeroEvent: { - assert(Step->Type->isEventT() && - "Event initialization on non-event type."); - - CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type, - CK_ZeroToOCLEvent, - CurInit.get()->getValueKind()); - break; - } - case SK_OCLZeroQueue: { - assert(Step->Type->isQueueT() && - "Event initialization on non queue type."); + case SK_OCLZeroOpaqueType: { + assert((Step->Type->isEventT() || Step->Type->isQueueT() || + Step->Type->isOCLIntelSubgroupAVCType()) && + "Wrong type for initialization of OpenCL opaque type."); CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type, - CK_ZeroToOCLQueue, + CK_ZeroToOCLOpaqueType, CurInit.get()->getValueKind()); break; } @@ -8019,7 +8163,7 @@ static bool DiagnoseUninitializedReference(Sema &S, SourceLocation Loc, } for (const auto &BI : RD->bases()) { - if (DiagnoseUninitializedReference(S, BI.getLocStart(), BI.getType())) { + if (DiagnoseUninitializedReference(S, BI.getBeginLoc(), BI.getType())) { S.Diag(Loc, diag::note_value_initialization_here) << RD; return true; } @@ -8074,7 +8218,7 @@ static void diagnoseListInit(Sema &S, const InitializedEntity &Entity, // inner initialization failed. QualType T = DestType->getAs<ReferenceType>()->getPointeeType(); diagnoseListInit(S, InitializedEntity::InitializeTemporary(T), InitList); - SourceLocation Loc = InitList->getLocStart(); + SourceLocation Loc = InitList->getBeginLoc(); if (auto *D = Entity.getDecl()) Loc = D->getLocation(); S.Diag(Loc, diag::note_in_reference_temporary_list_initializer) << T; @@ -8124,7 +8268,7 @@ bool InitializationSequence::Diagnose(Sema &S, (void)Diagnosed; } else // FIXME: diagnostic below could be better! S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits) - << SourceRange(Args.front()->getLocStart(), Args.back()->getLocEnd()); + << SourceRange(Args.front()->getBeginLoc(), Args.back()->getEndLoc()); break; case FK_ParenthesizedListInitForReference: S.Diag(Kind.getLocation(), diag::err_list_init_in_parens) @@ -8153,13 +8297,14 @@ bool InitializationSequence::Diagnose(Sema &S, case FK_PlainStringIntoUTF8Char: S.Diag(Kind.getLocation(), diag::err_array_init_plain_string_into_char8_t); - S.Diag(Args.front()->getLocStart(), + S.Diag(Args.front()->getBeginLoc(), diag::note_array_init_plain_string_into_char8_t) - << FixItHint::CreateInsertion(Args.front()->getLocStart(), "u8"); + << FixItHint::CreateInsertion(Args.front()->getBeginLoc(), "u8"); break; case FK_UTF8StringIntoPlainChar: S.Diag(Kind.getLocation(), - diag::err_array_init_utf8_string_into_char); + diag::err_array_init_utf8_string_into_char) + << S.getLangOpts().CPlusPlus2a; break; case FK_ArrayTypeMismatch: case FK_NonConstantArrayInit: @@ -8189,7 +8334,7 @@ bool InitializationSequence::Diagnose(Sema &S, case FK_AddressOfUnaddressableFunction: { auto *FD = cast<FunctionDecl>(cast<DeclRefExpr>(OnlyArg)->getDecl()); S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true, - OnlyArg->getLocStart()); + OnlyArg->getBeginLoc()); break; } @@ -8335,10 +8480,10 @@ bool InitializationSequence::Diagnose(Sema &S, auto *InitList = dyn_cast<InitListExpr>(Args[0]); if (InitList && InitList->getNumInits() >= 1) { - R = SourceRange(InitList->getInit(0)->getLocEnd(), InitList->getLocEnd()); + R = SourceRange(InitList->getInit(0)->getEndLoc(), InitList->getEndLoc()); } else { assert(Args.size() > 1 && "Expected multiple initializers!"); - R = SourceRange(Args.front()->getLocEnd(), Args.back()->getLocEnd()); + R = SourceRange(Args.front()->getEndLoc(), Args.back()->getEndLoc()); } R.setBegin(S.getLocForEndOfToken(R.getBegin())); @@ -8370,8 +8515,8 @@ bool InitializationSequence::Diagnose(Sema &S, case FK_ConstructorOverloadFailed: { SourceRange ArgsRange; if (Args.size()) - ArgsRange = SourceRange(Args.front()->getLocStart(), - Args.back()->getLocEnd()); + ArgsRange = + SourceRange(Args.front()->getBeginLoc(), Args.back()->getEndLoc()); if (Failure == FK_ListConstructorOverloadFailed) { assert(Args.size() == 1 && @@ -8849,12 +8994,8 @@ void InitializationSequence::dump(raw_ostream &OS) const { OS << "OpenCL sampler_t from integer constant"; break; - case SK_OCLZeroEvent: - OS << "OpenCL event_t from zero"; - break; - - case SK_OCLZeroQueue: - OS << "OpenCL queue_t from zero"; + case SK_OCLZeroOpaqueType: + OS << "OpenCL opaque type from zero"; break; } @@ -8906,7 +9047,7 @@ static void DiagnoseNarrowingInInitList(Sema &S, // This was a floating-to-integer conversion, which is always considered a // narrowing conversion even if the value is a constant and can be // represented exactly as an integer. - S.Diag(PostInit->getLocStart(), NarrowingErrs(S.getLangOpts()) + S.Diag(PostInit->getBeginLoc(), NarrowingErrs(S.getLangOpts()) ? diag::ext_init_list_type_narrowing : diag::warn_init_list_type_narrowing) << PostInit->getSourceRange() @@ -8916,7 +9057,7 @@ static void DiagnoseNarrowingInInitList(Sema &S, case NK_Constant_Narrowing: // A constant value was narrowed. - S.Diag(PostInit->getLocStart(), + S.Diag(PostInit->getBeginLoc(), NarrowingErrs(S.getLangOpts()) ? diag::ext_init_list_constant_narrowing : diag::warn_init_list_constant_narrowing) @@ -8927,7 +9068,7 @@ static void DiagnoseNarrowingInInitList(Sema &S, case NK_Variable_Narrowing: // A variable's value may have been narrowed. - S.Diag(PostInit->getLocStart(), + S.Diag(PostInit->getBeginLoc(), NarrowingErrs(S.getLangOpts()) ? diag::ext_init_list_variable_narrowing : diag::warn_init_list_variable_narrowing) @@ -8955,11 +9096,11 @@ static void DiagnoseNarrowingInInitList(Sema &S, return; } OS << ">("; - S.Diag(PostInit->getLocStart(), diag::note_init_list_narrowing_silence) + S.Diag(PostInit->getBeginLoc(), diag::note_init_list_narrowing_silence) << PostInit->getSourceRange() - << FixItHint::CreateInsertion(PostInit->getLocStart(), OS.str()) + << FixItHint::CreateInsertion(PostInit->getBeginLoc(), OS.str()) << FixItHint::CreateInsertion( - S.getLocForEndOfToken(PostInit->getLocEnd()), ")"); + S.getLocForEndOfToken(PostInit->getEndLoc()), ")"); } //===----------------------------------------------------------------------===// @@ -8974,8 +9115,8 @@ Sema::CanPerformCopyInitialization(const InitializedEntity &Entity, Expr *InitE = Init.get(); assert(InitE && "No initialization expression"); - InitializationKind Kind - = InitializationKind::CreateCopy(InitE->getLocStart(), SourceLocation()); + InitializationKind Kind = + InitializationKind::CreateCopy(InitE->getBeginLoc(), SourceLocation()); InitializationSequence Seq(*this, Entity, Kind, InitE); return !Seq.Failed(); } @@ -8993,11 +9134,10 @@ Sema::PerformCopyInitialization(const InitializedEntity &Entity, assert(InitE && "No initialization expression?"); if (EqualLoc.isInvalid()) - EqualLoc = InitE->getLocStart(); + EqualLoc = InitE->getBeginLoc(); - InitializationKind Kind = InitializationKind::CreateCopy(InitE->getLocStart(), - EqualLoc, - AllowExplicit); + InitializationKind Kind = InitializationKind::CreateCopy( + InitE->getBeginLoc(), EqualLoc, AllowExplicit); InitializationSequence Seq(*this, Entity, Kind, InitE, TopLevelOfInitList); // Prevent infinite recursion when performing parameter copy-initialization. @@ -9060,8 +9200,11 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( TSInfo->getType()->getContainedDeducedType()); assert(DeducedTST && "not a deduced template specialization type"); - // We can only perform deduction for class templates. auto TemplateName = DeducedTST->getTemplateName(); + if (TemplateName.isDependent()) + return Context.DependentTy; + + // We can only perform deduction for class templates. auto *Template = dyn_cast_or_null<ClassTemplateDecl>(TemplateName.getAsTemplateDecl()); if (!Template) { @@ -9074,8 +9217,12 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( } // Can't deduce from dependent arguments. - if (Expr::hasAnyTypeDependentArguments(Inits)) + if (Expr::hasAnyTypeDependentArguments(Inits)) { + Diag(TSInfo->getTypeLoc().getBeginLoc(), + diag::warn_cxx14_compat_class_template_argument_deduction) + << TSInfo->getTypeLoc().getSourceRange() << 0; return Context.DependentTy; + } // FIXME: Perform "exact type" matching first, per CWG discussion? // Or implement this via an implied 'T(T) -> T' deduction guide? @@ -9278,5 +9425,10 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( // C++ [dcl.type.class.deduct]p1: // The placeholder is replaced by the return type of the function selected // by overload resolution for class template deduction. - return SubstAutoType(TSInfo->getType(), Best->Function->getReturnType()); + QualType DeducedType = + SubstAutoType(TSInfo->getType(), Best->Function->getReturnType()); + Diag(TSInfo->getTypeLoc().getBeginLoc(), + diag::warn_cxx14_compat_class_template_argument_deduction) + << TSInfo->getTypeLoc().getSourceRange() << 1 << DeducedType; + return DeducedType; } diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 440567e032e48..af233b96d69b4 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -479,7 +479,7 @@ void Sema::buildLambdaScope(LambdaScopeInfo *LSI, if (!LSI->ReturnType->isDependentType() && !LSI->ReturnType->isVoidType()) { - if (RequireCompleteType(CallOperator->getLocStart(), LSI->ReturnType, + if (RequireCompleteType(CallOperator->getBeginLoc(), LSI->ReturnType, diag::err_lambda_incomplete_result)) { // Do nothing. } @@ -493,7 +493,9 @@ void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) { LSI->finishedExplicitCaptures(); } -void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) { +void Sema::addLambdaParameters( + ArrayRef<LambdaIntroducer::LambdaCapture> Captures, + CXXMethodDecl *CallOperator, Scope *CurScope) { // Introduce our parameters into the function scope for (unsigned p = 0, NumParams = CallOperator->getNumParams(); p < NumParams; ++p) { @@ -501,7 +503,19 @@ void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) { // If this has an identifier, add it to the scope stack. if (CurScope && Param->getIdentifier()) { - CheckShadow(CurScope, Param); + bool Error = false; + // Resolution of CWG 2211 in C++17 renders shadowing ill-formed, but we + // retroactively apply it. + for (const auto &Capture : Captures) { + if (Capture.Id == Param->getIdentifier()) { + Error = true; + Diag(Param->getLocation(), diag::err_parameter_shadow_capture); + Diag(Capture.Loc, diag::note_var_explicitly_captured_here) + << Capture.Id << true; + } + } + if (!Error) + CheckShadow(CurScope, Param); PushOnScopeChains(Param, CurScope); } @@ -720,10 +734,9 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) { // FIXME: This is a poor diagnostic for ReturnStmts without expressions. // TODO: It's possible that the *first* return is the divergent one. - Diag(RS->getLocStart(), + Diag(RS->getBeginLoc(), diag::err_typecheck_missing_return_type_incompatible) - << ReturnType << CSI.ReturnType - << isa<LambdaScopeInfo>(CSI); + << ReturnType << CSI.ReturnType << isa<LambdaScopeInfo>(CSI); // Continue iterating so that we keep emitting diagnostics. } } @@ -746,14 +759,15 @@ QualType Sema::buildLambdaInitCaptureInitialization(SourceLocation Loc, TypeSourceInfo *TSI = TLB.getTypeSourceInfo(Context, DeductType); // Deduce the type of the init capture. + Expr *DeduceInit = Init; QualType DeducedType = deduceVarTypeFromInitializer( /*VarDecl*/nullptr, DeclarationName(Id), DeductType, TSI, - SourceRange(Loc, Loc), IsDirectInit, Init); + SourceRange(Loc, Loc), IsDirectInit, DeduceInit); if (DeducedType.isNull()) return QualType(); // Are we a non-list direct initialization? - ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init); + bool CXXDirectInit = isa<ParenListExpr>(Init); // Perform initialization analysis and ensure any implicit conversions // (such as lvalue-to-rvalue) are enforced. @@ -762,30 +776,17 @@ QualType Sema::buildLambdaInitCaptureInitialization(SourceLocation Loc, InitializationKind Kind = IsDirectInit ? (CXXDirectInit ? InitializationKind::CreateDirect( - Loc, Init->getLocStart(), Init->getLocEnd()) + Loc, Init->getBeginLoc(), Init->getEndLoc()) : InitializationKind::CreateDirectList(Loc)) - : InitializationKind::CreateCopy(Loc, Init->getLocStart()); + : InitializationKind::CreateCopy(Loc, Init->getBeginLoc()); - MultiExprArg Args = Init; - if (CXXDirectInit) - Args = - MultiExprArg(CXXDirectInit->getExprs(), CXXDirectInit->getNumExprs()); + MultiExprArg Args = DeduceInit; QualType DclT; InitializationSequence InitSeq(*this, Entity, Kind, Args); ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Args, &DclT); if (Result.isInvalid()) return QualType(); - Init = Result.getAs<Expr>(); - - // The init-capture initialization is a full-expression that must be - // processed as one before we enter the declcontext of the lambda's - // call-operator. - Result = ActOnFinishFullExpr(Init, Loc, /*DiscardedValue*/ false, - /*IsConstexpr*/ false, - /*IsLambdaInitCaptureInitializer*/ true); - if (Result.isInvalid()) - return QualType(); Init = Result.getAs<Expr>(); return DeducedType; @@ -856,7 +857,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, FunctionProtoType::ExtProtoInfo EPI(Context.getDefaultCallingConvention( /*IsVariadic=*/false, /*IsCXXMethod=*/true)); EPI.HasTrailingReturn = true; - EPI.TypeQuals |= DeclSpec::TQ_const; + EPI.TypeQuals.addConst(); // C++1y [expr.prim.lambda]: // The lambda return type is 'auto', which is replaced by the // trailing-return type if provided and/or deduced from 'return' @@ -881,8 +882,10 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, // This function call operator is declared const (9.3.1) if and only if // the lambda-expression's parameter-declaration-clause is not followed // by mutable. It is neither virtual nor declared volatile. [...] - if (!FTI.hasMutableQualifier()) - FTI.TypeQuals |= DeclSpec::TQ_const; + if (!FTI.hasMutableQualifier()) { + FTI.getOrCreateMethodQualifiers().SetTypeQual(DeclSpec::TQ_const, + SourceLocation()); + } MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope); assert(MethodTyInfo && "no type from lambda-declarator"); @@ -1153,7 +1156,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, LSI->ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack; // Add lambda parameters into scope. - addLambdaParameters(Method, CurScope); + addLambdaParameters(Intro.Captures, Method, CurScope); // Enter a new evaluation context to insulate the lambda from any // cleanups from the enclosing full-expression. @@ -1195,7 +1198,7 @@ QualType Sema::getLambdaConversionFunctionResultType( CallingConv CC = Context.getDefaultCallingConvention( CallOpProto->isVariadic(), /*IsCXXMethod=*/false); InvokerExtInfo.ExtInfo = InvokerExtInfo.ExtInfo.withCallingConv(CC); - InvokerExtInfo.TypeQuals = 0; + InvokerExtInfo.TypeQuals = Qualifiers(); assert(InvokerExtInfo.RefQualifier == RQ_None && "Lambda's call operator should not have a reference qualifier"); return Context.getFunctionType(CallOpProto->getReturnType(), @@ -1226,7 +1229,8 @@ static void addFunctionPointerConversion(Sema &S, S.Context.getDefaultCallingConvention( /*IsVariadic=*/false, /*IsCXXMethod=*/true)); // The conversion function is always const. - ConvExtInfo.TypeQuals = Qualifiers::Const; + ConvExtInfo.TypeQuals = Qualifiers(); + ConvExtInfo.TypeQuals.addConst(); QualType ConvTy = S.Context.getFunctionType(PtrToFunctionTy, None, ConvExtInfo); @@ -1286,29 +1290,23 @@ static void addFunctionPointerConversion(Sema &S, for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) { ParmVarDecl *From = CallOperator->getParamDecl(I); - InvokerParams.push_back(ParmVarDecl::Create(S.Context, - // Temporarily add to the TU. This is set to the invoker below. - S.Context.getTranslationUnitDecl(), - From->getLocStart(), - From->getLocation(), - From->getIdentifier(), - From->getType(), - From->getTypeSourceInfo(), - From->getStorageClass(), - /*DefaultArg=*/nullptr)); + InvokerParams.push_back(ParmVarDecl::Create( + S.Context, + // Temporarily add to the TU. This is set to the invoker below. + S.Context.getTranslationUnitDecl(), From->getBeginLoc(), + From->getLocation(), From->getIdentifier(), From->getType(), + From->getTypeSourceInfo(), From->getStorageClass(), + /*DefaultArg=*/nullptr)); CallOpConvTL.setParam(I, From); CallOpConvNameTL.setParam(I, From); } - CXXConversionDecl *Conversion - = CXXConversionDecl::Create(S.Context, Class, Loc, - DeclarationNameInfo(ConversionName, - Loc, ConvNameLoc), - ConvTy, - ConvTSI, - /*isInline=*/true, /*isExplicit=*/false, - /*isConstexpr=*/S.getLangOpts().CPlusPlus17, - CallOperator->getBody()->getLocEnd()); + CXXConversionDecl *Conversion = CXXConversionDecl::Create( + S.Context, Class, Loc, + DeclarationNameInfo(ConversionName, Loc, ConvNameLoc), ConvTy, ConvTSI, + /*isInline=*/true, /*isExplicit=*/false, + /*isConstexpr=*/S.getLangOpts().CPlusPlus17, + CallOperator->getBody()->getEndLoc()); Conversion->setAccess(AS_public); Conversion->setImplicit(true); @@ -1343,14 +1341,11 @@ static void addFunctionPointerConversion(Sema &S, // trailing return type of the invoker would require a visitor to rebuild // the trailing return type and adjusting all back DeclRefExpr's to refer // to the new static invoker parameters - not the call operator's. - CXXMethodDecl *Invoke - = CXXMethodDecl::Create(S.Context, Class, Loc, - DeclarationNameInfo(InvokerName, Loc), - InvokerFunctionTy, - CallOperator->getTypeSourceInfo(), - SC_Static, /*IsInline=*/true, - /*IsConstexpr=*/false, - CallOperator->getBody()->getLocEnd()); + CXXMethodDecl *Invoke = CXXMethodDecl::Create( + S.Context, Class, Loc, DeclarationNameInfo(InvokerName, Loc), + InvokerFunctionTy, CallOperator->getTypeSourceInfo(), SC_Static, + /*IsInline=*/true, + /*IsConstexpr=*/false, CallOperator->getBody()->getEndLoc()); for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) InvokerParams[I]->setOwningFunction(Invoke); Invoke->setParams(InvokerParams); @@ -1383,7 +1378,8 @@ static void addBlockPointerConversion(Sema &S, FunctionProtoType::ExtProtoInfo ConversionEPI( S.Context.getDefaultCallingConvention( /*IsVariadic=*/false, /*IsCXXMethod=*/true)); - ConversionEPI.TypeQuals = Qualifiers::Const; + ConversionEPI.TypeQuals = Qualifiers(); + ConversionEPI.TypeQuals.addConst(); QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, None, ConversionEPI); SourceLocation Loc = IntroducerRange.getBegin(); @@ -1392,26 +1388,24 @@ static void addBlockPointerConversion(Sema &S, S.Context.getCanonicalType(BlockPtrTy)); DeclarationNameLoc NameLoc; NameLoc.NamedType.TInfo = S.Context.getTrivialTypeSourceInfo(BlockPtrTy, Loc); - CXXConversionDecl *Conversion - = CXXConversionDecl::Create(S.Context, Class, Loc, - DeclarationNameInfo(Name, Loc, NameLoc), - ConvTy, - S.Context.getTrivialTypeSourceInfo(ConvTy, Loc), - /*isInline=*/true, /*isExplicit=*/false, - /*isConstexpr=*/false, - CallOperator->getBody()->getLocEnd()); + CXXConversionDecl *Conversion = CXXConversionDecl::Create( + S.Context, Class, Loc, DeclarationNameInfo(Name, Loc, NameLoc), ConvTy, + S.Context.getTrivialTypeSourceInfo(ConvTy, Loc), + /*isInline=*/true, /*isExplicit=*/false, + /*isConstexpr=*/false, CallOperator->getBody()->getEndLoc()); Conversion->setAccess(AS_public); Conversion->setImplicit(true); Class->addDecl(Conversion); } -static ExprResult performLambdaVarCaptureInitialization(Sema &S, - const Capture &Capture, - FieldDecl *Field) { +static ExprResult performLambdaVarCaptureInitialization( + Sema &S, const Capture &Capture, FieldDecl *Field, + SourceLocation ImplicitCaptureLoc, bool IsImplicitCapture) { assert(Capture.isVariableCapture() && "not a variable capture"); auto *Var = Capture.getVariable(); - SourceLocation Loc = Capture.getLocation(); + SourceLocation Loc = + IsImplicitCapture ? ImplicitCaptureLoc : Capture.getLocation(); // C++11 [expr.prim.lambda]p21: // When the lambda-expression is evaluated, the entities that @@ -1442,7 +1436,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, Scope *CurScope) { LambdaScopeInfo LSI = *cast<LambdaScopeInfo>(FunctionScopes.back()); ActOnFinishFunctionBody(LSI.CallOperator, Body); - return BuildLambdaExpr(StartLoc, Body->getLocEnd(), &LSI); + return BuildLambdaExpr(StartLoc, Body->getEndLoc(), &LSI); } static LambdaCaptureDefault @@ -1620,8 +1614,8 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, Var, From.getEllipsisLoc())); Expr *Init = From.getInitExpr(); if (!Init) { - auto InitResult = - performLambdaVarCaptureInitialization(*this, From, *CurField); + auto InitResult = performLambdaVarCaptureInitialization( + *this, From, *CurField, CaptureDefaultLoc, IsImplicit); if (InitResult.isInvalid()) return ExprError(); Init = InitResult.get(); @@ -1644,7 +1638,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, // same parameter and return types as the closure type's function call // operator. // FIXME: Fix generic lambda to block conversions. - if (getLangOpts().Blocks && getLangOpts().ObjC1 && !IsGenericLambda) + if (getLangOpts().Blocks && getLangOpts().ObjC && !IsGenericLambda) addBlockPointerConversion(*this, IntroducerRange, Class, CallOperator); // Finalize the lambda class. @@ -1730,7 +1724,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, /*NRVO=*/false), CurrentLocation, Src); if (!Init.isInvalid()) - Init = ActOnFinishFullExpr(Init.get()); + Init = ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false); if (Init.isInvalid()) return ExprError(); @@ -1747,14 +1741,11 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, SmallVector<ParmVarDecl *, 4> BlockParams; for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) { ParmVarDecl *From = CallOperator->getParamDecl(I); - BlockParams.push_back(ParmVarDecl::Create(Context, Block, - From->getLocStart(), - From->getLocation(), - From->getIdentifier(), - From->getType(), - From->getTypeSourceInfo(), - From->getStorageClass(), - /*DefaultArg=*/nullptr)); + BlockParams.push_back(ParmVarDecl::Create( + Context, Block, From->getBeginLoc(), From->getLocation(), + From->getIdentifier(), From->getType(), From->getTypeSourceInfo(), + From->getStorageClass(), + /*DefaultArg=*/nullptr)); } Block->setParams(BlockParams); diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 0ab70e9dca375..effccc2f3d383 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -186,9 +186,7 @@ namespace { list.push_back(UnqualUsingEntry(UD->getNominatedNamespace(), Common)); } - void done() { - llvm::sort(list.begin(), list.end(), UnqualUsingEntry::Comparator()); - } + void done() { llvm::sort(list, UnqualUsingEntry::Comparator()); } typedef ListTy::const_iterator const_iterator; @@ -1392,23 +1390,25 @@ llvm::DenseSet<Module*> &Sema::getLookupModules() { return LookupModulesCache; } +/// Determine whether the module M is part of the current module from the +/// perspective of a module-private visibility check. +static bool isInCurrentModule(const Module *M, const LangOptions &LangOpts) { + // If M is the global module fragment of a module that we've not yet finished + // parsing, then it must be part of the current module. + return M->getTopLevelModuleName() == LangOpts.CurrentModule || + (M->Kind == Module::GlobalModuleFragment && !M->Parent); +} + bool Sema::hasVisibleMergedDefinition(NamedDecl *Def) { - for (Module *Merged : Context.getModulesWithMergedDefinition(Def)) + for (const Module *Merged : Context.getModulesWithMergedDefinition(Def)) if (isModuleVisible(Merged)) return true; return false; } bool Sema::hasMergedDefinitionInCurrentModule(NamedDecl *Def) { - // FIXME: When not in local visibility mode, we can't tell the difference - // between a declaration being visible because we merged a local copy of - // the same declaration into it, and it being visible because its owning - // module is visible. - if (Def->getModuleOwnershipKind() == Decl::ModuleOwnershipKind::Visible && - getLangOpts().ModulesLocalVisibility) - return true; - for (Module *Merged : Context.getModulesWithMergedDefinition(Def)) - if (Merged->getTopLevelModuleName() == getLangOpts().CurrentModule) + for (const Module *Merged : Context.getModulesWithMergedDefinition(Def)) + if (isInCurrentModule(Merged, getLangOpts())) return true; return false; } @@ -1428,8 +1428,6 @@ hasVisibleDefaultArgument(Sema &S, const ParmDecl *D, if (!DefaultArg.isInherited() && Modules) { auto *NonConstD = const_cast<ParmDecl*>(D); Modules->push_back(S.getOwningModule(NonConstD)); - const auto &Merged = S.Context.getModulesWithMergedDefinition(NonConstD); - Modules->insert(Modules->end(), Merged.begin(), Merged.end()); } // If there was a previous default argument, maybe its parameter is visible. @@ -1464,11 +1462,8 @@ static bool hasVisibleDeclarationImpl(Sema &S, const NamedDecl *D, HasFilteredRedecls = true; - if (Modules) { + if (Modules) Modules->push_back(R->getOwningModule()); - const auto &Merged = S.Context.getModulesWithMergedDefinition(R); - Modules->insert(Modules->end(), Merged.begin(), Merged.end()); - } } // Only return false if there is at least one redecl that is not filtered out. @@ -1519,27 +1514,11 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) { assert(D->isHidden() && "should not call this: not in slow case"); Module *DeclModule = SemaRef.getOwningModule(D); - if (!DeclModule) { - // A module-private declaration with no owning module means this is in the - // global module in the C++ Modules TS. This is visible within the same - // translation unit only. - // FIXME: Don't assume that "same translation unit" means the same thing - // as "not from an AST file". - assert(D->isModulePrivate() && "hidden decl has no module"); - if (!D->isFromASTFile() || SemaRef.hasMergedDefinitionInCurrentModule(D)) - return true; - } else { - // If the owning module is visible, and the decl is not module private, - // then the decl is visible too. (Module private is ignored within the same - // top-level module.) - if (D->isModulePrivate() - ? DeclModule->getTopLevelModuleName() == - SemaRef.getLangOpts().CurrentModule || - SemaRef.hasMergedDefinitionInCurrentModule(D) - : SemaRef.isModuleVisible(DeclModule) || - SemaRef.hasVisibleMergedDefinition(D)) - return true; - } + assert(DeclModule && "hidden decl has no owning module"); + + // If the owning module is visible, the decl is visible. + if (SemaRef.isModuleVisible(DeclModule, D->isModulePrivate())) + return true; // Determine whether a decl context is a file context for the purpose of // visibility. This looks through some (export and linkage spec) transparent @@ -1589,29 +1568,41 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) { return VisibleWithinParent; } - // FIXME: All uses of DeclModule below this point should also check merged - // modules. - if (!DeclModule) - return false; + return false; +} + +bool Sema::isModuleVisible(const Module *M, bool ModulePrivate) { + // The module might be ordinarily visible. For a module-private query, that + // means it is part of the current module. For any other query, that means it + // is in our visible module set. + if (ModulePrivate) { + if (isInCurrentModule(M, getLangOpts())) + return true; + } else { + if (VisibleModules.isVisible(M)) + return true; + } + + // Otherwise, it might be visible by virtue of the query being within a + // template instantiation or similar that is permitted to look inside M. // Find the extra places where we need to look. - const auto &LookupModules = SemaRef.getLookupModules(); + const auto &LookupModules = getLookupModules(); if (LookupModules.empty()) return false; - // If our lookup set contains the decl's module, it's visible. - if (LookupModules.count(DeclModule)) + // If our lookup set contains the module, it's visible. + if (LookupModules.count(M)) return true; - // If the declaration isn't exported, it's not visible in any other module. - if (D->isModulePrivate()) + // For a module-private query, that's everywhere we get to look. + if (ModulePrivate) return false; - // Check whether DeclModule is transitively exported to an import of - // the lookup set. - return std::any_of(LookupModules.begin(), LookupModules.end(), - [&](const Module *M) { - return M->isModuleVisible(DeclModule); }); + // Check whether M is transitively exported to an import of the lookup set. + return llvm::any_of(LookupModules, [&](const Module *LookupM) { + return LookupM->isModuleVisible(M); + }); } bool Sema::isVisibleSlow(const NamedDecl *D) { @@ -3346,38 +3337,29 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc, !isa<FunctionTemplateDecl>(Underlying)) continue; - if (!isVisible(D)) { - D = findAcceptableDecl( - *this, D, (Decl::IDNS_Ordinary | Decl::IDNS_OrdinaryFriend)); - if (!D) - continue; - if (auto *USD = dyn_cast<UsingShadowDecl>(D)) - Underlying = USD->getTargetDecl(); - } - - // If the only declaration here is an ordinary friend, consider - // it only if it was declared in an associated classes. - if ((D->getIdentifierNamespace() & Decl::IDNS_Ordinary) == 0) { - // If it's neither ordinarily visible nor a friend, we can't find it. - if ((D->getIdentifierNamespace() & Decl::IDNS_OrdinaryFriend) == 0) - continue; - - bool DeclaredInAssociatedClass = false; - for (Decl *DI = D; DI; DI = DI->getPreviousDecl()) { - DeclContext *LexDC = DI->getLexicalDeclContext(); - if (isa<CXXRecordDecl>(LexDC) && - AssociatedClasses.count(cast<CXXRecordDecl>(LexDC)) && - isVisible(cast<NamedDecl>(DI))) { - DeclaredInAssociatedClass = true; + // The declaration is visible to argument-dependent lookup if either + // it's ordinarily visible or declared as a friend in an associated + // class. + bool Visible = false; + for (D = D->getMostRecentDecl(); D; + D = cast_or_null<NamedDecl>(D->getPreviousDecl())) { + if (D->getIdentifierNamespace() & Decl::IDNS_Ordinary) { + if (isVisible(D)) { + Visible = true; + break; + } + } else if (D->getFriendObjectKind()) { + auto *RD = cast<CXXRecordDecl>(D->getLexicalDeclContext()); + if (AssociatedClasses.count(RD) && isVisible(D)) { + Visible = true; break; } } - if (!DeclaredInAssociatedClass) - continue; } // FIXME: Preserve D as the FoundDecl. - Result.insert(Underlying); + if (Visible) + Result.insert(Underlying); } } } @@ -3628,8 +3610,9 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, // Find results in this base class (and its bases). ShadowContextRAII Shadow(Visited); - LookupVisibleDecls(RD, Result, QualifiedNameLookup, true, Consumer, - Visited, IncludeDependentBases, LoadExternal); + LookupVisibleDecls(RD, Result, QualifiedNameLookup, /*InBaseClass=*/true, + Consumer, Visited, IncludeDependentBases, + LoadExternal); } } @@ -3998,9 +3981,9 @@ void TypoCorrectionConsumer::addName(StringRef Name, NamedDecl *ND, // Compute an upper bound on the allowable edit distance, so that the // edit-distance algorithm can short-circuit. - unsigned UpperBound = (TypoStr.size() + 2) / 3 + 1; + unsigned UpperBound = (TypoStr.size() + 2) / 3; unsigned ED = TypoStr.edit_distance(Name, true, UpperBound); - if (ED >= UpperBound) return; + if (ED > UpperBound) return; TypoCorrection TC(&SemaRef.Context.Idents.get(Name), ND, NNS, ED); if (isKeyword) TC.makeKeyword(); @@ -4070,7 +4053,7 @@ void TypoCorrectionConsumer::addNamespaces( } // Do not transform this into an iterator-based loop. The loop body can // trigger the creation of further types (through lazy deserialization) and - // invalide iterators into this list. + // invalid iterators into this list. auto &Types = SemaRef.getASTContext().getTypes(); for (unsigned I = 0; I != Types.size(); ++I) { const auto *TI = Types[I]; @@ -4211,7 +4194,7 @@ void TypoCorrectionConsumer::performQualifiedLookups() { SS->getScopeRep()->print(OldOStream, SemaRef.getPrintingPolicy()); OldOStream << Typo->getName(); // If correction candidate would be an identical written qualified - // identifer, then the existing CXXScopeSpec probably included a + // identifier, then the existing CXXScopeSpec probably included a // typedef that didn't get accounted for properly. if (OldOStream.str() == NewQualified) break; @@ -4628,7 +4611,7 @@ std::unique_ptr<TypoCorrectionConsumer> Sema::makeTypoCorrectionConsumer( getLangOpts().ModulesSearchAll) { // The following has the side effect of loading the missing module. getModuleLoader().lookupMissingImports(Typo->getName(), - TypoName.getLocStart()); + TypoName.getBeginLoc()); } CorrectionCandidateCallback &CCCRef = *CCC; @@ -5061,12 +5044,12 @@ void Sema::diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl, if (!Def) Def = Decl; - Module *Owner = getOwningModule(Decl); + Module *Owner = getOwningModule(Def); assert(Owner && "definition of hidden declaration is not in a module"); llvm::SmallVector<Module*, 8> OwningModules; OwningModules.push_back(Owner); - auto Merged = Context.getModulesWithMergedDefinition(Decl); + auto Merged = Context.getModulesWithMergedDefinition(Def); OwningModules.insert(OwningModules.end(), Merged.begin(), Merged.end()); diagnoseMissingImport(Loc, Decl, Decl->getLocation(), OwningModules, MIK, diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index 3e55cf003fced..9412d0160048a 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -609,12 +609,12 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, } if (T->isObjCObjectType()) { - SourceLocation StarLoc = TInfo->getTypeLoc().getLocEnd(); + SourceLocation StarLoc = TInfo->getTypeLoc().getEndLoc(); StarLoc = getLocForEndOfToken(StarLoc); Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object) << FixItHint::CreateInsertion(StarLoc, "*"); T = Context.getObjCObjectPointerType(T); - SourceLocation TLoc = TInfo->getTypeLoc().getLocStart(); + SourceLocation TLoc = TInfo->getTypeLoc().getBeginLoc(); TInfo = Context.getTrivialTypeSourceInfo(T, TLoc); } @@ -1061,7 +1061,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, PropertyIvarLoc = PropertyLoc; SourceLocation PropertyDiagLoc = PropertyLoc; if (PropertyDiagLoc.isInvalid()) - PropertyDiagLoc = ClassImpDecl->getLocStart(); + PropertyDiagLoc = ClassImpDecl->getBeginLoc(); ObjCPropertyDecl *property = nullptr; ObjCInterfaceDecl *IDecl = nullptr; // Find the class or category class where this property must have @@ -1412,9 +1412,9 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, // FIXME. Eventually we want to do this for Objective-C as well. SynthesizedFunctionScope Scope(*this, getterMethod); ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl(); - DeclRefExpr *SelfExpr = - new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(), - VK_LValue, PropertyDiagLoc); + DeclRefExpr *SelfExpr = new (Context) + DeclRefExpr(Context, SelfDecl, false, SelfDecl->getType(), VK_LValue, + PropertyDiagLoc); MarkDeclRefReferenced(SelfExpr); Expr *LoadSelfExpr = ImplicitCastExpr::Create(Context, SelfDecl->getType(), @@ -1464,9 +1464,9 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, // FIXME. Eventually we want to do this for Objective-C as well. SynthesizedFunctionScope Scope(*this, setterMethod); ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl(); - DeclRefExpr *SelfExpr = - new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(), - VK_LValue, PropertyDiagLoc); + DeclRefExpr *SelfExpr = new (Context) + DeclRefExpr(Context, SelfDecl, false, SelfDecl->getType(), VK_LValue, + PropertyDiagLoc); MarkDeclRefReferenced(SelfExpr); Expr *LoadSelfExpr = ImplicitCastExpr::Create(Context, SelfDecl->getType(), @@ -1481,8 +1481,8 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, ObjCMethodDecl::param_iterator P = setterMethod->param_begin(); ParmVarDecl *Param = (*P); QualType T = Param->getType().getNonReferenceType(); - DeclRefExpr *rhs = new (Context) DeclRefExpr(Param, false, T, - VK_LValue, PropertyDiagLoc); + DeclRefExpr *rhs = new (Context) + DeclRefExpr(Context, Param, false, T, VK_LValue, PropertyDiagLoc); MarkDeclRefReferenced(rhs); ExprResult Res = BuildBinOp(S, PropertyDiagLoc, BO_Assign, lhs, rhs); @@ -1497,8 +1497,8 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, Diag(PropertyDiagLoc, diag::err_atomic_property_nontrivial_assign_op) << property->getType(); - Diag(FuncDecl->getLocStart(), - diag::note_callee_decl) << FuncDecl; + Diag(FuncDecl->getBeginLoc(), diag::note_callee_decl) + << FuncDecl; } } PIDecl->setSetterCXXAssignment(Res.getAs<Expr>()); @@ -2100,7 +2100,7 @@ void Sema::diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl) !impDecl->getInstanceMethod(getterMethod->getSelector())) { SourceLocation loc = propertyImpl->getLocation(); if (loc.isInvalid()) - loc = impDecl->getLocStart(); + loc = impDecl->getBeginLoc(); Diag(loc, diag::warn_null_resettable_setter) << setterMethod->getSelector() << property->getDeclName(); @@ -2235,7 +2235,7 @@ void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D if (getterRedecl->getDeclContext() != PD->getDeclContext()) continue; noteLoc = getterRedecl->getLocation(); - fixItLoc = getterRedecl->getLocEnd(); + fixItLoc = getterRedecl->getEndLoc(); } Preprocessor &PP = getPreprocessor(); @@ -2384,7 +2384,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) { QualType modifiedTy = resultTy; if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)) { if (*nullability == NullabilityKind::Unspecified) - resultTy = Context.getAttributedType(AttributedType::attr_nonnull, + resultTy = Context.getAttributedType(attr::TypeNonNull, modifiedTy, modifiedTy); } } @@ -2458,7 +2458,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) { QualType modifiedTy = paramTy; if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)){ if (*nullability == NullabilityKind::Unspecified) - paramTy = Context.getAttributedType(AttributedType::attr_nullable, + paramTy = Context.getAttributedType(attr::TypeNullable, modifiedTy, modifiedTy); } } @@ -2557,6 +2557,14 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl, PropertyDecl->setInvalidDecl(); } + // Check for assign on object types. + if ((Attributes & ObjCDeclSpec::DQ_PR_assign) && + !(Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) && + PropertyTy->isObjCRetainableType() && + !PropertyTy->isObjCARCImplicitlyUnretainedType()) { + Diag(Loc, diag::warn_objc_property_assign_on_object); + } + // Check for more than one of { assign, copy, retain }. if (Attributes & ObjCDeclSpec::DQ_PR_assign) { if (Attributes & ObjCDeclSpec::DQ_PR_copy) { diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index e1a4c420d4024..36048a38b999c 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -22,6 +22,7 @@ #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtOpenMP.h" #include "clang/AST/StmtVisitor.h" +#include "clang/AST/TypeOrdering.h" #include "clang/Basic/OpenMPKinds.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" @@ -73,6 +74,8 @@ public: }; using OperatorOffsetTy = llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>; + using DoacrossDependMapTy = + llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>; private: struct DSAInfo { @@ -97,8 +100,6 @@ private: llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>; using CriticalsWithHintsTy = llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>; - using DoacrossDependMapTy = - llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>; struct ReductionData { using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>; SourceRange ReductionRange; @@ -137,13 +138,16 @@ private: /// first argument (Expr *) contains optional argument of the /// 'ordered' clause, the second one is true if the regions has 'ordered' /// clause, false otherwise. - llvm::PointerIntPair<const Expr *, 1, bool> OrderedRegion; + llvm::Optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion; + unsigned AssociatedLoops = 1; + const Decl *PossiblyLoopCounter = nullptr; bool NowaitRegion = false; bool CancelRegion = false; - unsigned AssociatedLoops = 1; + bool LoopStart = false; SourceLocation InnerTeamsRegionLoc; /// Reference to the taskgroup task_reduction reference expression. Expr *TaskgroupReductionRef = nullptr; + llvm::DenseSet<QualType> MappedClassesQualTypes; SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name, Scope *CurScope, SourceLocation Loc) : Directive(DKind), DirectiveName(Name), CurScope(CurScope), @@ -162,6 +166,9 @@ private: OpenMPClauseKind ClauseKindMode = OMPC_unknown; Sema &SemaRef; bool ForceCapturing = false; + /// true if all the vaiables in the target executable directives must be + /// captured by reference. + bool ForceCaptureByReferenceInTargetExecutable = false; CriticalsWithHintsTy Criticals; using iterator = StackTy::const_reverse_iterator; @@ -177,6 +184,9 @@ private: Stack.back().first.empty(); } + /// Vector of previously declared requires directives + SmallVector<const OMPRequiresDecl *, 2> RequiresDecls; + public: explicit DSAStackTy(Sema &S) : SemaRef(S) {} @@ -190,6 +200,13 @@ public: bool isForceVarCapturing() const { return ForceCapturing; } void setForceVarCapturing(bool V) { ForceCapturing = V; } + void setForceCaptureByReferenceInTargetExecutable(bool V) { + ForceCaptureByReferenceInTargetExecutable = V; + } + bool isForceCaptureByReferenceInTargetExecutable() const { + return ForceCaptureByReferenceInTargetExecutable; + } + void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName, Scope *CurScope, SourceLocation Loc) { if (Stack.empty() || @@ -205,6 +222,33 @@ public: Stack.back().first.pop_back(); } + /// Marks that we're started loop parsing. + void loopInit() { + assert(isOpenMPLoopDirective(getCurrentDirective()) && + "Expected loop-based directive."); + Stack.back().first.back().LoopStart = true; + } + /// Start capturing of the variables in the loop context. + void loopStart() { + assert(isOpenMPLoopDirective(getCurrentDirective()) && + "Expected loop-based directive."); + Stack.back().first.back().LoopStart = false; + } + /// true, if variables are captured, false otherwise. + bool isLoopStarted() const { + assert(isOpenMPLoopDirective(getCurrentDirective()) && + "Expected loop-based directive."); + return !Stack.back().first.back().LoopStart; + } + /// Marks (or clears) declaration as possibly loop counter. + void resetPossibleLoopCounter(const Decl *D = nullptr) { + Stack.back().first.back().PossiblyLoopCounter = + D ? D->getCanonicalDecl() : D; + } + /// Gets the possible loop counter decl. + const Decl *getPossiblyLoopCunter() const { + return Stack.back().first.back().PossiblyLoopCounter; + } /// Start new OpenMP region stack in new non-capturing function. void pushFunction() { const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction(); @@ -352,6 +396,33 @@ public: return std::next(Stack.back().first.rbegin())->Directive; } + /// Add requires decl to internal vector + void addRequiresDecl(OMPRequiresDecl *RD) { + RequiresDecls.push_back(RD); + } + + /// Checks for a duplicate clause amongst previously declared requires + /// directives + bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const { + bool IsDuplicate = false; + for (OMPClause *CNew : ClauseList) { + for (const OMPRequiresDecl *D : RequiresDecls) { + for (const OMPClause *CPrev : D->clauselists()) { + if (CNew->getClauseKind() == CPrev->getClauseKind()) { + SemaRef.Diag(CNew->getBeginLoc(), + diag::err_omp_requires_clause_redeclaration) + << getOpenMPClauseName(CNew->getClauseKind()); + SemaRef.Diag(CPrev->getBeginLoc(), + diag::note_omp_requires_previous_clause) + << getOpenMPClauseName(CPrev->getClauseKind()); + IsDuplicate = true; + } + } + } + } + return IsDuplicate; + } + /// Set default data sharing attribute to none. void setDefaultDSANone(SourceLocation Loc) { assert(!isStackEmpty()); @@ -398,23 +469,42 @@ public: } /// Marks current region as ordered (it has an 'ordered' clause). - void setOrderedRegion(bool IsOrdered, const Expr *Param) { + void setOrderedRegion(bool IsOrdered, const Expr *Param, + OMPOrderedClause *Clause) { assert(!isStackEmpty()); - Stack.back().first.back().OrderedRegion.setInt(IsOrdered); - Stack.back().first.back().OrderedRegion.setPointer(Param); + if (IsOrdered) + Stack.back().first.back().OrderedRegion.emplace(Param, Clause); + else + Stack.back().first.back().OrderedRegion.reset(); + } + /// Returns true, if region is ordered (has associated 'ordered' clause), + /// false - otherwise. + bool isOrderedRegion() const { + if (isStackEmpty()) + return false; + return Stack.back().first.rbegin()->OrderedRegion.hasValue(); + } + /// Returns optional parameter for the ordered region. + std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const { + if (isStackEmpty() || + !Stack.back().first.rbegin()->OrderedRegion.hasValue()) + return std::make_pair(nullptr, nullptr); + return Stack.back().first.rbegin()->OrderedRegion.getValue(); } /// Returns true, if parent region is ordered (has associated /// 'ordered' clause), false - otherwise. bool isParentOrderedRegion() const { if (isStackEmpty() || Stack.back().first.size() == 1) return false; - return std::next(Stack.back().first.rbegin())->OrderedRegion.getInt(); + return std::next(Stack.back().first.rbegin())->OrderedRegion.hasValue(); } /// Returns optional parameter for the ordered region. - const Expr *getParentOrderedRegionParam() const { - if (isStackEmpty() || Stack.back().first.size() == 1) - return nullptr; - return std::next(Stack.back().first.rbegin())->OrderedRegion.getPointer(); + std::pair<const Expr *, OMPOrderedClause *> + getParentOrderedRegionParam() const { + if (isStackEmpty() || Stack.back().first.size() == 1 || + !std::next(Stack.back().first.rbegin())->OrderedRegion.hasValue()) + return std::make_pair(nullptr, nullptr); + return std::next(Stack.back().first.rbegin())->OrderedRegion.getValue(); } /// Marks current region as nowait (it has a 'nowait' clause). void setNowaitRegion(bool IsNowait = true) { @@ -572,17 +662,34 @@ public: return llvm::make_range(StackElem.DoacrossDepends.end(), StackElem.DoacrossDepends.end()); } + + // Store types of classes which have been explicitly mapped + void addMappedClassesQualTypes(QualType QT) { + SharingMapTy &StackElem = Stack.back().first.back(); + StackElem.MappedClassesQualTypes.insert(QT); + } + + // Return set of mapped classes types + bool isClassPreviouslyMapped(QualType QT) const { + const SharingMapTy &StackElem = Stack.back().first.back(); + return StackElem.MappedClassesQualTypes.count(QT) != 0; + } + }; -bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) { - return isOpenMPParallelDirective(DKind) || isOpenMPTaskingDirective(DKind) || - isOpenMPTeamsDirective(DKind) || DKind == OMPD_unknown; + +bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) { + return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind); +} + +bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) { + return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) || DKind == OMPD_unknown; } } // namespace static const Expr *getExprAsWritten(const Expr *E) { - if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(E)) - E = ExprTemp->getSubExpr(); + if (const auto *FE = dyn_cast<FullExpr>(E)) + E = FE->getSubExpr(); if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) E = MTE->GetTemporaryExpr(); @@ -716,7 +823,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(iterator &Iter, DVar.CKind = OMPC_firstprivate; return DVar; } - } while (I != E && !isParallelOrTaskRegion(I->Directive)); + } while (I != E && !isImplicitTaskingRegion(I->Directive)); DVar.CKind = (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared; return DVar; @@ -963,7 +1070,7 @@ bool DSAStackTy::isOpenMPLocal(VarDecl *D, iterator Iter) const { if (!isStackEmpty()) { iterator I = Iter, E = Stack.back().first.rend(); Scope *TopScope = nullptr; - while (I != E && !isParallelOrTaskRegion(I->Directive) && + while (I != E && !isImplicitOrExplicitTaskingRegion(I->Directive) && !isOpenMPTargetExecutionDirective(I->Directive)) ++I; if (I == E) @@ -977,6 +1084,51 @@ bool DSAStackTy::isOpenMPLocal(VarDecl *D, iterator Iter) const { return false; } +static bool isConstNotMutableType(Sema &SemaRef, QualType Type, + bool AcceptIfMutable = true, + bool *IsClassType = nullptr) { + ASTContext &Context = SemaRef.getASTContext(); + Type = Type.getNonReferenceType().getCanonicalType(); + bool IsConstant = Type.isConstant(Context); + Type = Context.getBaseElementType(Type); + const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus + ? Type->getAsCXXRecordDecl() + : nullptr; + if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD)) + if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate()) + RD = CTD->getTemplatedDecl(); + if (IsClassType) + *IsClassType = RD; + return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD && + RD->hasDefinition() && RD->hasMutableFields()); +} + +static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D, + QualType Type, OpenMPClauseKind CKind, + SourceLocation ELoc, + bool AcceptIfMutable = true, + bool ListItemNotVar = false) { + ASTContext &Context = SemaRef.getASTContext(); + bool IsClassType; + if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) { + unsigned Diag = ListItemNotVar + ? diag::err_omp_const_list_item + : IsClassType ? diag::err_omp_const_not_mutable_variable + : diag::err_omp_const_variable; + SemaRef.Diag(ELoc, Diag) << getOpenMPClauseName(CKind); + if (!ListItemNotVar && D) { + const VarDecl *VD = dyn_cast<VarDecl>(D); + bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) == + VarDecl::DeclarationOnly; + SemaRef.Diag(D->getLocation(), + IsDecl ? diag::note_previous_decl : diag::note_defined_here) + << D; + } + return true; + } + return false; +} + const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) { D = getCanonicalDecl(D); @@ -1074,31 +1226,28 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, return DVar; } - QualType Type = D->getType().getNonReferenceType().getCanonicalType(); - bool IsConstant = Type.isConstant(SemaRef.getASTContext()); - Type = SemaRef.getASTContext().getBaseElementType(Type); - // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced - // in a Construct, C/C++, predetermined, p.6] - // Variables with const qualified type having no mutable member are - // shared. - const CXXRecordDecl *RD = - SemaRef.getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr; - if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD)) - if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate()) - RD = CTD->getTemplatedDecl(); - if (IsConstant && - !(SemaRef.getLangOpts().CPlusPlus && RD && RD->hasDefinition() && - RD->hasMutableFields())) { - // Variables with const-qualified type having no mutable member may be - // listed in a firstprivate clause, even if they are static data members. - DSAVarData DVarTemp = - hasDSA(D, [](OpenMPClauseKind C) { return C == OMPC_firstprivate; }, - MatchesAlways, FromParent); - if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr) - return DVarTemp; + // The predetermined shared attribute for const-qualified types having no + // mutable members was removed after OpenMP 3.1. + if (SemaRef.LangOpts.OpenMP <= 31) { + // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced + // in a Construct, C/C++, predetermined, p.6] + // Variables with const qualified type having no mutable member are + // shared. + if (isConstNotMutableType(SemaRef, D->getType())) { + // Variables with const-qualified type having no mutable member may be + // listed in a firstprivate clause, even if they are static data members. + DSAVarData DVarTemp = hasInnermostDSA( + D, + [](OpenMPClauseKind C) { + return C == OMPC_firstprivate || C == OMPC_shared; + }, + MatchesAlways, FromParent); + if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr) + return DVarTemp; - DVar.CKind = OMPC_shared; - return DVar; + DVar.CKind = OMPC_shared; + return DVar; + } } // Explicitly specified attributes and local variables with predetermined @@ -1147,7 +1296,7 @@ DSAStackTy::hasDSA(ValueDecl *D, if (FromParent && I != EndI) std::advance(I, 1); for (; I != EndI; std::advance(I, 1)) { - if (!DPred(I->Directive) && !isParallelOrTaskRegion(I->Directive)) + if (!DPred(I->Directive) && !isImplicitOrExplicitTaskingRegion(I->Directive)) continue; iterator NewI = I; DSAVarData DVar = getDSA(NewI, D); @@ -1187,10 +1336,16 @@ bool DSAStackTy::hasExplicitDSA( return false; std::advance(StartI, Level); auto I = StartI->SharingMap.find(D); - return (I != StartI->SharingMap.end()) && + if ((I != StartI->SharingMap.end()) && I->getSecond().RefExpr.getPointer() && CPred(I->getSecond().Attributes) && - (!NotLastprivate || !I->getSecond().RefExpr.getInt()); + (!NotLastprivate || !I->getSecond().RefExpr.getInt())) + return true; + // Check predetermined rules for the loop control variables. + auto LI = StartI->LCVMap.find(D); + if (LI != StartI->LCVMap.end()) + return CPred(OMPC_private); + return false; } bool DSAStackTy::hasExplicitDirective( @@ -1239,17 +1394,6 @@ void Sema::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) { DSAStack->popFunction(OldFSI); } -static llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> -isDeclareTargetDeclaration(const ValueDecl *VD) { - for (const Decl *D : VD->redecls()) { - if (!D->hasAttrs()) - continue; - if (const auto *Attr = D->getAttr<OMPDeclareTargetDeclAttr>()) - return Attr->getMapType(); - } - return llvm::None; -} - bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level) const { assert(LangOpts.OpenMP && "OpenMP is not allowed"); @@ -1368,6 +1512,8 @@ bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level) const { // By default, all the data that has a scalar type is mapped by copy // (except for reduction variables). IsByRef = + (DSAStack->isForceCaptureByReferenceInTargetExecutable() && + !Ty->isAnyPointerType()) || !Ty->isScalarType() || DSAStack->getDefaultDMAAtLevel(Level) == DMA_tofrom_scalar || DSAStack->hasExplicitDSA( @@ -1377,10 +1523,12 @@ bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level) const { if (IsByRef && Ty.getNonReferenceType()->isScalarType()) { IsByRef = - !DSAStack->hasExplicitDSA( - D, - [](OpenMPClauseKind K) -> bool { return K == OMPC_firstprivate; }, - Level, /*NotLastprivate=*/true) && + ((DSAStack->isForceCaptureByReferenceInTargetExecutable() && + !Ty->isAnyPointerType()) || + !DSAStack->hasExplicitDSA( + D, + [](OpenMPClauseKind K) -> bool { return K == OMPC_firstprivate; }, + Level, /*NotLastprivate=*/true)) && // If the variable is artificial and must be captured by value - try to // capture by value. !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() && @@ -1417,7 +1565,7 @@ bool Sema::isInOpenMPTargetExecutionDirective() const { false); } -VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D) const { +VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D) { assert(LangOpts.OpenMP && "OpenMP is not allowed"); D = getCanonicalDecl(D); @@ -1425,13 +1573,65 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D) const { // 'target' we return true so that this global is also mapped to the device. // auto *VD = dyn_cast<VarDecl>(D); - if (VD && !VD->hasLocalStorage() && isInOpenMPTargetExecutionDirective()) { - // If the declaration is enclosed in a 'declare target' directive, - // then it should not be captured. - // - if (isDeclareTargetDeclaration(VD)) + if (VD && !VD->hasLocalStorage()) { + if (isInOpenMPDeclareTargetContext() && + (getCurCapturedRegion() || getCurBlock() || getCurLambda())) { + // Try to mark variable as declare target if it is used in capturing + // regions. + if (!OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) + checkDeclIsAllowedInOpenMPTarget(nullptr, VD); return nullptr; - return VD; + } else if (isInOpenMPTargetExecutionDirective()) { + // If the declaration is enclosed in a 'declare target' directive, + // then it should not be captured. + // + if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) + return nullptr; + return VD; + } + } + // Capture variables captured by reference in lambdas for target-based + // directives. + if (VD && !DSAStack->isClauseParsingMode()) { + if (const auto *RD = VD->getType() + .getCanonicalType() + .getNonReferenceType() + ->getAsCXXRecordDecl()) { + bool SavedForceCaptureByReferenceInTargetExecutable = + DSAStack->isForceCaptureByReferenceInTargetExecutable(); + DSAStack->setForceCaptureByReferenceInTargetExecutable(/*V=*/true); + if (RD->isLambda()) { + llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; + FieldDecl *ThisCapture; + RD->getCaptureFields(Captures, ThisCapture); + for (const LambdaCapture &LC : RD->captures()) { + if (LC.getCaptureKind() == LCK_ByRef) { + VarDecl *VD = LC.getCapturedVar(); + DeclContext *VDC = VD->getDeclContext(); + if (!VDC->Encloses(CurContext)) + continue; + DSAStackTy::DSAVarData DVarPrivate = + DSAStack->getTopDSA(VD, /*FromParent=*/false); + // Do not capture already captured variables. + if (!OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && + DVarPrivate.CKind == OMPC_unknown && + !DSAStack->checkMappableExprComponentListsForDecl( + D, /*CurrentRegionOnly=*/true, + [](OMPClauseMappableExprCommon:: + MappableExprComponentListRef, + OpenMPClauseKind) { return true; })) + MarkVariableReferenced(LC.getLocation(), LC.getCapturedVar()); + } else if (LC.getCaptureKind() == LCK_This) { + QualType ThisTy = getCurrentThisType(); + if (!ThisTy.isNull() && + Context.typesAreCompatible(ThisTy, ThisCapture->getType())) + CheckCXXThisCapture(LC.getLocation()); + } + } + } + DSAStack->setForceCaptureByReferenceInTargetExecutable( + SavedForceCaptureByReferenceInTargetExecutable); + } } if (DSAStack->getCurrentDirective() != OMPD_unknown && @@ -1440,7 +1640,7 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D) const { auto &&Info = DSAStack->isLoopControlVariable(D); if (Info.first || (VD && VD->hasLocalStorage() && - isParallelOrTaskRegion(DSAStack->getCurrentDirective())) || + isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) || (VD && DSAStack->isForceVarCapturing())) return VD ? VD : Info.second; DSAStackTy::DSAVarData DVarPrivate = @@ -1463,8 +1663,28 @@ void Sema::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex, FunctionScopesIndex -= Regions.size(); } +void Sema::startOpenMPLoop() { + assert(LangOpts.OpenMP && "OpenMP must be enabled."); + if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) + DSAStack->loopInit(); +} + bool Sema::isOpenMPPrivateDecl(const ValueDecl *D, unsigned Level) const { assert(LangOpts.OpenMP && "OpenMP is not allowed"); + if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) { + if (DSAStack->getAssociatedLoops() > 0 && + !DSAStack->isLoopStarted()) { + DSAStack->resetPossibleLoopCounter(D); + DSAStack->loopStart(); + return true; + } + if ((DSAStack->getPossiblyLoopCunter() == D->getCanonicalDecl() || + DSAStack->isLoopControlVariable(D).first) && + !DSAStack->hasExplicitDSA( + D, [](OpenMPClauseKind K) { return K != OMPC_private; }, Level) && + !isOpenMPSimdDirective(DSAStack->getCurrentDirective())) + return true; + } return DSAStack->hasExplicitDSA( D, [](OpenMPClauseKind K) { return K == OMPC_private; }, Level) || (DSAStack->isClauseParsingMode() && @@ -1780,7 +2000,7 @@ public: bool VisitDeclRefExpr(const DeclRefExpr *E) { if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) { if (VD->hasLocalStorage()) { - SemaRef.Diag(E->getLocStart(), + SemaRef.Diag(E->getBeginLoc(), diag::err_omp_local_var_in_threadprivate_init) << E->getSourceRange(); SemaRef.Diag(VD->getLocation(), diag::note_defined_here) @@ -1882,6 +2102,30 @@ Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) { return D; } +Sema::DeclGroupPtrTy +Sema::ActOnOpenMPRequiresDirective(SourceLocation Loc, + ArrayRef<OMPClause *> ClauseList) { + OMPRequiresDecl *D = nullptr; + if (!CurContext->isFileContext()) { + Diag(Loc, diag::err_omp_invalid_scope) << "requires"; + } else { + D = CheckOMPRequiresDecl(Loc, ClauseList); + if (D) { + CurContext->addDecl(D); + DSAStack->addRequiresDecl(D); + } + } + return DeclGroupPtrTy::make(DeclGroupRef(D)); +} + +OMPRequiresDecl *Sema::CheckOMPRequiresDecl(SourceLocation Loc, + ArrayRef<OMPClause *> ClauseList) { + if (!DSAStack->hasDuplicateRequiresClause(ClauseList)) + return OMPRequiresDecl::Create(Context, getCurLexicalContext(), Loc, + ClauseList); + return nullptr; +} + static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack, const ValueDecl *D, const DSAStackTy::DSAVarData &DVar, @@ -1950,6 +2194,30 @@ class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> { Sema::VarsWithInheritedDSAType VarsWithInheritedDSA; llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations; + void VisitSubCaptures(OMPExecutableDirective *S) { + // Check implicitly captured variables. + if (!S->hasAssociatedStmt() || !S->getAssociatedStmt()) + return; + for (const CapturedStmt::Capture &Cap : + S->getInnermostCapturedStmt()->captures()) { + if (!Cap.capturesVariable()) + continue; + VarDecl *VD = Cap.getCapturedVar(); + // Do not try to map the variable if it or its sub-component was mapped + // already. + if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) && + Stack->checkMappableExprComponentListsForDecl( + VD, /*CurrentRegionOnly=*/true, + [](OMPClauseMappableExprCommon::MappableExprComponentListRef, + OpenMPClauseKind) { return true; })) + continue; + DeclRefExpr *DRE = buildDeclRefExpr( + SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context), + Cap.getLocation(), /*RefersToCapture=*/true); + Visit(DRE); + } + } + public: void VisitDeclRefExpr(DeclRefExpr *E) { if (E->isTypeDependent() || E->isValueDependent() || @@ -1968,7 +2236,7 @@ public: // Skip internally declared static variables. llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = - isDeclareTargetDeclaration(VD); + OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); if (VD->hasGlobalStorage() && !CS->capturesVariable(VD) && (!Res || *Res != OMPDeclareTargetDeclAttr::MT_Link)) return; @@ -1980,7 +2248,7 @@ public: // attribute, must have its data-sharing attribute explicitly determined // by being listed in a data-sharing attribute clause. if (DVar.CKind == OMPC_unknown && Stack->getDefaultDSA() == DSA_none && - isParallelOrTaskRegion(DKind) && + isImplicitOrExplicitTaskingRegion(DKind) && VarsWithInheritedDSA.count(VD) == 0) { VarsWithInheritedDSA[VD] = E; return; @@ -2057,7 +2325,7 @@ public: return; auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl()); OpenMPDirectiveKind DKind = Stack->getCurrentDirective(); - if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) { + if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParens())) { if (!FD) return; DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false); @@ -2084,6 +2352,12 @@ public: // if (FD->isBitField()) return; + + // Check to see if the member expression is referencing a class that + // has already been explicitly mapped + if (Stack->isClassPreviouslyMapped(TE->getType())) + return; + ImplicitMap.emplace_back(E); return; } @@ -2110,8 +2384,14 @@ public: // Define implicit data-sharing attributes for task. DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false); if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared && - !Stack->isLoopControlVariable(FD).first) - ImplicitFirstprivate.push_back(E); + !Stack->isLoopControlVariable(FD).first) { + // Check if there is a captured expression for the current field in the + // region. Do not mark it as firstprivate unless there is no captured + // expression. + // TODO: try to make it firstprivate. + if (DVar.CKind != OMPC_unknown) + ImplicitFirstprivate.push_back(E); + } return; } if (isOpenMPTargetExecutionDirective(DKind)) { @@ -2171,11 +2451,16 @@ public: } } } + // Check implicitly captured variables. + VisitSubCaptures(S); } void VisitStmt(Stmt *S) { for (Stmt *C : S->children()) { - if (C && !isa<OMPExecutableDirective>(C)) + if (C) { + // Check implicitly captured variables in the task-based directives to + // check if they must be firstprivatized. Visit(C); + } } } @@ -2527,6 +2812,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { case OMPD_declare_simd: case OMPD_declare_target: case OMPD_end_declare_target: + case OMPD_requires: llvm_unreachable("OpenMP Directive is not allowed"); case OMPD_unknown: llvm_unreachable("Unknown OpenMP directive"); @@ -2560,7 +2846,7 @@ static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id, WithInit = true; } auto *CED = OMPCapturedExprDecl::Create(C, S.CurContext, Id, Ty, - CaptureExpr->getLocStart()); + CaptureExpr->getBeginLoc()); if (!WithInit) CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C)); S.CurContext->addHiddenDecl(CED); @@ -2697,20 +2983,20 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S, ? SC->getFirstScheduleModifierLoc() : SC->getSecondScheduleModifierLoc(), diag::err_omp_schedule_nonmonotonic_ordered) - << SourceRange(OC->getLocStart(), OC->getLocEnd()); + << SourceRange(OC->getBeginLoc(), OC->getEndLoc()); ErrorFound = true; } if (!LCs.empty() && OC && OC->getNumForLoops()) { for (const OMPLinearClause *C : LCs) { - Diag(C->getLocStart(), diag::err_omp_linear_ordered) - << SourceRange(OC->getLocStart(), OC->getLocEnd()); + Diag(C->getBeginLoc(), diag::err_omp_linear_ordered) + << SourceRange(OC->getBeginLoc(), OC->getEndLoc()); } ErrorFound = true; } if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) && isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC && OC->getNumForLoops()) { - Diag(OC->getLocStart(), diag::err_omp_ordered_simd) + Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd) << getOpenMPDirectiveName(DSAStack->getCurrentDirective()); ErrorFound = true; } @@ -2812,11 +3098,13 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, } return false; } - // Allow some constructs (except teams) to be orphaned (they could be - // used in functions, called from OpenMP regions with the required - // preconditions). + // Allow some constructs (except teams and cancellation constructs) to be + // orphaned (they could be used in functions, called from OpenMP regions + // with the required preconditions). if (ParentRegion == OMPD_unknown && - !isOpenMPNestingTeamsDirective(CurrentRegion)) + !isOpenMPNestingTeamsDirective(CurrentRegion) && + CurrentRegion != OMPD_cancellation_point && + CurrentRegion != OMPD_cancel) return false; if (CurrentRegion == OMPD_cancellation_point || CurrentRegion == OMPD_cancel) { @@ -2845,6 +3133,7 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, (CancelRegion == OMPD_sections && (ParentRegion == OMPD_section || ParentRegion == OMPD_sections || ParentRegion == OMPD_parallel_sections))); + OrphanSeen = ParentRegion == OMPD_unknown; } else if (CurrentRegion == OMPD_master) { // OpenMP [2.16, Nesting of Regions] // A master region may not be closely nested inside a worksharing, @@ -2989,7 +3278,7 @@ static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, // the directive. OpenMPDirectiveKind CurNM = IC->getNameModifier(); if (FoundNameModifiers[CurNM]) { - S.Diag(C->getLocStart(), diag::err_omp_more_one_clause) + S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause) << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if) << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM); ErrorFound = true; @@ -3023,7 +3312,7 @@ static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, // all if clauses on the directive must include a directive-name-modifier. if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) { if (NamedModifiersNumber == AllowedNameModifiers.size()) { - S.Diag(FoundNameModifiers[OMPD_unknown]->getLocStart(), + S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(), diag::err_omp_no_more_if_clause); } else { std::string Values; @@ -3045,7 +3334,7 @@ static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, ++AllowedCnt; } } - S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getLocStart(), + S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(), diag::err_omp_unnamed_if_clause) << (TotalAllowedNum > 1) << Values; } @@ -3113,9 +3402,10 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( } if (!ImplicitMaps.empty()) { if (OMPClause *Implicit = ActOnOpenMPMapClause( - OMPC_MAP_unknown, OMPC_MAP_tofrom, /*IsMapTypeImplicit=*/true, - SourceLocation(), SourceLocation(), ImplicitMaps, - SourceLocation(), SourceLocation(), SourceLocation())) { + llvm::None, llvm::None, OMPC_MAP_tofrom, + /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), + ImplicitMaps, SourceLocation(), SourceLocation(), + SourceLocation())) { ClausesWithImplicit.emplace_back(Implicit); ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() != ImplicitMaps.size(); @@ -3368,6 +3658,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( case OMPD_threadprivate: case OMPD_declare_reduction: case OMPD_declare_simd: + case OMPD_requires: llvm_unreachable("OpenMP Directive is not allowed"); case OMPD_unknown: llvm_unreachable("Unknown OpenMP directive"); @@ -3687,7 +3978,8 @@ class OpenMPIterationSpaceChecker { /// Var <= UB /// UB > Var /// UB >= Var - bool TestIsLessOp = false; + /// This will have no value when the condition is != + llvm::Optional<bool> TestIsLessOp; /// This flag is true when condition is strict ( < or > ). bool TestIsStrictOp = false; /// This flag is true when step is subtracted on each iteration. @@ -3736,6 +4028,13 @@ public: Expr *buildCounterInit() const; /// Build step of the counter be used for codegen. Expr *buildCounterStep() const; + /// Build loop data with counter value for depend clauses in ordered + /// directives. + Expr * + buildOrderedLoopData(Scope *S, Expr *Counter, + llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, + SourceLocation Loc, Expr *Inc = nullptr, + OverloadedOperatorKind OOK = OO_Amp); /// Return true if any expression is dependent. bool dependent() const; @@ -3746,8 +4045,8 @@ private: /// Helper to set loop counter variable and its initializer. bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB); /// Helper to set upper bound. - bool setUB(Expr *NewUB, bool LessOp, bool StrictOp, SourceRange SR, - SourceLocation SL); + bool setUB(Expr *NewUB, llvm::Optional<bool> LessOp, bool StrictOp, + SourceRange SR, SourceLocation SL); /// Helper to set loop increment. bool setStep(Expr *NewStep, bool Subtract); }; @@ -3782,15 +4081,17 @@ bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl, return false; } -bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, bool LessOp, bool StrictOp, - SourceRange SR, SourceLocation SL) { +bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, llvm::Optional<bool> LessOp, + bool StrictOp, SourceRange SR, + SourceLocation SL) { // State consistency checking to ensure correct usage. assert(LCDecl != nullptr && LB != nullptr && UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp); if (!NewUB) return true; UB = NewUB; - TestIsLessOp = LessOp; + if (LessOp) + TestIsLessOp = LessOp; TestIsStrictOp = StrictOp; ConditionSrcRange = SR; ConditionLoc = SL; @@ -3804,7 +4105,7 @@ bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) { return true; if (!NewStep->isValueDependent()) { // Check that the step is integer expression. - SourceLocation StepLoc = NewStep->getLocStart(); + SourceLocation StepLoc = NewStep->getBeginLoc(); ExprResult Val = SemaRef.PerformOpenMPImplicitIntegerConversion( StepLoc, getExprAsWritten(NewStep)); if (Val.isInvalid()) @@ -3830,18 +4131,23 @@ bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) { bool IsConstPos = IsConstant && Result.isSigned() && (Subtract == Result.isNegative()); bool IsConstZero = IsConstant && !Result.getBoolValue(); + + // != with increment is treated as <; != with decrement is treated as > + if (!TestIsLessOp.hasValue()) + TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract); if (UB && (IsConstZero || - (TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract)) - : (IsConstPos || (IsUnsigned && !Subtract))))) { + (TestIsLessOp.getValue() ? + (IsConstNeg || (IsUnsigned && Subtract)) : + (IsConstPos || (IsUnsigned && !Subtract))))) { SemaRef.Diag(NewStep->getExprLoc(), diag::err_omp_loop_incr_not_compatible) - << LCDecl << TestIsLessOp << NewStep->getSourceRange(); + << LCDecl << TestIsLessOp.getValue() << NewStep->getSourceRange(); SemaRef.Diag(ConditionLoc, diag::note_omp_loop_cond_requres_compatible_incr) - << TestIsLessOp << ConditionSrcRange; + << TestIsLessOp.getValue() << ConditionSrcRange; return true; } - if (TestIsLessOp == Subtract) { + if (TestIsLessOp.getValue() == Subtract) { NewStep = SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep) .get(); @@ -3897,10 +4203,15 @@ bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) { if (Var->hasInit() && !Var->getType()->isReferenceType()) { // Accept non-canonical init form here but emit ext. warning. if (Var->getInitStyle() != VarDecl::CInit && EmitDiags) - SemaRef.Diag(S->getLocStart(), + SemaRef.Diag(S->getBeginLoc(), diag::ext_omp_loop_not_canonical_init) << S->getSourceRange(); - return setLCDeclAndLB(Var, nullptr, Var->getInit()); + return setLCDeclAndLB( + Var, + buildDeclRefExpr(SemaRef, Var, + Var->getType().getNonReferenceType(), + DS->getBeginLoc()), + Var->getInit()); } } } @@ -3924,7 +4235,7 @@ bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) { if (dependent() || SemaRef.CurContext->isDependentContext()) return false; if (EmitDiags) { - SemaRef.Diag(S->getLocStart(), diag::err_omp_loop_not_canonical_init) + SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init) << S->getSourceRange(); } return true; @@ -3964,7 +4275,7 @@ bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) { return true; } S = getExprAsWritten(S); - SourceLocation CondLoc = S->getLocStart(); + SourceLocation CondLoc = S->getBeginLoc(); if (auto *BO = dyn_cast<BinaryOperator>(S)) { if (BO->isRelationalOp()) { if (getInitLCDecl(BO->getLHS()) == LCDecl) @@ -3977,7 +4288,12 @@ bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) { (BO->getOpcode() == BO_GT || BO->getOpcode() == BO_GE), (BO->getOpcode() == BO_LT || BO->getOpcode() == BO_GT), BO->getSourceRange(), BO->getOperatorLoc()); - } + } else if (BO->getOpcode() == BO_NE) + return setUB(getInitLCDecl(BO->getLHS()) == LCDecl ? + BO->getRHS() : BO->getLHS(), + /*LessOp=*/llvm::None, + /*StrictOp=*/true, + BO->getSourceRange(), BO->getOperatorLoc()); } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) { if (CE->getNumArgs() == 2) { auto Op = CE->getOperator(); @@ -3995,6 +4311,14 @@ bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) { Op == OO_Less || Op == OO_Greater, CE->getSourceRange(), CE->getOperatorLoc()); break; + case OO_ExclaimEqual: + return setUB(getInitLCDecl(CE->getArg(0)) == LCDecl ? + CE->getArg(1) : CE->getArg(0), + /*LessOp=*/llvm::None, + /*StrictOp=*/true, + CE->getSourceRange(), + CE->getOperatorLoc()); + break; default: break; } @@ -4033,7 +4357,7 @@ bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) { } if (dependent() || SemaRef.CurContext->isDependentContext()) return false; - SemaRef.Diag(RHS->getLocStart(), diag::err_omp_loop_not_canonical_incr) + SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr) << RHS->getSourceRange() << LCDecl; return true; } @@ -4066,7 +4390,7 @@ bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) { if (UO->isIncrementDecrementOp() && getInitLCDecl(UO->getSubExpr()) == LCDecl) return setStep(SemaRef - .ActOnIntegerConstant(UO->getLocStart(), + .ActOnIntegerConstant(UO->getBeginLoc(), (UO->isDecrementOp() ? -1 : 1)) .get(), /*Subtract=*/false); @@ -4091,7 +4415,7 @@ bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) { if (getInitLCDecl(CE->getArg(0)) == LCDecl) return setStep(SemaRef .ActOnIntegerConstant( - CE->getLocStart(), + CE->getBeginLoc(), ((CE->getOperator() == OO_MinusMinus) ? -1 : 1)) .get(), /*Subtract=*/false); @@ -4111,7 +4435,7 @@ bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) { } if (dependent() || SemaRef.CurContext->isDependentContext()) return false; - SemaRef.Diag(S->getLocStart(), diag::err_omp_loop_not_canonical_incr) + SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr) << S->getSourceRange() << LCDecl; return true; } @@ -4143,8 +4467,8 @@ Expr *OpenMPIterationSpaceChecker::buildNumIterations( if (VarType->isIntegerType() || VarType->isPointerType() || SemaRef.getLangOpts().CPlusPlus) { // Upper - Lower - Expr *UBExpr = TestIsLessOp ? UB : LB; - Expr *LBExpr = TestIsLessOp ? LB : UB; + Expr *UBExpr = TestIsLessOp.getValue() ? UB : LB; + Expr *LBExpr = TestIsLessOp.getValue() ? LB : UB; Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures).get(); Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures).get(); if (!Upper || !Lower) @@ -4155,7 +4479,7 @@ Expr *OpenMPIterationSpaceChecker::buildNumIterations( if (!Diff.isUsable() && VarType->getAsCXXRecordDecl()) { // BuildBinOp already emitted error, this one is to point user to upper // and lower bound, and to tell what is passed to 'operator-'. - SemaRef.Diag(Upper->getLocStart(), diag::err_omp_loop_diff_cxx) + SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx) << Upper->getSourceRange() << Lower->getSourceRange(); return nullptr; } @@ -4245,8 +4569,9 @@ Expr *OpenMPIterationSpaceChecker::buildPreCond( ExprResult CondExpr = SemaRef.BuildBinOp(S, DefaultLoc, - TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE) - : (TestIsStrictOp ? BO_GT : BO_GE), + TestIsLessOp.getValue() ? + (TestIsStrictOp ? BO_LT : BO_LE) : + (TestIsStrictOp ? BO_GT : BO_GE), NewLB.get(), NewUB.get()); if (CondExpr.isUsable()) { if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(), @@ -4262,7 +4587,8 @@ Expr *OpenMPIterationSpaceChecker::buildPreCond( /// Build reference expression to the counter be used for codegen. DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar( - llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, DSAStackTy &DSA) const { + llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, + DSAStackTy &DSA) const { auto *VD = dyn_cast<VarDecl>(LCDecl); if (!VD) { VD = SemaRef.isOpenMPCapturedDecl(LCDecl); @@ -4302,6 +4628,63 @@ Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; } /// Build step of the counter be used for codegen. Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; } +Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData( + Scope *S, Expr *Counter, + llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc, + Expr *Inc, OverloadedOperatorKind OOK) { + Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get(); + if (!Cnt) + return nullptr; + if (Inc) { + assert((OOK == OO_Plus || OOK == OO_Minus) && + "Expected only + or - operations for depend clauses."); + BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub; + Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get(); + if (!Cnt) + return nullptr; + } + ExprResult Diff; + QualType VarType = LCDecl->getType().getNonReferenceType(); + if (VarType->isIntegerType() || VarType->isPointerType() || + SemaRef.getLangOpts().CPlusPlus) { + // Upper - Lower + Expr *Upper = + TestIsLessOp.getValue() ? Cnt : tryBuildCapture(SemaRef, UB, Captures).get(); + Expr *Lower = + TestIsLessOp.getValue() ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt; + if (!Upper || !Lower) + return nullptr; + + Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower); + + if (!Diff.isUsable() && VarType->getAsCXXRecordDecl()) { + // BuildBinOp already emitted error, this one is to point user to upper + // and lower bound, and to tell what is passed to 'operator-'. + SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx) + << Upper->getSourceRange() << Lower->getSourceRange(); + return nullptr; + } + } + + if (!Diff.isUsable()) + return nullptr; + + // Parentheses (for dumping/debugging purposes only). + Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get()); + if (!Diff.isUsable()) + return nullptr; + + ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures); + if (!NewStep.isUsable()) + return nullptr; + // (Upper - Lower) / Step + Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get()); + if (!Diff.isUsable()) + return nullptr; + + return Diff.get(); +} + /// Iteration space of a single for loop. struct LoopIterationSpace final { /// Condition of the loop. @@ -4336,6 +4719,7 @@ void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) { unsigned AssociatedLoops = DSAStack->getAssociatedLoops(); if (AssociatedLoops > 0 && isOpenMPLoopDirective(DSAStack->getCurrentDirective())) { + DSAStack->loopStart(); OpenMPIterationSpaceChecker ISC(*this, ForLoc); if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) { if (ValueDecl *D = ISC.getLoopDecl()) { @@ -4350,6 +4734,15 @@ void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) { } } DSAStack->addLoopControlVariable(D, VD); + const Decl *LD = DSAStack->getPossiblyLoopCunter(); + if (LD != D->getCanonicalDecl()) { + DSAStack->resetPossibleLoopCounter(); + if (auto *Var = dyn_cast_or_null<VarDecl>(LD)) + MarkDeclarationsReferencedInExpr( + buildDeclRefExpr(*this, const_cast<VarDecl *>(Var), + Var->getType().getNonLValueExprType(Context), + ForLoc, /*RefersToCapture=*/true)); + } } } DSAStack->setAssociatedLoops(AssociatedLoops - 1); @@ -4361,7 +4754,8 @@ void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) { static bool checkOpenMPIterationSpace( OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA, unsigned CurrentNestedLoopCount, unsigned NestedLoopCount, - Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, + unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr, + Expr *OrderedLoopCountExpr, Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA, LoopIterationSpace &ResultIterSpace, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) { @@ -4369,11 +4763,11 @@ static bool checkOpenMPIterationSpace( // for (init-expr; test-expr; incr-expr) structured-block auto *For = dyn_cast_or_null<ForStmt>(S); if (!For) { - SemaRef.Diag(S->getLocStart(), diag::err_omp_not_for) + SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for) << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr) - << getOpenMPDirectiveName(DKind) << NestedLoopCount + << getOpenMPDirectiveName(DKind) << TotalNestedLoopCount << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount; - if (NestedLoopCount > 1) { + if (TotalNestedLoopCount > 1) { if (CollapseLoopCountExpr && OrderedLoopCountExpr) SemaRef.Diag(DSA.getConstructLoc(), diag::note_omp_collapse_ordered_expr) @@ -4414,7 +4808,7 @@ static bool checkOpenMPIterationSpace( if (!VarType->isDependentType() && !VarType->isIntegerType() && !VarType->isPointerType() && !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) { - SemaRef.Diag(Init->getLocStart(), diag::err_omp_loop_variable_type) + SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type) << SemaRef.getLangOpts().CPlusPlus; HasErrors = true; } @@ -4452,7 +4846,7 @@ static bool checkOpenMPIterationSpace( !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) && (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) { - SemaRef.Diag(Init->getLocStart(), diag::err_omp_loop_var_dsa) + SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa) << getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(PredeterminedCKind); if (DVar.RefExpr == nullptr) @@ -4506,6 +4900,41 @@ static bool checkOpenMPIterationSpace( ResultIterSpace.PrivateCounterVar == nullptr || ResultIterSpace.CounterInit == nullptr || ResultIterSpace.CounterStep == nullptr); + if (!HasErrors && DSA.isOrderedRegion()) { + if (DSA.getOrderedRegionParam().second->getNumForLoops()) { + if (CurrentNestedLoopCount < + DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) { + DSA.getOrderedRegionParam().second->setLoopNumIterations( + CurrentNestedLoopCount, ResultIterSpace.NumIterations); + DSA.getOrderedRegionParam().second->setLoopCounter( + CurrentNestedLoopCount, ResultIterSpace.CounterVar); + } + } + for (auto &Pair : DSA.getDoacrossDependClauses()) { + if (CurrentNestedLoopCount >= Pair.first->getNumLoops()) { + // Erroneous case - clause has some problems. + continue; + } + if (Pair.first->getDependencyKind() == OMPC_DEPEND_sink && + Pair.second.size() <= CurrentNestedLoopCount) { + // Erroneous case - clause has some problems. + Pair.first->setLoopData(CurrentNestedLoopCount, nullptr); + continue; + } + Expr *CntValue; + if (Pair.first->getDependencyKind() == OMPC_DEPEND_source) + CntValue = ISC.buildOrderedLoopData( + DSA.getCurScope(), ResultIterSpace.CounterVar, Captures, + Pair.first->getDependencyLoc()); + else + CntValue = ISC.buildOrderedLoopData( + DSA.getCurScope(), ResultIterSpace.CounterVar, Captures, + Pair.first->getDependencyLoc(), + Pair.second[CurrentNestedLoopCount].first, + Pair.second[CurrentNestedLoopCount].second); + Pair.first->setLoopData(CurrentNestedLoopCount, CntValue); + } + } return HasErrors; } @@ -4687,14 +5116,16 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, unsigned NestedLoopCount = 1; if (CollapseLoopCountExpr) { // Found 'collapse' clause - calculate collapse number. - llvm::APSInt Result; + Expr::EvalResult Result; if (CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) - NestedLoopCount = Result.getLimitedValue(); + NestedLoopCount = Result.Val.getInt().getLimitedValue(); } + unsigned OrderedLoopCount = 1; if (OrderedLoopCountExpr) { // Found 'ordered' clause - calculate collapse number. - llvm::APSInt Result; - if (OrderedLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) { + Expr::EvalResult EVResult; + if (OrderedLoopCountExpr->EvaluateAsInt(EVResult, SemaRef.getASTContext())) { + llvm::APSInt Result = EVResult.Val.getInt(); if (Result.getLimitedValue() < NestedLoopCount) { SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(), diag::err_omp_wrong_ordered_loop_count) @@ -4703,20 +5134,21 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, diag::note_collapse_loop_count) << CollapseLoopCountExpr->getSourceRange(); } - NestedLoopCount = Result.getLimitedValue(); + OrderedLoopCount = Result.getLimitedValue(); } } // This is helper routine for loop directives (e.g., 'for', 'simd', // 'for simd', etc.). llvm::MapVector<const Expr *, DeclRefExpr *> Captures; SmallVector<LoopIterationSpace, 4> IterSpaces; - IterSpaces.resize(NestedLoopCount); + IterSpaces.resize(std::max(OrderedLoopCount, NestedLoopCount)); Stmt *CurStmt = AStmt->IgnoreContainers(/* IgnoreCaptured */ true); for (unsigned Cnt = 0; Cnt < NestedLoopCount; ++Cnt) { - if (checkOpenMPIterationSpace(DKind, CurStmt, SemaRef, DSA, Cnt, - NestedLoopCount, CollapseLoopCountExpr, - OrderedLoopCountExpr, VarsWithImplicitDSA, - IterSpaces[Cnt], Captures)) + if (checkOpenMPIterationSpace( + DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount, + std::max(OrderedLoopCount, NestedLoopCount), CollapseLoopCountExpr, + OrderedLoopCountExpr, VarsWithImplicitDSA, IterSpaces[Cnt], + Captures)) return 0; // Move on to the next nested for loop, or to the loop body. // OpenMP [2.8.1, simd construct, Restrictions] @@ -4725,6 +5157,27 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // any two loops. CurStmt = cast<ForStmt>(CurStmt)->getBody()->IgnoreContainers(); } + for (unsigned Cnt = NestedLoopCount; Cnt < OrderedLoopCount; ++Cnt) { + if (checkOpenMPIterationSpace( + DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount, + std::max(OrderedLoopCount, NestedLoopCount), CollapseLoopCountExpr, + OrderedLoopCountExpr, VarsWithImplicitDSA, IterSpaces[Cnt], + Captures)) + return 0; + if (Cnt > 0 && IterSpaces[Cnt].CounterVar) { + // Handle initialization of captured loop iterator variables. + auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar); + if (isa<OMPCapturedExprDecl>(DRE->getDecl())) { + Captures[DRE] = DRE; + } + } + // Move on to the next nested for loop, or to the loop body. + // OpenMP [2.8.1, simd construct, Restrictions] + // All loops associated with the construct must be perfectly nested; that + // is, there must be no intervening code nor any OpenMP directive between + // any two loops. + CurStmt = cast<ForStmt>(CurStmt)->getBody()->IgnoreContainers(); + } Built.clear(/* size */ NestedLoopCount); @@ -4817,13 +5270,14 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // Choose either the 32-bit or 64-bit version. ExprResult LastIteration = LastIteration64; - if (LastIteration32.isUsable() && - C.getTypeSize(LastIteration32.get()->getType()) == 32 && - (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 || - fitsInto( - /*Bits=*/32, - LastIteration32.get()->getType()->hasSignedIntegerRepresentation(), - LastIteration64.get(), SemaRef))) + if (SemaRef.getLangOpts().OpenMPOptimisticCollapse || + (LastIteration32.isUsable() && + C.getTypeSize(LastIteration32.get()->getType()) == 32 && + (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 || + fitsInto( + /*Bits=*/32, + LastIteration32.get()->getType()->hasSignedIntegerRepresentation(), + LastIteration64.get(), SemaRef)))) LastIteration = LastIteration32; QualType VType = LastIteration.get()->getType(); QualType RealVType = VType; @@ -4913,7 +5367,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, LastIteration.get(), UB.get()); EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(), CondOp.get()); - EUB = SemaRef.ActOnFinishFullExpr(EUB.get()); + EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue*/ false); // If we have a combined directive that combines 'distribute', 'for' or // 'simd' we need to be able to access the bounds of the schedule of the @@ -4942,7 +5396,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, LastIteration.get(), CombUB.get()); CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(), CombCondOp.get()); - CombEUB = SemaRef.ActOnFinishFullExpr(CombEUB.get()); + CombEUB = + SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue*/ false); const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl(); // We expect to have at least 2 more parameters than the 'parallel' @@ -4976,7 +5431,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, ? LB.get() : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get(); Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS); - Init = SemaRef.ActOnFinishFullExpr(Init.get()); + Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false); if (isOpenMPLoopBoundSharingDirective(DKind)) { Expr *CombRHS = @@ -4987,32 +5442,40 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get(); CombInit = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS); - CombInit = SemaRef.ActOnFinishFullExpr(CombInit.get()); + CombInit = + SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue*/ false); } } // Loop condition (IV < NumIterations) or (IV <= UB) for worksharing loops. - SourceLocation CondLoc = AStmt->getLocStart(); + SourceLocation CondLoc = AStmt->getBeginLoc(); ExprResult Cond = (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind)) ? SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), UB.get()) : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(), NumIterations.get()); + ExprResult CombDistCond; + if (isOpenMPLoopBoundSharingDirective(DKind)) { + CombDistCond = + SemaRef.BuildBinOp( + CurScope, CondLoc, BO_LT, IV.get(), NumIterations.get()); + } + ExprResult CombCond; if (isOpenMPLoopBoundSharingDirective(DKind)) { CombCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), CombUB.get()); } // Loop increment (IV = IV + 1) - SourceLocation IncLoc = AStmt->getLocStart(); + SourceLocation IncLoc = AStmt->getBeginLoc(); ExprResult Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(), SemaRef.ActOnIntegerConstant(IncLoc, 1).get()); if (!Inc.isUsable()) return 0; Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get()); - Inc = SemaRef.ActOnFinishFullExpr(Inc.get()); + Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue*/ false); if (!Inc.isUsable()) return 0; @@ -5030,7 +5493,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // LB = LB + ST NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get()); - NextLB = SemaRef.ActOnFinishFullExpr(NextLB.get()); + NextLB = + SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue*/ false); if (!NextLB.isUsable()) return 0; // UB + ST @@ -5040,7 +5504,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // UB = UB + ST NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get()); - NextUB = SemaRef.ActOnFinishFullExpr(NextUB.get()); + NextUB = + SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue*/ false); if (!NextUB.isUsable()) return 0; if (isOpenMPLoopBoundSharingDirective(DKind)) { @@ -5051,7 +5516,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // LB = LB + ST CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(), CombNextLB.get()); - CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get()); + CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(), + /*DiscardedValue*/ false); if (!CombNextLB.isUsable()) return 0; // UB + ST @@ -5062,7 +5528,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // UB = UB + ST CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(), CombNextUB.get()); - CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get()); + CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(), + /*DiscardedValue*/ false); if (!CombNextUB.isUsable()) return 0; } @@ -5072,8 +5539,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // directive with for as IV = IV + ST; ensure upper bound expression based // on PrevUB instead of NumIterations - used to implement 'for' when found // in combination with 'distribute', like in 'distribute parallel for' - SourceLocation DistIncLoc = AStmt->getLocStart(); - ExprResult DistCond, DistInc, PrevEUB; + SourceLocation DistIncLoc = AStmt->getBeginLoc(); + ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond; if (isOpenMPLoopBoundSharingDirective(DKind)) { DistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), UB.get()); assert(DistCond.isUsable() && "distribute cond expr was not built"); @@ -5083,19 +5550,26 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, assert(DistInc.isUsable() && "distribute inc expr was not built"); DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(), DistInc.get()); - DistInc = SemaRef.ActOnFinishFullExpr(DistInc.get()); + DistInc = + SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue*/ false); assert(DistInc.isUsable() && "distribute inc expr was not built"); // Build expression: UB = min(UB, prevUB) for #for in composite or combined // construct - SourceLocation DistEUBLoc = AStmt->getLocStart(); + SourceLocation DistEUBLoc = AStmt->getBeginLoc(); ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT, UB.get(), PrevUB.get()); ExprResult CondOp = SemaRef.ActOnConditionalOp( DistEUBLoc, DistEUBLoc, IsUBGreater.get(), PrevUB.get(), UB.get()); PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(), CondOp.get()); - PrevEUB = SemaRef.ActOnFinishFullExpr(PrevEUB.get()); + PrevEUB = + SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue*/ false); + + // Build IV <= PrevUB to be used in parallel for is in combination with + // a distribute directive with schedule(static, 1) + ParForInDistCond = + SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), PrevUB.get()); } // Build updates and final values of the loop counters. @@ -5104,33 +5578,60 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Built.Inits.resize(NestedLoopCount); Built.Updates.resize(NestedLoopCount); Built.Finals.resize(NestedLoopCount); - SmallVector<Expr *, 4> LoopMultipliers; { - ExprResult Div; - // Go from inner nested loop to outer. - for (int Cnt = NestedLoopCount - 1; Cnt >= 0; --Cnt) { + // We implement the following algorithm for obtaining the + // original loop iteration variable values based on the + // value of the collapsed loop iteration variable IV. + // + // Let n+1 be the number of collapsed loops in the nest. + // Iteration variables (I0, I1, .... In) + // Iteration counts (N0, N1, ... Nn) + // + // Acc = IV; + // + // To compute Ik for loop k, 0 <= k <= n, generate: + // Prod = N(k+1) * N(k+2) * ... * Nn; + // Ik = Acc / Prod; + // Acc -= Ik * Prod; + // + ExprResult Acc = IV; + for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) { LoopIterationSpace &IS = IterSpaces[Cnt]; SourceLocation UpdLoc = IS.IncSrcRange.getBegin(); - // Build: Iter = (IV / Div) % IS.NumIters - // where Div is product of previous iterations' IS.NumIters. ExprResult Iter; - if (Div.isUsable()) { - Iter = - SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, IV.get(), Div.get()); - } else { - Iter = IV; - assert((Cnt == (int)NestedLoopCount - 1) && - "unusable div expected on first iteration only"); - } - if (Cnt != 0 && Iter.isUsable()) - Iter = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Rem, Iter.get(), - IS.NumIterations); + // Compute prod + ExprResult Prod = + SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(); + for (unsigned int K = Cnt+1; K < NestedLoopCount; ++K) + Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(), + IterSpaces[K].NumIterations); + + // Iter = Acc / Prod + // If there is at least one more inner loop to avoid + // multiplication by 1. + if (Cnt + 1 < NestedLoopCount) + Iter = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, + Acc.get(), Prod.get()); + else + Iter = Acc; if (!Iter.isUsable()) { HasErrors = true; break; } + // Update Acc: + // Acc -= Iter * Prod + // Check if there is at least one more inner loop to avoid + // multiplication by 1. + if (Cnt + 1 < NestedLoopCount) + Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, + Iter.get(), Prod.get()); + else + Prod = Iter; + Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, + Acc.get(), Prod.get()); + // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl()); DeclRefExpr *CounterVar = buildDeclRefExpr( @@ -5159,23 +5660,6 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, break; } - // Build Div for the next iteration: Div <- Div * IS.NumIters - if (Cnt != 0) { - if (Div.isUnset()) - Div = IS.NumIterations; - else - Div = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Div.get(), - IS.NumIterations); - - // Add parentheses (for debugging purposes only). - if (Div.isUsable()) - Div = tryBuildCapture(SemaRef, Div.get(), Captures); - if (!Div.isUsable()) { - HasErrors = true; - break; - } - LoopMultipliers.push_back(Div.get()); - } if (!Update.isUsable() || !Final.isUsable()) { HasErrors = true; break; @@ -5196,8 +5680,10 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Built.IterationVarRef = IV.get(); Built.LastIteration = LastIteration.get(); Built.NumIterations = NumIterations.get(); - Built.CalcLastIteration = - SemaRef.ActOnFinishFullExpr(CalcLastIteration.get()).get(); + Built.CalcLastIteration = SemaRef + .ActOnFinishFullExpr(CalcLastIteration.get(), + /*DiscardedValue*/ false) + .get(); Built.PreCond = PreCond.get(); Built.PreInits = buildPreInits(C, Captures); Built.Cond = Cond.get(); @@ -5221,55 +5707,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Built.DistCombinedFields.Cond = CombCond.get(); Built.DistCombinedFields.NLB = CombNextLB.get(); Built.DistCombinedFields.NUB = CombNextUB.get(); - - Expr *CounterVal = SemaRef.DefaultLvalueConversion(IV.get()).get(); - // Fill data for doacross depend clauses. - for (const auto &Pair : DSA.getDoacrossDependClauses()) { - if (Pair.first->getDependencyKind() == OMPC_DEPEND_source) { - Pair.first->setCounterValue(CounterVal); - } else { - if (NestedLoopCount != Pair.second.size() || - NestedLoopCount != LoopMultipliers.size() + 1) { - // Erroneous case - clause has some problems. - Pair.first->setCounterValue(CounterVal); - continue; - } - assert(Pair.first->getDependencyKind() == OMPC_DEPEND_sink); - auto I = Pair.second.rbegin(); - auto IS = IterSpaces.rbegin(); - auto ILM = LoopMultipliers.rbegin(); - Expr *UpCounterVal = CounterVal; - Expr *Multiplier = nullptr; - for (int Cnt = NestedLoopCount - 1; Cnt >= 0; --Cnt) { - if (I->first) { - assert(IS->CounterStep); - Expr *NormalizedOffset = - SemaRef - .BuildBinOp(CurScope, I->first->getExprLoc(), BO_Div, - I->first, IS->CounterStep) - .get(); - if (Multiplier) { - NormalizedOffset = - SemaRef - .BuildBinOp(CurScope, I->first->getExprLoc(), BO_Mul, - NormalizedOffset, Multiplier) - .get(); - } - assert(I->second == OO_Plus || I->second == OO_Minus); - BinaryOperatorKind BOK = (I->second == OO_Plus) ? BO_Add : BO_Sub; - UpCounterVal = SemaRef - .BuildBinOp(CurScope, I->first->getExprLoc(), BOK, - UpCounterVal, NormalizedOffset) - .get(); - } - Multiplier = *ILM; - ++I; - ++IS; - ++ILM; - } - Pair.first->setCounterValue(UpCounterVal); - } - } + Built.DistCombinedFields.DistCond = CombDistCond.get(); + Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get(); return NestedLoopCount; } @@ -5305,7 +5744,6 @@ static bool checkSimdlenSafelenSpecified(Sema &S, } if (Simdlen && Safelen) { - llvm::APSInt SimdlenRes, SafelenRes; const Expr *SimdlenLength = Simdlen->getSimdlen(); const Expr *SafelenLength = Safelen->getSafelen(); if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() || @@ -5316,8 +5754,11 @@ static bool checkSimdlenSafelenSpecified(Sema &S, SafelenLength->isInstantiationDependent() || SafelenLength->containsUnexpandedParameterPack()) return false; - SimdlenLength->EvaluateAsInt(SimdlenRes, S.Context); - SafelenLength->EvaluateAsInt(SafelenRes, S.Context); + Expr::EvalResult SimdlenResult, SafelenResult; + SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context); + SafelenLength->EvaluateAsInt(SafelenResult, S.Context); + llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt(); + llvm::APSInt SafelenRes = SafelenResult.Val.getInt(); // OpenMP 4.5 [2.8.1, simd Construct, Restrictions] // If both simdlen and safelen clauses are specified, the value of the // simdlen parameter must be less than or equal to the value of the safelen @@ -5466,7 +5907,7 @@ StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses, for (Stmt *SectionStmt : llvm::make_range(std::next(S.begin()), S.end())) { if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) { if (SectionStmt) - Diag(SectionStmt->getLocStart(), + Diag(SectionStmt->getBeginLoc(), diag::err_omp_sections_substmt_not_section); return StmtError(); } @@ -5474,7 +5915,7 @@ StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses, ->setHasCancel(DSAStack->isCancelRegion()); } } else { - Diag(AStmt->getLocStart(), diag::err_omp_sections_not_compound_stmt); + Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt); return StmtError(); } @@ -5520,9 +5961,9 @@ StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses, else if (Clause->getClauseKind() == OMPC_copyprivate) Copyprivate = Clause; if (Copyprivate && Nowait) { - Diag(Copyprivate->getLocStart(), + Diag(Copyprivate->getBeginLoc(), diag::err_omp_single_copyprivate_with_nowait); - Diag(Nowait->getLocStart(), diag::note_omp_nowait_clause_here); + Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here); return StmtError(); } } @@ -5558,7 +5999,7 @@ StmtResult Sema::ActOnOpenMPCriticalDirective( for (const OMPClause *C : Clauses) { if (C->getClauseKind() == OMPC_hint) { if (!DirName.getName()) { - Diag(C->getLocStart(), diag::err_omp_hint_clause_no_name); + Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name); ErrorFound = true; } Expr *E = cast<OMPHintClause>(C)->getHint(); @@ -5567,7 +6008,7 @@ StmtResult Sema::ActOnOpenMPCriticalDirective( DependentHint = true; } else { Hint = E->EvaluateKnownConstInt(Context); - HintLoc = C->getLocStart(); + HintLoc = C->getBeginLoc(); } } } @@ -5583,12 +6024,12 @@ StmtResult Sema::ActOnOpenMPCriticalDirective( else Diag(StartLoc, diag::note_omp_critical_no_hint) << 0; if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) { - Diag(C->getLocStart(), diag::note_omp_critical_hint_here) + Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here) << 1 << C->getHint()->EvaluateKnownConstInt(Context).toString( /*Radix=*/10, /*Signed=*/false); } else { - Diag(Pair.first->getLocStart(), diag::note_omp_critical_no_hint) << 1; + Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1; } } } @@ -5709,7 +6150,7 @@ Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses, for (Stmt *SectionStmt : llvm::make_range(std::next(S.begin()), S.end())) { if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) { if (SectionStmt) - Diag(SectionStmt->getLocStart(), + Diag(SectionStmt->getBeginLoc(), diag::err_omp_parallel_sections_substmt_not_section); return StmtError(); } @@ -5717,7 +6158,7 @@ Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses, ->setHasCancel(DSAStack->isCancelRegion()); } } else { - Diag(AStmt->getLocStart(), + Diag(AStmt->getBeginLoc(), diag::err_omp_parallel_sections_not_compound_stmt); return StmtError(); } @@ -5801,7 +6242,7 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses, DependFound = C; if (DC->getDependencyKind() == OMPC_DEPEND_source) { if (DependSourceClause) { - Diag(C->getLocStart(), diag::err_omp_more_one_clause) + Diag(C->getBeginLoc(), diag::err_omp_more_one_clause) << getOpenMPDirectiveName(OMPD_ordered) << getOpenMPClauseName(OMPC_depend) << 2; ErrorFound = true; @@ -5809,13 +6250,13 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses, DependSourceClause = C; } if (DependSinkClause) { - Diag(C->getLocStart(), diag::err_omp_depend_sink_source_not_allowed) + Diag(C->getBeginLoc(), diag::err_omp_depend_sink_source_not_allowed) << 0; ErrorFound = true; } } else if (DC->getDependencyKind() == OMPC_DEPEND_sink) { if (DependSourceClause) { - Diag(C->getLocStart(), diag::err_omp_depend_sink_source_not_allowed) + Diag(C->getBeginLoc(), diag::err_omp_depend_sink_source_not_allowed) << 1; ErrorFound = true; } @@ -5835,19 +6276,19 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses, Diag(StartLoc, diag::err_omp_prohibited_region_simd); ErrorFound = true; } else if (DependFound && (TC || SC)) { - Diag(DependFound->getLocStart(), diag::err_omp_depend_clause_thread_simd) + Diag(DependFound->getBeginLoc(), diag::err_omp_depend_clause_thread_simd) << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind()); ErrorFound = true; - } else if (DependFound && !DSAStack->getParentOrderedRegionParam()) { - Diag(DependFound->getLocStart(), + } else if (DependFound && !DSAStack->getParentOrderedRegionParam().first) { + Diag(DependFound->getBeginLoc(), diag::err_omp_ordered_directive_without_param); ErrorFound = true; } else if (TC || Clauses.empty()) { - if (const Expr *Param = DSAStack->getParentOrderedRegionParam()) { - SourceLocation ErrLoc = TC ? TC->getLocStart() : StartLoc; + if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) { + SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc; Diag(ErrLoc, diag::err_omp_ordered_directive_with_param) << (TC != nullptr); - Diag(Param->getLocStart(), diag::note_omp_ordered_param); + Diag(Param->getBeginLoc(), diag::note_omp_ordered_param); ErrorFound = true; } } @@ -6068,12 +6509,12 @@ bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId, } } else { ErrorFound = NotAScalarType; - NoteLoc = ErrorLoc = AtomicBody->getLocStart(); + NoteLoc = ErrorLoc = AtomicBody->getBeginLoc(); NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); } } else { ErrorFound = NotAnExpression; - NoteLoc = ErrorLoc = S->getLocStart(); + NoteLoc = ErrorLoc = S->getBeginLoc(); NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); } if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) { @@ -6125,13 +6566,13 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, C->getClauseKind() == OMPC_update || C->getClauseKind() == OMPC_capture) { if (AtomicKind != OMPC_unknown) { - Diag(C->getLocStart(), diag::err_omp_atomic_several_clauses) - << SourceRange(C->getLocStart(), C->getLocEnd()); + Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses) + << SourceRange(C->getBeginLoc(), C->getEndLoc()); Diag(AtomicKindLoc, diag::note_omp_atomic_previous_clause) << getOpenMPClauseName(AtomicKind); } else { AtomicKind = C->getClauseKind(); - AtomicKindLoc = C->getLocStart(); + AtomicKindLoc = C->getBeginLoc(); } } } @@ -6219,7 +6660,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, } } else { ErrorFound = NotAnExpression; - NoteLoc = ErrorLoc = Body->getLocStart(); + NoteLoc = ErrorLoc = Body->getBeginLoc(); NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); } if (ErrorFound != NoError) { @@ -6281,7 +6722,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, } } else { ErrorFound = NotAnExpression; - NoteLoc = ErrorLoc = Body->getLocStart(); + NoteLoc = ErrorLoc = Body->getBeginLoc(); NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); } if (ErrorFound != NoError) { @@ -6465,7 +6906,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) { ErrorFound = NotAnAssignmentOp; NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc() - : First->getLocStart(); + : First->getBeginLoc(); NoteRange = ErrorRange = FirstBinOp ? FirstBinOp->getSourceRange() : SourceRange(ErrorLoc, ErrorLoc); @@ -6475,7 +6916,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, ErrorFound = NotAnAssignmentOp; NoteLoc = ErrorLoc = SecondBinOp ? SecondBinOp->getOperatorLoc() - : Second->getLocStart(); + : Second->getBeginLoc(); NoteRange = ErrorRange = SecondBinOp ? SecondBinOp->getSourceRange() : SourceRange(ErrorLoc, ErrorLoc); @@ -6509,15 +6950,15 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, } } } else { - NoteLoc = ErrorLoc = Body->getLocStart(); + NoteLoc = ErrorLoc = Body->getBeginLoc(); NoteRange = ErrorRange = - SourceRange(Body->getLocStart(), Body->getLocStart()); + SourceRange(Body->getBeginLoc(), Body->getBeginLoc()); ErrorFound = NotTwoSubstatements; } } else { - NoteLoc = ErrorLoc = Body->getLocStart(); + NoteLoc = ErrorLoc = Body->getBeginLoc(); NoteRange = ErrorRange = - SourceRange(Body->getLocStart(), Body->getLocStart()); + SourceRange(Body->getBeginLoc(), Body->getBeginLoc()); ErrorFound = NotACompoundStatement; } if (ErrorFound != NoError) { @@ -6590,7 +7031,7 @@ StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses, Diag(StartLoc, diag::err_omp_target_contains_not_only_teams); Diag(DSAStack->getInnerTeamsRegionLoc(), diag::note_omp_nested_teams_construct_here); - Diag(S->getLocStart(), diag::note_omp_nested_statement_here) + Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here) << isa<OMPExecutableDirective>(S); return StmtError(); } @@ -6894,11 +7335,11 @@ static bool checkGrainsizeNumTasksClauses(Sema &S, if (!PrevClause) PrevClause = C; else if (PrevClause->getClauseKind() != C->getClauseKind()) { - S.Diag(C->getLocStart(), + S.Diag(C->getBeginLoc(), diag::err_omp_grainsize_num_tasks_mutually_exclusive) << getOpenMPClauseName(C->getClauseKind()) << getOpenMPClauseName(PrevClause->getClauseKind()); - S.Diag(PrevClause->getLocStart(), + S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_grainsize_num_tasks) << getOpenMPClauseName(PrevClause->getClauseKind()); ErrorFound = true; @@ -6927,9 +7368,9 @@ static bool checkReductionClauseWithNogroup(Sema &S, } } if (ReductionClause && NogroupClause) { - S.Diag(ReductionClause->getLocStart(), diag::err_omp_reduction_with_nogroup) - << SourceRange(NogroupClause->getLocStart(), - NogroupClause->getLocEnd()); + S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup) + << SourceRange(NogroupClause->getBeginLoc(), + NogroupClause->getEndLoc()); return true; } return false; @@ -7859,6 +8300,11 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, case OMPC_from: case OMPC_use_device_ptr: case OMPC_is_device_ptr: + case OMPC_unified_address: + case OMPC_unified_shared_memory: + case OMPC_reverse_offload: + case OMPC_dynamic_allocators: + case OMPC_atomic_default_mem_order: llvm_unreachable("Clause is not allowed."); } return Res; @@ -7944,6 +8390,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_distribute_simd: case OMPD_teams_distribute: case OMPD_teams_distribute_simd: + case OMPD_requires: llvm_unreachable("Unexpected OpenMP directive with if-clause"); case OMPD_unknown: llvm_unreachable("Unknown OpenMP directive"); @@ -8009,6 +8456,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_distribute_simd: case OMPD_teams_distribute: case OMPD_teams_distribute_simd: + case OMPD_requires: llvm_unreachable("Unexpected OpenMP directive with num_threads-clause"); case OMPD_unknown: llvm_unreachable("Unknown OpenMP directive"); @@ -8072,6 +8520,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_ordered: case OMPD_atomic: case OMPD_distribute_simd: + case OMPD_requires: llvm_unreachable("Unexpected OpenMP directive with num_teams-clause"); case OMPD_unknown: llvm_unreachable("Unknown OpenMP directive"); @@ -8135,6 +8584,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_ordered: case OMPD_atomic: case OMPD_distribute_simd: + case OMPD_requires: llvm_unreachable("Unexpected OpenMP directive with thread_limit-clause"); case OMPD_unknown: llvm_unreachable("Unknown OpenMP directive"); @@ -8198,6 +8648,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_atomic: case OMPD_distribute_simd: case OMPD_target_teams: + case OMPD_requires: llvm_unreachable("Unexpected OpenMP directive with schedule clause"); case OMPD_unknown: llvm_unreachable("Unknown OpenMP directive"); @@ -8261,6 +8712,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_ordered: case OMPD_atomic: case OMPD_target_teams: + case OMPD_requires: llvm_unreachable("Unexpected OpenMP directive with schedule clause"); case OMPD_unknown: llvm_unreachable("Unknown OpenMP directive"); @@ -8324,6 +8776,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_ordered: case OMPD_atomic: case OMPD_distribute_simd: + case OMPD_requires: llvm_unreachable("Unexpected OpenMP directive with num_teams-clause"); case OMPD_unknown: llvm_unreachable("Unknown OpenMP directive"); @@ -8373,6 +8826,11 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPC_from: case OMPC_use_device_ptr: case OMPC_is_device_ptr: + case OMPC_unified_address: + case OMPC_unified_shared_memory: + case OMPC_reverse_offload: + case OMPC_dynamic_allocators: + case OMPC_atomic_default_mem_order: llvm_unreachable("Unexpected OpenMP clause."); } return CaptureRegion; @@ -8619,9 +9077,11 @@ OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc, } else { NumForLoops = nullptr; } - DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops); - return new (Context) - OMPOrderedClause(NumForLoops, StartLoc, LParenLoc, EndLoc); + auto *Clause = OMPOrderedClause::Create( + Context, NumForLoops, NumForLoops ? DSAStack->getAssociatedLoops() : 0, + StartLoc, LParenLoc, EndLoc); + DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause); + return Clause; } OMPClause *Sema::ActOnOpenMPSimpleClause( @@ -8639,6 +9099,11 @@ OMPClause *Sema::ActOnOpenMPSimpleClause( static_cast<OpenMPProcBindClauseKind>(Argument), ArgumentLoc, StartLoc, LParenLoc, EndLoc); break; + case OMPC_atomic_default_mem_order: + Res = ActOnOpenMPAtomicDefaultMemOrderClause( + static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument), + ArgumentLoc, StartLoc, LParenLoc, EndLoc); + break; case OMPC_if: case OMPC_final: case OMPC_num_threads: @@ -8688,6 +9153,10 @@ OMPClause *Sema::ActOnOpenMPSimpleClause( case OMPC_from: case OMPC_use_device_ptr: case OMPC_is_device_ptr: + case OMPC_unified_address: + case OMPC_unified_shared_memory: + case OMPC_reverse_offload: + case OMPC_dynamic_allocators: llvm_unreachable("Clause is not allowed."); } return Res; @@ -8760,6 +9229,21 @@ OMPClause *Sema::ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind, OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc); } +OMPClause *Sema::ActOnOpenMPAtomicDefaultMemOrderClause( + OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindKwLoc, + SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { + if (Kind == OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown) { + Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) + << getListOfPossibleValues( + OMPC_atomic_default_mem_order, /*First=*/0, + /*Last=*/OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown) + << getOpenMPClauseName(OMPC_atomic_default_mem_order); + return nullptr; + } + return new (Context) OMPAtomicDefaultMemOrderClause(Kind, KindKwLoc, StartLoc, + LParenLoc, EndLoc); +} + OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause( OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, @@ -8844,6 +9328,11 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause( case OMPC_from: case OMPC_use_device_ptr: case OMPC_is_device_ptr: + case OMPC_unified_address: + case OMPC_unified_shared_memory: + case OMPC_reverse_offload: + case OMPC_dynamic_allocators: + case OMPC_atomic_default_mem_order: llvm_unreachable("Clause is not allowed."); } return Res; @@ -8923,7 +9412,7 @@ OMPClause *Sema::ActOnOpenMPScheduleClause( if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() && !ChunkSize->isInstantiationDependent() && !ChunkSize->containsUnexpandedParameterPack()) { - SourceLocation ChunkSizeLoc = ChunkSize->getLocStart(); + SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc(); ExprResult Val = PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize); if (Val.isInvalid()) @@ -8999,6 +9488,18 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind, case OMPC_nogroup: Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc); break; + case OMPC_unified_address: + Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc); + break; + case OMPC_unified_shared_memory: + Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc); + break; + case OMPC_reverse_offload: + Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc); + break; + case OMPC_dynamic_allocators: + Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc); + break; case OMPC_if: case OMPC_final: case OMPC_num_threads: @@ -9038,6 +9539,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind, case OMPC_from: case OMPC_use_device_ptr: case OMPC_is_device_ptr: + case OMPC_atomic_default_mem_order: llvm_unreachable("Clause is not allowed."); } return Res; @@ -9099,12 +9601,34 @@ OMPClause *Sema::ActOnOpenMPNogroupClause(SourceLocation StartLoc, return new (Context) OMPNogroupClause(StartLoc, EndLoc); } +OMPClause *Sema::ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc, + SourceLocation EndLoc) { + return new (Context) OMPUnifiedAddressClause(StartLoc, EndLoc); +} + +OMPClause *Sema::ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc, + SourceLocation EndLoc) { + return new (Context) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc); +} + +OMPClause *Sema::ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc, + SourceLocation EndLoc) { + return new (Context) OMPReverseOffloadClause(StartLoc, EndLoc); +} + +OMPClause *Sema::ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc, + SourceLocation EndLoc) { + return new (Context) OMPDynamicAllocatorsClause(StartLoc, EndLoc); +} + OMPClause *Sema::ActOnOpenMPVarListClause( OpenMPClauseKind Kind, ArrayRef<Expr *> VarList, Expr *TailExpr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, OpenMPDependClauseKind DepKind, - OpenMPLinearClauseKind LinKind, OpenMPMapClauseKind MapTypeModifier, + OpenMPLinearClauseKind LinKind, + ArrayRef<OpenMPMapModifierKind> MapTypeModifiers, + ArrayRef<SourceLocation> MapTypeModifiersLoc, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation DepLinMapLoc) { OMPClause *Res = nullptr; @@ -9157,9 +9681,9 @@ OMPClause *Sema::ActOnOpenMPVarListClause( StartLoc, LParenLoc, EndLoc); break; case OMPC_map: - Res = ActOnOpenMPMapClause(MapTypeModifier, MapType, IsMapTypeImplicit, - DepLinMapLoc, ColonLoc, VarList, StartLoc, - LParenLoc, EndLoc); + Res = ActOnOpenMPMapClause(MapTypeModifiers, MapTypeModifiersLoc, MapType, + IsMapTypeImplicit, DepLinMapLoc, ColonLoc, + VarList, StartLoc, LParenLoc, EndLoc); break; case OMPC_to: Res = ActOnOpenMPToClause(VarList, StartLoc, LParenLoc, EndLoc); @@ -9206,6 +9730,11 @@ OMPClause *Sema::ActOnOpenMPVarListClause( case OMPC_defaultmap: case OMPC_unknown: case OMPC_uniform: + case OMPC_unified_address: + case OMPC_unified_shared_memory: + case OMPC_reverse_offload: + case OMPC_dynamic_allocators: + case OMPC_atomic_default_mem_order: llvm_unreachable("Clause is not allowed."); } return Res; @@ -9321,6 +9850,17 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList, continue; Type = Type.getNonReferenceType(); + // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions] + // A variable that is privatized must not have a const-qualified type + // unless it is of class type with a mutable member. This restriction does + // not apply to the firstprivate clause. + // + // OpenMP 3.1 [2.9.3.3, private clause, Restrictions] + // A variable that appears in a private clause must not have a + // const-qualified type unless it is of class type with a mutable member. + if (rejectConstNotMutableType(*this, D, Type, OMPC_private, ELoc)) + continue; + // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced // in a Construct] // Variables with the predetermined data-sharing attributes may not be @@ -9742,6 +10282,17 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, continue; Type = Type.getNonReferenceType(); + // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions] + // A variable that is privatized must not have a const-qualified type + // unless it is of class type with a mutable member. This restriction does + // not apply to the firstprivate clause. + // + // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions] + // A variable that appears in a lastprivate clause must not have a + // const-qualified type unless it is of class type with a mutable member. + if (rejectConstNotMutableType(*this, D, Type, OMPC_lastprivate, ELoc)) + continue; + OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective(); // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced // in a Construct] @@ -9807,8 +10358,8 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, PseudoDstExpr, PseudoSrcExpr); if (AssignmentOp.isInvalid()) continue; - AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), ELoc, - /*DiscardedValue=*/true); + AssignmentOp = + ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false); if (AssignmentOp.isInvalid()) continue; @@ -9971,6 +10522,79 @@ static T filterLookupForUDR(SmallVectorImpl<U> &Lookups, return T(); } +static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) { + assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case"); + + for (auto RD : D->redecls()) { + // Don't bother with extra checks if we already know this one isn't visible. + if (RD == D) + continue; + + auto ND = cast<NamedDecl>(RD); + if (LookupResult::isVisible(SemaRef, ND)) + return ND; + } + + return nullptr; +} + +static void +argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &ReductionId, + SourceLocation Loc, QualType Ty, + SmallVectorImpl<UnresolvedSet<8>> &Lookups) { + // Find all of the associated namespaces and classes based on the + // arguments we have. + Sema::AssociatedNamespaceSet AssociatedNamespaces; + Sema::AssociatedClassSet AssociatedClasses; + OpaqueValueExpr OVE(Loc, Ty, VK_LValue); + SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces, + AssociatedClasses); + + // C++ [basic.lookup.argdep]p3: + // Let X be the lookup set produced by unqualified lookup (3.4.1) + // and let Y be the lookup set produced by argument dependent + // lookup (defined as follows). If X contains [...] then Y is + // empty. Otherwise Y is the set of declarations found in the + // namespaces associated with the argument types as described + // below. The set of declarations found by the lookup of the name + // is the union of X and Y. + // + // Here, we compute Y and add its members to the overloaded + // candidate set. + for (auto *NS : AssociatedNamespaces) { + // When considering an associated namespace, the lookup is the + // same as the lookup performed when the associated namespace is + // used as a qualifier (3.4.3.2) except that: + // + // -- Any using-directives in the associated namespace are + // ignored. + // + // -- Any namespace-scope friend functions declared in + // associated classes are visible within their respective + // namespaces even if they are not visible during an ordinary + // lookup (11.4). + DeclContext::lookup_result R = NS->lookup(ReductionId.getName()); + for (auto *D : R) { + auto *Underlying = D; + if (auto *USD = dyn_cast<UsingShadowDecl>(D)) + Underlying = USD->getTargetDecl(); + + if (!isa<OMPDeclareReductionDecl>(Underlying)) + continue; + + if (!SemaRef.isVisible(D)) { + D = findAcceptableDecl(SemaRef, D); + if (!D) + continue; + if (auto *USD = dyn_cast<UsingShadowDecl>(D)) + Underlying = USD->getTargetDecl(); + } + Lookups.emplace_back(); + Lookups.back().addDecl(Underlying); + } + } +} + static ExprResult buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, Scope *S, CXXScopeSpec &ReductionIdScopeSpec, @@ -9989,7 +10613,7 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, } while (S && !S->isDeclScope(D)); if (S) S = S->getParent(); - Lookups.push_back(UnresolvedSet<8>()); + Lookups.emplace_back(); Lookups.back().append(Lookup.begin(), Lookup.end()); Lookup.clear(); } @@ -10016,6 +10640,8 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, })) { UnresolvedSet<8> ResSet; for (const UnresolvedSet<8> &Set : Lookups) { + if (Set.empty()) + continue; ResSet.append(Set.begin(), Set.end()); // The last item marks the end of all declarations at the specified scope. ResSet.addDecl(Set[Set.size() - 1]); @@ -10025,6 +10651,36 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId, /*ADL=*/true, /*Overloaded=*/true, ResSet.begin(), ResSet.end()); } + // Lookup inside the classes. + // C++ [over.match.oper]p3: + // For a unary operator @ with an operand of a type whose + // cv-unqualified version is T1, and for a binary operator @ with + // a left operand of a type whose cv-unqualified version is T1 and + // a right operand of a type whose cv-unqualified version is T2, + // three sets of candidate functions, designated member + // candidates, non-member candidates and built-in candidates, are + // constructed as follows: + // -- If T1 is a complete class type or a class currently being + // defined, the set of member candidates is the result of the + // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise, + // the set of member candidates is empty. + LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName); + Lookup.suppressDiagnostics(); + if (const auto *TyRec = Ty->getAs<RecordType>()) { + // Complete the type if it can be completed. + // If the type is neither complete nor being defined, bail out now. + if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() || + TyRec->getDecl()->getDefinition()) { + Lookup.clear(); + SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl()); + if (Lookup.empty()) { + Lookups.emplace_back(); + Lookups.back().append(Lookup.begin(), Lookup.end()); + } + } + } + // Perform ADL. + argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups); if (auto *VD = filterLookupForUDR<ValueDecl *>( Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * { if (!D->isInvalidDecl() && @@ -10131,10 +10787,11 @@ static bool checkOMPArraySectionConstantForReduction( SingleElement = true; ArraySizes.push_back(llvm::APSInt::get(1)); } else { - llvm::APSInt ConstantLengthValue; - if (!Length->EvaluateAsInt(ConstantLengthValue, Context)) + Expr::EvalResult Result; + if (!Length->EvaluateAsInt(Result, Context)) return false; + llvm::APSInt ConstantLengthValue = Result.Val.getInt(); SingleElement = (ConstantLengthValue.getSExtValue() == 1); ArraySizes.push_back(ConstantLengthValue); } @@ -10155,9 +10812,12 @@ static bool checkOMPArraySectionConstantForReduction( // This is an array subscript which has implicit length 1! ArraySizes.push_back(llvm::APSInt::get(1)); } else { - llvm::APSInt ConstantLengthValue; - if (!Length->EvaluateAsInt(ConstantLengthValue, Context) || - ConstantLengthValue.getSExtValue() != 1) + Expr::EvalResult Result; + if (!Length->EvaluateAsInt(Result, Context)) + return false; + + llvm::APSInt ConstantLengthValue = Result.Val.getInt(); + if (ConstantLengthValue.getSExtValue() != 1) return false; ArraySizes.push_back(ConstantLengthValue); @@ -10342,76 +11002,71 @@ static bool actOnOMPReductionKindClause( // OpenMP [2.14.3.6, reduction clause, Restrictions] // A list item that appears in a reduction clause must not be // const-qualified. - if (Type.getNonReferenceType().isConstant(Context)) { - S.Diag(ELoc, diag::err_omp_const_reduction_list_item) << ERange; - if (!ASE && !OASE) { - bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) == - VarDecl::DeclarationOnly; - S.Diag(D->getLocation(), - IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << D; - } + if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc, + /*AcceptIfMutable*/ false, ASE || OASE)) continue; - } + + OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective(); // OpenMP [2.9.3.6, Restrictions, C/C++, p.4] // If a list-item is a reference type then it must bind to the same object // for all threads of the team. - if (!ASE && !OASE && VD) { - VarDecl *VDDef = VD->getDefinition(); - if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) { - DSARefChecker Check(Stack); - if (Check.Visit(VDDef->getInit())) { - S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg) - << getOpenMPClauseName(ClauseKind) << ERange; - S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef; - continue; + if (!ASE && !OASE) { + if (VD) { + VarDecl *VDDef = VD->getDefinition(); + if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) { + DSARefChecker Check(Stack); + if (Check.Visit(VDDef->getInit())) { + S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg) + << getOpenMPClauseName(ClauseKind) << ERange; + S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef; + continue; + } } } - } - - // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced - // in a Construct] - // Variables with the predetermined data-sharing attributes may not be - // listed in data-sharing attributes clauses, except for the cases - // listed below. For these exceptions only, listing a predetermined - // variable in a data-sharing attribute clause is allowed and overrides - // the variable's predetermined data-sharing attributes. - // OpenMP [2.14.3.6, Restrictions, p.3] - // Any number of reduction clauses can be specified on the directive, - // but a list item can appear only once in the reduction clauses for that - // directive. - DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false); - if (DVar.CKind == OMPC_reduction) { - S.Diag(ELoc, diag::err_omp_once_referenced) - << getOpenMPClauseName(ClauseKind); - if (DVar.RefExpr) - S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced); - continue; - } - if (DVar.CKind != OMPC_unknown) { - S.Diag(ELoc, diag::err_omp_wrong_dsa) - << getOpenMPClauseName(DVar.CKind) - << getOpenMPClauseName(OMPC_reduction); - reportOriginalDsa(S, Stack, D, DVar); - continue; - } - // OpenMP [2.14.3.6, Restrictions, p.1] - // A list item that appears in a reduction clause of a worksharing - // construct must be shared in the parallel regions to which any of the - // worksharing regions arising from the worksharing construct bind. - OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective(); - if (isOpenMPWorksharingDirective(CurrDir) && - !isOpenMPParallelDirective(CurrDir) && - !isOpenMPTeamsDirective(CurrDir)) { - DVar = Stack->getImplicitDSA(D, true); - if (DVar.CKind != OMPC_shared) { - S.Diag(ELoc, diag::err_omp_required_access) - << getOpenMPClauseName(OMPC_reduction) - << getOpenMPClauseName(OMPC_shared); + // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced + // in a Construct] + // Variables with the predetermined data-sharing attributes may not be + // listed in data-sharing attributes clauses, except for the cases + // listed below. For these exceptions only, listing a predetermined + // variable in a data-sharing attribute clause is allowed and overrides + // the variable's predetermined data-sharing attributes. + // OpenMP [2.14.3.6, Restrictions, p.3] + // Any number of reduction clauses can be specified on the directive, + // but a list item can appear only once in the reduction clauses for that + // directive. + DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false); + if (DVar.CKind == OMPC_reduction) { + S.Diag(ELoc, diag::err_omp_once_referenced) + << getOpenMPClauseName(ClauseKind); + if (DVar.RefExpr) + S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced); + continue; + } + if (DVar.CKind != OMPC_unknown) { + S.Diag(ELoc, diag::err_omp_wrong_dsa) + << getOpenMPClauseName(DVar.CKind) + << getOpenMPClauseName(OMPC_reduction); reportOriginalDsa(S, Stack, D, DVar); continue; } + + // OpenMP [2.14.3.6, Restrictions, p.1] + // A list item that appears in a reduction clause of a worksharing + // construct must be shared in the parallel regions to which any of the + // worksharing regions arising from the worksharing construct bind. + if (isOpenMPWorksharingDirective(CurrDir) && + !isOpenMPParallelDirective(CurrDir) && + !isOpenMPTeamsDirective(CurrDir)) { + DVar = Stack->getImplicitDSA(D, true); + if (DVar.CKind != OMPC_shared) { + S.Diag(ELoc, diag::err_omp_required_access) + << getOpenMPClauseName(OMPC_reduction) + << getOpenMPClauseName(OMPC_shared); + reportOriginalDsa(S, Stack, D, DVar); + continue; + } + } } // Try to find 'declare reduction' corresponding construct before using @@ -10430,7 +11085,7 @@ static bool actOnOMPReductionKindClause( } if (BOK == BO_Comma && DeclareReductionRef.isUnset()) { // Not allowed reduction identifier is found. - S.Diag(ReductionId.getLocStart(), + S.Diag(ReductionId.getBeginLoc(), diag::err_omp_unknown_reduction_identifier) << Type << ReductionIdRange; continue; @@ -10683,26 +11338,27 @@ static bool actOnOMPReductionKindClause( ELoc, Context.getPointerType(FnTy), VK_RValue, OK_Ordinary, S.DefaultLvalueConversion(DeclareReductionRef.get()).get()); Expr *Args[] = {LHS.get(), RHS.get()}; - ReductionOp = new (Context) - CallExpr(Context, OVE, Args, Context.VoidTy, VK_RValue, ELoc); + ReductionOp = + CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_RValue, ELoc); } else { ReductionOp = S.BuildBinOp( - Stack->getCurScope(), ReductionId.getLocStart(), BOK, LHSDRE, RHSDRE); + Stack->getCurScope(), ReductionId.getBeginLoc(), BOK, LHSDRE, RHSDRE); if (ReductionOp.isUsable()) { if (BOK != BO_LT && BOK != BO_GT) { ReductionOp = - S.BuildBinOp(Stack->getCurScope(), ReductionId.getLocStart(), + S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BO_Assign, LHSDRE, ReductionOp.get()); } else { auto *ConditionalOp = new (Context) ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc, RHSDRE, Type, VK_LValue, OK_Ordinary); ReductionOp = - S.BuildBinOp(Stack->getCurScope(), ReductionId.getLocStart(), + S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BO_Assign, LHSDRE, ConditionalOp); } if (ReductionOp.isUsable()) - ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get()); + ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(), + /*DiscardedValue*/ false); } if (!ReductionOp.isUsable()) continue; @@ -10744,7 +11400,7 @@ static bool actOnOMPReductionKindClause( EmitError = RedId != ParentRedId; } if (EmitError) { - S.Diag(ReductionId.getLocStart(), + S.Diag(ReductionId.getBeginLoc(), diag::err_omp_reduction_identifier_mismatch) << ReductionIdRange << RefExpr->getSourceRange(); S.Diag(ParentSR.getBegin(), @@ -10895,20 +11551,12 @@ bool Sema::CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, } Type = Type.getNonReferenceType(); - // A list item must not be const-qualified. - if (Type.isConstant(Context)) { - Diag(ELoc, diag::err_omp_const_variable) - << getOpenMPClauseName(OMPC_linear); - if (D) { - bool IsDecl = - !VD || - VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; - Diag(D->getLocation(), - IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << D; - } + // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions] + // A variable that is privatized must not have a const-qualified type + // unless it is of class type with a mutable member. This restriction does + // not apply to the firstprivate clause. + if (rejectConstNotMutableType(*this, D, Type, OMPC_linear, ELoc)) return true; - } // A list item must be of integral or pointer type. Type = Type.getUnqualifiedType().getCanonicalType(); @@ -10945,8 +11593,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause( SourceLocation ELoc; SourceRange ERange; Expr *SimpleRefExpr = RefExpr; - auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange, - /*AllowArraySection=*/false); + auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange); if (Res.second) { // It will be analyzed later. Vars.push_back(RefExpr); @@ -11028,7 +11675,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause( if (Step && !Step->isValueDependent() && !Step->isTypeDependent() && !Step->isInstantiationDependent() && !Step->containsUnexpandedParameterPack()) { - SourceLocation StepLoc = Step->getLocStart(); + SourceLocation StepLoc = Step->getBeginLoc(); ExprResult Val = PerformOpenMPImplicitIntegerConversion(StepLoc, Step); if (Val.isInvalid()) return nullptr; @@ -11041,7 +11688,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause( buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc); ExprResult CalcStep = BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr); - CalcStep = ActOnFinishFullExpr(CalcStep.get()); + CalcStep = ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue*/ false); // Warn about zero linear step (it would be probably better specified as // making corresponding variables 'const'). @@ -11086,8 +11733,7 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, SourceLocation ELoc; SourceRange ERange; Expr *SimpleRefExpr = RefExpr; - auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange, - /*AllowArraySection=*/false); + auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); ValueDecl *D = Res.first; if (Res.second || !D) { Updates.push_back(nullptr); @@ -11129,8 +11775,8 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, InitExpr, IV, Step, /* Subtract */ false); else Update = *CurPrivate; - Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getLocStart(), - /*DiscardedValue=*/true); + Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(), + /*DiscardedValue*/ false); // Build final: Var = InitExpr + NumIterations * Step ExprResult Final; @@ -11140,8 +11786,8 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, InitExpr, NumIterations, Step, /*Subtract=*/false); else Final = *CurPrivate; - Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getLocStart(), - /*DiscardedValue=*/true); + Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(), + /*DiscardedValue*/ false); if (!Update.isUsable() || !Final.isUsable()) { Updates.push_back(nullptr); @@ -11168,8 +11814,7 @@ OMPClause *Sema::ActOnOpenMPAlignedClause( SourceLocation ELoc; SourceRange ERange; Expr *SimpleRefExpr = RefExpr; - auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange, - /*AllowArraySection=*/false); + auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange); if (Res.second) { // It will be analyzed later. Vars.push_back(RefExpr); @@ -11293,12 +11938,12 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList, // operator for the class type. QualType ElemType = Context.getBaseElementType(Type).getNonReferenceType(); VarDecl *SrcVD = - buildVarDecl(*this, DE->getLocStart(), ElemType.getUnqualifiedType(), + buildVarDecl(*this, DE->getBeginLoc(), ElemType.getUnqualifiedType(), ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr); DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr( *this, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc()); VarDecl *DstVD = - buildVarDecl(*this, DE->getLocStart(), ElemType, ".copyin.dst", + buildVarDecl(*this, DE->getBeginLoc(), ElemType, ".copyin.dst", VD->hasAttrs() ? &VD->getAttrs() : nullptr); DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, ElemType, DE->getExprLoc()); @@ -11310,7 +11955,7 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList, if (AssignmentOp.isInvalid()) continue; AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(), - /*DiscardedValue=*/true); + /*DiscardedValue*/ false); if (AssignmentOp.isInvalid()) continue; @@ -11341,8 +11986,7 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList, SourceLocation ELoc; SourceRange ERange; Expr *SimpleRefExpr = RefExpr; - auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange, - /*AllowArraySection=*/false); + auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange); if (Res.second) { // It will be analyzed later. Vars.push_back(RefExpr); @@ -11408,19 +12052,19 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList, Type = Context.getBaseElementType(Type.getNonReferenceType()) .getUnqualifiedType(); VarDecl *SrcVD = - buildVarDecl(*this, RefExpr->getLocStart(), Type, ".copyprivate.src", + buildVarDecl(*this, RefExpr->getBeginLoc(), Type, ".copyprivate.src", D->hasAttrs() ? &D->getAttrs() : nullptr); DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(*this, SrcVD, Type, ELoc); VarDecl *DstVD = - buildVarDecl(*this, RefExpr->getLocStart(), Type, ".copyprivate.dst", + buildVarDecl(*this, RefExpr->getBeginLoc(), Type, ".copyprivate.dst", D->hasAttrs() ? &D->getAttrs() : nullptr); DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc); ExprResult AssignmentOp = BuildBinOp( DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr); if (AssignmentOp.isInvalid()) continue; - AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), ELoc, - /*DiscardedValue=*/true); + AssignmentOp = + ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false); if (AssignmentOp.isInvalid()) continue; @@ -11477,8 +12121,9 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, DSAStackTy::OperatorOffsetTy OpsOffs; llvm::APSInt DepCounter(/*BitWidth=*/32); llvm::APSInt TotalDepCount(/*BitWidth=*/32); - if (DepKind == OMPC_DEPEND_sink) { - if (const Expr *OrderedCountExpr = DSAStack->getParentOrderedRegionParam()) { + if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) { + if (const Expr *OrderedCountExpr = + DSAStack->getParentOrderedRegionParam().first) { TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Context); TotalDepCount.setIsUnsigned(/*Val=*/true); } @@ -11494,7 +12139,7 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, SourceLocation ELoc = RefExpr->getExprLoc(); Expr *SimpleExpr = RefExpr->IgnoreParenCasts(); if (DepKind == OMPC_DEPEND_sink) { - if (DSAStack->getParentOrderedRegionParam() && + if (DSAStack->getParentOrderedRegionParam().first && DepCounter >= TotalDepCount) { Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr); continue; @@ -11539,8 +12184,7 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, } SourceLocation ELoc; SourceRange ERange; - auto Res = getPrivateItem(*this, LHS, ELoc, ERange, - /*AllowArraySection=*/false); + auto Res = getPrivateItem(*this, LHS, ELoc, ERange); if (Res.second) { // It will be analyzed later. Vars.push_back(RefExpr); @@ -11560,7 +12204,7 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, continue; } if (!CurContext->isDependentContext() && - DSAStack->getParentOrderedRegionParam() && + DSAStack->getParentOrderedRegionParam().first && DepCounter != DSAStack->isParentLoopControlVariable(D).first) { const ValueDecl *VD = DSAStack->getParentLoopControlVariable(DepCounter.getZExtValue()); @@ -11598,7 +12242,7 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, if (!CurContext->isDependentContext() && DepKind == OMPC_DEPEND_sink && TotalDepCount > VarList.size() && - DSAStack->getParentOrderedRegionParam() && + DSAStack->getParentOrderedRegionParam().first && DSAStack->getParentLoopControlVariable(VarList.size() + 1)) { Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration) << 1 << DSAStack->getParentLoopControlVariable(VarList.size() + 1); @@ -11608,7 +12252,8 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, return nullptr; auto *C = OMPDependClause::Create(Context, StartLoc, LParenLoc, EndLoc, - DepKind, DepLoc, ColonLoc, Vars); + DepKind, DepLoc, ColonLoc, Vars, + TotalDepCount.getZExtValue()); if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) && DSAStack->isParentOrderedRegion()) DSAStack->addDoacrossDependClause(C, OpsOffs); @@ -11680,9 +12325,11 @@ static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef, // If there is a lower bound that does not evaluates to zero, we are not // covering the whole dimension. if (LowerBound) { - llvm::APSInt ConstLowerBound; - if (!LowerBound->EvaluateAsInt(ConstLowerBound, SemaRef.getASTContext())) + Expr::EvalResult Result; + if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext())) return false; // Can't get the integer value as a constant. + + llvm::APSInt ConstLowerBound = Result.Val.getInt(); if (ConstLowerBound.getSExtValue()) return true; } @@ -11702,10 +12349,11 @@ static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef, if (!CATy) return false; - llvm::APSInt ConstLength; - if (!Length->EvaluateAsInt(ConstLength, SemaRef.getASTContext())) + Expr::EvalResult Result; + if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext())) return false; // Can't get the integer value as a constant. + llvm::APSInt ConstLength = Result.Val.getInt(); return CATy->getSize().getSExtValue() != ConstLength.getSExtValue(); } @@ -11736,10 +12384,11 @@ static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef, } // Check if the length evaluates to 1. - llvm::APSInt ConstLength; - if (!Length->EvaluateAsInt(ConstLength, SemaRef.getASTContext())) + Expr::EvalResult Result; + if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext())) return false; // Can't get the integer value as a constant. + llvm::APSInt ConstLength = Result.Val.getInt(); return ConstLength.getSExtValue() != 1; } @@ -11896,6 +12545,19 @@ static const Expr *checkMapClauseExpressionBase( E->getType())) AllowWholeSizeArraySection = false; + if (const auto *TE = dyn_cast<CXXThisExpr>(E)) { + Expr::EvalResult Result; + if (CurE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext())) { + if (!Result.Val.getInt().isNullValue()) { + SemaRef.Diag(CurE->getIdx()->getExprLoc(), + diag::err_omp_invalid_map_this_expr); + SemaRef.Diag(CurE->getIdx()->getExprLoc(), + diag::note_omp_invalid_subscript_on_this_ptr_map); + } + } + RelevantExpr = TE; + } + // Record the component - we don't have any declaration associated. CurComponents.emplace_back(CurE, nullptr); } else if (auto *CurE = dyn_cast<OMPArraySectionExpr>(E)) { @@ -11942,6 +12604,30 @@ static const Expr *checkMapClauseExpressionBase( return nullptr; } + if (const auto *TE = dyn_cast<CXXThisExpr>(E)) { + Expr::EvalResult ResultR; + Expr::EvalResult ResultL; + if (CurE->getLength()->EvaluateAsInt(ResultR, + SemaRef.getASTContext())) { + if (!ResultR.Val.getInt().isOneValue()) { + SemaRef.Diag(CurE->getLength()->getExprLoc(), + diag::err_omp_invalid_map_this_expr); + SemaRef.Diag(CurE->getLength()->getExprLoc(), + diag::note_omp_invalid_length_on_this_ptr_mapping); + } + } + if (CurE->getLowerBound() && CurE->getLowerBound()->EvaluateAsInt( + ResultL, SemaRef.getASTContext())) { + if (!ResultL.Val.getInt().isNullValue()) { + SemaRef.Diag(CurE->getLowerBound()->getExprLoc(), + diag::err_omp_invalid_map_this_expr); + SemaRef.Diag(CurE->getLowerBound()->getExprLoc(), + diag::note_omp_invalid_lower_bound_on_this_ptr_mapping); + } + } + RelevantExpr = TE; + } + // Record the component - we don't have any declaration associated. CurComponents.emplace_back(CurE, nullptr); } else { @@ -12129,6 +12815,26 @@ static bool checkMapConflicts( // An expression is a subset of the other. if (CurrentRegionOnly && (CI == CE || SI == SE)) { if (CKind == OMPC_map) { + if (CI != CE || SI != SE) { + // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is + // a pointer. + auto Begin = + CI != CE ? CurComponents.begin() : StackComponents.begin(); + auto End = CI != CE ? CurComponents.end() : StackComponents.end(); + auto It = Begin; + while (It != End && !It->getAssociatedDeclaration()) + std::advance(It, 1); + assert(It != End && + "Expected at least one component with the declaration."); + if (It != Begin && It->getAssociatedDeclaration() + ->getType() + .getCanonicalType() + ->isAnyPointerType()) { + IsEnclosedByDataEnvironmentExpr = false; + EnclosingExpr = nullptr; + return false; + } + } SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange; } else { assert(CKind == OMPC_to || CKind == OMPC_from); @@ -12259,6 +12965,18 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS, assert(!CurComponents.empty() && "Invalid mappable expression information."); + if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) { + // Add store "this" pointer to class in DSAStackTy for future checking + DSAS->addMappedClassesQualTypes(TE->getType()); + // Skip restriction checking for variable or field declarations + MVLI.ProcessedVarList.push_back(RE); + MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1); + MVLI.VarComponents.back().append(CurComponents.begin(), + CurComponents.end()); + MVLI.VarBaseDeclarations.push_back(nullptr); + continue; + } + // For the following checks, we rely on the base declaration which is // expected to be associated with the last component. The declaration is // expected to be a variable or a field (if 'this' is being mapped). @@ -12388,7 +13106,8 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS, } OMPClause * -Sema::ActOnOpenMPMapClause(OpenMPMapClauseKind MapTypeModifier, +Sema::ActOnOpenMPMapClause(ArrayRef<OpenMPMapModifierKind> MapTypeModifiers, + ArrayRef<SourceLocation> MapTypeModifiersLoc, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc, @@ -12397,12 +13116,31 @@ Sema::ActOnOpenMPMapClause(OpenMPMapClauseKind MapTypeModifier, checkMappableExpressionList(*this, DSAStack, OMPC_map, MVLI, StartLoc, MapType, IsMapTypeImplicit); + OpenMPMapModifierKind Modifiers[] = { OMPC_MAP_MODIFIER_unknown, + OMPC_MAP_MODIFIER_unknown }; + SourceLocation ModifiersLoc[OMPMapClause::NumberOfModifiers]; + + // Process map-type-modifiers, flag errors for duplicate modifiers. + unsigned Count = 0; + for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) { + if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown && + llvm::find(Modifiers, MapTypeModifiers[I]) != std::end(Modifiers)) { + Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier); + continue; + } + assert(Count < OMPMapClause::NumberOfModifiers && + "Modifiers exceed the allowed number of map type modifiers"); + Modifiers[Count] = MapTypeModifiers[I]; + ModifiersLoc[Count] = MapTypeModifiersLoc[I]; + ++Count; + } + // We need to produce a map clause even if we don't have variables so that // other diagnostics related with non-existing map clauses are accurate. return OMPMapClause::Create(Context, StartLoc, LParenLoc, EndLoc, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations, - MVLI.VarComponents, MapTypeModifier, MapType, - IsMapTypeImplicit, MapLoc); + MVLI.VarComponents, Modifiers, ModifiersLoc, + MapType, IsMapTypeImplicit, MapLoc); } QualType Sema::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, @@ -12559,6 +13297,11 @@ void Sema::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) { DRD->addDecl(OmpInParm); DRD->addDecl(OmpOutParm); } + Expr *InE = + ::buildDeclRefExpr(*this, OmpInParm, ReductionType, D->getLocation()); + Expr *OutE = + ::buildDeclRefExpr(*this, OmpOutParm, ReductionType, D->getLocation()); + DRD->setCombinerData(InE, OutE); } void Sema::ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner) { @@ -12614,6 +13357,11 @@ VarDecl *Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) { DRD->addDecl(OmpPrivParm); DRD->addDecl(OmpOrigParm); } + Expr *OrigE = + ::buildDeclRefExpr(*this, OmpOrigParm, ReductionType, D->getLocation()); + Expr *PrivE = + ::buildDeclRefExpr(*this, OmpPrivParm, ReductionType, D->getLocation()); + DRD->setInitializerData(OrigE, PrivE); return OmpPrivParm; } @@ -12785,7 +13533,7 @@ OMPClause *Sema::ActOnOpenMPDistScheduleClause( if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() && !ChunkSize->isInstantiationDependent() && !ChunkSize->containsUnexpandedParameterPack()) { - SourceLocation ChunkSizeLoc = ChunkSize->getLocStart(); + SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc(); ExprResult Val = PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize); if (Val.isInvalid()) @@ -12861,19 +13609,14 @@ bool Sema::ActOnStartOpenMPDeclareTargetDirective(SourceLocation Loc) { Diag(Loc, diag::err_omp_region_not_file_context); return false; } - if (IsInOpenMPDeclareTargetContext) { - Diag(Loc, diag::err_omp_enclosed_declare_target); - return false; - } - - IsInOpenMPDeclareTargetContext = true; + ++DeclareTargetNestingLevel; return true; } void Sema::ActOnFinishOpenMPDeclareTargetDirective() { - assert(IsInOpenMPDeclareTargetContext && + assert(DeclareTargetNestingLevel > 0 && "Unexpected ActOnFinishOpenMPDeclareTargetDirective"); - IsInOpenMPDeclareTargetContext = false; + --DeclareTargetNestingLevel; } void Sema::ActOnOpenMPDeclareTargetName(Scope *CurScope, @@ -12904,16 +13647,20 @@ void Sema::ActOnOpenMPDeclareTargetName(Scope *CurScope, } NamedDecl *ND = Lookup.getAsSingle<NamedDecl>(); - if (isa<VarDecl>(ND) || isa<FunctionDecl>(ND)) { + if (isa<VarDecl>(ND) || isa<FunctionDecl>(ND) || + isa<FunctionTemplateDecl>(ND)) { if (!SameDirectiveDecls.insert(cast<NamedDecl>(ND->getCanonicalDecl()))) Diag(Id.getLoc(), diag::err_omp_declare_target_multiple) << Id.getName(); - if (!ND->hasAttr<OMPDeclareTargetDeclAttr>()) { + llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = + OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( + cast<ValueDecl>(ND)); + if (!Res) { auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(Context, MT); ND->addAttr(A); if (ASTMutationListener *ML = Context.getASTMutationListener()) ML->DeclarationMarkedOpenMPDeclareTarget(ND, A); checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Id.getLoc()); - } else if (ND->getAttr<OMPDeclareTargetDeclAttr>()->getMapType() != MT) { + } else if (*Res != MT) { Diag(Id.getLoc(), diag::err_omp_declare_target_to_and_link) << Id.getName(); } @@ -12924,79 +13671,13 @@ void Sema::ActOnOpenMPDeclareTargetName(Scope *CurScope, static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR, Sema &SemaRef, Decl *D) { - if (!D) + if (!D || !isa<VarDecl>(D)) return; - const Decl *LD = nullptr; - if (isa<TagDecl>(D)) { - LD = cast<TagDecl>(D)->getDefinition(); - } else if (isa<VarDecl>(D)) { - LD = cast<VarDecl>(D)->getDefinition(); - - // If this is an implicit variable that is legal and we do not need to do - // anything. - if (cast<VarDecl>(D)->isImplicit()) { - auto *A = OMPDeclareTargetDeclAttr::CreateImplicit( - SemaRef.Context, OMPDeclareTargetDeclAttr::MT_To); - D->addAttr(A); - if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener()) - ML->DeclarationMarkedOpenMPDeclareTarget(D, A); - return; - } - } else if (const auto *F = dyn_cast<FunctionDecl>(D)) { - const FunctionDecl *FD = nullptr; - if (cast<FunctionDecl>(D)->hasBody(FD)) { - LD = FD; - // If the definition is associated with the current declaration in the - // target region (it can be e.g. a lambda) that is legal and we do not - // need to do anything else. - if (LD == D) { - auto *A = OMPDeclareTargetDeclAttr::CreateImplicit( - SemaRef.Context, OMPDeclareTargetDeclAttr::MT_To); - D->addAttr(A); - if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener()) - ML->DeclarationMarkedOpenMPDeclareTarget(D, A); - return; - } - } else if (F->isFunctionTemplateSpecialization() && - F->getTemplateSpecializationKind() == - TSK_ImplicitInstantiation) { - // Check if the function is implicitly instantiated from the template - // defined in the declare target region. - const FunctionTemplateDecl *FTD = F->getPrimaryTemplate(); - if (FTD && FTD->hasAttr<OMPDeclareTargetDeclAttr>()) - return; - } - } - if (!LD) - LD = D; - if (LD && !LD->hasAttr<OMPDeclareTargetDeclAttr>() && - ((isa<VarDecl>(LD) && !isa<ParmVarDecl>(LD)) || isa<FunctionDecl>(LD))) { - // Outlined declaration is not declared target. - if (!isa<FunctionDecl>(LD)) { - if (LD->isOutOfLine()) { - SemaRef.Diag(LD->getLocation(), diag::warn_omp_not_in_target_context); - SemaRef.Diag(SL, diag::note_used_here) << SR; - } else { - const DeclContext *DC = LD->getDeclContext(); - while (DC && - (!isa<FunctionDecl>(DC) || - !cast<FunctionDecl>(DC)->hasAttr<OMPDeclareTargetDeclAttr>())) - DC = DC->getParent(); - if (DC) - return; - - // Is not declared in target context. - SemaRef.Diag(LD->getLocation(), diag::warn_omp_not_in_target_context); - SemaRef.Diag(SL, diag::note_used_here) << SR; - } - } - // Mark decl as declared target to prevent further diagnostic. - auto *A = OMPDeclareTargetDeclAttr::CreateImplicit( - SemaRef.Context, OMPDeclareTargetDeclAttr::MT_To); - D->addAttr(A); - if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener()) - ML->DeclarationMarkedOpenMPDeclareTarget(D, A); - } + auto *VD = cast<VarDecl>(D); + if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) + return; + SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context); + SemaRef.Diag(SL, diag::note_used_here) << SR; } static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR, @@ -13012,10 +13693,11 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, if (!D || D->isInvalidDecl()) return; SourceRange SR = E ? E->getSourceRange() : D->getSourceRange(); - SourceLocation SL = E ? E->getLocStart() : D->getLocation(); + SourceLocation SL = E ? E->getBeginLoc() : D->getLocation(); if (auto *VD = dyn_cast<VarDecl>(D)) { // Only global variables can be marked as declare target. - if (VD->isLocalVarDeclOrParm()) + if (!VD->isFileVarDecl() && !VD->isStaticLocal() && + !VD->isStaticDataMember()) return; // 2.10.6: threadprivate variable cannot appear in a declare target // directive. @@ -13025,56 +13707,39 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, return; } } + if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D)) + D = FTD->getTemplatedDecl(); + if (const auto *FD = dyn_cast<FunctionDecl>(D)) { + llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = + OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD); + if (Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) { + assert(IdLoc.isValid() && "Source location is expected"); + Diag(IdLoc, diag::err_omp_function_in_link_clause); + Diag(FD->getLocation(), diag::note_defined_here) << FD; + return; + } + } if (auto *VD = dyn_cast<ValueDecl>(D)) { // Problem if any with var declared with incomplete type will be reported // as normal, so no need to check it here. if ((E || !VD->getType()->isIncompleteType()) && - !checkValueDeclInTarget(SL, SR, *this, DSAStack, VD)) { - // Mark decl as declared target to prevent further diagnostic. - if (isa<VarDecl>(VD) || isa<FunctionDecl>(VD) || - isa<FunctionTemplateDecl>(VD)) { + !checkValueDeclInTarget(SL, SR, *this, DSAStack, VD)) + return; + if (!E && !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { + // Checking declaration inside declare target region. + if (isa<VarDecl>(D) || isa<FunctionDecl>(D) || + isa<FunctionTemplateDecl>(D)) { auto *A = OMPDeclareTargetDeclAttr::CreateImplicit( Context, OMPDeclareTargetDeclAttr::MT_To); - VD->addAttr(A); + D->addAttr(A); if (ASTMutationListener *ML = Context.getASTMutationListener()) - ML->DeclarationMarkedOpenMPDeclareTarget(VD, A); + ML->DeclarationMarkedOpenMPDeclareTarget(D, A); } return; } } - if (const auto *FD = dyn_cast<FunctionDecl>(D)) { - if (FD->hasAttr<OMPDeclareTargetDeclAttr>() && - (FD->getAttr<OMPDeclareTargetDeclAttr>()->getMapType() == - OMPDeclareTargetDeclAttr::MT_Link)) { - assert(IdLoc.isValid() && "Source location is expected"); - Diag(IdLoc, diag::err_omp_function_in_link_clause); - Diag(FD->getLocation(), diag::note_defined_here) << FD; - return; - } - } - if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D)) { - if (FTD->hasAttr<OMPDeclareTargetDeclAttr>() && - (FTD->getAttr<OMPDeclareTargetDeclAttr>()->getMapType() == - OMPDeclareTargetDeclAttr::MT_Link)) { - assert(IdLoc.isValid() && "Source location is expected"); - Diag(IdLoc, diag::err_omp_function_in_link_clause); - Diag(FTD->getLocation(), diag::note_defined_here) << FTD; - return; - } - } - if (!E) { - // Checking declaration inside declare target region. - if (!D->hasAttr<OMPDeclareTargetDeclAttr>() && - (isa<VarDecl>(D) || isa<FunctionDecl>(D) || - isa<FunctionTemplateDecl>(D))) { - auto *A = OMPDeclareTargetDeclAttr::CreateImplicit( - Context, OMPDeclareTargetDeclAttr::MT_To); - D->addAttr(A); - if (ASTMutationListener *ML = Context.getASTMutationListener()) - ML->DeclarationMarkedOpenMPDeclareTarget(D, A); - } + if (!E) return; - } checkDeclInTargetContext(E->getExprLoc(), E->getSourceRange(), *this, D); } diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 08af485ef4c72..52be0598fbc03 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -63,8 +63,8 @@ CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, NamedDecl *FoundDecl, return ExprError(); if (auto *FPT = Fn->getType()->getAs<FunctionProtoType>()) S.ResolveExceptionSpec(Loc, FPT); - DeclRefExpr *DRE = new (S.Context) DeclRefExpr(Fn, false, Fn->getType(), - VK_LValue, Loc, LocInfo); + DeclRefExpr *DRE = new (S.Context) + DeclRefExpr(S.Context, Fn, false, Fn->getType(), VK_LValue, Loc, LocInfo); if (HadMultipleCandidates) DRE->setHadMultipleCandidates(true); @@ -1041,6 +1041,36 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old, } } + // C++ [temp.friend]p1: + // For a friend function declaration that is not a template declaration: + // -- if the name of the friend is a qualified or unqualified template-id, + // [...], otherwise + // -- if the name of the friend is a qualified-id and a matching + // non-template function is found in the specified class or namespace, + // the friend declaration refers to that function, otherwise, + // -- if the name of the friend is a qualified-id and a matching function + // template is found in the specified class or namespace, the friend + // declaration refers to the deduced specialization of that function + // template, otherwise + // -- the name shall be an unqualified-id [...] + // If we get here for a qualified friend declaration, we've just reached the + // third bullet. If the type of the friend is dependent, skip this lookup + // until instantiation. + if (New->getFriendObjectKind() && New->getQualifier() && + !New->getDependentSpecializationInfo() && + !New->getType()->isDependentType()) { + LookupResult TemplateSpecResult(LookupResult::Temporary, Old); + TemplateSpecResult.addAllDecls(Old); + if (CheckFunctionTemplateSpecialization(New, nullptr, TemplateSpecResult, + /*QualifiedFriend*/true)) { + New->setInvalidDecl(); + return Ovl_Overload; + } + + Match = TemplateSpecResult.getAsSingle<FunctionDecl>(); + return Ovl_Match; + } + return Ovl_Overload; } @@ -1105,7 +1135,8 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(), OldTemplate->getTemplateParameters(), false, TPL_TemplateMatch) || - OldType->getReturnType() != NewType->getReturnType())) + !Context.hasSameType(Old->getDeclaredReturnType(), + New->getDeclaredReturnType()))) return true; // If the function is a class member, its signature includes the @@ -1141,8 +1172,9 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, // function yet (because we haven't yet resolved whether this is a static // or non-static member function). Add it now, on the assumption that this // is a redeclaration of OldMethod. - unsigned OldQuals = OldMethod->getTypeQualifiers(); - unsigned NewQuals = NewMethod->getTypeQualifiers(); + // FIXME: OpenCL: Need to consider address spaces + unsigned OldQuals = OldMethod->getTypeQualifiers().getCVRUQualifiers(); + unsigned NewQuals = NewMethod->getTypeQualifiers().getCVRUQualifiers(); if (!getLangOpts().CPlusPlus14 && NewMethod->isConstexpr() && !isa<CXXConstructorDecl>(NewMethod)) NewQuals |= Qualifiers::Const; @@ -1263,7 +1295,7 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType, = S.Context.getCanonicalType(ToType).getUnqualifiedType(); if (Constructor->isCopyConstructor() && (FromCanon == ToCanon || - S.IsDerivedFrom(From->getLocStart(), FromCanon, ToCanon))) { + S.IsDerivedFrom(From->getBeginLoc(), FromCanon, ToCanon))) { // Turn this into a "standard" conversion sequence, so that it // gets ranked with standard conversion sequences. DeclAccessPair Found = ICS.UserDefined.FoundConversionFunction; @@ -1355,7 +1387,7 @@ TryImplicitConversion(Sema &S, Expr *From, QualType ToType, QualType FromType = From->getType(); if (ToType->getAs<RecordType>() && FromType->getAs<RecordType>() && (S.Context.hasSameUnqualifiedType(FromType, ToType) || - S.IsDerivedFrom(From->getLocStart(), FromType, ToType))) { + S.IsDerivedFrom(From->getBeginLoc(), FromType, ToType))) { ICS.setStandard(); ICS.Standard.setAsIdentityConversion(); ICS.Standard.setFromType(FromType); @@ -1417,9 +1449,9 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, bool AllowObjCWritebackConversion = getLangOpts().ObjCAutoRefCount && (Action == AA_Passing || Action == AA_Sending); - if (getLangOpts().ObjC1) - CheckObjCBridgeRelatedConversions(From->getLocStart(), - ToType, From->getType(), From); + if (getLangOpts().ObjC) + CheckObjCBridgeRelatedConversions(From->getBeginLoc(), ToType, + From->getType(), From); ICS = ::TryImplicitConversion(*this, From, ToType, /*SuppressUserConversions=*/false, AllowExplicit, @@ -2011,7 +2043,7 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { // We have already pre-calculated the promotion type, so this is trivial. if (ToType->isIntegerType() && - isCompleteType(From->getLocStart(), FromType)) + isCompleteType(From->getBeginLoc(), FromType)) return Context.hasSameUnqualifiedType( ToType, FromEnumType->getDecl()->getPromotionType()); @@ -2353,10 +2385,10 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType, // // Note that we do not check for ambiguity or inaccessibility // here. That is handled by CheckPointerConversion. - if (getLangOpts().CPlusPlus && - FromPointeeType->isRecordType() && ToPointeeType->isRecordType() && + if (getLangOpts().CPlusPlus && FromPointeeType->isRecordType() && + ToPointeeType->isRecordType() && !Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType) && - IsDerivedFrom(From->getLocStart(), FromPointeeType, ToPointeeType)) { + IsDerivedFrom(From->getBeginLoc(), FromPointeeType, ToPointeeType)) { ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, ToPointeeType, ToType, Context); @@ -2394,7 +2426,7 @@ static QualType AdoptQualifiers(ASTContext &Context, QualType T, Qualifiers Qs){ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, QualType& ConvertedType, bool &IncompatibleObjC) { - if (!getLangOpts().ObjC1) + if (!getLangOpts().ObjC) return false; // The set of qualifiers on the type we're converting from. @@ -2822,10 +2854,9 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag, return; } - unsigned FromQuals = FromFunction->getTypeQuals(), - ToQuals = ToFunction->getTypeQuals(); - if (FromQuals != ToQuals) { - PDiag << ft_qualifer_mismatch << ToQuals << FromQuals; + if (FromFunction->getTypeQuals() != ToFunction->getTypeQuals()) { + PDiag << ft_qualifer_mismatch << ToFunction->getTypeQuals() + << FromFunction->getTypeQuals(); return; } @@ -2983,7 +3014,7 @@ bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType, QualType ToClass(ToTypePtr->getClass(), 0); if (!Context.hasSameUnqualifiedType(FromClass, ToClass) && - IsDerivedFrom(From->getLocStart(), ToClass, FromClass)) { + IsDerivedFrom(From->getBeginLoc(), ToClass, FromClass)) { ConvertedType = Context.getMemberPointerType(FromTypePtr->getPointeeType(), ToClass.getTypePtr()); return true; @@ -3027,7 +3058,7 @@ bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType, CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, /*DetectVirtual=*/true); bool DerivationOkay = - IsDerivedFrom(From->getLocStart(), ToClass, FromClass, Paths); + IsDerivedFrom(From->getBeginLoc(), ToClass, FromClass, Paths); assert(DerivationOkay && "Should not have been called if derivation isn't OK."); (void)DerivationOkay; @@ -3242,13 +3273,12 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType, OverloadCandidateSet::iterator Best; switch (auto Result = - CandidateSet.BestViableFunction(S, From->getLocStart(), - Best)) { + CandidateSet.BestViableFunction(S, From->getBeginLoc(), Best)) { case OR_Deleted: case OR_Success: { // Record the standard conversion we used and the conversion function. CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function); - QualType ThisType = Constructor->getThisType(S.Context); + QualType ThisType = Constructor->getThisType(); // Initializer lists don't have conversions as such. User.Before.setAsIdentityConversion(); User.HadMultipleCandidates = HadMultipleCandidates; @@ -3308,7 +3338,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // the parentheses of the initializer. if (S.Context.hasSameUnqualifiedType(ToType, From->getType()) || (From->getType()->getAs<RecordType>() && - S.IsDerivedFrom(From->getLocStart(), From->getType(), ToType))) + S.IsDerivedFrom(From->getBeginLoc(), From->getType(), ToType))) ConstructorsOnly = true; if (!S.isCompleteType(From->getExprLoc(), ToType)) { @@ -3376,10 +3406,10 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // Enumerate conversion functions, if we're allowed to. if (ConstructorsOnly || isa<InitListExpr>(From)) { - } else if (!S.isCompleteType(From->getLocStart(), From->getType())) { + } else if (!S.isCompleteType(From->getBeginLoc(), From->getType())) { // No conversion functions from incomplete types. - } else if (const RecordType *FromRecordType - = From->getType()->getAs<RecordType>()) { + } else if (const RecordType *FromRecordType = + From->getType()->getAs<RecordType>()) { if (CXXRecordDecl *FromRecordDecl = dyn_cast<CXXRecordDecl>(FromRecordType->getDecl())) { // Add all of the conversion functions as candidates. @@ -3416,8 +3446,8 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, bool HadMultipleCandidates = (CandidateSet.size() > 1); OverloadCandidateSet::iterator Best; - switch (auto Result = CandidateSet.BestViableFunction(S, From->getLocStart(), - Best)) { + switch (auto Result = + CandidateSet.BestViableFunction(S, From->getBeginLoc(), Best)) { case OR_Success: case OR_Deleted: // Record the standard conversion we used and the conversion function. @@ -3429,7 +3459,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // sequence converts the source type to the type required by // the argument of the constructor. // - QualType ThisType = Constructor->getThisType(S.Context); + QualType ThisType = Constructor->getThisType(); if (isa<InitListExpr>(From)) { // Initializer lists don't have conversions as such. User.Before.setAsIdentityConversion(); @@ -3496,13 +3526,13 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) { IsUserDefinedConversion(*this, From, ToType, ICS.UserDefined, CandidateSet, false, false); if (OvResult == OR_Ambiguous) - Diag(From->getLocStart(), diag::err_typecheck_ambiguous_condition) + Diag(From->getBeginLoc(), diag::err_typecheck_ambiguous_condition) << From->getType() << ToType << From->getSourceRange(); else if (OvResult == OR_No_Viable_Function && !CandidateSet.empty()) { - if (!RequireCompleteType(From->getLocStart(), ToType, + if (!RequireCompleteType(From->getBeginLoc(), ToType, diag::err_typecheck_nonviable_condition_incomplete, From->getType(), From->getSourceRange())) - Diag(From->getLocStart(), diag::err_typecheck_nonviable_condition) + Diag(From->getBeginLoc(), diag::err_typecheck_nonviable_condition) << false << From->getType() << From->getSourceRange() << ToType; } else return false; @@ -3516,7 +3546,7 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) { static ImplicitConversionSequence::CompareKind compareConversionFunctions(Sema &S, FunctionDecl *Function1, FunctionDecl *Function2) { - if (!S.getLangOpts().ObjC1 || !S.getLangOpts().CPlusPlus11) + if (!S.getLangOpts().ObjC || !S.getLangOpts().CPlusPlus11) return ImplicitConversionSequence::Indistinguishable; // Objective-C++: @@ -3900,6 +3930,31 @@ CompareStandardConversionSequences(Sema &S, SourceLocation Loc, S.Context.getTypeSize(SCS1.getToType(2))) return ImplicitConversionSequence::Better; + // Prefer a compatible vector conversion over a lax vector conversion + // For example: + // + // typedef float __v4sf __attribute__((__vector_size__(16))); + // void f(vector float); + // void f(vector signed int); + // int main() { + // __v4sf a; + // f(a); + // } + // Here, we'd like to choose f(vector float) and not + // report an ambiguous call error + if (SCS1.Second == ICK_Vector_Conversion && + SCS2.Second == ICK_Vector_Conversion) { + bool SCS1IsCompatibleVectorConversion = S.Context.areCompatibleVectorTypes( + SCS1.getFromType(), SCS1.getToType(2)); + bool SCS2IsCompatibleVectorConversion = S.Context.areCompatibleVectorTypes( + SCS2.getFromType(), SCS2.getToType(2)); + + if (SCS1IsCompatibleVectorConversion != SCS2IsCompatibleVectorConversion) + return SCS1IsCompatibleVectorConversion + ? ImplicitConversionSequence::Better + : ImplicitConversionSequence::Worse; + } + return ImplicitConversionSequence::Indistinguishable; } @@ -4750,7 +4805,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, // We need a complete type for what follows. Incomplete types can never be // initialized from init lists. - if (!S.isCompleteType(From->getLocStart(), ToType)) + if (!S.isCompleteType(From->getBeginLoc(), ToType)) return Result; // Per DR1467: @@ -4767,7 +4822,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, if (ToType->isRecordType()) { QualType InitType = From->getInit(0)->getType(); if (S.Context.hasSameUnqualifiedType(InitType, ToType) || - S.IsDerivedFrom(From->getLocStart(), InitType, ToType)) + S.IsDerivedFrom(From->getBeginLoc(), InitType, ToType)) return TryCopyInitialization(S, From->getInit(0), ToType, SuppressUserConversions, InOverloadResolution, @@ -4823,10 +4878,9 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, break; } // Otherwise, look for the worst conversion. - if (Result.isBad() || - CompareImplicitConversionSequences(S, From->getLocStart(), ICS, - Result) == - ImplicitConversionSequence::Worse) + if (Result.isBad() || CompareImplicitConversionSequences( + S, From->getBeginLoc(), ICS, Result) == + ImplicitConversionSequence::Worse) Result = ICS; } @@ -4920,12 +4974,12 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, bool dummy1 = false; bool dummy2 = false; bool dummy3 = false; - Sema::ReferenceCompareResult RefRelationship - = S.CompareReferenceRelationship(From->getLocStart(), T1, T2, dummy1, + Sema::ReferenceCompareResult RefRelationship = + S.CompareReferenceRelationship(From->getBeginLoc(), T1, T2, dummy1, dummy2, dummy3); if (RefRelationship >= Sema::Ref_Related) { - return TryReferenceInit(S, Init, ToType, /*FIXME*/From->getLocStart(), + return TryReferenceInit(S, Init, ToType, /*FIXME*/ From->getBeginLoc(), SuppressUserConversions, /*AllowExplicit=*/false); } @@ -5006,9 +5060,8 @@ TryCopyInitialization(Sema &S, Expr *From, QualType ToType, if (ToType->isReferenceType()) return TryReferenceInit(S, From, ToType, - /*FIXME:*/From->getLocStart(), - SuppressUserConversions, - AllowExplicit); + /*FIXME:*/ From->getBeginLoc(), + SuppressUserConversions, AllowExplicit); return TryImplicitConversion(S, From, ToType, SuppressUserConversions, @@ -5042,9 +5095,15 @@ TryObjectArgumentInitialization(Sema &S, SourceLocation Loc, QualType FromType, QualType ClassType = S.Context.getTypeDeclType(ActingContext); // [class.dtor]p2: A destructor can be invoked for a const, volatile or // const volatile object. - unsigned Quals = isa<CXXDestructorDecl>(Method) ? - Qualifiers::Const | Qualifiers::Volatile : Method->getTypeQualifiers(); - QualType ImplicitParamType = S.Context.getCVRQualifiedType(ClassType, Quals); + Qualifiers Quals; + if (isa<CXXDestructorDecl>(Method)) { + Quals.addConst(); + Quals.addVolatile(); + } else { + Quals = Method->getTypeQualifiers(); + } + + QualType ImplicitParamType = S.Context.getQualifiedType(ClassType, Quals); // Set up the conversion sequence as a "bad" conversion, to allow us // to exit early. @@ -5110,7 +5169,7 @@ TryObjectArgumentInitialization(Sema &S, SourceLocation Loc, QualType FromType, break; case RQ_LValue: - if (!FromClassification.isLValue() && Quals != Qualifiers::Const) { + if (!FromClassification.isLValue() && !Quals.hasOnlyConst()) { // non-const lvalue reference cannot bind to an rvalue ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, FromType, ImplicitParamType); @@ -5154,12 +5213,12 @@ Sema::PerformObjectArgumentInitialization(Expr *From, CXXMethodDecl *Method) { QualType FromRecordType, DestType; QualType ImplicitParamRecordType = - Method->getThisType(Context)->getAs<PointerType>()->getPointeeType(); + Method->getThisType()->getAs<PointerType>()->getPointeeType(); Expr::Classification FromClassification; if (const PointerType *PT = From->getType()->getAs<PointerType>()) { FromRecordType = PT->getPointeeType(); - DestType = Method->getThisType(Context); + DestType = Method->getThisType(); FromClassification = Expr::Classification::makeSimpleLValue(); } else { FromRecordType = From->getType(); @@ -5177,7 +5236,7 @@ Sema::PerformObjectArgumentInitialization(Expr *From, // Note that we always use the true parent context when performing // the actual argument initialization. ImplicitConversionSequence ICS = TryObjectArgumentInitialization( - *this, From->getLocStart(), From->getType(), FromClassification, Method, + *this, From->getBeginLoc(), From->getType(), FromClassification, Method, Method->getParent()); if (ICS.isBad()) { switch (ICS.Bad.Kind) { @@ -5186,10 +5245,9 @@ Sema::PerformObjectArgumentInitialization(Expr *From, Qualifiers ToQs = DestType.getQualifiers(); unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers(); if (CVR) { - Diag(From->getLocStart(), - diag::err_member_function_call_bad_cvr) - << Method->getDeclName() << FromRecordType << (CVR - 1) - << From->getSourceRange(); + Diag(From->getBeginLoc(), diag::err_member_function_call_bad_cvr) + << Method->getDeclName() << FromRecordType << (CVR - 1) + << From->getSourceRange(); Diag(Method->getLocation(), diag::note_previous_decl) << Method->getDeclName(); return ExprError(); @@ -5201,9 +5259,9 @@ Sema::PerformObjectArgumentInitialization(Expr *From, case BadConversionSequence::rvalue_ref_to_lvalue: { bool IsRValueQualified = Method->getRefQualifier() == RefQualifierKind::RQ_RValue; - Diag(From->getLocStart(), diag::err_member_function_call_bad_ref) - << Method->getDeclName() << FromClassification.isRValue() - << IsRValueQualified; + Diag(From->getBeginLoc(), diag::err_member_function_call_bad_ref) + << Method->getDeclName() << FromClassification.isRValue() + << IsRValueQualified; Diag(Method->getLocation(), diag::note_previous_decl) << Method->getDeclName(); return ExprError(); @@ -5214,9 +5272,9 @@ Sema::PerformObjectArgumentInitialization(Expr *From, break; } - return Diag(From->getLocStart(), - diag::err_member_function_call_bad_type) - << ImplicitParamRecordType << FromRecordType << From->getSourceRange(); + return Diag(From->getBeginLoc(), diag::err_member_function_call_bad_type) + << ImplicitParamRecordType << FromRecordType + << From->getSourceRange(); } if (ICS.Standard.Second == ICK_Derived_To_Base) { @@ -5227,9 +5285,14 @@ Sema::PerformObjectArgumentInitialization(Expr *From, From = FromRes.get(); } - if (!Context.hasSameType(From->getType(), DestType)) - From = ImpCastExprToType(From, DestType, CK_NoOp, + if (!Context.hasSameType(From->getType(), DestType)) { + if (From->getType().getAddressSpace() != DestType.getAddressSpace()) + From = ImpCastExprToType(From, DestType, CK_AddressSpaceConversion, From->getValueKind()).get(); + else + From = ImpCastExprToType(From, DestType, CK_NoOp, + From->getValueKind()).get(); + } return From; } @@ -5257,9 +5320,8 @@ ExprResult Sema::PerformContextuallyConvertToBool(Expr *From) { return PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting); if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy)) - return Diag(From->getLocStart(), - diag::err_typecheck_bool_condition) - << From->getType() << From->getSourceRange(); + return Diag(From->getBeginLoc(), diag::err_typecheck_bool_condition) + << From->getType() << From->getSourceRange(); return ExprError(); } @@ -5372,9 +5434,9 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From, case ImplicitConversionSequence::AmbiguousConversion: case ImplicitConversionSequence::BadConversion: if (!S.DiagnoseMultipleUserDefinedConversion(From, T)) - return S.Diag(From->getLocStart(), + return S.Diag(From->getBeginLoc(), diag::err_typecheck_converted_constant_expression) - << From->getType() << From->getSourceRange() << T; + << From->getType() << From->getSourceRange() << T; return ExprError(); case ImplicitConversionSequence::EllipsisConversion: @@ -5383,15 +5445,15 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From, // Check that we would only use permitted conversions. if (!CheckConvertedConstantConversions(S, *SCS)) { - return S.Diag(From->getLocStart(), + return S.Diag(From->getBeginLoc(), diag::err_typecheck_converted_constant_expression_disallowed) - << From->getType() << From->getSourceRange() << T; + << From->getType() << From->getSourceRange() << T; } // [...] and where the reference binding (if any) binds directly. if (SCS->ReferenceBinding && !SCS->DirectBinding) { - return S.Diag(From->getLocStart(), + return S.Diag(From->getBeginLoc(), diag::err_typecheck_converted_constant_expression_indirect) - << From->getType() << From->getSourceRange() << T; + << From->getType() << From->getSourceRange() << T; } ExprResult Result = @@ -5414,14 +5476,14 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From, break; case NK_Constant_Narrowing: - S.Diag(From->getLocStart(), diag::ext_cce_narrowing) - << CCE << /*Constant*/1 - << PreNarrowingValue.getAsString(S.Context, PreNarrowingType) << T; + S.Diag(From->getBeginLoc(), diag::ext_cce_narrowing) + << CCE << /*Constant*/ 1 + << PreNarrowingValue.getAsString(S.Context, PreNarrowingType) << T; break; case NK_Type_Narrowing: - S.Diag(From->getLocStart(), diag::ext_cce_narrowing) - << CCE << /*Constant*/0 << From->getType() << T; + S.Diag(From->getBeginLoc(), diag::ext_cce_narrowing) + << CCE << /*Constant*/ 0 << From->getType() << T; break; } @@ -5448,7 +5510,7 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From, if (Notes.empty()) { // It's a constant expression. - return Result; + return ConstantExpr::Create(S.Context, Result.get()); } } @@ -5457,8 +5519,8 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From, Notes[0].second.getDiagID() == diag::note_invalid_subexpr_in_const_expr) S.Diag(Notes[0].first, diag::err_expr_not_cce) << CCE; else { - S.Diag(From->getLocStart(), diag::err_expr_not_cce) - << CCE << From->getSourceRange(); + S.Diag(From->getBeginLoc(), diag::err_expr_not_cce) + << CCE << From->getSourceRange(); for (unsigned I = 0; I < Notes.size(); ++I) S.Diag(Notes[I].first, Notes[I].second); } @@ -5586,10 +5648,10 @@ diagnoseNoViableConversion(Sema &SemaRef, SourceLocation Loc, Expr *&From, ConvTy.getAsStringInternal(TypeStr, SemaRef.getPrintingPolicy()); Converter.diagnoseExplicitConv(SemaRef, Loc, T, ConvTy) - << FixItHint::CreateInsertion(From->getLocStart(), + << FixItHint::CreateInsertion(From->getBeginLoc(), "static_cast<" + TypeStr + ">(") << FixItHint::CreateInsertion( - SemaRef.getLocForEndOfToken(From->getLocEnd()), ")"); + SemaRef.getLocForEndOfToken(From->getEndLoc()), ")"); Converter.noteExplicitConv(SemaRef, Conversion, ConvTy); // If we aren't in a SFINAE context, build a call to the @@ -5925,15 +5987,13 @@ static bool IsAcceptableNonMemberOperatorCandidate(ASTContext &Context, /// \param PartialOverloading true if we are performing "partial" overloading /// based on an incomplete set of function arguments. This feature is used by /// code completion. -void -Sema::AddOverloadCandidate(FunctionDecl *Function, - DeclAccessPair FoundDecl, - ArrayRef<Expr *> Args, - OverloadCandidateSet &CandidateSet, - bool SuppressUserConversions, - bool PartialOverloading, - bool AllowExplicit, - ConversionSequenceList EarlyConversions) { +void Sema::AddOverloadCandidate(FunctionDecl *Function, + DeclAccessPair FoundDecl, ArrayRef<Expr *> Args, + OverloadCandidateSet &CandidateSet, + bool SuppressUserConversions, + bool PartialOverloading, bool AllowExplicit, + ADLCallKind IsADLCandidate, + ConversionSequenceList EarlyConversions) { const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>()); assert(Proto && "Functions without a prototype cannot be overloaded"); @@ -5992,6 +6052,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, Candidate.Function = Function; Candidate.Viable = true; Candidate.IsSurrogate = false; + Candidate.IsADLCandidate = IsADLCandidate; Candidate.IgnoreObjectArgument = false; Candidate.ExplicitCallArguments = Args.size(); @@ -6009,7 +6070,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, QualType ClassType = Context.getTypeDeclType(Constructor->getParent()); if (Args.size() == 1 && Constructor->isSpecializationCopyingObject() && (Context.hasSameUnqualifiedType(ClassType, Args[0]->getType()) || - IsDerivedFrom(Args[0]->getLocStart(), Args[0]->getType(), + IsDerivedFrom(Args[0]->getBeginLoc(), Args[0]->getType(), ClassType))) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_illegal_constructor; @@ -6215,24 +6276,6 @@ Sema::SelectBestMethod(Selector Sel, MultiExprArg Args, bool IsInstance, return nullptr; } -// specific_attr_iterator iterates over enable_if attributes in reverse, and -// enable_if is order-sensitive. As a result, we need to reverse things -// sometimes. Size of 4 elements is arbitrary. -static SmallVector<EnableIfAttr *, 4> -getOrderedEnableIfAttrs(const FunctionDecl *Function) { - SmallVector<EnableIfAttr *, 4> Result; - if (!Function->hasAttrs()) - return Result; - - const auto &FuncAttrs = Function->getAttrs(); - for (Attr *Attr : FuncAttrs) - if (auto *EnableIf = dyn_cast<EnableIfAttr>(Attr)) - Result.push_back(EnableIf); - - std::reverse(Result.begin(), Result.end()); - return Result; -} - static bool convertArgsForAvailabilityChecks(Sema &S, FunctionDecl *Function, Expr *ThisArg, ArrayRef<Expr *> Args, Sema::SFINAETrap &Trap, @@ -6306,9 +6349,8 @@ convertArgsForAvailabilityChecks(Sema &S, FunctionDecl *Function, Expr *ThisArg, EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args, bool MissingImplicitThis) { - SmallVector<EnableIfAttr *, 4> EnableIfAttrs = - getOrderedEnableIfAttrs(Function); - if (EnableIfAttrs.empty()) + auto EnableIfAttrs = Function->specific_attrs<EnableIfAttr>(); + if (EnableIfAttrs.begin() == EnableIfAttrs.end()) return nullptr; SFINAETrap Trap(*this); @@ -6318,7 +6360,7 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args, if (!convertArgsForAvailabilityChecks( *this, Function, /*ThisArg=*/nullptr, Args, Trap, /*MissingImplicitThis=*/true, DiscardedThis, ConvertedArgs)) - return EnableIfAttrs[0]; + return *EnableIfAttrs.begin(); for (auto *EIA : EnableIfAttrs) { APValue Result; @@ -6427,7 +6469,12 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, if (Expr *E = Args[0]) { // Use the explicit base to restrict the lookup: ObjectType = E->getType(); - ObjectClassification = E->Classify(Context); + // Pointers in the object arguments are implicitly dereferenced, so we + // always classify them as l-values. + if (!ObjectType.isNull() && ObjectType->isPointerType()) + ObjectClassification = Expr::Classification::makeSimpleLValue(); + else + ObjectClassification = E->Classify(Context); } // .. else there is an implicit base. FunctionArgs = Args.slice(1); } @@ -6708,14 +6755,11 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, /// Add a C++ function template specialization as a candidate /// in the candidate set, using template argument deduction to produce /// an appropriate function template specialization. -void -Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, - DeclAccessPair FoundDecl, - TemplateArgumentListInfo *ExplicitTemplateArgs, - ArrayRef<Expr *> Args, - OverloadCandidateSet& CandidateSet, - bool SuppressUserConversions, - bool PartialOverloading) { +void Sema::AddTemplateOverloadCandidate( + FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, + TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, + OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, + bool PartialOverloading, ADLCallKind IsADLCandidate) { if (!CandidateSet.isNewCandidate(FunctionTemplate)) return; @@ -6744,6 +6788,7 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, Candidate.Function = FunctionTemplate->getTemplatedDecl(); Candidate.Viable = false; Candidate.IsSurrogate = false; + Candidate.IsADLCandidate = IsADLCandidate; // Ignore the object argument if there is one, since we don't have an object // type. Candidate.IgnoreObjectArgument = @@ -6765,7 +6810,7 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, assert(Specialization && "Missing function template specialization?"); AddOverloadCandidate(Specialization, FoundDecl, Args, CandidateSet, SuppressUserConversions, PartialOverloading, - /*AllowExplicit*/false, Conversions); + /*AllowExplicit*/ false, IsADLCandidate, Conversions); } /// Check that implicit conversion sequences can be formed for each argument @@ -6966,15 +7011,15 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, // lvalues/rvalues and the type. Fortunately, we can allocate this // call on the stack and we don't need its arguments to be // well-formed. - DeclRefExpr ConversionRef(Conversion, false, Conversion->getType(), - VK_LValue, From->getLocStart()); + DeclRefExpr ConversionRef(Context, Conversion, false, Conversion->getType(), + VK_LValue, From->getBeginLoc()); ImplicitCastExpr ConversionFn(ImplicitCastExpr::OnStack, Context.getPointerType(Conversion->getType()), CK_FunctionToPointerDecay, &ConversionRef, VK_RValue); QualType ConversionType = Conversion->getConversionType(); - if (!isCompleteType(From->getLocStart(), ConversionType)) { + if (!isCompleteType(From->getBeginLoc(), ConversionType)) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_final_conversion; return; @@ -6986,13 +7031,17 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, // there are 0 arguments (i.e., nothing is allocated using ASTContext's // allocator). QualType CallResultType = ConversionType.getNonLValueExprType(Context); - CallExpr Call(Context, &ConversionFn, None, CallResultType, VK, - From->getLocStart()); + + llvm::AlignedCharArray<alignof(CallExpr), sizeof(CallExpr) + sizeof(Stmt *)> + Buffer; + CallExpr *TheTemporaryCall = CallExpr::CreateTemporary( + Buffer.buffer, &ConversionFn, CallResultType, VK, From->getBeginLoc()); + ImplicitConversionSequence ICS = - TryCopyInitialization(*this, &Call, ToType, - /*SuppressUserConversions=*/true, - /*InOverloadResolution=*/false, - /*AllowObjCWritebackConversion=*/false); + TryCopyInitialization(*this, TheTemporaryCall, ToType, + /*SuppressUserConversions=*/true, + /*InOverloadResolution=*/false, + /*AllowObjCWritebackConversion=*/false); switch (ICS.getKind()) { case ImplicitConversionSequence::StandardConversion: @@ -8928,16 +8977,20 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, // set. for (ADLResult::iterator I = Fns.begin(), E = Fns.end(); I != E; ++I) { DeclAccessPair FoundDecl = DeclAccessPair::make(*I, AS_none); + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) { if (ExplicitTemplateArgs) continue; - AddOverloadCandidate(FD, FoundDecl, Args, CandidateSet, false, - PartialOverloading); - } else - AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*I), - FoundDecl, ExplicitTemplateArgs, - Args, CandidateSet, PartialOverloading); + AddOverloadCandidate(FD, FoundDecl, Args, CandidateSet, + /*SupressUserConversions=*/false, PartialOverloading, + /*AllowExplicit=*/false, ADLCallKind::UsesADL); + } else { + AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*I), FoundDecl, + ExplicitTemplateArgs, Args, CandidateSet, + /*SupressUserConversions=*/false, + PartialOverloading, ADLCallKind::UsesADL); + } } } @@ -8967,31 +9020,31 @@ static Comparison compareEnableIfAttrs(const Sema &S, const FunctionDecl *Cand1, return Cand1Attr ? Comparison::Better : Comparison::Worse; } - // FIXME: The next several lines are just - // specific_attr_iterator<EnableIfAttr> but going in declaration order, - // instead of reverse order which is how they're stored in the AST. - auto Cand1Attrs = getOrderedEnableIfAttrs(Cand1); - auto Cand2Attrs = getOrderedEnableIfAttrs(Cand2); - - // It's impossible for Cand1 to be better than (or equal to) Cand2 if Cand1 - // has fewer enable_if attributes than Cand2. - if (Cand1Attrs.size() < Cand2Attrs.size()) - return Comparison::Worse; + auto Cand1Attrs = Cand1->specific_attrs<EnableIfAttr>(); + auto Cand2Attrs = Cand2->specific_attrs<EnableIfAttr>(); - auto Cand1I = Cand1Attrs.begin(); llvm::FoldingSetNodeID Cand1ID, Cand2ID; - for (auto &Cand2A : Cand2Attrs) { + for (auto Pair : zip_longest(Cand1Attrs, Cand2Attrs)) { + Optional<EnableIfAttr *> Cand1A = std::get<0>(Pair); + Optional<EnableIfAttr *> Cand2A = std::get<1>(Pair); + + // It's impossible for Cand1 to be better than (or equal to) Cand2 if Cand1 + // has fewer enable_if attributes than Cand2, and vice versa. + if (!Cand1A) + return Comparison::Worse; + if (!Cand2A) + return Comparison::Better; + Cand1ID.clear(); Cand2ID.clear(); - auto &Cand1A = *Cand1I++; - Cand1A->getCond()->Profile(Cand1ID, S.getASTContext(), true); - Cand2A->getCond()->Profile(Cand2ID, S.getASTContext(), true); + (*Cand1A)->getCond()->Profile(Cand1ID, S.getASTContext(), true); + (*Cand2A)->getCond()->Profile(Cand2ID, S.getASTContext(), true); if (Cand1ID != Cand2ID) return Comparison::Worse; } - return Cand1I == Cand1Attrs.end() ? Comparison::Equal : Comparison::Better; + return Comparison::Equal; } static bool isBetterMultiversionCandidate(const OverloadCandidate &Cand1, @@ -9000,6 +9053,11 @@ static bool isBetterMultiversionCandidate(const OverloadCandidate &Cand1, !Cand2.Function->isMultiVersion()) return false; + // If Cand1 is invalid, it cannot be a better match, if Cand2 is invalid, this + // is obviously better. + if (Cand1.Function->isInvalidDecl()) return false; + if (Cand2.Function->isInvalidDecl()) return true; + // If this is a cpu_dispatch/cpu_specific multiversion situation, prefer // cpu_dispatch, else arbitrarily based on the identifiers. bool Cand1CPUDisp = Cand1.Function->hasAttr<CPUDispatchAttr>(); @@ -9506,7 +9564,7 @@ static bool checkAddressOfFunctionIsAvailable(Sema &S, const FunctionDecl *FD, if (!isFunctionAlwaysEnabled(S.Context, FD)) { if (Complain) { if (InOverloadResolution) - S.Diag(FD->getLocStart(), + S.Diag(FD->getBeginLoc(), diag::note_addrof_ovl_candidate_disabled_by_enable_if_attr); else S.Diag(Loc, diag::err_addrof_function_disabled_by_enable_if_attr) << FD; @@ -10010,7 +10068,7 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated, DeductionFailure.getFirstArg()->getNonTypeTemplateArgumentType(); QualType T2 = DeductionFailure.getSecondArg()->getNonTypeTemplateArgumentType(); - if (!S.Context.hasSameType(T1, T2)) { + if (!T1.isNull() && !T2.isNull() && !S.Context.hasSameType(T1, T2)) { S.Diag(Templated->getLocation(), diag::note_ovl_candidate_inconsistent_deduction_types) << ParamD->getDeclName() << *DeductionFailure.getFirstArg() << T1 @@ -10268,7 +10326,8 @@ static void DiagnoseOpenCLExtensionDisabled(Sema &S, OverloadCandidate *Cand) { FunctionDecl *Callee = Cand->Function; S.Diag(Callee->getLocation(), - diag::note_ovl_candidate_disabled_by_extension); + diag::note_ovl_candidate_disabled_by_extension) + << S.getOpenCLExtensionsFromDeclExtMap(Callee); } /// Generates a 'note' diagnostic for an overload candidate. We've @@ -10836,8 +10895,7 @@ void TemplateSpecCandidateSet::NoteCandidates(Sema &S, SourceLocation Loc) { // in general, want to list every possible builtin candidate. } - llvm::sort(Cands.begin(), Cands.end(), - CompareTemplateSpecCandidatesForDisplay(S)); + llvm::sort(Cands, CompareTemplateSpecCandidatesForDisplay(S)); // FIXME: Perhaps rename OverloadsShown and getShowOverloads() // for generalization purposes (?). @@ -11023,7 +11081,7 @@ private: // Note: We explicitly leave Matches unmodified if there isn't a clear best // option, so we can potentially give the user a better error - if (!std::all_of(Matches.begin(), Matches.end(), IsBestOrInferiorToBest)) + if (!llvm::all_of(Matches, IsBestOrInferiorToBest)) return false; Matches[0] = *Best; Matches.resize(1); @@ -11114,7 +11172,7 @@ private: // If any candidate has a placeholder return type, trigger its deduction // now. - if (completeFunctionType(S, FunDecl, SourceExpr->getLocStart(), + if (completeFunctionType(S, FunDecl, SourceExpr->getBeginLoc(), Complain)) { HasComplained |= Complain; return false; @@ -11190,7 +11248,7 @@ private: // here, since the no_viable diagnostic has index 0. UnresolvedSetIterator Result = S.getMostSpecialized( MatchesCopy.begin(), MatchesCopy.end(), FailedCandidates, - SourceExpr->getLocStart(), S.PDiag(), + SourceExpr->getBeginLoc(), S.PDiag(), S.PDiag(diag::err_addr_ovl_ambiguous) << Matches[0].second->getDeclName(), S.PDiag(diag::note_ovl_candidate) @@ -11226,7 +11284,7 @@ private: public: void ComplainNoMatchesFound() const { assert(Matches.empty()); - S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_no_viable) + S.Diag(OvlExpr->getBeginLoc(), diag::err_addr_ovl_no_viable) << OvlExpr->getName() << TargetFunctionType << OvlExpr->getSourceRange(); if (FailedCandidates.empty()) @@ -11244,7 +11302,7 @@ public: if (!functionHasPassObjectSizeParams(Fun)) S.NoteOverloadCandidate(*I, Fun, TargetFunctionType, /*TakingAddress=*/true); - FailedCandidates.NoteCandidates(S, OvlExpr->getLocStart()); + FailedCandidates.NoteCandidates(S, OvlExpr->getBeginLoc()); } } @@ -11266,21 +11324,20 @@ public: } void ComplainIsStaticMemberFunctionFromBoundPointer() const { - S.Diag(OvlExpr->getLocStart(), + S.Diag(OvlExpr->getBeginLoc(), diag::err_invalid_form_pointer_member_function) - << OvlExpr->getSourceRange(); + << OvlExpr->getSourceRange(); } void ComplainOfInvalidConversion() const { - S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_not_func_ptrref) - << OvlExpr->getName() << TargetType; + S.Diag(OvlExpr->getBeginLoc(), diag::err_addr_ovl_not_func_ptrref) + << OvlExpr->getName() << TargetType; } void ComplainMultipleMatchesFound() const { assert(Matches.size() > 1); - S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_ambiguous) - << OvlExpr->getName() - << OvlExpr->getSourceRange(); + S.Diag(OvlExpr->getBeginLoc(), diag::err_addr_ovl_ambiguous) + << OvlExpr->getName() << OvlExpr->getSourceRange(); S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType, /*TakingAddress=*/true); } @@ -11530,7 +11587,7 @@ bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization( ExprResult SingleFunctionExpression; if (FunctionDecl *fn = ResolveSingleFunctionTemplateSpecialization( ovl.Expression, /*complain*/ false, &found)) { - if (DiagnoseUseOfDecl(fn, SrcExpr.get()->getLocStart())) { + if (DiagnoseUseOfDecl(fn, SrcExpr.get()->getBeginLoc())) { SrcExpr = ExprError(); return true; } @@ -11966,14 +12023,14 @@ bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn, OverloadCandidateSet::iterator Best; if (CandidateSet->empty() || - CandidateSet->BestViableFunction(*this, Fn->getLocStart(), Best) == + CandidateSet->BestViableFunction(*this, Fn->getBeginLoc(), Best) == OR_No_Viable_Function) { - // In Microsoft mode, if we are inside a template class member function 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 = new (Context) CallExpr( - Context, Fn, Args, Context.DependentTy, VK_RValue, RParenLoc); + // In Microsoft mode, if we are inside a template class member function + // 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); CE->setTypeDependent(true); CE->setValueDependent(true); CE->setInstantiationDependent(true); @@ -12015,7 +12072,8 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, return ExprError(); Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl); return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, RParenLoc, - ExecConfig); + ExecConfig, /*IsExecConfig=*/false, + (*Best)->IsADLCandidate); } case OR_No_Viable_Function: { @@ -12043,24 +12101,23 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, } } - SemaRef.Diag(Fn->getLocStart(), diag::err_ovl_no_viable_function_in_call) + SemaRef.Diag(Fn->getBeginLoc(), diag::err_ovl_no_viable_function_in_call) << ULE->getName() << Fn->getSourceRange(); CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, Args); break; } case OR_Ambiguous: - SemaRef.Diag(Fn->getLocStart(), diag::err_ovl_ambiguous_call) - << ULE->getName() << Fn->getSourceRange(); + SemaRef.Diag(Fn->getBeginLoc(), diag::err_ovl_ambiguous_call) + << ULE->getName() << Fn->getSourceRange(); CandidateSet->NoteCandidates(SemaRef, OCD_ViableCandidates, Args); break; case OR_Deleted: { - SemaRef.Diag(Fn->getLocStart(), diag::err_ovl_deleted_call) - << (*Best)->Function->isDeleted() - << ULE->getName() - << SemaRef.getDeletedOrUnavailableSuffix((*Best)->Function) - << Fn->getSourceRange(); + SemaRef.Diag(Fn->getBeginLoc(), diag::err_ovl_deleted_call) + << (*Best)->Function->isDeleted() << ULE->getName() + << SemaRef.getDeletedOrUnavailableSuffix((*Best)->Function) + << Fn->getSourceRange(); CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, Args); // We emitted an error for the unavailable/deleted function call but keep @@ -12068,7 +12125,8 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, FunctionDecl *FDecl = (*Best)->Function; Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl); return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, RParenLoc, - ExecConfig); + ExecConfig, /*IsExecConfig=*/false, + (*Best)->IsADLCandidate); } } @@ -12116,7 +12174,7 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, OverloadCandidateSet::iterator Best; OverloadingResult OverloadResult = - CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best); + CandidateSet.BestViableFunction(*this, Fn->getBeginLoc(), Best); return FinishOverloadedCallExpr(*this, S, Fn, ULE, LParenLoc, Args, RParenLoc, ExecConfig, &CandidateSet, @@ -12178,14 +12236,12 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, VK_RValue, OK_Ordinary, OpLoc, false); CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators - UnresolvedLookupExpr *Fn - = UnresolvedLookupExpr::Create(Context, NamingClass, - NestedNameSpecifierLoc(), OpNameInfo, - /*ADL*/ true, IsOverloaded(Fns), - Fns.begin(), Fns.end()); - return new (Context) - CXXOperatorCallExpr(Context, Op, Fn, ArgsArray, Context.DependentTy, - VK_RValue, OpLoc, FPOptions()); + UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create( + Context, NamingClass, NestedNameSpecifierLoc(), OpNameInfo, + /*ADL*/ true, IsOverloaded(Fns), Fns.begin(), Fns.end()); + return CXXOperatorCallExpr::Create(Context, Op, Fn, ArgsArray, + Context.DependentTy, VK_RValue, OpLoc, + FPOptions()); } // Build an empty overload set. @@ -12257,9 +12313,9 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, ResultTy = ResultTy.getNonLValueExprType(Context); Args[0] = Input; - CallExpr *TheCall = - new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.get(), ArgsArray, - ResultTy, VK, OpLoc, FPOptions()); + CallExpr *TheCall = CXXOperatorCallExpr::Create( + Context, Op, FnExpr.get(), ArgsArray, ResultTy, VK, OpLoc, + FPOptions(), Best->IsADLCandidate); if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall, FnDecl)) return ExprError(); @@ -12369,14 +12425,12 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators // TODO: provide better source location info in DNLoc component. DeclarationNameInfo OpNameInfo(OpName, OpLoc); - UnresolvedLookupExpr *Fn - = UnresolvedLookupExpr::Create(Context, NamingClass, - NestedNameSpecifierLoc(), OpNameInfo, - /*ADL*/PerformADL, IsOverloaded(Fns), - Fns.begin(), Fns.end()); - return new (Context) - CXXOperatorCallExpr(Context, Op, Fn, Args, Context.DependentTy, - VK_RValue, OpLoc, FPFeatures); + UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create( + Context, NamingClass, NestedNameSpecifierLoc(), OpNameInfo, + /*ADL*/ PerformADL, IsOverloaded(Fns), Fns.begin(), Fns.end()); + return CXXOperatorCallExpr::Create(Context, Op, Fn, Args, + Context.DependentTy, VK_RValue, OpLoc, + FPFeatures); } // Always do placeholder-like conversions on the RHS. @@ -12489,10 +12543,9 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, ExprValueKind VK = Expr::getValueKindForType(ResultTy); ResultTy = ResultTy.getNonLValueExprType(Context); - CXXOperatorCallExpr *TheCall = - new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.get(), - Args, ResultTy, VK, OpLoc, - FPFeatures); + CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create( + Context, Op, FnExpr.get(), Args, ResultTy, VK, OpLoc, FPFeatures, + Best->IsADLCandidate); if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall, FnDecl)) @@ -12638,9 +12691,9 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, UnresolvedSetIterator()); // Can't add any actual overloads yet - return new (Context) - CXXOperatorCallExpr(Context, OO_Subscript, Fn, Args, - Context.DependentTy, VK_RValue, RLoc, FPOptions()); + return CXXOperatorCallExpr::Create(Context, OO_Subscript, Fn, Args, + Context.DependentTy, VK_RValue, RLoc, + FPOptions()); } // Handle placeholders on both operands. @@ -12714,10 +12767,8 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, ResultTy = ResultTy.getNonLValueExprType(Context); CXXOperatorCallExpr *TheCall = - new (Context) CXXOperatorCallExpr(Context, OO_Subscript, - FnExpr.get(), Args, - ResultTy, VK, RLoc, - FPOptions()); + CXXOperatorCallExpr::Create(Context, OO_Subscript, FnExpr.get(), + Args, ResultTy, VK, RLoc, FPOptions()); if (CheckCallReturnType(FnDecl->getReturnType(), LLoc, TheCall, FnDecl)) return ExprError(); @@ -12819,7 +12870,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, // Check that the object type isn't more qualified than the // member function we're calling. - Qualifiers funcQuals = Qualifiers::fromCVRMask(proto->getTypeQuals()); + Qualifiers funcQuals = proto->getTypeQuals(); QualType objectType = op->getLHS()->getType(); if (op->getOpcode() == BO_PtrMemI) @@ -12837,11 +12888,11 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, << (qualsString.find(' ') == std::string::npos ? 1 : 2); } - CXXMemberCallExpr *call - = new (Context) CXXMemberCallExpr(Context, MemExprE, Args, - resultType, valueKind, RParenLoc); + CXXMemberCallExpr *call = + CXXMemberCallExpr::Create(Context, MemExprE, Args, resultType, + valueKind, RParenLoc, proto->getNumParams()); - if (CheckCallReturnType(proto->getReturnType(), op->getRHS()->getLocStart(), + if (CheckCallReturnType(proto->getReturnType(), op->getRHS()->getBeginLoc(), call, nullptr)) return ExprError(); @@ -12855,8 +12906,8 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, } if (isa<CXXPseudoDestructorExpr>(NakedMemExpr)) - return new (Context) - CallExpr(Context, MemExprE, Args, Context.VoidTy, VK_RValue, RParenLoc); + return CallExpr::Create(Context, MemExprE, Args, Context.VoidTy, VK_RValue, + RParenLoc); UnbridgedCastsSet UnbridgedCasts; if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts)) @@ -12927,7 +12978,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, UnbridgedCasts.restore(); OverloadCandidateSet::iterator Best; - switch (CandidateSet.BestViableFunction(*this, UnresExpr->getLocStart(), + switch (CandidateSet.BestViableFunction(*this, UnresExpr->getBeginLoc(), Best)) { case OR_Success: Method = cast<CXXMethodDecl>(Best->Function); @@ -12989,9 +13040,10 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, ResultType = ResultType.getNonLValueExprType(Context); assert(Method && "Member call to something that isn't a method?"); + const auto *Proto = Method->getType()->getAs<FunctionProtoType>(); CXXMemberCallExpr *TheCall = - new (Context) CXXMemberCallExpr(Context, MemExprE, Args, - ResultType, VK, RParenLoc); + CXXMemberCallExpr::Create(Context, MemExprE, Args, ResultType, VK, + RParenLoc, Proto->getNumParams()); // Check for a valid return type. if (CheckCallReturnType(Method->getReturnType(), MemExpr->getMemberLoc(), @@ -13011,8 +13063,6 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, } // Convert the rest of the arguments - const FunctionProtoType *Proto = - Method->getType()->getAs<FunctionProtoType>(); if (ConvertArgumentsForCall(TheCall, MemExpr, Method, Proto, Args, RParenLoc)) return ExprError(); @@ -13044,17 +13094,15 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, if (isa<CXXThisExpr>(MemExpr->getBase()->IgnoreParenCasts()) && MemExpr->performsVirtualDispatch(getLangOpts())) { - Diag(MemExpr->getLocStart(), + Diag(MemExpr->getBeginLoc(), diag::warn_call_to_pure_virtual_member_function_from_ctor_dtor) - << MD->getDeclName() << isa<CXXDestructorDecl>(CurContext) - << MD->getParent()->getDeclName(); + << MD->getDeclName() << isa<CXXDestructorDecl>(CurContext) + << MD->getParent()->getDeclName(); - Diag(MD->getLocStart(), diag::note_previous_decl) << MD->getDeclName(); + Diag(MD->getBeginLoc(), diag::note_previous_decl) << MD->getDeclName(); if (getLangOpts().AppleKext) - Diag(MemExpr->getLocStart(), - diag::note_pure_qualified_call_kext) - << MD->getParent()->getDeclName() - << MD->getDeclName(); + Diag(MemExpr->getBeginLoc(), diag::note_pure_qualified_call_kext) + << MD->getParent()->getDeclName() << MD->getDeclName(); } } @@ -13062,7 +13110,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, dyn_cast<CXXDestructorDecl>(TheCall->getMethodDecl())) { // a->A::f() doesn't go through the vtable, except in AppleKext mode. bool CallCanBeVirtual = !MemExpr->hasQualifier() || getLangOpts().AppleKext; - CheckVirtualDtorCall(DD, MemExpr->getLocStart(), /*IsDelete=*/false, + CheckVirtualDtorCall(DD, MemExpr->getBeginLoc(), /*IsDelete=*/false, CallCanBeVirtual, /*WarnOnNonAbstractTypes=*/true, MemExpr->getMemberLoc()); } @@ -13167,7 +13215,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, // Perform overload resolution. OverloadCandidateSet::iterator Best; - switch (CandidateSet.BestViableFunction(*this, Object.get()->getLocStart(), + switch (CandidateSet.BestViableFunction(*this, Object.get()->getBeginLoc(), Best)) { case OR_Success: // Overload resolution succeeded; we'll build the appropriate call @@ -13176,30 +13224,26 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, case OR_No_Viable_Function: if (CandidateSet.empty()) - Diag(Object.get()->getLocStart(), diag::err_ovl_no_oper) - << Object.get()->getType() << /*call*/ 1 - << Object.get()->getSourceRange(); + Diag(Object.get()->getBeginLoc(), diag::err_ovl_no_oper) + << Object.get()->getType() << /*call*/ 1 + << Object.get()->getSourceRange(); else - Diag(Object.get()->getLocStart(), - diag::err_ovl_no_viable_object_call) - << Object.get()->getType() << Object.get()->getSourceRange(); + Diag(Object.get()->getBeginLoc(), diag::err_ovl_no_viable_object_call) + << Object.get()->getType() << Object.get()->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args); break; case OR_Ambiguous: - Diag(Object.get()->getLocStart(), - diag::err_ovl_ambiguous_object_call) - << Object.get()->getType() << Object.get()->getSourceRange(); + Diag(Object.get()->getBeginLoc(), diag::err_ovl_ambiguous_object_call) + << Object.get()->getType() << Object.get()->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args); break; case OR_Deleted: - Diag(Object.get()->getLocStart(), - diag::err_ovl_deleted_object_call) - << Best->Function->isDeleted() - << Object.get()->getType() - << getDeletedOrUnavailableSuffix(Best->Function) - << Object.get()->getSourceRange(); + Diag(Object.get()->getBeginLoc(), diag::err_ovl_deleted_object_call) + << Best->Function->isDeleted() << Object.get()->getType() + << getDeletedOrUnavailableSuffix(Best->Function) + << Object.get()->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args); break; } @@ -13266,29 +13310,14 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, if (NewFn.isInvalid()) return true; + // The number of argument slots to allocate in the call. If we have default + // arguments we need to allocate space for them as well. We additionally + // need one more slot for the object parameter. + unsigned NumArgsSlots = 1 + std::max<unsigned>(Args.size(), NumParams); + // Build the full argument list for the method call (the implicit object // parameter is placed at the beginning of the list). - SmallVector<Expr *, 8> MethodArgs(Args.size() + 1); - MethodArgs[0] = Object.get(); - std::copy(Args.begin(), Args.end(), MethodArgs.begin() + 1); - - // Once we've built TheCall, all of the expressions are properly - // owned. - QualType ResultTy = Method->getReturnType(); - ExprValueKind VK = Expr::getValueKindForType(ResultTy); - ResultTy = ResultTy.getNonLValueExprType(Context); - - CXXOperatorCallExpr *TheCall = new (Context) - CXXOperatorCallExpr(Context, OO_Call, NewFn.get(), MethodArgs, ResultTy, - VK, RParenLoc, FPOptions()); - - if (CheckCallReturnType(Method->getReturnType(), LParenLoc, TheCall, Method)) - return true; - - // We may have default arguments. If so, we need to allocate more - // slots in the call for them. - if (Args.size() < NumParams) - TheCall->setNumArgs(Context, NumParams + 1); + SmallVector<Expr *, 8> MethodArgs(NumArgsSlots); bool IsError = false; @@ -13300,7 +13329,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, IsError = true; else Object = ObjRes; - TheCall->setArg(0, Object.get()); + MethodArgs[0] = Object.get(); // Check the argument types. for (unsigned i = 0; i != NumParams; i++) { @@ -13329,7 +13358,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, Arg = DefArg.getAs<Expr>(); } - TheCall->setArg(i + 1, Arg); + MethodArgs[i + 1] = Arg; } // If this is a variadic call, handle args passed through "...". @@ -13339,14 +13368,27 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, nullptr); IsError |= Arg.isInvalid(); - TheCall->setArg(i + 1, Arg.get()); + MethodArgs[i + 1] = Arg.get(); } } - if (IsError) return true; + if (IsError) + return true; DiagnoseSentinelCalls(Method, LParenLoc, Args); + // Once we've built TheCall, all of the expressions are properly owned. + QualType ResultTy = Method->getReturnType(); + ExprValueKind VK = Expr::getValueKindForType(ResultTy); + ResultTy = ResultTy.getNonLValueExprType(Context); + + CXXOperatorCallExpr *TheCall = + CXXOperatorCallExpr::Create(Context, OO_Call, NewFn.get(), MethodArgs, + ResultTy, VK, RParenLoc, FPOptions()); + + if (CheckCallReturnType(Method->getReturnType(), LParenLoc, TheCall, Method)) + return true; + if (CheckFunctionCall(Method, TheCall, Proto)) return true; @@ -13458,9 +13500,8 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, QualType ResultTy = Method->getReturnType(); ExprValueKind VK = Expr::getValueKindForType(ResultTy); ResultTy = ResultTy.getNonLValueExprType(Context); - CXXOperatorCallExpr *TheCall = - new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr.get(), - Base, ResultTy, VK, OpLoc, FPOptions()); + CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create( + Context, OO_Arrow, FnExpr.get(), Base, ResultTy, VK, OpLoc, FPOptions()); if (CheckCallReturnType(Method->getReturnType(), OpLoc, TheCall, Method)) return ExprError(); @@ -13532,10 +13573,9 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R, ExprValueKind VK = Expr::getValueKindForType(ResultTy); ResultTy = ResultTy.getNonLValueExprType(Context); - UserDefinedLiteral *UDL = - new (Context) UserDefinedLiteral(Context, Fn.get(), - llvm::makeArrayRef(ConvArgs, Args.size()), - ResultTy, VK, LitEndLoc, UDSuffixLoc); + UserDefinedLiteral *UDL = UserDefinedLiteral::Create( + Context, Fn.get(), llvm::makeArrayRef(ConvArgs, Args.size()), ResultTy, + VK, LitEndLoc, UDSuffixLoc); if (CheckCallReturnType(FD->getReturnType(), UDSuffixLoc, UDL, FD)) return ExprError(); @@ -13596,7 +13636,7 @@ Sema::BuildForRangeBeginEndCall(SourceLocation Loc, } OverloadCandidateSet::iterator Best; OverloadingResult OverloadResult = - CandidateSet->BestViableFunction(*this, Fn->getLocStart(), Best); + CandidateSet->BestViableFunction(*this, Fn->getBeginLoc(), Best); if (OverloadResult == OR_No_Viable_Function) { *CallExpr = ExprError(); diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp index a8af75d87c8d4..ebf1d10aa16a3 100644 --- a/lib/Sema/SemaPseudoObject.cpp +++ b/lib/Sema/SemaPseudoObject.cpp @@ -977,7 +977,7 @@ ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) { if (isWeakProperty() && !S.isUnevaluatedContext() && !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, - SyntacticForm->getLocStart())) + SyntacticForm->getBeginLoc())) S.getCurFunction()->recordUseOfWeak(SyntacticRefExpr, SyntacticRefExpr->isMessagingGetter()); diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 377e2c4dfa23f..9e30c9a396c0a 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -42,12 +42,11 @@ using namespace clang; using namespace sema; -StmtResult Sema::ActOnExprStmt(ExprResult FE) { +StmtResult Sema::ActOnExprStmt(ExprResult FE, bool DiscardedValue) { if (FE.isInvalid()) return StmtError(); - FE = ActOnFinishFullExpr(FE.get(), FE.get()->getExprLoc(), - /*DiscardedValue*/ true); + FE = ActOnFinishFullExpr(FE.get(), FE.get()->getExprLoc(), DiscardedValue); if (FE.isInvalid()) return StmtError(); @@ -246,7 +245,7 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { // we might want to make a more specific diagnostic. Check for one of these // cases now. unsigned DiagID = diag::warn_unused_expr; - if (const ExprWithCleanups *Temps = dyn_cast<ExprWithCleanups>(E)) + if (const FullExpr *Temps = dyn_cast<FullExpr>(E)) E = Temps->getSubExpr(); if (const CXXBindTemporaryExpr *TempExpr = dyn_cast<CXXBindTemporaryExpr>(E)) E = TempExpr->getSubExpr(); @@ -259,17 +258,16 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { if (E->getType()->isVoidType()) return; + if (const Attr *A = CE->getUnusedResultAttr(Context)) { + Diag(Loc, diag::warn_unused_result) << A << R1 << R2; + return; + } + // If the callee has attribute pure, const, or warn_unused_result, warn with // a more specific message to make it clear what is happening. If the call // is written in a macro body, only warn if it has the warn_unused_result // attribute. if (const Decl *FD = CE->getCalleeDecl()) { - if (const Attr *A = isa<FunctionDecl>(FD) - ? cast<FunctionDecl>(FD)->getUnusedResultAttr() - : FD->getAttr<WarnUnusedResultAttr>()) { - Diag(Loc, diag::warn_unused_result) << A << R1 << R2; - return; - } if (ShouldSuppress) return; if (FD->hasAttr<PureAttr>()) { @@ -349,6 +347,10 @@ sema::CompoundScopeInfo &Sema::getCurCompoundScope() const { return getCurFunction()->CompoundScopes.back(); } +bool Sema::isCurCompoundStmtAStmtExpr() const { + return getCurCompoundScope().IsStmtExpr; +} + StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef<Stmt *> Elts, bool isStmtExpr) { const unsigned NumElts = Elts.size(); @@ -371,14 +373,6 @@ StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, Diag(D->getLocation(), diag::ext_mixed_decls_code); } } - // Warn about unused expressions in statements. - for (unsigned i = 0; i != NumElts; ++i) { - // Ignore statements that are last in a statement expression. - if (isStmtExpr && i == NumElts - 1) - continue; - - DiagnoseUnusedExprResult(Elts[i]); - } // Check for suspicious empty body (null statement) in `for' and `while' // statements. Don't do anything for template instantiations, this just adds @@ -462,25 +456,20 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, ExprResult LHSVal, return StmtError(); } - CaseStmt *CS = new (Context) - CaseStmt(LHSVal.get(), RHSVal.get(), CaseLoc, DotDotDotLoc, ColonLoc); + auto *CS = CaseStmt::Create(Context, LHSVal.get(), RHSVal.get(), + CaseLoc, DotDotDotLoc, ColonLoc); getCurFunction()->SwitchStack.back().getPointer()->addSwitchCase(CS); return CS; } /// ActOnCaseStmtBody - This installs a statement as the body of a case. -void Sema::ActOnCaseStmtBody(Stmt *caseStmt, Stmt *SubStmt) { - DiagnoseUnusedExprResult(SubStmt); - - CaseStmt *CS = static_cast<CaseStmt*>(caseStmt); - CS->setSubStmt(SubStmt); +void Sema::ActOnCaseStmtBody(Stmt *S, Stmt *SubStmt) { + cast<CaseStmt>(S)->setSubStmt(SubStmt); } StmtResult Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc, Stmt *SubStmt, Scope *CurScope) { - DiagnoseUnusedExprResult(SubStmt); - if (getCurFunction()->SwitchStack.empty()) { Diag(DefaultLoc, diag::err_default_not_in_switch); return SubStmt; @@ -551,12 +540,13 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr, Stmt *InitStmt, false); Expr *CondExpr = Cond.get().second; - if (!Diags.isIgnored(diag::warn_comma_operator, - CondExpr->getExprLoc())) + // Only call the CommaVisitor when not C89 due to differences in scope flags. + if ((getLangOpts().C99 || getLangOpts().CPlusPlus) && + !Diags.isIgnored(diag::warn_comma_operator, CondExpr->getExprLoc())) CommaVisitor(*this).Visit(CondExpr); if (!elseStmt) - DiagnoseEmptyStmtBody(CondExpr->getLocEnd(), thenStmt, + DiagnoseEmptyStmtBody(CondExpr->getEndLoc(), thenStmt, diag::warn_empty_if_body); return BuildIfStmt(IfLoc, IsConstexpr, InitStmt, Cond, thenStmt, ElseLoc, @@ -573,12 +563,8 @@ StmtResult Sema::BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr, if (IsConstexpr || isa<ObjCAvailabilityCheckExpr>(Cond.get().second)) setFunctionHasBranchProtectedScope(); - DiagnoseUnusedExprResult(thenStmt); - DiagnoseUnusedExprResult(elseStmt); - - return new (Context) - IfStmt(Context, IfLoc, IsConstexpr, InitStmt, Cond.get().first, - Cond.get().second, thenStmt, ElseLoc, elseStmt); + return IfStmt::Create(Context, IfLoc, IsConstexpr, InitStmt, Cond.get().first, + Cond.get().second, thenStmt, ElseLoc, elseStmt); } namespace { @@ -631,8 +617,8 @@ static bool EqEnumVals(const std::pair<llvm::APSInt, EnumConstantDecl*>& lhs, /// GetTypeBeforeIntegralPromotion - Returns the pre-promotion type of /// potentially integral-promoted expression @p expr. static QualType GetTypeBeforeIntegralPromotion(const Expr *&E) { - if (const auto *CleanUps = dyn_cast<ExprWithCleanups>(E)) - E = CleanUps->getSubExpr(); + if (const auto *FE = dyn_cast<FullExpr>(E)) + E = FE->getSubExpr(); while (const auto *ImpCast = dyn_cast<ImplicitCastExpr>(E)) { if (ImpCast->getCastKind() != CK_IntegralCast) break; E = ImpCast->getSubExpr(); @@ -727,8 +713,7 @@ StmtResult Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, setFunctionHasBranchIntoScope(); - SwitchStmt *SS = new (Context) - SwitchStmt(Context, InitStmt, Cond.get().first, CondExpr); + auto *SS = SwitchStmt::Create(Context, InitStmt, Cond.get().first, CondExpr); getCurFunction()->SwitchStack.push_back( FunctionScopeInfo::SwitchInfo(SS, false)); return SS; @@ -918,8 +903,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, // Check the unconverted value is within the range of possible values of // the switch expression. - checkCaseValue(*this, Lo->getLocStart(), LoVal, - CondWidthBeforePromotion, CondIsSignedBeforePromotion); + checkCaseValue(*this, Lo->getBeginLoc(), LoVal, CondWidthBeforePromotion, + CondIsSignedBeforePromotion); // FIXME: This duplicates the check performed for warn_not_in_enum below. checkEnumTypesInSwitchStmt(*this, CondExprBeforePromotion, @@ -946,8 +931,11 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, llvm::APSInt ConstantCondValue; bool HasConstantCond = false; if (!HasDependentValue && !TheDefaultStmt) { - HasConstantCond = CondExpr->EvaluateAsInt(ConstantCondValue, Context, + Expr::EvalResult Result; + HasConstantCond = CondExpr->EvaluateAsInt(Result, Context, Expr::SE_AllowSideEffects); + if (Result.Val.isInt()) + ConstantCondValue = Result.Val.getInt(); assert(!HasConstantCond || (ConstantCondValue.getBitWidth() == CondWidth && ConstantCondValue.isSigned() == CondIsSigned)); @@ -979,17 +967,17 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, CaseVals[i-1].first.toString(CaseValStr); if (PrevString == CurrString) - Diag(CaseVals[i].second->getLHS()->getLocStart(), - diag::err_duplicate_case) << - (PrevString.empty() ? StringRef(CaseValStr) : PrevString); + Diag(CaseVals[i].second->getLHS()->getBeginLoc(), + diag::err_duplicate_case) + << (PrevString.empty() ? StringRef(CaseValStr) : PrevString); else - Diag(CaseVals[i].second->getLHS()->getLocStart(), - diag::err_duplicate_case_differing_expr) << - (PrevString.empty() ? StringRef(CaseValStr) : PrevString) << - (CurrString.empty() ? StringRef(CaseValStr) : CurrString) << - CaseValStr; + Diag(CaseVals[i].second->getLHS()->getBeginLoc(), + diag::err_duplicate_case_differing_expr) + << (PrevString.empty() ? StringRef(CaseValStr) : PrevString) + << (CurrString.empty() ? StringRef(CaseValStr) : CurrString) + << CaseValStr; - Diag(CaseVals[i-1].second->getLHS()->getLocStart(), + Diag(CaseVals[i - 1].second->getLHS()->getBeginLoc(), diag::note_duplicate_case_prev); // FIXME: We really want to remove the bogus case stmt from the // substmt, but we have no way to do this right now. @@ -1018,7 +1006,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, // Check the unconverted value is within the range of possible values of // the switch expression. - checkCaseValue(*this, Hi->getLocStart(), HiVal, + checkCaseValue(*this, Hi->getBeginLoc(), HiVal, CondWidthBeforePromotion, CondIsSignedBeforePromotion); // Convert the value to the same width/sign as the condition. @@ -1026,9 +1014,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, // If the low value is bigger than the high value, the case is empty. if (LoVal > HiVal) { - Diag(CR->getLHS()->getLocStart(), diag::warn_case_empty_range) - << SourceRange(CR->getLHS()->getLocStart(), - Hi->getLocEnd()); + Diag(CR->getLHS()->getBeginLoc(), diag::warn_case_empty_range) + << SourceRange(CR->getLHS()->getBeginLoc(), Hi->getEndLoc()); CaseRanges.erase(CaseRanges.begin()+i); --i; --e; @@ -1082,9 +1069,9 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, if (OverlapStmt) { // If we have a duplicate, report it. - Diag(CR->getLHS()->getLocStart(), diag::err_duplicate_case) - << OverlapVal.toString(10); - Diag(OverlapStmt->getLHS()->getLocStart(), + Diag(CR->getLHS()->getBeginLoc(), diag::err_duplicate_case) + << OverlapVal.toString(10); + Diag(OverlapStmt->getLHS()->getBeginLoc(), diag::note_duplicate_case_prev); // FIXME: We really want to remove the bogus case stmt from the // substmt, but we have no way to do this right now. @@ -1165,7 +1152,21 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, SmallVector<DeclarationName,8> UnhandledNames; - for (EI = EnumVals.begin(); EI != EIEnd; EI++){ + for (EI = EnumVals.begin(); EI != EIEnd; EI++) { + // Don't warn about omitted unavailable EnumConstantDecls. + switch (EI->second->getAvailability()) { + case AR_Deprecated: + // Omitting a deprecated constant is ok; it should never materialize. + case AR_Unavailable: + continue; + + case AR_NotYetIntroduced: + // Partially available enum constants should be present. Note that we + // suppress -Wunguarded-availability diagnostics for such uses. + case AR_Available: + break; + } + // Drop unneeded case values while (CI != CaseVals.end() && CI->first < EI->first) CI++; @@ -1209,7 +1210,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, } if (BodyStmt) - DiagnoseEmptyStmtBody(CondExpr->getLocEnd(), BodyStmt, + DiagnoseEmptyStmtBody(CondExpr->getEndLoc(), BodyStmt, diag::warn_empty_switch_body); // FIXME: If the case list was broken is some way, we don't have a good system @@ -1289,13 +1290,11 @@ StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc, ConditionResult Cond, !Diags.isIgnored(diag::warn_comma_operator, CondVal.second->getExprLoc())) CommaVisitor(*this).Visit(CondVal.second); - DiagnoseUnusedExprResult(Body); - if (isa<NullStmt>(Body)) getCurCompoundScope().setHasEmptyLoopBodies(); - return new (Context) - WhileStmt(Context, CondVal.first, CondVal.second, Body, WhileLoc); + return WhileStmt::Create(Context, CondVal.first, CondVal.second, Body, + WhileLoc); } StmtResult @@ -1310,12 +1309,15 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, return StmtError(); Cond = CondResult.get(); - CondResult = ActOnFinishFullExpr(Cond, DoLoc); + CondResult = ActOnFinishFullExpr(Cond, DoLoc, /*DiscardedValue*/ false); if (CondResult.isInvalid()) return StmtError(); Cond = CondResult.get(); - DiagnoseUnusedExprResult(Body); + // Only call the CommaVisitor for C89 due to differences in scope flags. + if (Cond && !getLangOpts().C99 && !getLangOpts().CPlusPlus && + !Diags.isIgnored(diag::warn_comma_operator, Cond->getExprLoc())) + CommaVisitor(*this).Visit(Cond); return new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen); } @@ -1396,7 +1398,11 @@ namespace { void VisitDeclRefExpr(DeclRefExpr *E) { VarDecl *VD = dyn_cast<VarDecl>(E->getDecl()); - if (!VD) return; + if (!VD) { + // Don't allow unhandled Decl types. + Simple = false; + return; + } Ranges.push_back(E->getSourceRange()); @@ -1492,7 +1498,7 @@ namespace { if (!Second) return; if (S.Diags.isIgnored(diag::warn_variables_not_in_loop_body, - Second->getLocStart())) + Second->getBeginLoc())) return; PartialDiagnostic PDiag = S.PDiag(diag::warn_variables_not_in_loop_body); @@ -1634,6 +1640,8 @@ namespace { void VisitCXXForRangeStmt(const CXXForRangeStmt *S) { // Only visit the initialization of a for loop; the body // has a different break/continue scope. + if (const Stmt *Init = S->getInit()) + Visit(Init); if (const Stmt *Range = S->getRangeStmt()) Visit(Range); if (const Stmt *Begin = S->getBeginStmt()) @@ -1668,7 +1676,7 @@ namespace { if (!Body || !Third) return; if (S.Diags.isIgnored(diag::warn_redundant_loop_iteration, - Third->getLocStart())) + Third->getBeginLoc())) return; // Get the last statement from the loop body. @@ -1755,11 +1763,6 @@ StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, CommaVisitor(*this).Visit(Second.get().second); Expr *Third = third.release().getAs<Expr>(); - - DiagnoseUnusedExprResult(First); - DiagnoseUnusedExprResult(Third); - DiagnoseUnusedExprResult(Body); - if (isa<NullStmt>(Body)) getCurCompoundScope().setHasEmptyLoopBodies(); @@ -1779,7 +1782,7 @@ StmtResult Sema::ActOnForEachLValueExpr(Expr *E) { if (result.isInvalid()) return StmtError(); E = result.get(); - ExprResult FullExpr = ActOnFinishFullExpr(E); + ExprResult FullExpr = ActOnFinishFullExpr(E, /*DiscardedValue*/ false); if (FullExpr.isInvalid()) return StmtError(); return StmtResult(static_cast<Stmt*>(FullExpr.get())); @@ -1914,9 +1917,9 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, } else { Expr *FirstE = cast<Expr>(First); if (!FirstE->isTypeDependent() && !FirstE->isLValue()) - return StmtError(Diag(First->getLocStart(), - diag::err_selector_element_not_lvalue) - << First->getSourceRange()); + return StmtError( + Diag(First->getBeginLoc(), diag::err_selector_element_not_lvalue) + << First->getSourceRange()); FirstType = static_cast<Expr*>(First)->getType(); if (FirstType.isConstQualified()) @@ -1933,7 +1936,8 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, if (CollectionExprResult.isInvalid()) return StmtError(); - CollectionExprResult = ActOnFinishFullExpr(CollectionExprResult.get()); + CollectionExprResult = + ActOnFinishFullExpr(CollectionExprResult.get(), /*DiscardedValue*/ false); if (CollectionExprResult.isInvalid()) return StmtError(); @@ -2052,21 +2056,26 @@ static bool ObjCEnumerationCollection(Expr *Collection) { /// The body of the loop is not available yet, since it cannot be analysed until /// we have determined the type of the for-range-declaration. StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc, - SourceLocation CoawaitLoc, Stmt *First, - SourceLocation ColonLoc, Expr *Range, - SourceLocation RParenLoc, + SourceLocation CoawaitLoc, Stmt *InitStmt, + Stmt *First, SourceLocation ColonLoc, + Expr *Range, SourceLocation RParenLoc, BuildForRangeKind Kind) { if (!First) return StmtError(); - if (Range && ObjCEnumerationCollection(Range)) + if (Range && ObjCEnumerationCollection(Range)) { + // FIXME: Support init-statements in Objective-C++20 ranged for statement. + if (InitStmt) + return Diag(InitStmt->getBeginLoc(), diag::err_objc_for_range_init_stmt) + << InitStmt->getSourceRange(); return ActOnObjCForCollectionStmt(ForLoc, First, Range, RParenLoc); + } DeclStmt *DS = dyn_cast<DeclStmt>(First); assert(DS && "first part of for range not a decl stmt"); if (!DS->isSingleDecl()) { - Diag(DS->getStartLoc(), diag::err_type_defined_in_for_range); + Diag(DS->getBeginLoc(), diag::err_type_defined_in_for_range); return StmtError(); } @@ -2087,7 +2096,7 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc, // Build auto && __range = range-init // Divide by 2, since the variables are in the inner scope (loop body). const auto DepthStr = std::to_string(S->getDepth() / 2); - SourceLocation RangeLoc = Range->getLocStart(); + SourceLocation RangeLoc = Range->getBeginLoc(); VarDecl *RangeVar = BuildForRangeVarDecl(*this, RangeLoc, Context.getAutoRRefDeductType(), std::string("__range") + DepthStr); @@ -2106,10 +2115,10 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc, return StmtError(); } - return BuildCXXForRangeStmt(ForLoc, CoawaitLoc, ColonLoc, RangeDecl.get(), - /*BeginStmt=*/nullptr, /*EndStmt=*/nullptr, - /*Cond=*/nullptr, /*Inc=*/nullptr, - DS, RParenLoc, Kind); + return BuildCXXForRangeStmt( + ForLoc, CoawaitLoc, InitStmt, ColonLoc, RangeDecl.get(), + /*BeginStmt=*/nullptr, /*EndStmt=*/nullptr, + /*Cond=*/nullptr, /*Inc=*/nullptr, DS, RParenLoc, Kind); } /// Create the initialization, compare, and increment steps for @@ -2136,6 +2145,56 @@ BuildNonArrayForRange(Sema &SemaRef, Expr *BeginRange, Expr *EndRange, Sema::LookupMemberName); LookupResult EndMemberLookup(SemaRef, EndNameInfo, Sema::LookupMemberName); + auto BuildBegin = [&] { + *BEF = BEF_begin; + Sema::ForRangeStatus RangeStatus = + SemaRef.BuildForRangeBeginEndCall(ColonLoc, ColonLoc, BeginNameInfo, + BeginMemberLookup, CandidateSet, + BeginRange, BeginExpr); + + if (RangeStatus != Sema::FRS_Success) { + if (RangeStatus == Sema::FRS_DiagnosticIssued) + SemaRef.Diag(BeginRange->getBeginLoc(), diag::note_in_for_range) + << ColonLoc << BEF_begin << BeginRange->getType(); + return RangeStatus; + } + if (!CoawaitLoc.isInvalid()) { + // FIXME: getCurScope() should not be used during template instantiation. + // We should pick up the set of unqualified lookup results for operator + // co_await during the initial parse. + *BeginExpr = SemaRef.ActOnCoawaitExpr(SemaRef.getCurScope(), ColonLoc, + BeginExpr->get()); + if (BeginExpr->isInvalid()) + return Sema::FRS_DiagnosticIssued; + } + if (FinishForRangeVarDecl(SemaRef, BeginVar, BeginExpr->get(), ColonLoc, + diag::err_for_range_iter_deduction_failure)) { + NoteForRangeBeginEndFunction(SemaRef, BeginExpr->get(), *BEF); + return Sema::FRS_DiagnosticIssued; + } + return Sema::FRS_Success; + }; + + auto BuildEnd = [&] { + *BEF = BEF_end; + Sema::ForRangeStatus RangeStatus = + SemaRef.BuildForRangeBeginEndCall(ColonLoc, ColonLoc, EndNameInfo, + EndMemberLookup, CandidateSet, + EndRange, EndExpr); + if (RangeStatus != Sema::FRS_Success) { + if (RangeStatus == Sema::FRS_DiagnosticIssued) + SemaRef.Diag(EndRange->getBeginLoc(), diag::note_in_for_range) + << ColonLoc << BEF_end << EndRange->getType(); + return RangeStatus; + } + if (FinishForRangeVarDecl(SemaRef, EndVar, EndExpr->get(), ColonLoc, + diag::err_for_range_iter_deduction_failure)) { + NoteForRangeBeginEndFunction(SemaRef, EndExpr->get(), *BEF); + return Sema::FRS_DiagnosticIssued; + } + return Sema::FRS_Success; + }; + if (CXXRecordDecl *D = RangeType->getAsCXXRecordDecl()) { // - if _RangeT is a class type, the unqualified-ids begin and end are // looked up in the scope of class _RangeT as if by class member access @@ -2143,68 +2202,62 @@ BuildNonArrayForRange(Sema &SemaRef, Expr *BeginRange, Expr *EndRange, // declaration, begin-expr and end-expr are __range.begin() and // __range.end(), respectively; SemaRef.LookupQualifiedName(BeginMemberLookup, D); + if (BeginMemberLookup.isAmbiguous()) + return Sema::FRS_DiagnosticIssued; + SemaRef.LookupQualifiedName(EndMemberLookup, D); + if (EndMemberLookup.isAmbiguous()) + return Sema::FRS_DiagnosticIssued; if (BeginMemberLookup.empty() != EndMemberLookup.empty()) { - SourceLocation RangeLoc = BeginVar->getLocation(); - *BEF = BeginMemberLookup.empty() ? BEF_end : BEF_begin; - - SemaRef.Diag(RangeLoc, diag::err_for_range_member_begin_end_mismatch) - << RangeLoc << BeginRange->getType() << *BEF; - return Sema::FRS_DiagnosticIssued; + // Look up the non-member form of the member we didn't find, first. + // This way we prefer a "no viable 'end'" diagnostic over a "i found + // a 'begin' but ignored it because there was no member 'end'" + // diagnostic. + auto BuildNonmember = [&]( + BeginEndFunction BEFFound, LookupResult &Found, + llvm::function_ref<Sema::ForRangeStatus()> BuildFound, + llvm::function_ref<Sema::ForRangeStatus()> BuildNotFound) { + LookupResult OldFound = std::move(Found); + Found.clear(); + + if (Sema::ForRangeStatus Result = BuildNotFound()) + return Result; + + switch (BuildFound()) { + case Sema::FRS_Success: + return Sema::FRS_Success; + + case Sema::FRS_NoViableFunction: + SemaRef.Diag(BeginRange->getBeginLoc(), diag::err_for_range_invalid) + << BeginRange->getType() << BEFFound; + CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, BeginRange); + LLVM_FALLTHROUGH; + + case Sema::FRS_DiagnosticIssued: + for (NamedDecl *D : OldFound) { + SemaRef.Diag(D->getLocation(), + diag::note_for_range_member_begin_end_ignored) + << BeginRange->getType() << BEFFound; + } + return Sema::FRS_DiagnosticIssued; + } + llvm_unreachable("unexpected ForRangeStatus"); + }; + if (BeginMemberLookup.empty()) + return BuildNonmember(BEF_end, EndMemberLookup, BuildEnd, BuildBegin); + return BuildNonmember(BEF_begin, BeginMemberLookup, BuildBegin, BuildEnd); } } else { // - otherwise, begin-expr and end-expr are begin(__range) and // end(__range), respectively, where begin and end are looked up with // argument-dependent lookup (3.4.2). For the purposes of this name // lookup, namespace std is an associated namespace. - - } - - *BEF = BEF_begin; - Sema::ForRangeStatus RangeStatus = - SemaRef.BuildForRangeBeginEndCall(ColonLoc, ColonLoc, BeginNameInfo, - BeginMemberLookup, CandidateSet, - BeginRange, BeginExpr); - - if (RangeStatus != Sema::FRS_Success) { - if (RangeStatus == Sema::FRS_DiagnosticIssued) - SemaRef.Diag(BeginRange->getLocStart(), diag::note_in_for_range) - << ColonLoc << BEF_begin << BeginRange->getType(); - return RangeStatus; - } - if (!CoawaitLoc.isInvalid()) { - // FIXME: getCurScope() should not be used during template instantiation. - // We should pick up the set of unqualified lookup results for operator - // co_await during the initial parse. - *BeginExpr = SemaRef.ActOnCoawaitExpr(SemaRef.getCurScope(), ColonLoc, - BeginExpr->get()); - if (BeginExpr->isInvalid()) - return Sema::FRS_DiagnosticIssued; - } - if (FinishForRangeVarDecl(SemaRef, BeginVar, BeginExpr->get(), ColonLoc, - diag::err_for_range_iter_deduction_failure)) { - NoteForRangeBeginEndFunction(SemaRef, BeginExpr->get(), *BEF); - return Sema::FRS_DiagnosticIssued; } - *BEF = BEF_end; - RangeStatus = - SemaRef.BuildForRangeBeginEndCall(ColonLoc, ColonLoc, EndNameInfo, - EndMemberLookup, CandidateSet, - EndRange, EndExpr); - if (RangeStatus != Sema::FRS_Success) { - if (RangeStatus == Sema::FRS_DiagnosticIssued) - SemaRef.Diag(EndRange->getLocStart(), diag::note_in_for_range) - << ColonLoc << BEF_end << EndRange->getType(); - return RangeStatus; - } - if (FinishForRangeVarDecl(SemaRef, EndVar, EndExpr->get(), ColonLoc, - diag::err_for_range_iter_deduction_failure)) { - NoteForRangeBeginEndFunction(SemaRef, EndExpr->get(), *BEF); - return Sema::FRS_DiagnosticIssued; - } - return Sema::FRS_Success; + if (Sema::ForRangeStatus Result = BuildBegin()) + return Result; + return BuildEnd(); } /// Speculatively attempt to dereference an invalid range expression. @@ -2213,6 +2266,7 @@ BuildNonArrayForRange(Sema &SemaRef, Expr *BeginRange, Expr *EndRange, static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S, SourceLocation ForLoc, SourceLocation CoawaitLoc, + Stmt *InitStmt, Stmt *LoopVarDecl, SourceLocation ColonLoc, Expr *Range, @@ -2229,8 +2283,8 @@ static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S, return StmtResult(); StmtResult SR = SemaRef.ActOnCXXForRangeStmt( - S, ForLoc, CoawaitLoc, LoopVarDecl, ColonLoc, AdjustedRange.get(), - RParenLoc, Sema::BFRK_Check); + S, ForLoc, CoawaitLoc, InitStmt, LoopVarDecl, ColonLoc, + AdjustedRange.get(), RParenLoc, Sema::BFRK_Check); if (SR.isInvalid()) return StmtResult(); } @@ -2240,9 +2294,9 @@ static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S, // case there are any other (non-fatal) problems with it. SemaRef.Diag(RangeLoc, diag::err_for_range_dereference) << Range->getType() << FixItHint::CreateInsertion(RangeLoc, "*"); - return SemaRef.ActOnCXXForRangeStmt(S, ForLoc, CoawaitLoc, LoopVarDecl, - ColonLoc, AdjustedRange.get(), RParenLoc, - Sema::BFRK_Rebuild); + return SemaRef.ActOnCXXForRangeStmt( + S, ForLoc, CoawaitLoc, InitStmt, LoopVarDecl, ColonLoc, + AdjustedRange.get(), RParenLoc, Sema::BFRK_Rebuild); } namespace { @@ -2262,12 +2316,13 @@ struct InvalidateOnErrorScope { } /// BuildCXXForRangeStmt - Build or instantiate a C++11 for-range statement. -StmtResult -Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc, - SourceLocation ColonLoc, Stmt *RangeDecl, - Stmt *Begin, Stmt *End, Expr *Cond, - Expr *Inc, Stmt *LoopVarDecl, - SourceLocation RParenLoc, BuildForRangeKind Kind) { +StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, + SourceLocation CoawaitLoc, Stmt *InitStmt, + SourceLocation ColonLoc, Stmt *RangeDecl, + Stmt *Begin, Stmt *End, Expr *Cond, + Expr *Inc, Stmt *LoopVarDecl, + SourceLocation RParenLoc, + BuildForRangeKind Kind) { // FIXME: This should not be used during template instantiation. We should // pick up the set of unqualified lookup results for the != and + operators // in the initial parse. @@ -2451,8 +2506,8 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc, QualType ArrayTy = PVD->getOriginalType(); QualType PointerTy = PVD->getType(); if (PointerTy->isPointerType() && ArrayTy->isArrayType()) { - Diag(Range->getLocStart(), diag::err_range_on_array_parameter) - << RangeLoc << PVD << ArrayTy << PointerTy; + Diag(Range->getBeginLoc(), diag::err_range_on_array_parameter) + << RangeLoc << PVD << ArrayTy << PointerTy; Diag(PVD->getLocation(), diag::note_declared_at); return StmtError(); } @@ -2462,7 +2517,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc, // If building the range failed, try dereferencing the range expression // unless a diagnostic was issued or the end function is problematic. StmtResult SR = RebuildForRangeWithDereference(*this, S, ForLoc, - CoawaitLoc, + CoawaitLoc, InitStmt, LoopVarDecl, ColonLoc, Range, RangeLoc, RParenLoc); @@ -2473,7 +2528,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc, // Otherwise, emit diagnostics if we haven't already. if (RangeStatus == FRS_NoViableFunction) { Expr *Range = BEFFailure ? EndRangeRef.get() : BeginRangeRef.get(); - Diag(Range->getLocStart(), diag::err_for_range_invalid) + Diag(Range->getBeginLoc(), diag::err_for_range_invalid) << RangeLoc << Range->getType() << BEFFailure; CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Range); } @@ -2519,7 +2574,8 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc, if (!NotEqExpr.isInvalid()) NotEqExpr = CheckBooleanCondition(ColonLoc, NotEqExpr.get()); if (!NotEqExpr.isInvalid()) - NotEqExpr = ActOnFinishFullExpr(NotEqExpr.get()); + NotEqExpr = + ActOnFinishFullExpr(NotEqExpr.get(), /*DiscardedValue*/ false); if (NotEqExpr.isInvalid()) { Diag(RangeLoc, diag::note_for_range_invalid_iterator) << RangeLoc << 0 << BeginRangeRef.get()->getType(); @@ -2542,7 +2598,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc, // co_await during the initial parse. IncrExpr = ActOnCoawaitExpr(S, CoawaitLoc, IncrExpr.get()); if (!IncrExpr.isInvalid()) - IncrExpr = ActOnFinishFullExpr(IncrExpr.get()); + IncrExpr = ActOnFinishFullExpr(IncrExpr.get(), /*DiscardedValue*/ false); if (IncrExpr.isInvalid()) { Diag(RangeLoc, diag::note_for_range_invalid_iterator) << RangeLoc << 2 << BeginRangeRef.get()->getType() ; @@ -2579,7 +2635,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc, return StmtResult(); return new (Context) CXXForRangeStmt( - RangeDS, cast_or_null<DeclStmt>(BeginDeclStmt.get()), + InitStmt, RangeDS, cast_or_null<DeclStmt>(BeginDeclStmt.get()), cast_or_null<DeclStmt>(EndDeclStmt.get()), NotEqExpr.get(), IncrExpr.get(), LoopVarDS, /*Body=*/nullptr, ForLoc, CoawaitLoc, ColonLoc, RParenLoc); @@ -2660,7 +2716,7 @@ static void DiagnoseForRangeReferenceVariableCopies(Sema &SemaRef, NonReferenceType.removeLocalConst(); QualType NewReferenceType = SemaRef.Context.getLValueReferenceType(E->getType().withConst()); - SemaRef.Diag(VD->getLocStart(), diag::note_use_type_or_non_reference) + SemaRef.Diag(VD->getBeginLoc(), diag::note_use_type_or_non_reference) << NonReferenceType << NewReferenceType << VD->getSourceRange(); } else { // The range always returns a copy, so a temporary is always created. @@ -2669,7 +2725,7 @@ static void DiagnoseForRangeReferenceVariableCopies(Sema &SemaRef, << VD << RangeInitType; QualType NonReferenceType = VariableType.getNonReferenceType(); NonReferenceType.removeLocalConst(); - SemaRef.Diag(VD->getLocStart(), diag::note_use_non_reference_type) + SemaRef.Diag(VD->getBeginLoc(), diag::note_use_non_reference_type) << NonReferenceType << VD->getSourceRange(); } } @@ -2705,7 +2761,7 @@ static void DiagnoseForRangeConstVariableCopies(Sema &SemaRef, // if doing so will prevent a copy. SemaRef.Diag(VD->getLocation(), diag::warn_for_range_copy) << VD << VariableType << InitExpr->getType(); - SemaRef.Diag(VD->getLocStart(), diag::note_use_reference_type) + SemaRef.Diag(VD->getBeginLoc(), diag::note_use_reference_type) << SemaRef.Context.getLValueReferenceType(VariableType) << VD->getSourceRange(); } @@ -2721,11 +2777,11 @@ static void DiagnoseForRangeConstVariableCopies(Sema &SemaRef, static void DiagnoseForRangeVariableCopies(Sema &SemaRef, const CXXForRangeStmt *ForStmt) { if (SemaRef.Diags.isIgnored(diag::warn_for_range_const_reference_copy, - ForStmt->getLocStart()) && + ForStmt->getBeginLoc()) && SemaRef.Diags.isIgnored(diag::warn_for_range_variable_always_copy, - ForStmt->getLocStart()) && + ForStmt->getBeginLoc()) && SemaRef.Diags.isIgnored(diag::warn_for_range_copy, - ForStmt->getLocStart())) { + ForStmt->getBeginLoc())) { return; } @@ -2797,7 +2853,7 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc, return StmtError(); } - ExprResult ExprRes = ActOnFinishFullExpr(E); + ExprResult ExprRes = ActOnFinishFullExpr(E, /*DiscardedValue*/ false); if (ExprRes.isInvalid()) return StmtError(); E = ExprRes.get(); @@ -2951,7 +3007,7 @@ static void TryMoveInitialization(Sema& S, Expr *InitExpr = &AsRvalue; InitializationKind Kind = InitializationKind::CreateCopy( - Value->getLocStart(), Value->getLocStart()); + Value->getBeginLoc(), Value->getBeginLoc()); InitializationSequence Seq(S, Entity, Kind, InitExpr); @@ -3147,12 +3203,14 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { ExpressionEvaluationContext::DiscardedStatement && (HasDeducedReturnType || CurCap->HasImplicitReturnType)) { if (RetValExp) { - ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); + ExprResult ER = + ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); } - return new (Context) ReturnStmt(ReturnLoc, RetValExp, nullptr); + return ReturnStmt::Create(Context, ReturnLoc, RetValExp, + /* NRVOCandidate=*/nullptr); } if (HasDeducedReturnType) { @@ -3273,13 +3331,14 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } if (RetValExp) { - ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); + ExprResult ER = + ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); } - ReturnStmt *Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, - NRVOCandidate); + auto *Result = + ReturnStmt::Create(Context, ReturnLoc, RetValExp, NRVOCandidate); // If we need to check for the named return value optimization, // or if we need to infer the return type, @@ -3503,12 +3562,14 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { ExpressionEvaluationContext::DiscardedStatement && FnRetType->getContainedAutoType()) { if (RetValExp) { - ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); + ExprResult ER = + ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); } - return new (Context) ReturnStmt(ReturnLoc, RetValExp, nullptr); + return ReturnStmt::Create(Context, ReturnLoc, RetValExp, + /* NRVOCandidate=*/nullptr); } // FIXME: Add a flag to the ScopeInfo to indicate whether we're performing @@ -3596,14 +3657,16 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } if (RetValExp) { - ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); + ExprResult ER = + ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); } } - Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, nullptr); + Result = ReturnStmt::Create(Context, ReturnLoc, RetValExp, + /* NRVOCandidate=*/nullptr); } else if (!RetValExp && !HasDependentReturnType) { FunctionDecl *FD = getCurFunctionDecl(); @@ -3625,7 +3688,8 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { else Diag(ReturnLoc, DiagID) << getCurMethodDecl()->getDeclName() << 1/*meth*/; - Result = new (Context) ReturnStmt(ReturnLoc); + Result = ReturnStmt::Create(Context, ReturnLoc, /* RetExpr=*/nullptr, + /* NRVOCandidate=*/nullptr); } else { assert(RetValExp || HasDependentReturnType); const VarDecl *NRVOCandidate = nullptr; @@ -3673,12 +3737,13 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } if (RetValExp) { - ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); + ExprResult ER = + ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); } - Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, NRVOCandidate); + Result = ReturnStmt::Create(Context, ReturnLoc, RetValExp, NRVOCandidate); } // If we need to check for the named return value optimization, save the @@ -3726,7 +3791,7 @@ StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) { if (Result.isInvalid()) return StmtError(); - Result = ActOnFinishFullExpr(Result.get()); + Result = ActOnFinishFullExpr(Result.get(), /*DiscardedValue*/ false); if (Result.isInvalid()) return StmtError(); Throw = Result.get(); @@ -3798,7 +3863,7 @@ Sema::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, Expr *operand) { } // The operand to @synchronized is a full-expression. - return ActOnFinishFullExpr(operand); + return ActOnFinishFullExpr(operand, /*DiscardedValue*/ false); } StmtResult @@ -3969,7 +4034,7 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, // declarations that are invalid, since we can't usefully report on them. if (!H->getExceptionDecl()) { if (i < NumHandlers - 1) - return StmtError(Diag(H->getLocStart(), diag::err_early_catch_all)); + return StmtError(Diag(H->getBeginLoc(), diag::err_early_catch_all)); continue; } else if (H->getExceptionDecl()->isInvalidDecl()) continue; diff --git a/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp index 0db15ea1f646a..9e084c99d0dd4 100644 --- a/lib/Sema/SemaStmtAsm.cpp +++ b/lib/Sema/SemaStmtAsm.cpp @@ -27,6 +27,58 @@ using namespace clang; using namespace sema; +/// Remove the upper-level LValueToRValue cast from an expression. +static void removeLValueToRValueCast(Expr *E) { + Expr *Parent = E; + Expr *ExprUnderCast = nullptr; + SmallVector<Expr *, 8> ParentsToUpdate; + + while (true) { + ParentsToUpdate.push_back(Parent); + if (auto *ParenE = dyn_cast<ParenExpr>(Parent)) { + Parent = ParenE->getSubExpr(); + continue; + } + + Expr *Child = nullptr; + CastExpr *ParentCast = dyn_cast<CastExpr>(Parent); + if (ParentCast) + Child = ParentCast->getSubExpr(); + else + return; + + if (auto *CastE = dyn_cast<CastExpr>(Child)) + if (CastE->getCastKind() == CK_LValueToRValue) { + ExprUnderCast = CastE->getSubExpr(); + // LValueToRValue cast inside GCCAsmStmt requires an explicit cast. + ParentCast->setSubExpr(ExprUnderCast); + break; + } + Parent = Child; + } + + // Update parent expressions to have same ValueType as the underlying. + assert(ExprUnderCast && + "Should be reachable only if LValueToRValue cast was found!"); + auto ValueKind = ExprUnderCast->getValueKind(); + for (Expr *E : ParentsToUpdate) + E->setValueKind(ValueKind); +} + +/// Emit a warning about usage of "noop"-like casts for lvalues (GNU extension) +/// and fix the argument with removing LValueToRValue cast from the expression. +static void emitAndFixInvalidAsmCastLValue(const Expr *LVal, Expr *BadArgument, + Sema &S) { + if (!S.getLangOpts().HeinousExtensions) { + S.Diag(LVal->getBeginLoc(), diag::err_invalid_asm_cast_lvalue) + << BadArgument->getSourceRange(); + } else { + S.Diag(LVal->getBeginLoc(), diag::warn_invalid_asm_cast_lvalue) + << BadArgument->getSourceRange(); + } + removeLValueToRValueCast(BadArgument); +} + /// CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently /// ignore "noop" casts in places where an lvalue is required by an inline asm. /// We emulate this behavior when -fheinous-gnu-extensions is specified, but @@ -34,7 +86,7 @@ using namespace sema; /// /// This method checks to see if the argument is an acceptable l-value and /// returns false if it is a case we can handle. -static bool CheckAsmLValue(const Expr *E, Sema &S) { +static bool CheckAsmLValue(Expr *E, Sema &S) { // Type dependent expressions will be checked during instantiation. if (E->isTypeDependent()) return false; @@ -46,12 +98,7 @@ static bool CheckAsmLValue(const Expr *E, Sema &S) { // are supposed to allow. const Expr *E2 = E->IgnoreParenNoopCasts(S.Context); if (E != E2 && E2->isLValue()) { - if (!S.getLangOpts().HeinousExtensions) - S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue) - << E->getSourceRange(); - else - S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue) - << E->getSourceRange(); + emitAndFixInvalidAsmCastLValue(E2, E, S); // Accept, even if we emitted an error diagnostic. return false; } @@ -90,13 +137,13 @@ static bool CheckNakedParmReference(Expr *E, Sema &S) { while (WorkList.size()) { Expr *E = WorkList.pop_back_val(); if (isa<CXXThisExpr>(E)) { - S.Diag(E->getLocStart(), diag::err_asm_naked_this_ref); + S.Diag(E->getBeginLoc(), diag::err_asm_naked_this_ref); S.Diag(Func->getAttr<NakedAttr>()->getLocation(), diag::note_attribute); return true; } if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { if (isa<ParmVarDecl>(DRE->getDecl())) { - S.Diag(DRE->getLocStart(), diag::err_asm_naked_parm_ref); + S.Diag(DRE->getBeginLoc(), diag::err_asm_naked_parm_ref); S.Diag(Func->getAttr<NakedAttr>()->getLocation(), diag::note_attribute); return true; } @@ -131,7 +178,7 @@ static bool checkExprMemoryConstraintCompat(Sema &S, Expr *E, EType = ExprGlobalRegVar; if (EType != ExprSafeType) { - S.Diag(E->getLocStart(), diag::err_asm_non_addr_value_in_memory_constraint) + S.Diag(E->getBeginLoc(), diag::err_asm_non_addr_value_in_memory_constraint) << EType << is_input_expr << Info.getConstraintStr() << E->getSourceRange(); return true; @@ -185,7 +232,7 @@ getClobberConflictLocation(MultiExprArg Exprs, StringLiteral **Constraints, Clobber = Target.getNormalizedGCCRegisterName(Clobber, true); // Go over the output's registers we collected if (InOutVars.count(Clobber)) - return Clobbers[i]->getLocStart(); + return Clobbers[i]->getBeginLoc(); } return SourceLocation(); } @@ -226,9 +273,9 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName); if (!Context.getTargetInfo().validateOutputConstraint(Info)) - return StmtError(Diag(Literal->getLocStart(), - diag::err_asm_invalid_output_constraint) - << Info.getConstraintStr()); + return StmtError( + Diag(Literal->getBeginLoc(), diag::err_asm_invalid_output_constraint) + << Info.getConstraintStr()); ExprResult ER = CheckPlaceholderExpr(Exprs[i]); if (ER.isInvalid()) @@ -264,24 +311,18 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, break; case Expr::MLV_LValueCast: { const Expr *LVal = OutputExpr->IgnoreParenNoopCasts(Context); - if (!getLangOpts().HeinousExtensions) { - Diag(LVal->getLocStart(), diag::err_invalid_asm_cast_lvalue) - << OutputExpr->getSourceRange(); - } else { - Diag(LVal->getLocStart(), diag::warn_invalid_asm_cast_lvalue) - << OutputExpr->getSourceRange(); - } + emitAndFixInvalidAsmCastLValue(LVal, OutputExpr, *this); // Accept, even if we emitted an error diagnostic. break; } case Expr::MLV_IncompleteType: case Expr::MLV_IncompleteVoidType: - if (RequireCompleteType(OutputExpr->getLocStart(), Exprs[i]->getType(), + if (RequireCompleteType(OutputExpr->getBeginLoc(), Exprs[i]->getType(), diag::err_dereference_incomplete_type)) return StmtError(); LLVM_FALLTHROUGH; default: - return StmtError(Diag(OutputExpr->getLocStart(), + return StmtError(Diag(OutputExpr->getBeginLoc(), diag::err_asm_invalid_lvalue_in_output) << OutputExpr->getSourceRange()); } @@ -289,9 +330,9 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, unsigned Size = Context.getTypeSize(OutputExpr->getType()); if (!Context.getTargetInfo().validateOutputSize(Literal->getString(), Size)) - return StmtError(Diag(OutputExpr->getLocStart(), - diag::err_asm_invalid_output_size) - << Info.getConstraintStr()); + return StmtError( + Diag(OutputExpr->getBeginLoc(), diag::err_asm_invalid_output_size) + << Info.getConstraintStr()); } SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos; @@ -307,9 +348,9 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, TargetInfo::ConstraintInfo Info(Literal->getString(), InputName); if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos, Info)) { - return StmtError(Diag(Literal->getLocStart(), - diag::err_asm_invalid_input_constraint) - << Info.getConstraintStr()); + return StmtError( + Diag(Literal->getBeginLoc(), diag::err_asm_invalid_input_constraint) + << Info.getConstraintStr()); } ExprResult ER = CheckPlaceholderExpr(Exprs[i]); @@ -331,22 +372,23 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, // Only allow void types for memory constraints. if (Info.allowsMemory() && !Info.allowsRegister()) { if (CheckAsmLValue(InputExpr, *this)) - return StmtError(Diag(InputExpr->getLocStart(), + return StmtError(Diag(InputExpr->getBeginLoc(), diag::err_asm_invalid_lvalue_in_input) << Info.getConstraintStr() << InputExpr->getSourceRange()); } else if (Info.requiresImmediateConstant() && !Info.allowsRegister()) { if (!InputExpr->isValueDependent()) { - llvm::APSInt Result; - if (!InputExpr->EvaluateAsInt(Result, Context)) - return StmtError( - Diag(InputExpr->getLocStart(), diag::err_asm_immediate_expected) - << Info.getConstraintStr() << InputExpr->getSourceRange()); - if (!Info.isValidAsmImmediate(Result)) - return StmtError(Diag(InputExpr->getLocStart(), - diag::err_invalid_asm_value_for_constraint) - << Result.toString(10) << Info.getConstraintStr() - << InputExpr->getSourceRange()); + Expr::EvalResult EVResult; + if (!InputExpr->EvaluateAsRValue(EVResult, Context, true)) + return StmtError( + Diag(InputExpr->getBeginLoc(), diag::err_asm_immediate_expected) + << Info.getConstraintStr() << InputExpr->getSourceRange()); + llvm::APSInt Result = EVResult.Val.getInt(); + if (!Info.isValidAsmImmediate(Result)) + return StmtError(Diag(InputExpr->getBeginLoc(), + diag::err_invalid_asm_value_for_constraint) + << Result.toString(10) << Info.getConstraintStr() + << InputExpr->getSourceRange()); } } else { @@ -359,10 +401,10 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, if (Info.allowsRegister()) { if (InputExpr->getType()->isVoidType()) { - return StmtError(Diag(InputExpr->getLocStart(), - diag::err_asm_invalid_type_in_input) - << InputExpr->getType() << Info.getConstraintStr() - << InputExpr->getSourceRange()); + return StmtError( + Diag(InputExpr->getBeginLoc(), diag::err_asm_invalid_type_in_input) + << InputExpr->getType() << Info.getConstraintStr() + << InputExpr->getSourceRange()); } } @@ -373,16 +415,16 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, continue; if (!Ty->isVoidType() || !Info.allowsMemory()) - if (RequireCompleteType(InputExpr->getLocStart(), Exprs[i]->getType(), + if (RequireCompleteType(InputExpr->getBeginLoc(), Exprs[i]->getType(), diag::err_dereference_incomplete_type)) return StmtError(); unsigned Size = Context.getTypeSize(Ty); if (!Context.getTargetInfo().validateInputSize(Literal->getString(), Size)) - return StmtError(Diag(InputExpr->getLocStart(), - diag::err_asm_invalid_input_size) - << Info.getConstraintStr()); + return StmtError( + Diag(InputExpr->getBeginLoc(), diag::err_asm_invalid_input_size) + << Info.getConstraintStr()); } // Check that the clobbers are valid. @@ -393,8 +435,9 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, StringRef Clobber = Literal->getString(); if (!Context.getTargetInfo().isValidClobber(Clobber)) - return StmtError(Diag(Literal->getLocStart(), - diag::err_asm_unknown_register_name) << Clobber); + return StmtError( + Diag(Literal->getBeginLoc(), diag::err_asm_unknown_register_name) + << Clobber); } GCCAsmStmt *NS = @@ -446,7 +489,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, if (!Context.getTargetInfo().validateConstraintModifier( Literal->getString(), Piece.getModifier(), Size, SuggestedModifier)) { - Diag(Exprs[ConstraintIdx]->getLocStart(), + Diag(Exprs[ConstraintIdx]->getBeginLoc(), diag::warn_asm_mismatched_size_modifier); if (!SuggestedModifier.empty()) { @@ -469,7 +512,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, if (NumAlternatives == ~0U) NumAlternatives = AltCount; else if (NumAlternatives != AltCount) - return StmtError(Diag(NS->getOutputExpr(i)->getLocStart(), + return StmtError(Diag(NS->getOutputExpr(i)->getBeginLoc(), diag::err_asm_unexpected_constraint_alternatives) << NumAlternatives << AltCount); } @@ -482,7 +525,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, if (NumAlternatives == ~0U) NumAlternatives = AltCount; else if (NumAlternatives != AltCount) - return StmtError(Diag(NS->getInputExpr(i)->getLocStart(), + return StmtError(Diag(NS->getInputExpr(i)->getBeginLoc(), diag::err_asm_unexpected_constraint_alternatives) << NumAlternatives << AltCount); @@ -499,10 +542,10 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, // Make sure no more than one input constraint matches each output. assert(TiedTo < InputMatchedToOutput.size() && "TiedTo value out of range"); if (InputMatchedToOutput[TiedTo] != ~0U) { - Diag(NS->getInputExpr(i)->getLocStart(), + Diag(NS->getInputExpr(i)->getBeginLoc(), diag::err_asm_input_duplicate_match) << TiedTo; - Diag(NS->getInputExpr(InputMatchedToOutput[TiedTo])->getLocStart(), + Diag(NS->getInputExpr(InputMatchedToOutput[TiedTo])->getBeginLoc(), diag::note_asm_input_duplicate_first) << TiedTo; return StmtError(); @@ -590,10 +633,9 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, continue; } - Diag(InputExpr->getLocStart(), - diag::err_asm_tying_incompatible_types) - << InTy << OutTy << OutputExpr->getSourceRange() - << InputExpr->getSourceRange(); + Diag(InputExpr->getBeginLoc(), diag::err_asm_tying_incompatible_types) + << InTy << OutTy << OutputExpr->getSourceRange() + << InputExpr->getSourceRange(); return StmtError(); } diff --git a/lib/Sema/SemaStmtAttr.cpp b/lib/Sema/SemaStmtAttr.cpp index e39a65c6ce0cf..a8e54b36b29b3 100644 --- a/lib/Sema/SemaStmtAttr.cpp +++ b/lib/Sema/SemaStmtAttr.cpp @@ -16,7 +16,6 @@ #include "clang/Basic/SourceManager.h" #include "clang/Sema/DelayedDiagnostic.h" #include "clang/Sema/Lookup.h" -#include "clang/Sema/LoopHint.h" #include "clang/Sema/ScopeInfo.h" #include "llvm/ADT/StringExtras.h" @@ -29,7 +28,7 @@ static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const ParsedAttr &A, A.getAttributeSpellingListIndex()); if (!isa<NullStmt>(St)) { S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_wrong_target) - << Attr.getSpelling() << St->getLocStart(); + << Attr.getSpelling() << St->getBeginLoc(); if (isa<SwitchCase>(St)) { SourceLocation L = S.getLocForEndOfToken(Range.getEnd()); S.Diag(L, diag::note_fallthrough_insert_semi_fixit) @@ -56,8 +55,7 @@ static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const ParsedAttr &A, static Attr *handleSuppressAttr(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range) { if (A.getNumArgs() < 1) { - S.Diag(A.getLoc(), diag::err_attribute_too_few_arguments) - << A.getName() << 1; + S.Diag(A.getLoc(), diag::err_attribute_too_few_arguments) << A << 1; return nullptr; } @@ -87,6 +85,9 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A, bool PragmaUnroll = PragmaNameLoc->Ident->getName() == "unroll"; bool PragmaNoUnroll = PragmaNameLoc->Ident->getName() == "nounroll"; + bool PragmaUnrollAndJam = PragmaNameLoc->Ident->getName() == "unroll_and_jam"; + bool PragmaNoUnrollAndJam = + PragmaNameLoc->Ident->getName() == "nounroll_and_jam"; if (St->getStmtClass() != Stmt::DoStmtClass && St->getStmtClass() != Stmt::ForStmtClass && St->getStmtClass() != Stmt::CXXForRangeStmtClass && @@ -95,8 +96,10 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A, llvm::StringSwitch<const char *>(PragmaNameLoc->Ident->getName()) .Case("unroll", "#pragma unroll") .Case("nounroll", "#pragma nounroll") + .Case("unroll_and_jam", "#pragma unroll_and_jam") + .Case("nounroll_and_jam", "#pragma nounroll_and_jam") .Default("#pragma clang loop"); - S.Diag(St->getLocStart(), diag::err_pragma_loop_precedes_nonloop) << Pragma; + S.Diag(St->getBeginLoc(), diag::err_pragma_loop_precedes_nonloop) << Pragma; return nullptr; } @@ -118,6 +121,20 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A, Option = LoopHintAttr::Unroll; State = LoopHintAttr::Enable; } + } else if (PragmaNoUnrollAndJam) { + // #pragma nounroll_and_jam + Option = LoopHintAttr::UnrollAndJam; + State = LoopHintAttr::Disable; + } else if (PragmaUnrollAndJam) { + if (ValueExpr) { + // #pragma unroll_and_jam N + Option = LoopHintAttr::UnrollAndJamCount; + State = LoopHintAttr::Numeric; + } else { + // #pragma unroll_and_jam + Option = LoopHintAttr::UnrollAndJam; + State = LoopHintAttr::Enable; + } } else { // #pragma clang loop ... assert(OptionLoc && OptionLoc->Ident && @@ -130,19 +147,24 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A, .Case("interleave_count", LoopHintAttr::InterleaveCount) .Case("unroll", LoopHintAttr::Unroll) .Case("unroll_count", LoopHintAttr::UnrollCount) + .Case("pipeline", LoopHintAttr::PipelineDisabled) + .Case("pipeline_initiation_interval", + LoopHintAttr::PipelineInitiationInterval) .Case("distribute", LoopHintAttr::Distribute) .Default(LoopHintAttr::Vectorize); if (Option == LoopHintAttr::VectorizeWidth || Option == LoopHintAttr::InterleaveCount || - Option == LoopHintAttr::UnrollCount) { + Option == LoopHintAttr::UnrollCount || + Option == LoopHintAttr::PipelineInitiationInterval) { assert(ValueExpr && "Attribute must have a valid value expression."); - if (S.CheckLoopHintExpr(ValueExpr, St->getLocStart())) + if (S.CheckLoopHintExpr(ValueExpr, St->getBeginLoc())) return nullptr; State = LoopHintAttr::Numeric; } else if (Option == LoopHintAttr::Vectorize || Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll || - Option == LoopHintAttr::Distribute) { + Option == LoopHintAttr::Distribute || + Option == LoopHintAttr::PipelineDisabled) { assert(StateLoc && StateLoc->Ident && "Loop hint must have an argument"); if (StateLoc->Ident->isStr("disable")) State = LoopHintAttr::Disable; @@ -165,21 +187,20 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A, static void CheckForIncompatibleAttributes(Sema &S, const SmallVectorImpl<const Attr *> &Attrs) { - // There are 4 categories of loop hints attributes: vectorize, interleave, - // unroll and distribute. Except for distribute they come in two variants: a - // state form and a numeric form. The state form selectively - // defaults/enables/disables the transformation for the loop (for unroll, - // default indicates full unrolling rather than enabling the transformation). - // The numeric form form provides an integer hint (for example, unroll count) - // to the transformer. The following array accumulates the hints encountered - // while iterating through the attributes to check for compatibility. + // There are 6 categories of loop hints attributes: vectorize, interleave, + // unroll, unroll_and_jam, pipeline and distribute. Except for distribute they + // come in two variants: a state form and a numeric form. The state form + // selectively defaults/enables/disables the transformation for the loop + // (for unroll, default indicates full unrolling rather than enabling the + // transformation). The numeric form form provides an integer hint (for + // example, unroll count) to the transformer. The following array accumulates + // the hints encountered while iterating through the attributes to check for + // compatibility. struct { const LoopHintAttr *StateAttr; const LoopHintAttr *NumericAttr; - } HintAttrs[] = {{nullptr, nullptr}, - {nullptr, nullptr}, - {nullptr, nullptr}, - {nullptr, nullptr}}; + } HintAttrs[] = {{nullptr, nullptr}, {nullptr, nullptr}, {nullptr, nullptr}, + {nullptr, nullptr}, {nullptr, nullptr}, {nullptr, nullptr}}; for (const auto *I : Attrs) { const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(I); @@ -189,7 +210,14 @@ CheckForIncompatibleAttributes(Sema &S, continue; LoopHintAttr::OptionType Option = LH->getOption(); - enum { Vectorize, Interleave, Unroll, Distribute } Category; + enum { + Vectorize, + Interleave, + Unroll, + UnrollAndJam, + Distribute, + Pipeline + } Category; switch (Option) { case LoopHintAttr::Vectorize: case LoopHintAttr::VectorizeWidth: @@ -203,16 +231,27 @@ CheckForIncompatibleAttributes(Sema &S, case LoopHintAttr::UnrollCount: Category = Unroll; break; + case LoopHintAttr::UnrollAndJam: + case LoopHintAttr::UnrollAndJamCount: + Category = UnrollAndJam; + break; case LoopHintAttr::Distribute: // Perform the check for duplicated 'distribute' hints. Category = Distribute; break; + case LoopHintAttr::PipelineDisabled: + case LoopHintAttr::PipelineInitiationInterval: + Category = Pipeline; + break; }; + assert(Category < sizeof(HintAttrs) / sizeof(HintAttrs[0])); auto &CategoryState = HintAttrs[Category]; const LoopHintAttr *PrevAttr; if (Option == LoopHintAttr::Vectorize || Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll || + Option == LoopHintAttr::UnrollAndJam || + Option == LoopHintAttr::PipelineDisabled || Option == LoopHintAttr::Distribute) { // Enable|Disable|AssumeSafety hint. For example, vectorize(enable). PrevAttr = CategoryState.StateAttr; @@ -232,7 +271,7 @@ CheckForIncompatibleAttributes(Sema &S, << LH->getDiagnosticName(Policy); if (CategoryState.StateAttr && CategoryState.NumericAttr && - (Category == Unroll || + (Category == Unroll || Category == UnrollAndJam || CategoryState.StateAttr->getState() == LoopHintAttr::Disable)) { // Disable hints are not compatible with numeric hints of the same // category. As a special case, numeric unroll hints are also not @@ -257,8 +296,7 @@ static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A, unsigned NumArgs = A.getNumArgs(); if (NumArgs > 1) { - S.Diag(A.getLoc(), diag::err_attribute_too_many_arguments) << A.getName() - << 1; + S.Diag(A.getLoc(), diag::err_attribute_too_many_arguments) << A << 1; return nullptr; } @@ -270,7 +308,7 @@ static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A, if (!E->isIntegerConstantExpr(ArgVal, S.Context)) { S.Diag(A.getLoc(), diag::err_attribute_argument_type) - << A.getName() << AANT_ArgumentIntegerConstant << E->getSourceRange(); + << A << AANT_ArgumentIntegerConstant << E->getSourceRange(); return nullptr; } @@ -279,7 +317,7 @@ static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A, if (Val <= 0) { S.Diag(A.getRange().getBegin(), diag::err_attribute_requires_positive_integer) - << A.getName(); + << A << /* positive */ 0; return nullptr; } UnrollFactor = Val; @@ -292,9 +330,10 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range) { switch (A.getKind()) { case ParsedAttr::UnknownAttribute: - S.Diag(A.getLoc(), A.isDeclspecAttribute() ? - diag::warn_unhandled_ms_attribute_ignored : - diag::warn_unknown_attribute_ignored) << A.getName(); + S.Diag(A.getLoc(), A.isDeclspecAttribute() + ? (unsigned)diag::warn_unhandled_ms_attribute_ignored + : (unsigned)diag::warn_unknown_attribute_ignored) + << A.getName(); return nullptr; case ParsedAttr::AT_FallThrough: return handleFallThroughAttr(S, St, A, Range); @@ -308,7 +347,7 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A, // if we're here, then we parsed a known attribute, but didn't recognize // it as a statement attribute => it is declaration attribute S.Diag(A.getRange().getBegin(), diag::err_decl_attribute_invalid_on_stmt) - << A.getName() << St->getLocStart(); + << A.getName() << St->getBeginLoc(); return nullptr; } } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index fa002de3f5f11..3f9dc989103fa 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -194,7 +194,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S, QualType ObjectType = ObjectTypePtr.get(); - LookupResult R(*this, TName, Name.getLocStart(), LookupOrdinaryName); + LookupResult R(*this, TName, Name.getBeginLoc(), LookupOrdinaryName); if (LookupTemplateName(R, S, SS, ObjectType, EnteringContext, MemberOfUnknownSpecialization)) return TNK_Non_template; @@ -539,9 +539,8 @@ void Sema::diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName, // If this is a dependent-scope lookup, diagnose that the 'template' keyword // was missing. if (MissingTemplateKeyword) { - Diag(NameInfo.getLocStart(), diag::err_template_kw_missing) - << "" << NameInfo.getName().getAsString() - << SourceRange(Less, Greater); + Diag(NameInfo.getBeginLoc(), diag::err_template_kw_missing) + << "" << NameInfo.getName().getAsString() << SourceRange(Less, Greater); return; } @@ -628,7 +627,7 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, if (!MightBeCxx11UnevalField && !isAddressOfOperand && !IsEnum && isa<CXXMethodDecl>(DC) && cast<CXXMethodDecl>(DC)->isInstance()) { - QualType ThisType = cast<CXXMethodDecl>(DC)->getThisType(Context); + QualType ThisType = cast<CXXMethodDecl>(DC)->getThisType(); // Since the 'this' expression is synthesized, we don't need to // perform the double-lookup check. @@ -892,7 +891,7 @@ ParsedTemplateArgument Sema::ActOnTemplateTypeArgument(TypeResult ParsedType) { // convertTypeTemplateArgumentToTemplate. return ParsedTemplateArgument(ParsedTemplateArgument::Type, ParsedType.get().getAsOpaquePtr(), - TInfo->getTypeLoc().getLocStart()); + TInfo->getTypeLoc().getBeginLoc()); } /// ActOnTypeParameter - Called when a C++ template type parameter @@ -974,7 +973,7 @@ NamedDecl *Sema::ActOnTypeParameter(Scope *S, bool Typename, QualType Sema::CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI, SourceLocation Loc) { if (TSI->getType()->isUndeducedType()) { - // C++1z [temp.dep.expr]p3: + // C++17 [temp.dep.expr]p3: // An id-expression is type-dependent if it contains // - an identifier associated by name lookup with a non-type // template-parameter declared with a type that contains a @@ -1113,12 +1112,10 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, IdentifierInfo *ParamName = D.getIdentifier(); bool IsParameterPack = D.hasEllipsis(); - NonTypeTemplateParmDecl *Param - = NonTypeTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(), - D.getLocStart(), - D.getIdentifierLoc(), - Depth, Position, ParamName, T, - IsParameterPack, TInfo); + NonTypeTemplateParmDecl *Param = NonTypeTemplateParmDecl::Create( + Context, Context.getTranslationUnitDecl(), D.getBeginLoc(), + D.getIdentifierLoc(), Depth, Position, ParamName, T, IsParameterPack, + TInfo); Param->setAccess(AS_public); if (Invalid) @@ -1258,9 +1255,10 @@ Sema::ActOnTemplateParameterList(unsigned Depth, RAngleLoc, RequiresClause); } -static void SetNestedNameSpecifier(TagDecl *T, const CXXScopeSpec &SS) { +static void SetNestedNameSpecifier(Sema &S, TagDecl *T, + const CXXScopeSpec &SS) { if (SS.isSet()) - T->setQualifierInfo(SS.getWithLocInContext(T->getASTContext())); + T->setQualifierInfo(SS.getWithLocInContext(S.Context)); } DeclResult Sema::CheckClassTemplate( @@ -1459,10 +1457,11 @@ DeclResult Sema::CheckClassTemplate( }(); if (RedeclACMismatch) { - Diag(CurAC ? CurAC->getLocStart() : NameLoc, + Diag(CurAC ? CurAC->getBeginLoc() : NameLoc, diag::err_template_different_associated_constraints); - Diag(PrevAC ? PrevAC->getLocStart() : PrevClassTemplate->getLocation(), - diag::note_template_prev_declaration) << /*declaration*/0; + Diag(PrevAC ? PrevAC->getBeginLoc() : PrevClassTemplate->getLocation(), + diag::note_template_prev_declaration) + << /*declaration*/ 0; return true; } @@ -1489,19 +1488,19 @@ DeclResult Sema::CheckClassTemplate( NamedDecl *Hidden = nullptr; if (SkipBody && !hasVisibleDefinition(Def, &Hidden)) { SkipBody->ShouldSkip = true; + SkipBody->Previous = Def; auto *Tmpl = cast<CXXRecordDecl>(Hidden)->getDescribedClassTemplate(); assert(Tmpl && "original definition of a class template is not a " "class template?"); makeMergedDefinitionVisible(Hidden); makeMergedDefinitionVisible(Tmpl); - return Def; + } else { + Diag(NameLoc, diag::err_redefinition) << Name; + Diag(Def->getLocation(), diag::note_previous_definition); + // FIXME: Would it make sense to try to "forget" the previous + // definition, as part of error recovery? + return true; } - - Diag(NameLoc, diag::err_redefinition) << Name; - Diag(Def->getLocation(), diag::note_previous_definition); - // FIXME: Would it make sense to try to "forget" the previous - // definition, as part of error recovery? - return true; } } } else if (PrevDecl) { @@ -1522,13 +1521,14 @@ DeclResult Sema::CheckClassTemplate( if (!(TUK == TUK_Friend && CurContext->isDependentContext()) && CheckTemplateParameterList( TemplateParams, - PrevClassTemplate ? PrevClassTemplate->getTemplateParameters() - : nullptr, + PrevClassTemplate + ? PrevClassTemplate->getMostRecentDecl()->getTemplateParameters() + : nullptr, (SS.isSet() && SemanticContext && SemanticContext->isRecord() && SemanticContext->isDependentContext()) ? TPC_ClassTemplateMember - : TUK == TUK_Friend ? TPC_FriendClassTemplate - : TPC_ClassTemplate)) + : TUK == TUK_Friend ? TPC_FriendClassTemplate : TPC_ClassTemplate, + SkipBody)) Invalid = true; if (SS.isSet()) { @@ -1555,7 +1555,7 @@ DeclResult Sema::CheckClassTemplate( PrevClassTemplate && ShouldAddRedecl ? PrevClassTemplate->getTemplatedDecl() : nullptr, /*DelayTypeCreation=*/true); - SetNestedNameSpecifier(NewClass, SS); + SetNestedNameSpecifier(*this, NewClass, SS); if (NumOuterTemplateParamLists > 0) NewClass->setTemplateParameterListsInfo( Context, llvm::makeArrayRef(OuterTemplateParamLists, @@ -1563,7 +1563,7 @@ DeclResult Sema::CheckClassTemplate( // Add alignment attributes if necessary; these attributes are checked when // the ASTContext lays out the structure. - if (TUK == TUK_Definition) { + if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip)) { AddAlignmentAttributesForRecord(NewClass); AddMsStructLayoutForRecord(NewClass); } @@ -1606,7 +1606,7 @@ DeclResult Sema::CheckClassTemplate( NewClass->setLexicalDeclContext(CurContext); NewTemplate->setLexicalDeclContext(CurContext); - if (TUK == TUK_Definition) + if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip)) NewClass->startDefinition(); ProcessDeclAttributeList(S, NewClass, Attr); @@ -1655,6 +1655,9 @@ DeclResult Sema::CheckClassTemplate( ActOnDocumentableDecl(NewTemplate); + if (SkipBody && SkipBody->ShouldSkip) + return SkipBody->Previous; + return NewTemplate; } @@ -1763,8 +1766,8 @@ struct ConvertConstructorToDeductionGuideTransform { TypeSourceInfo *NewTInfo = TLB.getTypeSourceInfo(SemaRef.Context, NewType); return buildDeductionGuide(TemplateParams, CD->isExplicit(), NewTInfo, - CD->getLocStart(), CD->getLocation(), - CD->getLocEnd()); + CD->getBeginLoc(), CD->getLocation(), + CD->getEndLoc()); } /// Build a deduction guide with the specified parameter types. @@ -1806,8 +1809,8 @@ private: // TemplateTypeParmDecl's index cannot be changed after creation, so // substitute it directly. auto *NewTTP = TemplateTypeParmDecl::Create( - SemaRef.Context, DC, TTP->getLocStart(), TTP->getLocation(), - /*Depth*/0, Depth1IndexAdjustment + TTP->getIndex(), + SemaRef.Context, DC, TTP->getBeginLoc(), TTP->getLocation(), + /*Depth*/ 0, Depth1IndexAdjustment + TTP->getIndex(), TTP->getIdentifier(), TTP->wasDeclaredWithTypename(), TTP->isParameterPack()); if (TTP->hasDefaultArgument()) { @@ -1876,7 +1879,7 @@ private: EPI.HasTrailingReturn = true; QualType Result = SemaRef.BuildFunctionType( - ReturnType, ParamTypes, TL.getLocStart(), DeductionGuideName, EPI); + ReturnType, ParamTypes, TL.getBeginLoc(), DeductionGuideName, EPI); if (Result.isNull()) return QualType(); @@ -2152,10 +2155,17 @@ static bool DiagnoseUnexpandedParameterPacks(Sema &S, /// \param TPC Describes the context in which we are checking the given /// template parameter list. /// +/// \param SkipBody If we might have already made a prior merged definition +/// of this template visible, the corresponding body-skipping information. +/// Default argument redefinition is not an error when skipping such a body, +/// because (under the ODR) we can assume the default arguments are the same +/// as the prior merged definition. +/// /// \returns true if an error occurred, false otherwise. bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, TemplateParameterList *OldParams, - TemplateParamListContext TPC) { + TemplateParamListContext TPC, + SkipBodyInfo *SkipBody) { bool Invalid = false; // C++ [temp.param]p10: @@ -2205,7 +2215,8 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, "Parameter packs can't have a default argument!"); SawParameterPack = true; } else if (OldTypeParm && hasVisibleDefaultArgument(OldTypeParm) && - NewTypeParm->hasDefaultArgument()) { + NewTypeParm->hasDefaultArgument() && + (!SkipBody || !SkipBody->ShouldSkip)) { OldDefaultLoc = OldTypeParm->getDefaultArgumentLoc(); NewDefaultLoc = NewTypeParm->getDefaultArgumentLoc(); SawDefaultArgument = true; @@ -2249,7 +2260,8 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, if (!NewNonTypeParm->isPackExpansion()) SawParameterPack = true; } else if (OldNonTypeParm && hasVisibleDefaultArgument(OldNonTypeParm) && - NewNonTypeParm->hasDefaultArgument()) { + NewNonTypeParm->hasDefaultArgument() && + (!SkipBody || !SkipBody->ShouldSkip)) { OldDefaultLoc = OldNonTypeParm->getDefaultArgumentLoc(); NewDefaultLoc = NewNonTypeParm->getDefaultArgumentLoc(); SawDefaultArgument = true; @@ -2292,7 +2304,8 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, SawParameterPack = true; } else if (OldTemplateParm && hasVisibleDefaultArgument(OldTemplateParm) && - NewTemplateParm->hasDefaultArgument()) { + NewTemplateParm->hasDefaultArgument() && + (!SkipBody || !SkipBody->ShouldSkip)) { OldDefaultLoc = OldTemplateParm->getDefaultArgument().getLocation(); NewDefaultLoc = NewTemplateParm->getDefaultArgument().getLocation(); SawDefaultArgument = true; @@ -3040,8 +3053,42 @@ static Expr *lookThroughRangesV3Condition(Preprocessor &PP, Expr *Cond) { return Cond; } +namespace { + +// A PrinterHelper that prints more helpful diagnostics for some sub-expressions +// within failing boolean expression, such as substituting template parameters +// for actual types. +class FailedBooleanConditionPrinterHelper : public PrinterHelper { +public: + explicit FailedBooleanConditionPrinterHelper(const PrintingPolicy &P) + : Policy(P) {} + + bool handledStmt(Stmt *E, raw_ostream &OS) override { + const auto *DR = dyn_cast<DeclRefExpr>(E); + if (DR && DR->getQualifier()) { + // If this is a qualified name, expand the template arguments in nested + // qualifiers. + DR->getQualifier()->print(OS, Policy, true); + // Then print the decl itself. + const ValueDecl *VD = DR->getDecl(); + OS << VD->getName(); + if (const auto *IV = dyn_cast<VarTemplateSpecializationDecl>(VD)) { + // This is a template variable, print the expanded template arguments. + printTemplateArgumentList(OS, IV->getTemplateArgs().asArray(), Policy); + } + return true; + } + return false; + } + +private: + const PrintingPolicy Policy; +}; + +} // end anonymous namespace + std::pair<Expr *, std::string> -Sema::findFailedBooleanCondition(Expr *Cond, bool AllowTopLevelCond) { +Sema::findFailedBooleanCondition(Expr *Cond) { Cond = lookThroughRangesV3Condition(PP, Cond); // Separate out all of the terms in a conjunction. @@ -3070,18 +3117,16 @@ Sema::findFailedBooleanCondition(Expr *Cond, bool AllowTopLevelCond) { break; } } - - if (!FailedCond) { - if (!AllowTopLevelCond) - return { nullptr, "" }; - + if (!FailedCond) FailedCond = Cond->IgnoreParenImpCasts(); - } std::string Description; { llvm::raw_string_ostream Out(Description); - FailedCond->printPretty(Out, nullptr, getPrintingPolicy()); + PrintingPolicy Policy = getPrintingPolicy(); + Policy.PrintCanonicalTypes = true; + FailedBooleanConditionPrinterHelper Helper(Policy); + FailedCond->printPretty(Out, &Helper, Policy, 0, "\n", nullptr); } return { FailedCond, Description }; } @@ -3165,9 +3210,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, Expr *FailedCond; std::string FailedDescription; std::tie(FailedCond, FailedDescription) = - findFailedBooleanCondition( - TemplateArgs[0].getSourceExpression(), - /*AllowTopLevelCond=*/true); + findFailedBooleanCondition(TemplateArgs[0].getSourceExpression()); // Remove the old SFINAE diagnostic. PartialDiagnosticAt OldDiag = @@ -3247,13 +3290,11 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // This is the first time we have referenced this class template // specialization. Create the canonical declaration and add it to // the set of specializations. - Decl = ClassTemplateSpecializationDecl::Create(Context, - ClassTemplate->getTemplatedDecl()->getTagKind(), - ClassTemplate->getDeclContext(), - ClassTemplate->getTemplatedDecl()->getLocStart(), - ClassTemplate->getLocation(), - ClassTemplate, - Converted, nullptr); + Decl = ClassTemplateSpecializationDecl::Create( + Context, ClassTemplate->getTemplatedDecl()->getTagKind(), + ClassTemplate->getDeclContext(), + ClassTemplate->getTemplatedDecl()->getBeginLoc(), + ClassTemplate->getLocation(), ClassTemplate, Converted, nullptr); ClassTemplate->AddSpecialization(Decl, InsertPos); if (ClassTemplate->isOutOfLine()) Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext()); @@ -4218,12 +4259,12 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S, // a "not a template" case. FIXME: Refactor isTemplateName so we don't // need to do this. DeclarationNameInfo DNI = GetNameFromUnqualifiedId(Name); - LookupResult R(*this, DNI.getName(), Name.getLocStart(), + LookupResult R(*this, DNI.getName(), Name.getBeginLoc(), LookupOrdinaryName); bool MOUS; if (!LookupTemplateName(R, S, SS, ObjectType.get(), EnteringContext, MOUS, TemplateKWLoc)) - Diag(Name.getLocStart(), diag::err_no_member) + Diag(Name.getBeginLoc(), diag::err_no_member) << DNI.getName() << LookupCtx << SS.getRange(); return TNK_Non_template; } else { @@ -4241,10 +4282,11 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S, // We don't get here if naming the constructor would be valid, so we // just reject immediately and recover by treating the // injected-class-name as naming the template. - Diag(Name.getLocStart(), + Diag(Name.getBeginLoc(), diag::ext_out_of_line_qualified_id_type_names_constructor) - << Name.Identifier << 0 /*injected-class-name used as template name*/ - << 1 /*'template' keyword was used*/; + << Name.Identifier + << 0 /*injected-class-name used as template name*/ + << 1 /*'template' keyword was used*/; } return TNK; } @@ -4270,11 +4312,9 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S, break; } - Diag(Name.getLocStart(), - diag::err_template_kw_refers_to_non_template) - << GetNameFromUnqualifiedId(Name).getName() - << Name.getSourceRange() - << TemplateKWLoc; + Diag(Name.getBeginLoc(), diag::err_template_kw_refers_to_non_template) + << GetNameFromUnqualifiedId(Name).getName() << Name.getSourceRange() + << TemplateKWLoc; return TNK_Non_template; } @@ -4425,7 +4465,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef, // If the argument type is dependent, instantiate it now based // on the previously-computed template arguments. - if (ArgType->getType()->isDependentType()) { + if (ArgType->getType()->isInstantiationDependentType()) { Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, Param, Template, Converted, SourceRange(TemplateLoc, RAngleLoc)); @@ -5629,8 +5669,8 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param, if (Arg->isNullPointerConstant(S.Context, Expr::NPC_NeverValueDependent)) { std::string Code = "static_cast<" + ParamType.getAsString() + ">("; S.Diag(Arg->getExprLoc(), diag::err_template_arg_untyped_null_constant) - << ParamType << FixItHint::CreateInsertion(Arg->getLocStart(), Code) - << FixItHint::CreateInsertion(S.getLocForEndOfToken(Arg->getLocEnd()), + << ParamType << FixItHint::CreateInsertion(Arg->getBeginLoc(), Code) + << FixItHint::CreateInsertion(S.getLocForEndOfToken(Arg->getEndLoc()), ")"); S.Diag(Param->getLocation(), diag::note_template_param_here); return NPV_NullPointer; @@ -5670,9 +5710,9 @@ static bool CheckTemplateArgumentIsCompatibleWithParameter( unsigned ArgQuals = ArgType.getCVRQualifiers(); if ((ParamQuals | ArgQuals) != ParamQuals) { - S.Diag(Arg->getLocStart(), + S.Diag(Arg->getBeginLoc(), diag::err_template_arg_ref_bind_ignores_quals) - << ParamType << Arg->getType() << Arg->getSourceRange(); + << ParamType << Arg->getType() << Arg->getSourceRange(); S.Diag(Param->getLocation(), diag::note_template_param_here); return true; } @@ -5686,11 +5726,11 @@ static bool CheckTemplateArgumentIsCompatibleWithParameter( ParamType.getNonReferenceType())) { // We can't perform this conversion or binding. if (ParamType->isReferenceType()) - S.Diag(Arg->getLocStart(), diag::err_template_arg_no_ref_bind) - << ParamType << ArgIn->getType() << Arg->getSourceRange(); + S.Diag(Arg->getBeginLoc(), diag::err_template_arg_no_ref_bind) + << ParamType << ArgIn->getType() << Arg->getSourceRange(); else - S.Diag(Arg->getLocStart(), diag::err_template_arg_not_convertible) - << ArgIn->getType() << ParamType << Arg->getSourceRange(); + S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_convertible) + << ArgIn->getType() << ParamType << Arg->getSourceRange(); S.Diag(Param->getLocation(), diag::note_template_param_here); return true; } @@ -5736,8 +5776,8 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, } if (FirstOpLoc.isValid()) { if (ExtWarnMSTemplateArg) - S.Diag(ArgIn->getLocStart(), diag::ext_ms_deref_template_argument) - << ArgIn->getSourceRange(); + S.Diag(ArgIn->getBeginLoc(), diag::ext_ms_deref_template_argument) + << ArgIn->getSourceRange(); if (FirstOpKind == UO_AddrOf) AddressTaken = true; @@ -5745,8 +5785,8 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, // We cannot let pointers get dereferenced here, that is obviously not a // constant expression. assert(FirstOpKind == UO_Deref); - S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref) - << Arg->getSourceRange(); + S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_decl_ref) + << Arg->getSourceRange(); } } } else { @@ -5770,7 +5810,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, bool ExtraParens = false; while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) { if (!Invalid && !ExtraParens) { - S.Diag(Arg->getLocStart(), + S.Diag(Arg->getBeginLoc(), S.getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_template_arg_extra_parens : diag::ext_template_arg_extra_parens) @@ -5836,16 +5876,16 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, } if (!DRE) { - S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref) - << Arg->getSourceRange(); + S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_decl_ref) + << Arg->getSourceRange(); S.Diag(Param->getLocation(), diag::note_template_param_here); return true; } // Cannot refer to non-static data members if (isa<FieldDecl>(Entity) || isa<IndirectFieldDecl>(Entity)) { - S.Diag(Arg->getLocStart(), diag::err_template_arg_field) - << Entity << Arg->getSourceRange(); + S.Diag(Arg->getBeginLoc(), diag::err_template_arg_field) + << Entity << Arg->getSourceRange(); S.Diag(Param->getLocation(), diag::note_template_param_here); return true; } @@ -5853,8 +5893,8 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, // Cannot refer to non-static member functions if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Entity)) { if (!Method->isStatic()) { - S.Diag(Arg->getLocStart(), diag::err_template_arg_method) - << Method << Arg->getSourceRange(); + S.Diag(Arg->getBeginLoc(), diag::err_template_arg_method) + << Method << Arg->getSourceRange(); S.Diag(Param->getLocation(), diag::note_template_param_here); return true; } @@ -5866,23 +5906,24 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, // A non-type template argument must refer to an object or function. if (!Func && !Var) { // We found something, but we don't know specifically what it is. - S.Diag(Arg->getLocStart(), diag::err_template_arg_not_object_or_func) - << Arg->getSourceRange(); + S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_object_or_func) + << Arg->getSourceRange(); S.Diag(DRE->getDecl()->getLocation(), diag::note_template_arg_refers_here); return true; } // Address / reference template args must have external linkage in C++98. if (Entity->getFormalLinkage() == InternalLinkage) { - S.Diag(Arg->getLocStart(), S.getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_template_arg_object_internal : - diag::ext_template_arg_object_internal) - << !Func << Entity << Arg->getSourceRange(); + S.Diag(Arg->getBeginLoc(), + S.getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_template_arg_object_internal + : diag::ext_template_arg_object_internal) + << !Func << Entity << Arg->getSourceRange(); S.Diag(Entity->getLocation(), diag::note_template_arg_internal_object) << !Func; } else if (!Entity->hasLinkage()) { - S.Diag(Arg->getLocStart(), diag::err_template_arg_object_no_linkage) - << !Func << Entity << Arg->getSourceRange(); + S.Diag(Arg->getBeginLoc(), diag::err_template_arg_object_no_linkage) + << !Func << Entity << Arg->getSourceRange(); S.Diag(Entity->getLocation(), diag::note_template_arg_internal_object) << !Func; return true; @@ -5914,17 +5955,16 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, } else { // A value of reference type is not an object. if (Var->getType()->isReferenceType()) { - S.Diag(Arg->getLocStart(), - diag::err_template_arg_reference_var) - << Var->getType() << Arg->getSourceRange(); + S.Diag(Arg->getBeginLoc(), diag::err_template_arg_reference_var) + << Var->getType() << Arg->getSourceRange(); S.Diag(Param->getLocation(), diag::note_template_param_here); return true; } // A template argument must have static storage duration. if (Var->getTLSKind()) { - S.Diag(Arg->getLocStart(), diag::err_template_arg_thread_local) - << Arg->getSourceRange(); + S.Diag(Arg->getBeginLoc(), diag::err_template_arg_thread_local) + << Arg->getSourceRange(); S.Diag(Var->getLocation(), diag::note_template_arg_refers_here); return true; } @@ -5961,15 +6001,14 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, // taking the address of the entity. ArgType = S.Context.getPointerType(Var->getType()); if (!S.Context.hasSameUnqualifiedType(ArgType, ParamType)) { - S.Diag(Arg->getLocStart(), diag::err_template_arg_not_address_of) - << ParamType; + S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_address_of) + << ParamType; S.Diag(Param->getLocation(), diag::note_template_param_here); return true; } - S.Diag(Arg->getLocStart(), diag::err_template_arg_not_address_of) - << ParamType - << FixItHint::CreateInsertion(Arg->getLocStart(), "&"); + S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_address_of) + << ParamType << FixItHint::CreateInsertion(Arg->getBeginLoc(), "&"); S.Diag(Param->getLocation(), diag::note_template_param_here); } @@ -5983,7 +6022,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, // Create the template argument. Converted = TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()), ParamType); - S.MarkAnyDeclReferenced(Arg->getLocStart(), Entity, false); + S.MarkAnyDeclReferenced(Arg->getBeginLoc(), Entity, false); return false; } @@ -6012,11 +6051,11 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S, bool ExtraParens = false; while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) { if (!Invalid && !ExtraParens) { - S.Diag(Arg->getLocStart(), - S.getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_template_arg_extra_parens : - diag::ext_template_arg_extra_parens) - << Arg->getSourceRange(); + S.Diag(Arg->getBeginLoc(), + S.getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_template_arg_extra_parens + : diag::ext_template_arg_extra_parens) + << Arg->getSourceRange(); ExtraParens = true; } @@ -6078,16 +6117,16 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S, } else if (!S.Context.hasSameUnqualifiedType( ResultArg->getType(), ParamType.getNonReferenceType())) { // We can't perform this conversion. - S.Diag(ResultArg->getLocStart(), diag::err_template_arg_not_convertible) + S.Diag(ResultArg->getBeginLoc(), diag::err_template_arg_not_convertible) << ResultArg->getType() << ParamType << ResultArg->getSourceRange(); S.Diag(Param->getLocation(), diag::note_template_param_here); return true; } if (!DRE) - return S.Diag(Arg->getLocStart(), + return S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_pointer_to_member_form) - << Arg->getSourceRange(); + << Arg->getSourceRange(); if (isa<FieldDecl>(DRE->getDecl()) || isa<IndirectFieldDecl>(DRE->getDecl()) || @@ -6109,9 +6148,8 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S, } // We found something else, but we don't know specifically what it is. - S.Diag(Arg->getLocStart(), - diag::err_template_arg_not_pointer_to_member_form) - << Arg->getSourceRange(); + S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_pointer_to_member_form) + << Arg->getSourceRange(); S.Diag(DRE->getDecl()->getLocation(), diag::note_template_arg_refers_here); return true; } @@ -6127,7 +6165,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, QualType ParamType, Expr *Arg, TemplateArgument &Converted, CheckTemplateArgumentKind CTAK) { - SourceLocation StartLoc = Arg->getLocStart(); + SourceLocation StartLoc = Arg->getBeginLoc(); // If the parameter type somehow involves auto, deduce the type now. if (getLangOpts().CPlusPlus17 && ParamType->isUndeducedType()) { @@ -6248,7 +6286,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // FIXME: We need TemplateArgument representation and mangling for these. if (!Value.getMemberPointerPath().empty()) { - Diag(Arg->getLocStart(), + Diag(Arg->getBeginLoc(), diag::err_template_arg_member_ptr_base_derived_not_supported) << Value.getMemberPointerDecl() << ParamType << Arg->getSourceRange(); @@ -6274,8 +6312,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, Converted = TemplateArgument(ArgResult.get()); break; } - Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref) - << Arg->getSourceRange(); + Diag(Arg->getBeginLoc(), diag::err_template_arg_not_decl_ref) + << Arg->getSourceRange(); return ExprError(); } auto *VD = const_cast<ValueDecl *>( @@ -6384,9 +6422,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // -- the name of a non-type template-parameter; or llvm::APSInt Value; if (!ArgType->isIntegralOrEnumerationType()) { - Diag(Arg->getLocStart(), - diag::err_template_arg_not_integral_or_enumeral) - << ArgType << Arg->getSourceRange(); + Diag(Arg->getBeginLoc(), diag::err_template_arg_not_integral_or_enumeral) + << ArgType << Arg->getSourceRange(); Diag(Param->getLocation(), diag::note_template_param_here); return ExprError(); } else if (!Arg->isValueDependent()) { @@ -6424,9 +6461,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, Arg = ImpCastExprToType(Arg, ParamType, CK_IntegralCast).get(); } else { // We can't perform this conversion. - Diag(Arg->getLocStart(), - diag::err_template_arg_not_convertible) - << Arg->getType() << ParamType << Arg->getSourceRange(); + Diag(Arg->getBeginLoc(), diag::err_template_arg_not_convertible) + << Arg->getType() << ParamType << Arg->getSourceRange(); Diag(Param->getLocation(), diag::note_template_param_here); return ExprError(); } @@ -6465,9 +6501,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // Complain if an unsigned parameter received a negative value. if (IntegerType->isUnsignedIntegerOrEnumerationType() && (OldValue.isSigned() && OldValue.isNegative())) { - Diag(Arg->getLocStart(), diag::warn_template_arg_negative) - << OldValue.toString(10) << Value.toString(10) << Param->getType() - << Arg->getSourceRange(); + Diag(Arg->getBeginLoc(), diag::warn_template_arg_negative) + << OldValue.toString(10) << Value.toString(10) << Param->getType() + << Arg->getSourceRange(); Diag(Param->getLocation(), diag::note_template_param_here); } @@ -6480,10 +6516,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, else RequiredBits = OldValue.getMinSignedBits(); if (RequiredBits > AllowedBits) { - Diag(Arg->getLocStart(), - diag::warn_template_arg_too_large) - << OldValue.toString(10) << Value.toString(10) << Param->getType() - << Arg->getSourceRange(); + Diag(Arg->getBeginLoc(), diag::warn_template_arg_too_large) + << OldValue.toString(10) << Value.toString(10) << Param->getType() + << Arg->getSourceRange(); Diag(Param->getLocation(), diag::note_template_param_here); } } @@ -6526,7 +6561,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, ParamType, true, FoundResult)) { - if (DiagnoseUseOfDecl(Fn, Arg->getLocStart())) + if (DiagnoseUseOfDecl(Fn, Arg->getBeginLoc())) return ExprError(); Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn); @@ -6579,7 +6614,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, ParamRefType->getPointeeType(), true, FoundResult)) { - if (DiagnoseUseOfDecl(Fn, Arg->getLocStart())) + if (DiagnoseUseOfDecl(Fn, Arg->getBeginLoc())) return ExprError(); Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn); @@ -7357,9 +7392,9 @@ static bool CheckNonTypeTemplatePartialSpecializationArgs( ParamUseRange = findTemplateParameter( Param->getDepth(), Param->getTypeSourceInfo()->getTypeLoc()); if (ParamUseRange.isValid()) { - S.Diag(IsDefaultArgument ? TemplateNameLoc : ArgExpr->getLocStart(), + S.Diag(IsDefaultArgument ? TemplateNameLoc : ArgExpr->getBeginLoc(), diag::err_dependent_typed_non_type_arg_in_partial_spec) - << Param->getType(); + << Param->getType(); S.Diag(Param->getLocation(), diag::note_template_param_here) << (IsDefaultArgument ? ParamUseRange : SourceRange()) << ParamUseRange; @@ -7616,7 +7651,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization( TemplateArgs, CanonType, PrevPartial); - SetNestedNameSpecifier(Partial, SS); + SetNestedNameSpecifier(*this, Partial, SS); if (TemplateParameterLists.size() > 1 && SS.isSet()) { Partial->setTemplateParameterListsInfo( Context, TemplateParameterLists.drop_back(1)); @@ -7642,7 +7677,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization( ClassTemplate, Converted, PrevDecl); - SetNestedNameSpecifier(Specialization, SS); + SetNestedNameSpecifier(*this, Specialization, SS); if (TemplateParameterLists.size() > 0) { Specialization->setTemplateParameterListsInfo(Context, TemplateParameterLists); @@ -7699,9 +7734,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization( NamedDecl *Hidden = nullptr; if (Def && SkipBody && !hasVisibleDefinition(Def, &Hidden)) { SkipBody->ShouldSkip = true; + SkipBody->Previous = Def; makeMergedDefinitionVisible(Hidden); - // From here on out, treat this as just a redeclaration. - TUK = TUK_Declaration; } else if (Def) { SourceRange Range(TemplateNameLoc, RAngleLoc); Diag(TemplateNameLoc, diag::err_redefinition) << Specialization << Range; @@ -7715,7 +7749,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization( // Add alignment attributes if necessary; these attributes are checked when // the ASTContext lays out the structure. - if (TUK == TUK_Definition) { + if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip)) { AddAlignmentAttributesForRecord(Specialization); AddMsStructLayoutForRecord(Specialization); } @@ -7751,7 +7785,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization( Specialization->setLexicalDeclContext(CurContext); // We may be starting the definition of this specialization. - if (TUK == TUK_Definition) + if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip)) Specialization->startDefinition(); if (TUK == TUK_Friend) { @@ -7767,6 +7801,10 @@ DeclResult Sema::ActOnClassTemplateSpecialization( // context. However, specializations are not found by name lookup. CurContext->addDecl(Specialization); } + + if (SkipBody && SkipBody->ShouldSkip) + return SkipBody->Previous; + return Specialization; } @@ -7928,6 +7966,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, HasNoEffect = true; return false; } + llvm_unreachable("Unexpected TemplateSpecializationKind!"); case TSK_ExplicitInstantiationDefinition: switch (PrevTSK) { @@ -8065,9 +8104,13 @@ Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD, /// /// \param Previous the set of declarations that may be specialized by /// this function specialization. +/// +/// \param QualifiedFriend whether this is a lookup for a qualified friend +/// declaration with no explicit template argument list that might be +/// befriending a function template specialization. bool Sema::CheckFunctionTemplateSpecialization( FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs, - LookupResult &Previous) { + LookupResult &Previous, bool QualifiedFriend) { // The set of function template specializations that could match this // explicit function template specialization. UnresolvedSet<8> Candidates; @@ -8100,7 +8143,7 @@ bool Sema::CheckFunctionTemplateSpecialization( if (OldMD && OldMD->isConst()) { const FunctionProtoType *FPT = FT->castAs<FunctionProtoType>(); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); - EPI.TypeQuals |= Qualifiers::Const; + EPI.TypeQuals.addConst(); FT = Context.getFunctionType(FPT->getReturnType(), FPT->getParamTypes(), EPI); } @@ -8154,10 +8197,25 @@ bool Sema::CheckFunctionTemplateSpecialization( } } + // For a qualified friend declaration (with no explicit marker to indicate + // that a template specialization was intended), note all (template and + // non-template) candidates. + if (QualifiedFriend && Candidates.empty()) { + Diag(FD->getLocation(), diag::err_qualified_friend_no_match) + << FD->getDeclName() << FDLookupContext; + // FIXME: We should form a single candidate list and diagnose all + // candidates at once, to get proper sorting and limiting. + for (auto *OldND : Previous) { + if (auto *OldFD = dyn_cast<FunctionDecl>(OldND->getUnderlyingDecl())) + NoteOverloadCandidate(OldND, OldFD, FD->getType(), false); + } + FailedCandidates.NoteCandidates(*this, FD->getLocation()); + return true; + } + // Find the most specialized function template. UnresolvedSetIterator Result = getMostSpecialized( - Candidates.begin(), Candidates.end(), FailedCandidates, - FD->getLocation(), + Candidates.begin(), Candidates.end(), FailedCandidates, FD->getLocation(), PDiag(diag::err_function_template_spec_no_match) << FD->getDeclName(), PDiag(diag::err_function_template_spec_ambiguous) << FD->getDeclName() << (ExplicitTemplateArgs != nullptr), @@ -8304,6 +8362,8 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { QualType Adjusted = Function->getType(); if (!hasExplicitCallingConv(Adjusted)) Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType()); + // This doesn't handle deduced return types, but both function + // declarations should be undeduced at this point. if (Context.hasSameType(Adjusted, Method->getType())) { FoundInstantiation = *I; Instantiation = Method; @@ -8573,7 +8633,7 @@ static void dllExportImportClassTemplateSpecialization( for (auto &B : Def->bases()) { if (auto *BT = dyn_cast_or_null<ClassTemplateSpecializationDecl>( B.getType()->getAsCXXRecordDecl())) - S.propagateDLLAttrToBaseClassTemplate(Def, A, BT, B.getLocStart()); + S.propagateDLLAttrToBaseClassTemplate(Def, A, BT, B.getBeginLoc()); } S.referenceDLLExportedClassMethods(); @@ -8736,7 +8796,7 @@ DeclResult Sema::ActOnExplicitInstantiation( ClassTemplate, Converted, PrevDecl); - SetNestedNameSpecifier(Specialization, SS); + SetNestedNameSpecifier(*this, Specialization, SS); if (!HasNoEffect && !PrevDecl) { // Insert the new specialization. @@ -8990,10 +9050,9 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, DeclarationName Name = NameInfo.getName(); if (!Name) { if (!D.isInvalidType()) - Diag(D.getDeclSpec().getLocStart(), + Diag(D.getDeclSpec().getBeginLoc(), diag::err_explicit_instantiation_requires_name) - << D.getDeclSpec().getSourceRange() - << D.getSourceRange(); + << D.getDeclSpec().getSourceRange() << D.getSourceRange(); return true; } @@ -9046,8 +9105,8 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // A deduction guide is not on the list of entities that can be explicitly // instantiated. if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) { - Diag(D.getDeclSpec().getLocStart(), diag::err_deduction_guide_specialized) - << /*explicit instantiation*/ 0; + Diag(D.getDeclSpec().getBeginLoc(), diag::err_deduction_guide_specialized) + << /*explicit instantiation*/ 0; return true; } @@ -9105,7 +9164,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // // This includes auto-typed variable template instantiations. if (R->isUndeducedType()) { - Diag(T->getTypeLoc().getLocStart(), + Diag(T->getTypeLoc().getBeginLoc(), diag::err_auto_not_allowed_var_inst); return true; } @@ -9165,17 +9224,15 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, if (!HasNoEffect) { // Instantiate static data member or variable template. Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc()); - if (PrevTemplate) { - // Merge attributes. - ProcessDeclAttributeList(S, Prev, D.getDeclSpec().getAttributes()); - } + // Merge attributes. + ProcessDeclAttributeList(S, Prev, D.getDeclSpec().getAttributes()); if (TSK == TSK_ExplicitInstantiationDefinition) InstantiateVariableDefinition(D.getIdentifierLoc(), Prev); } // Check the new variable specialization against the parsed input. if (PrevTemplate && Prev && !Context.hasSameType(Prev->getType(), R)) { - Diag(T->getTypeLoc().getLocStart(), + Diag(T->getTypeLoc().getBeginLoc(), diag::err_invalid_var_template_spec_type) << 0 << PrevTemplate << R << Prev->getType(); Diag(PrevTemplate->getLocation(), diag::note_template_declared_here) @@ -9293,7 +9350,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, PDiag(DiagID) << Specialization->getType(), PDiag(diag::note_explicit_instantiation_here), Specialization->getType()->getAs<FunctionProtoType>(), - Specialization->getLocation(), FPT, D.getLocStart()); + Specialization->getLocation(), FPT, D.getBeginLoc()); // In Microsoft mode, mismatching exception specifications just cause a // warning. if (!getLangOpts().MicrosoftExt && Result) @@ -9621,7 +9678,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, Expr *FailedCond; std::string FailedDescription; std::tie(FailedCond, FailedDescription) = - findFailedBooleanCondition(Cond, /*AllowTopLevelCond=*/true); + findFailedBooleanCondition(Cond); Diag(FailedCond->getExprLoc(), diag::err_typename_nested_not_found_requirement) @@ -9866,6 +9923,15 @@ bool Sema::RebuildTemplateParamsInCurrentInstantiation( if (!NewTSI) return true; + if (NewTSI->getType()->isUndeducedType()) { + // C++17 [temp.dep.expr]p3: + // An id-expression is type-dependent if it contains + // - an identifier associated by name lookup with a non-type + // template-parameter declared with a type that contains a + // placeholder type (7.1.7.4), + NewTSI = SubstAutoTypeSourceInfo(NewTSI, Context.DependentTy); + } + if (NewTSI != NTTP->getTypeSourceInfo()) { NTTP->setTypeSourceInfo(NewTSI); NTTP->setType(NewTSI->getType()); diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index df46d6115a200..f2f989ce1241c 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -178,6 +178,8 @@ getDeducedParameterFromExpr(TemplateDeductionInfo &Info, Expr *E) { while (true) { if (ImplicitCastExpr *IC = dyn_cast<ImplicitCastExpr>(E)) E = IC->getSubExpr(); + else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(E)) + E = CE->getSubExpr(); else if (SubstNonTypeTemplateParmExpr *Subst = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) E = Subst->getReplacement(); @@ -3076,7 +3078,7 @@ Sema::SubstituteExplicitTemplateArguments( // "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq // and the end of the function-definition, member-declarator, or // declarator. - unsigned ThisTypeQuals = 0; + Qualifiers ThisTypeQuals; CXXRecordDecl *ThisContext = nullptr; if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) { ThisContext = Method->getParent(); @@ -4423,11 +4425,15 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result, if (const AutoType *AT = Type.getType()->getAs<AutoType>()) { if (AT->isDecltypeAuto()) { if (isa<InitListExpr>(Init)) { - Diag(Init->getLocStart(), diag::err_decltype_auto_initializer_list); + Diag(Init->getBeginLoc(), diag::err_decltype_auto_initializer_list); return DAR_FailedAlreadyDiagnosed; } - QualType Deduced = BuildDecltypeType(Init, Init->getLocStart(), false); + ExprResult ER = CheckPlaceholderExpr(Init); + if (ER.isInvalid()) + return DAR_FailedAlreadyDiagnosed; + Init = ER.get(); + QualType Deduced = BuildDecltypeType(Init, Init->getBeginLoc(), false); if (Deduced.isNull()) return DAR_FailedAlreadyDiagnosed; // FIXME: Support a non-canonical deduced type for 'auto'. @@ -4438,7 +4444,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result, return DAR_Succeeded; } else if (!getLangOpts().CPlusPlus) { if (isa<InitListExpr>(Init)) { - Diag(Init->getLocStart(), diag::err_auto_init_list_from_c); + Diag(Init->getBeginLoc(), diag::err_auto_init_list_from_c); return DAR_FailedAlreadyDiagnosed; } } @@ -4655,8 +4661,7 @@ AddImplicitObjectParameterType(ASTContext &Context, // The standard doesn't say explicitly, but we pick the appropriate kind of // reference type based on [over.match.funcs]p4. QualType ArgTy = Context.getTypeDeclType(Method->getParent()); - ArgTy = Context.getQualifiedType(ArgTy, - Qualifiers::fromCVRMask(Method->getTypeQualifiers())); + ArgTy = Context.getQualifiedType(ArgTy, Method->getTypeQualifiers()); if (Method->getRefQualifier() == RQ_RValue) ArgTy = Context.getRValueReferenceType(ArgTy); else @@ -5225,6 +5230,8 @@ MarkUsedTemplateParameters(ASTContext &Ctx, 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(); diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 1aa69bd35d67e..96abeed824930 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -199,6 +199,7 @@ bool Sema::CodeSynthesisContext::isInstantiationRecord() const { case DefaultTemplateArgumentChecking: case DeclaringSpecialMember: case DefiningSynthesizedFunction: + case ExceptionSpecEvaluation: return false; // This function should never be called when Kind's value is Memoization. @@ -621,6 +622,12 @@ void Sema::PrintInstantiationStack() { break; } + case CodeSynthesisContext::ExceptionSpecEvaluation: + Diags.Report(Active->PointOfInstantiation, + diag::note_evaluating_exception_spec_here) + << cast<FunctionDecl>(Active->Entity); + break; + case CodeSynthesisContext::ExceptionSpecInstantiation: Diags.Report(Active->PointOfInstantiation, diag::note_template_exception_spec_instantiation_here) @@ -668,7 +675,7 @@ Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const { // context, depending on what else is on the stack. if (isa<TypeAliasTemplateDecl>(Active->Entity)) break; - // Fall through. + LLVM_FALLTHROUGH; case CodeSynthesisContext::DefaultFunctionArgumentInstantiation: case CodeSynthesisContext::ExceptionSpecInstantiation: // This is a template instantiation, so there is no SFINAE. @@ -695,6 +702,12 @@ Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const { // there is no SFINAE. return None; + case CodeSynthesisContext::ExceptionSpecEvaluation: + // FIXME: This should not be treated as a SFINAE context, because + // we will cache an incorrect exception specification. However, clang + // bootstrap relies this! See PR31692. + break; + case CodeSynthesisContext::Memoization: break; } @@ -894,7 +907,7 @@ namespace { QualType TransformFunctionProtoType(TypeLocBuilder &TLB, FunctionProtoTypeLoc TL, CXXRecordDecl *ThisContext, - unsigned ThisTypeQuals, + Qualifiers ThisTypeQuals, Fn TransformExceptionSpec); ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm, @@ -1154,7 +1167,7 @@ TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) { if (!E->isTypeDependent()) return E; - return getSema().BuildPredefinedExpr(E->getLocation(), E->getIdentType()); + return getSema().BuildPredefinedExpr(E->getLocation(), E->getIdentKind()); } ExprResult @@ -1414,7 +1427,7 @@ template<typename Fn> QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB, FunctionProtoTypeLoc TL, CXXRecordDecl *ThisContext, - unsigned ThisTypeQuals, + Qualifiers ThisTypeQuals, Fn TransformExceptionSpec) { // We need a local instantiation scope for this function prototype. LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true); @@ -1653,7 +1666,7 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T, SourceLocation Loc, DeclarationName Entity, CXXRecordDecl *ThisContext, - unsigned ThisTypeQuals) { + Qualifiers ThisTypeQuals) { assert(!CodeSynthesisContexts.empty() && "Cannot perform an instantiation without some context on the " "instantiation stack"); @@ -1708,7 +1721,7 @@ void Sema::SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto, Proto->getExtProtoInfo().ExceptionSpec; SmallVector<QualType, 4> ExceptionStorage; - if (SubstExceptionSpec(New->getTypeSourceInfo()->getTypeLoc().getLocEnd(), + if (SubstExceptionSpec(New->getTypeSourceInfo()->getTypeLoc().getEndLoc(), ESI, ExceptionStorage, Args)) // On error, recover by dropping the exception specification. ESI.Type = EST_None; @@ -1789,7 +1802,7 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, ExprResult NewArg = SubstExpr(Arg, TemplateArgs); if (NewArg.isUsable()) { // It would be nice if we still had this. - SourceLocation EqualLoc = NewArg.get()->getLocStart(); + SourceLocation EqualLoc = NewArg.get()->getBeginLoc(); SetParamDefaultArgument(NewParm, NewArg.get(), EqualLoc); } } else { @@ -2135,7 +2148,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, NamedDecl *ND = dyn_cast<NamedDecl>(I->NewDecl); CXXRecordDecl *ThisContext = dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext()); - CXXThisScopeRAII ThisScope(*this, ThisContext, /*TypeQuals*/0, + CXXThisScopeRAII ThisScope(*this, ThisContext, Qualifiers(), ND && ND->isCXXInstanceMember()); Attr *NewAttr = @@ -2303,7 +2316,7 @@ bool Sema::InstantiateInClassInitializer( Diag(PointOfInstantiation, diag::err_in_class_initializer_not_yet_parsed) << OutermostClass << Pattern; - Diag(Pattern->getLocEnd(), diag::note_in_class_initializer_not_yet_parsed); + Diag(Pattern->getEndLoc(), diag::note_in_class_initializer_not_yet_parsed); Instantiation->setInvalidDecl(); return true; } @@ -2330,14 +2343,14 @@ bool Sema::InstantiateInClassInitializer( // Instantiate the initializer. ActOnStartCXXInClassMemberInitializer(); - CXXThisScopeRAII ThisScope(*this, Instantiation->getParent(), /*TypeQuals=*/0); + CXXThisScopeRAII ThisScope(*this, Instantiation->getParent(), Qualifiers()); ExprResult NewInit = SubstInitializer(OldInit, TemplateArgs, /*CXXDirectInit=*/false); Expr *Init = NewInit.get(); assert((!Init || !isa<ParenListExpr>(Init)) && "call-style init in class"); ActOnFinishCXXInClassMemberInitializer( - Instantiation, Init ? Init->getLocStart() : SourceLocation(), Init); + Instantiation, Init ? Init->getBeginLoc() : SourceLocation(), Init); if (auto *L = getASTMutationListener()) L->DefaultMemberInitializerInstantiated(Instantiation); @@ -2561,10 +2574,14 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation, for (auto *D : Instantiation->decls()) { bool SuppressNew = false; if (auto *Function = dyn_cast<FunctionDecl>(D)) { - if (FunctionDecl *Pattern - = Function->getInstantiatedFromMemberFunction()) { - MemberSpecializationInfo *MSInfo - = Function->getMemberSpecializationInfo(); + if (FunctionDecl *Pattern = + Function->getInstantiatedFromMemberFunction()) { + + if (Function->hasAttr<ExcludeFromExplicitInstantiationAttr>()) + continue; + + MemberSpecializationInfo *MSInfo = + Function->getMemberSpecializationInfo(); assert(MSInfo && "No member specialization information?"); if (MSInfo->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) @@ -2605,6 +2622,9 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation, continue; if (Var->isStaticDataMember()) { + if (Var->hasAttr<ExcludeFromExplicitInstantiationAttr>()) + continue; + MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo(); assert(MSInfo && "No member specialization information?"); if (MSInfo->getTemplateSpecializationKind() @@ -2636,6 +2656,9 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation, } } } else if (auto *Record = dyn_cast<CXXRecordDecl>(D)) { + if (Record->hasAttr<ExcludeFromExplicitInstantiationAttr>()) + continue; + // Always skip the injected-class-name, along with any // redeclarations of nested classes, since both would cause us // to try to instantiate the members of a class twice. diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 86492716f6851..fad3c065e896f 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -295,7 +295,7 @@ static void instantiateOMPDeclareSimdDeclAttr( PVD, FD->getParamDecl(PVD->getFunctionScopeIndex())); return S.SubstExpr(E, TemplateArgs); } - Sema::CXXThisScopeRAII ThisScope(S, ThisContext, /*TypeQuals=*/0, + Sema::CXXThisScopeRAII ThisScope(S, ThisContext, Qualifiers(), FD->isCXXInstanceMember()); return S.SubstExpr(E, TemplateArgs); }; @@ -355,7 +355,7 @@ void Sema::InstantiateAttrsForDecl( // applicable to template declaration, we'll need to add them here. CXXThisScopeRAII ThisScope( *this, dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext()), - /*TypeQuals*/ 0, ND->isCXXInstanceMember()); + Qualifiers(), ND->isCXXInstanceMember()); Attr *NewAttr = sema::instantiateTemplateAttributeForDecl( TmplAttr, Context, *this, TemplateArgs); @@ -365,6 +365,20 @@ void Sema::InstantiateAttrsForDecl( } } +static Sema::RetainOwnershipKind +attrToRetainOwnershipKind(const Attr *A) { + switch (A->getKind()) { + case clang::attr::CFConsumed: + return Sema::RetainOwnershipKind::CF; + case clang::attr::OSConsumed: + return Sema::RetainOwnershipKind::OS; + case clang::attr::NSConsumed: + return Sema::RetainOwnershipKind::NS; + default: + llvm_unreachable("Wrong argument supplied"); + } +} + void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Tmpl, Decl *New, LateInstantiatedAttrVec *LateAttrs, @@ -438,11 +452,12 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, continue; } - if (isa<NSConsumedAttr>(TmplAttr) || isa<CFConsumedAttr>(TmplAttr)) { - AddNSConsumedAttr(TmplAttr->getRange(), New, - TmplAttr->getSpellingListIndex(), - isa<NSConsumedAttr>(TmplAttr), - /*template instantiation*/ true); + if (isa<NSConsumedAttr>(TmplAttr) || isa<OSConsumedAttr>(TmplAttr) || + isa<CFConsumedAttr>(TmplAttr)) { + AddXConsumedAttr(New, TmplAttr->getRange(), + TmplAttr->getSpellingListIndex(), + attrToRetainOwnershipKind(TmplAttr), + /*template instantiation=*/true); continue; } @@ -459,7 +474,7 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, NamedDecl *ND = dyn_cast<NamedDecl>(New); CXXRecordDecl *ThisContext = dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext()); - CXXThisScopeRAII ThisScope(*this, ThisContext, /*TypeQuals*/0, + CXXThisScopeRAII ThisScope(*this, ThisContext, Qualifiers(), ND && ND->isCXXInstanceMember()); Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context, @@ -562,7 +577,7 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D, RD->getEnclosingNamespaceContext() == SemaRef.getStdNamespace() && RD->getIdentifier() && RD->getIdentifier()->isStr("common_type") && D->getIdentifier() && D->getIdentifier()->isStr("type") && - SemaRef.getSourceManager().isInSystemHeader(D->getLocStart())) + SemaRef.getSourceManager().isInSystemHeader(D->getBeginLoc())) // Fold it to the (non-reference) type which g++ would have produced. DI = SemaRef.Context.getTrivialTypeSourceInfo( DI->getType().getNonReferenceType()); @@ -570,10 +585,10 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D, // Create the new typedef TypedefNameDecl *Typedef; if (IsTypeAlias) - Typedef = TypeAliasDecl::Create(SemaRef.Context, Owner, D->getLocStart(), + Typedef = TypeAliasDecl::Create(SemaRef.Context, Owner, D->getBeginLoc(), D->getLocation(), D->getIdentifier(), DI); else - Typedef = TypedefDecl::Create(SemaRef.Context, Owner, D->getLocStart(), + Typedef = TypedefDecl::Create(SemaRef.Context, Owner, D->getBeginLoc(), D->getLocation(), D->getIdentifier(), DI); if (Invalid) Typedef->setInvalidDecl(); @@ -748,6 +763,9 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D, Var->setImplicit(D->isImplicit()); + if (Var->isStaticLocal()) + SemaRef.CheckStaticLocalForDllExport(Var); + return Var; } @@ -872,7 +890,7 @@ Decl *TemplateDeclInstantiator::VisitMSPropertyDecl(MSPropertyDecl *D) { MSPropertyDecl *Property = MSPropertyDecl::Create( SemaRef.Context, Owner, D->getLocation(), D->getDeclName(), DI->getType(), - DI, D->getLocStart(), D->getGetterId(), D->getSetterId()); + DI, D->getBeginLoc(), D->getGetterId(), D->getSetterId()); SemaRef.InstantiateAttrs(TemplateArgs, D, Property, LateAttrs, StartingScope); @@ -932,7 +950,7 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) { if (!InstTy) return nullptr; - FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getLocStart(), + FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getBeginLoc(), D->getFriendLoc(), InstTy); if (!FD) return nullptr; @@ -991,10 +1009,10 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { PrevDecl = cast<EnumDecl>(Prev); } - EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner, D->getLocStart(), - D->getLocation(), D->getIdentifier(), - PrevDecl, D->isScoped(), - D->isScopedUsingClassTag(), D->isFixed()); + EnumDecl *Enum = + EnumDecl::Create(SemaRef.Context, Owner, D->getBeginLoc(), + D->getLocation(), D->getIdentifier(), PrevDecl, + D->isScoped(), D->isScopedUsingClassTag(), D->isFixed()); if (D->isFixed()) { if (TypeSourceInfo *TI = D->getIntegerTypeSourceInfo()) { // If we have type source information for the underlying type, it means it @@ -1228,7 +1246,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { } TemplateParameterList *PrevParams - = PrevClassTemplate->getTemplateParameters(); + = PrevClassTemplate->getMostRecentDecl()->getTemplateParameters(); // Make sure the parameter lists match. if (!SemaRef.TemplateParameterListsAreEqual(InstParams, PrevParams, @@ -1250,15 +1268,17 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { } } - CXXRecordDecl *RecordInst - = CXXRecordDecl::Create(SemaRef.Context, Pattern->getTagKind(), DC, - Pattern->getLocStart(), Pattern->getLocation(), - Pattern->getIdentifier(), PrevDecl, - /*DelayTypeCreation=*/true); + CXXRecordDecl *RecordInst = CXXRecordDecl::Create( + SemaRef.Context, Pattern->getTagKind(), DC, Pattern->getBeginLoc(), + Pattern->getLocation(), Pattern->getIdentifier(), PrevDecl, + /*DelayTypeCreation=*/true); if (QualifierLoc) RecordInst->setQualifierInfo(QualifierLoc); + SemaRef.InstantiateAttrsForDecl(TemplateArgs, Pattern, RecordInst, LateAttrs, + StartingScope); + ClassTemplateDecl *Inst = ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(), D->getIdentifier(), InstParams, RecordInst); @@ -1484,15 +1504,17 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { PrevDecl = cast<CXXRecordDecl>(Prev); } - CXXRecordDecl *Record - = CXXRecordDecl::Create(SemaRef.Context, D->getTagKind(), Owner, - D->getLocStart(), D->getLocation(), - D->getIdentifier(), PrevDecl); + CXXRecordDecl *Record = CXXRecordDecl::Create( + SemaRef.Context, D->getTagKind(), Owner, D->getBeginLoc(), + D->getLocation(), D->getIdentifier(), PrevDecl); // Substitute the nested name specifier, if any. if (SubstQualifier(D, Record)) return nullptr; + SemaRef.InstantiateAttrsForDecl(TemplateArgs, D, Record, LateAttrs, + StartingScope); + Record->setImplicit(D->isImplicit()); // FIXME: Check against AS_none is an ugly hack to work around the issue that // the tag decls introduced by friend class declarations don't have an access @@ -1725,10 +1747,13 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, Function->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation); } + if (isFriend) + Function->setObjectOfFriendDecl(); + if (InitFunctionInstantiation(Function, D)) Function->setInvalidDecl(); - bool isExplicitSpecialization = false; + bool IsExplicitSpecialization = false; LookupResult Previous( SemaRef, Function->getDeclName(), SourceLocation(), @@ -1741,9 +1766,6 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, = D->getDependentSpecializationInfo()) { assert(isFriend && "non-friend has dependent specialization info?"); - // This needs to be set now for future sanity. - Function->setObjectOfFriendDecl(); - // Instantiate the explicit template arguments. TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), Info->getRAngleLoc()); @@ -1766,8 +1788,25 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, Previous)) Function->setInvalidDecl(); - isExplicitSpecialization = true; + IsExplicitSpecialization = true; + } else if (const ASTTemplateArgumentListInfo *Info = + D->getTemplateSpecializationArgsAsWritten()) { + // The name of this function was written as a template-id. + SemaRef.LookupQualifiedName(Previous, DC); + + // Instantiate the explicit template arguments. + TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), + Info->getRAngleLoc()); + if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(), + ExplicitArgs, TemplateArgs)) + return nullptr; + + if (SemaRef.CheckFunctionTemplateSpecialization(Function, + &ExplicitArgs, + Previous)) + Function->setInvalidDecl(); + IsExplicitSpecialization = true; } else if (TemplateParams || !FunctionTemplate) { // Look only into the namespace where the friend would be declared to // find a previous declaration. This is the innermost enclosing namespace, @@ -1782,11 +1821,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, Previous.clear(); } - if (isFriend) - Function->setObjectOfFriendDecl(); - SemaRef.CheckFunctionDeclaration(/*Scope*/ nullptr, Function, Previous, - isExplicitSpecialization); + IsExplicitSpecialization); NamedDecl *PrincipalDecl = (TemplateParams ? cast<NamedDecl>(FunctionTemplate) @@ -1795,7 +1831,9 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, // If the original function was part of a friend declaration, // inherit its namespace state and add it to the owner. if (isFriend) { - PrincipalDecl->setObjectOfFriendDecl(); + Function->setObjectOfFriendDecl(); + if (FunctionTemplateDecl *FT = Function->getDescribedFunctionTemplate()) + FT->setObjectOfFriendDecl(); DC->makeDeclVisibleInContext(PrincipalDecl); bool QueuedInstantiation = false; @@ -1945,26 +1983,23 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, Constructor->isExplicit(), Constructor->isInlineSpecified(), false, Constructor->isConstexpr()); - Method->setRangeEnd(Constructor->getLocEnd()); + Method->setRangeEnd(Constructor->getEndLoc()); } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) { Method = CXXDestructorDecl::Create(SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, Destructor->isInlineSpecified(), false); - Method->setRangeEnd(Destructor->getLocEnd()); + Method->setRangeEnd(Destructor->getEndLoc()); } else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) { - Method = CXXConversionDecl::Create(SemaRef.Context, Record, - StartLoc, NameInfo, T, TInfo, - Conversion->isInlineSpecified(), - Conversion->isExplicit(), - Conversion->isConstexpr(), - Conversion->getLocEnd()); + Method = CXXConversionDecl::Create( + SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, + Conversion->isInlineSpecified(), Conversion->isExplicit(), + Conversion->isConstexpr(), Conversion->getEndLoc()); } else { StorageClass SC = D->isStatic() ? SC_Static : SC_None; - Method = CXXMethodDecl::Create(SemaRef.Context, Record, - StartLoc, NameInfo, T, TInfo, - SC, D->isInlineSpecified(), - D->isConstexpr(), D->getLocEnd()); + Method = CXXMethodDecl::Create(SemaRef.Context, Record, StartLoc, NameInfo, + T, TInfo, SC, D->isInlineSpecified(), + D->isConstexpr(), D->getEndLoc()); } if (D->isInlined()) @@ -2034,7 +2069,54 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName, Sema::ForExternalRedeclaration); - if (!FunctionTemplate || TemplateParams || isFriend) { + bool IsExplicitSpecialization = false; + + // If the name of this function was written as a template-id, instantiate + // the explicit template arguments. + if (DependentFunctionTemplateSpecializationInfo *Info + = D->getDependentSpecializationInfo()) { + assert(isFriend && "non-friend has dependent specialization info?"); + + // Instantiate the explicit template arguments. + TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), + Info->getRAngleLoc()); + if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(), + ExplicitArgs, TemplateArgs)) + return nullptr; + + // Map the candidate templates to their instantiations. + for (unsigned I = 0, E = Info->getNumTemplates(); I != E; ++I) { + Decl *Temp = SemaRef.FindInstantiatedDecl(D->getLocation(), + Info->getTemplate(I), + TemplateArgs); + if (!Temp) return nullptr; + + Previous.addDecl(cast<FunctionTemplateDecl>(Temp)); + } + + if (SemaRef.CheckFunctionTemplateSpecialization(Method, + &ExplicitArgs, + Previous)) + Method->setInvalidDecl(); + + IsExplicitSpecialization = true; + } else if (const ASTTemplateArgumentListInfo *Info = + D->getTemplateSpecializationArgsAsWritten()) { + SemaRef.LookupQualifiedName(Previous, DC); + + TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), + Info->getRAngleLoc()); + if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(), + ExplicitArgs, TemplateArgs)) + return nullptr; + + if (SemaRef.CheckFunctionTemplateSpecialization(Method, + &ExplicitArgs, + Previous)) + Method->setInvalidDecl(); + + IsExplicitSpecialization = true; + } else if (!FunctionTemplate || TemplateParams || isFriend) { SemaRef.LookupQualifiedName(Previous, Record); // In C++, the previous declaration we find might be a tag type @@ -2046,7 +2128,8 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, } if (!IsClassScopeSpecialization) - SemaRef.CheckFunctionDeclaration(nullptr, Method, Previous, false); + SemaRef.CheckFunctionDeclaration(nullptr, Method, Previous, + IsExplicitSpecialization); if (D->isPure()) SemaRef.CheckPureMethod(Method, SourceRange()); @@ -2119,7 +2202,7 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( assert(D->getTypeForDecl()->isTemplateTypeParmType()); TemplateTypeParmDecl *Inst = TemplateTypeParmDecl::Create( - SemaRef.Context, Owner, D->getLocStart(), D->getLocation(), + SemaRef.Context, Owner, D->getBeginLoc(), D->getLocation(), D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), D->getIndex(), D->getIdentifier(), D->wasDeclaredWithTypename(), D->isParameterPack()); Inst->setAccess(AS_public); @@ -2683,26 +2766,28 @@ Decl *TemplateDeclInstantiator::VisitUsingPackDecl(UsingPackDecl *D) { } Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl( - ClassScopeFunctionSpecializationDecl *Decl) { + ClassScopeFunctionSpecializationDecl *Decl) { CXXMethodDecl *OldFD = Decl->getSpecialization(); CXXMethodDecl *NewFD = cast_or_null<CXXMethodDecl>(VisitCXXMethodDecl(OldFD, nullptr, true)); if (!NewFD) return nullptr; - LookupResult Previous(SemaRef, NewFD->getNameInfo(), Sema::LookupOrdinaryName, - Sema::ForExternalRedeclaration); - - TemplateArgumentListInfo TemplateArgs; - TemplateArgumentListInfo *TemplateArgsPtr = nullptr; + TemplateArgumentListInfo ExplicitTemplateArgs; + TemplateArgumentListInfo *ExplicitTemplateArgsPtr = nullptr; if (Decl->hasExplicitTemplateArgs()) { - TemplateArgs = Decl->templateArgs(); - TemplateArgsPtr = &TemplateArgs; + if (SemaRef.Subst(Decl->templateArgs().getArgumentArray(), + Decl->templateArgs().size(), ExplicitTemplateArgs, + TemplateArgs)) + return nullptr; + ExplicitTemplateArgsPtr = &ExplicitTemplateArgs; } + LookupResult Previous(SemaRef, NewFD->getNameInfo(), Sema::LookupOrdinaryName, + Sema::ForExternalRedeclaration); SemaRef.LookupQualifiedName(Previous, SemaRef.CurContext); - if (SemaRef.CheckFunctionTemplateSpecialization(NewFD, TemplateArgsPtr, - Previous)) { + if (SemaRef.CheckFunctionTemplateSpecialization( + NewFD, ExplicitTemplateArgsPtr, Previous)) { NewFD->setInvalidDecl(); return NewFD; } @@ -2735,13 +2820,27 @@ Decl *TemplateDeclInstantiator::VisitOMPThreadPrivateDecl( return TD; } +Decl *TemplateDeclInstantiator::VisitOMPRequiresDecl(OMPRequiresDecl *D) { + llvm_unreachable( + "Requires directive cannot be instantiated within a dependent context"); +} + Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl( OMPDeclareReductionDecl *D) { // Instantiate type and check if it is allowed. - QualType SubstReductionType = SemaRef.ActOnOpenMPDeclareReductionType( - D->getLocation(), - ParsedType::make(SemaRef.SubstType(D->getType(), TemplateArgs, - D->getLocation(), DeclarationName()))); + const bool RequiresInstantiation = + D->getType()->isDependentType() || + D->getType()->isInstantiationDependentType() || + D->getType()->containsUnexpandedParameterPack(); + QualType SubstReductionType; + if (RequiresInstantiation) { + SubstReductionType = SemaRef.ActOnOpenMPDeclareReductionType( + D->getLocation(), + ParsedType::make(SemaRef.SubstType( + D->getType(), TemplateArgs, D->getLocation(), DeclarationName()))); + } else { + SubstReductionType = D->getType(); + } if (SubstReductionType.isNull()) return nullptr; bool IsCorrect = !SubstReductionType.isNull(); @@ -2758,25 +2857,35 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl( /*S=*/nullptr, Owner, D->getDeclName(), ReductionTypes, D->getAccess(), PrevDeclInScope); auto *NewDRD = cast<OMPDeclareReductionDecl>(DRD.get().getSingleDecl()); - if (isDeclWithinFunction(NewDRD)) - SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewDRD); + SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewDRD); + if (!RequiresInstantiation) { + if (Expr *Combiner = D->getCombiner()) { + NewDRD->setCombinerData(D->getCombinerIn(), D->getCombinerOut()); + NewDRD->setCombiner(Combiner); + if (Expr *Init = D->getInitializer()) { + NewDRD->setInitializerData(D->getInitOrig(), D->getInitPriv()); + NewDRD->setInitializer(Init, D->getInitializerKind()); + } + } + (void)SemaRef.ActOnOpenMPDeclareReductionDirectiveEnd( + /*S=*/nullptr, DRD, IsCorrect && !D->isInvalidDecl()); + return NewDRD; + } Expr *SubstCombiner = nullptr; Expr *SubstInitializer = nullptr; // Combiners instantiation sequence. if (D->getCombiner()) { SemaRef.ActOnOpenMPDeclareReductionCombinerStart( /*S=*/nullptr, NewDRD); - const char *Names[] = {"omp_in", "omp_out"}; - for (auto &Name : Names) { - DeclarationName DN(&SemaRef.Context.Idents.get(Name)); - auto OldLookup = D->lookup(DN); - auto Lookup = NewDRD->lookup(DN); - if (!OldLookup.empty() && !Lookup.empty()) { - assert(Lookup.size() == 1 && OldLookup.size() == 1); - SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldLookup.front(), - Lookup.front()); - } - } + SemaRef.CurrentInstantiationScope->InstantiatedLocal( + cast<DeclRefExpr>(D->getCombinerIn())->getDecl(), + cast<DeclRefExpr>(NewDRD->getCombinerIn())->getDecl()); + SemaRef.CurrentInstantiationScope->InstantiatedLocal( + cast<DeclRefExpr>(D->getCombinerOut())->getDecl(), + cast<DeclRefExpr>(NewDRD->getCombinerOut())->getDecl()); + auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(Owner); + Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, Qualifiers(), + ThisContext); SubstCombiner = SemaRef.SubstExpr(D->getCombiner(), TemplateArgs).get(); SemaRef.ActOnOpenMPDeclareReductionCombinerEnd(NewDRD, SubstCombiner); // Initializers instantiation sequence. @@ -2784,19 +2893,12 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl( VarDecl *OmpPrivParm = SemaRef.ActOnOpenMPDeclareReductionInitializerStart( /*S=*/nullptr, NewDRD); - const char *Names[] = {"omp_orig", "omp_priv"}; - for (auto &Name : Names) { - DeclarationName DN(&SemaRef.Context.Idents.get(Name)); - auto OldLookup = D->lookup(DN); - auto Lookup = NewDRD->lookup(DN); - if (!OldLookup.empty() && !Lookup.empty()) { - assert(Lookup.size() == 1 && OldLookup.size() == 1); - auto *OldVD = cast<VarDecl>(OldLookup.front()); - auto *NewVD = cast<VarDecl>(Lookup.front()); - SemaRef.InstantiateVariableInitializer(NewVD, OldVD, TemplateArgs); - SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldVD, NewVD); - } - } + SemaRef.CurrentInstantiationScope->InstantiatedLocal( + cast<DeclRefExpr>(D->getInitOrig())->getDecl(), + cast<DeclRefExpr>(NewDRD->getInitOrig())->getDecl()); + SemaRef.CurrentInstantiationScope->InstantiatedLocal( + cast<DeclRefExpr>(D->getInitPriv())->getDecl(), + cast<DeclRefExpr>(NewDRD->getInitPriv())->getDecl()); if (D->getInitializerKind() == OMPDeclareReductionDecl::CallInit) { SubstInitializer = SemaRef.SubstExpr(D->getInitializer(), TemplateArgs).get(); @@ -2813,8 +2915,9 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl( SubstInitializer) || (D->getInitializerKind() != OMPDeclareReductionDecl::CallInit && !SubstInitializer && !SubstInitializer)); - } else + } else { IsCorrect = false; + } (void)SemaRef.ActOnOpenMPDeclareReductionDirectiveEnd(/*S=*/nullptr, DRD, IsCorrect); @@ -2931,15 +3034,10 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl( } // Create the class template partial specialization declaration. - ClassTemplateSpecializationDecl *InstD - = ClassTemplateSpecializationDecl::Create(SemaRef.Context, - D->getTagKind(), - Owner, - D->getLocStart(), - D->getLocation(), - InstClassTemplate, - Converted, - PrevDecl); + ClassTemplateSpecializationDecl *InstD = + ClassTemplateSpecializationDecl::Create( + SemaRef.Context, D->getTagKind(), Owner, D->getBeginLoc(), + D->getLocation(), InstClassTemplate, Converted, PrevDecl); // Add this partial specialization to the set of class template partial // specializations. @@ -3008,7 +3106,7 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( // Check that the template argument list is well-formed for this template. SmallVector<TemplateArgument, 4> Converted; if (SemaRef.CheckTemplateArgumentList( - VarTemplate, VarTemplate->getLocStart(), + VarTemplate, VarTemplate->getBeginLoc(), const_cast<TemplateArgumentListInfo &>(VarTemplateArgsInfo), false, Converted)) return nullptr; @@ -3237,18 +3335,11 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( // Create the class template partial specialization declaration. - ClassTemplatePartialSpecializationDecl *InstPartialSpec - = ClassTemplatePartialSpecializationDecl::Create(SemaRef.Context, - PartialSpec->getTagKind(), - Owner, - PartialSpec->getLocStart(), - PartialSpec->getLocation(), - InstParams, - ClassTemplate, - Converted, - InstTemplateArgs, - CanonType, - nullptr); + ClassTemplatePartialSpecializationDecl *InstPartialSpec = + ClassTemplatePartialSpecializationDecl::Create( + SemaRef.Context, PartialSpec->getTagKind(), Owner, + PartialSpec->getBeginLoc(), PartialSpec->getLocation(), InstParams, + ClassTemplate, Converted, InstTemplateArgs, CanonType, nullptr); // Substitute the nested name specifier, if any. if (SubstQualifier(PartialSpec, InstPartialSpec)) return nullptr; @@ -3412,7 +3503,7 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, assert(Params.empty() && "parameter vector is non-empty at start"); CXXRecordDecl *ThisContext = nullptr; - unsigned ThisTypeQuals = 0; + Qualifiers ThisTypeQuals; if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { ThisContext = cast<CXXRecordDecl>(Owner); ThisTypeQuals = Method->getTypeQualifiers(); @@ -3707,6 +3798,9 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New, if (InitFunctionInstantiation(New, Tmpl)) return true; + if (isa<CXXDestructorDecl>(New) && SemaRef.getLangOpts().CPlusPlus11) + SemaRef.AdjustDestructorExceptionSpec(cast<CXXDestructorDecl>(New)); + New->setAccess(Tmpl->getAccess()); if (Tmpl->isVirtualAsWritten()) New->setVirtualAsWritten(true); @@ -3823,7 +3917,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, std::make_pair(Function, PointOfInstantiation)); } else if (TSK == TSK_ImplicitInstantiation) { if (AtEndOfTU && !getDiagnostics().hasErrorOccurred() && - !getSourceManager().isInSystemHeader(PatternDecl->getLocStart())) { + !getSourceManager().isInSystemHeader(PatternDecl->getBeginLoc())) { Diag(PointOfInstantiation, diag::warn_func_template_missing) << Function; Diag(PatternDecl->getLocation(), diag::note_forward_template_decl); @@ -4366,7 +4460,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, } else if (TSK == TSK_ImplicitInstantiation) { // Warn about missing definition at the end of translation unit. if (AtEndOfTU && !getDiagnostics().hasErrorOccurred() && - !getSourceManager().isInSystemHeader(PatternDecl->getLocStart())) { + !getSourceManager().isInSystemHeader(PatternDecl->getBeginLoc())) { Diag(PointOfInstantiation, diag::warn_var_template_missing) << Var; Diag(PatternDecl->getLocation(), diag::note_forward_template_decl); @@ -4911,7 +5005,9 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, return D; if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) || - (ParentDC->isFunctionOrMethod() && ParentDC->isDependentContext()) || + ((ParentDC->isFunctionOrMethod() || + isa<OMPDeclareReductionDecl>(ParentDC)) && + ParentDC->isDependentContext()) || (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda())) { // D is a local of some kind. Look into the map of local // declarations to their instantiations. @@ -5192,10 +5288,20 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) { if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Inst.first)) { bool DefinitionRequired = Function->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition; - InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true, - DefinitionRequired, true); - if (Function->isDefined()) - Function->setInstantiationIsPending(false); + if (Function->isMultiVersion()) { + getASTContext().forEachMultiversionedFunctionVersion( + Function, [this, Inst, DefinitionRequired](FunctionDecl *CurFD) { + InstantiateFunctionDefinition(/*FIXME:*/ Inst.second, CurFD, true, + DefinitionRequired, true); + if (CurFD->isDefined()) + CurFD->setInstantiationIsPending(false); + }); + } else { + InstantiateFunctionDefinition(/*FIXME:*/ Inst.second, Function, true, + DefinitionRequired, true); + if (Function->isDefined()) + Function->setInstantiationIsPending(false); + } continue; } diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp index 6f9dddf5c05ec..0e7fc20d24871 100644 --- a/lib/Sema/SemaTemplateVariadic.cpp +++ b/lib/Sema/SemaTemplateVariadic.cpp @@ -164,7 +164,7 @@ namespace { // A function parameter pack is a pack expansion, so cannot contain // an unexpanded parameter pack. Likewise for a template parameter // pack that contains any references to other packs. - if (D->isParameterPack()) + if (D && D->isParameterPack()) return true; return inherited::TraverseDecl(D); @@ -392,7 +392,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(Expr *E, SmallVector<UnexpandedParameterPack, 2> Unexpanded; CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(E); assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); - return DiagnoseUnexpandedParameterPacks(E->getLocStart(), UPPC, Unexpanded); + return DiagnoseUnexpandedParameterPacks(E->getBeginLoc(), UPPC, Unexpanded); } bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS, @@ -976,6 +976,7 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S, PDiag(diag::note_parameter_pack_here)); ParameterPack = Corrected.getCorrectionDecl(); } + break; case LookupResult::FoundOverloaded: case LookupResult::FoundUnresolvedValue: @@ -1125,8 +1126,8 @@ static void CheckFoldOperand(Sema &S, Expr *E) { isa<AbstractConditionalOperator>(E)) { S.Diag(E->getExprLoc(), diag::err_fold_expression_bad_operand) << E->getSourceRange() - << FixItHint::CreateInsertion(E->getLocStart(), "(") - << FixItHint::CreateInsertion(E->getLocEnd(), ")"); + << FixItHint::CreateInsertion(E->getBeginLoc(), "(") + << FixItHint::CreateInsertion(E->getEndLoc(), ")"); } } diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 284d34b22c04d..b4c075e9c46d4 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -116,6 +116,7 @@ static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr, case ParsedAttr::AT_Pascal: \ case ParsedAttr::AT_SwiftCall: \ case ParsedAttr::AT_VectorCall: \ + case ParsedAttr::AT_AArch64VectorPcs: \ case ParsedAttr::AT_MSABI: \ case ParsedAttr::AT_SysVABI: \ case ParsedAttr::AT_Pcs: \ @@ -172,11 +173,25 @@ namespace { /// processing is complete. SmallVector<ParsedAttr *, 2> ignoredTypeAttrs; + /// Attributes corresponding to AttributedTypeLocs that we have not yet + /// populated. + // FIXME: The two-phase mechanism by which we construct Types and fill + // their TypeLocs makes it hard to correctly assign these. We keep the + // attributes in creation order as an attempt to make them line up + // properly. + using TypeAttrPair = std::pair<const AttributedType*, const Attr*>; + SmallVector<TypeAttrPair, 8> AttrsForTypes; + bool AttrsForTypesSorted = true; + + /// Flag to indicate we parsed a noderef attribute. This is used for + /// validating that noderef was used on a pointer or array. + bool parsedNoDeref; + public: TypeProcessingState(Sema &sema, Declarator &declarator) - : sema(sema), declarator(declarator), - chunkIndex(declarator.getNumTypeObjects()), - trivial(true), hasSavedAttrs(false) {} + : sema(sema), declarator(declarator), + chunkIndex(declarator.getNumTypeObjects()), trivial(true), + hasSavedAttrs(false), parsedNoDeref(false) {} Sema &getSema() const { return sema; @@ -230,6 +245,47 @@ namespace { diagnoseBadTypeAttribute(getSema(), *Attr, type); } + /// Get an attributed type for the given attribute, and remember the Attr + /// object so that we can attach it to the AttributedTypeLoc. + QualType getAttributedType(Attr *A, QualType ModifiedType, + QualType EquivType) { + QualType T = + sema.Context.getAttributedType(A->getKind(), ModifiedType, EquivType); + AttrsForTypes.push_back({cast<AttributedType>(T.getTypePtr()), A}); + AttrsForTypesSorted = false; + return T; + } + + /// Extract and remove the Attr* for a given attributed type. + const Attr *takeAttrForAttributedType(const AttributedType *AT) { + if (!AttrsForTypesSorted) { + std::stable_sort(AttrsForTypes.begin(), AttrsForTypes.end(), + [](const TypeAttrPair &A, const TypeAttrPair &B) { + return A.first < B.first; + }); + AttrsForTypesSorted = true; + } + + // FIXME: This is quadratic if we have lots of reuses of the same + // attributed type. + for (auto It = std::partition_point( + AttrsForTypes.begin(), AttrsForTypes.end(), + [=](const TypeAttrPair &A) { return A.first < AT; }); + It != AttrsForTypes.end() && It->first == AT; ++It) { + if (It->second) { + const Attr *Result = It->second; + It->second = nullptr; + return Result; + } + } + + llvm_unreachable("no Attr* for AttributedType*"); + } + + void setParsedNoDeref(bool parsed) { parsedNoDeref = parsed; } + + bool didParseNoDeref() const { return parsedNoDeref; } + ~TypeProcessingState() { if (trivial) return; @@ -246,7 +302,7 @@ namespace { getMutableDeclSpec().getAttributes().clearListOnly(); for (ParsedAttr *AL : savedAttrs) - getMutableDeclSpec().getAttributes().addAtStart(AL); + getMutableDeclSpec().getAttributes().addAtEnd(AL); } }; } // end anonymous namespace @@ -255,7 +311,7 @@ static void moveAttrFromListToList(ParsedAttr &attr, ParsedAttributesView &fromList, ParsedAttributesView &toList) { fromList.remove(&attr); - toList.addAtStart(&attr); + toList.addAtEnd(&attr); } /// The location of a type attribute. @@ -656,7 +712,7 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state, // faking up the function chunk is still the right thing to do. // Otherwise, we need to fake up a function declarator. - SourceLocation loc = declarator.getLocStart(); + SourceLocation loc = declarator.getBeginLoc(); // ...and *prepend* it to the declarator. SourceLocation NoLoc; @@ -668,12 +724,8 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state, /*NumArgs=*/0, /*EllipsisLoc=*/NoLoc, /*RParenLoc=*/NoLoc, - /*TypeQuals=*/0, /*RefQualifierIsLvalueRef=*/true, /*RefQualifierLoc=*/NoLoc, - /*ConstQualifierLoc=*/NoLoc, - /*VolatileQualifierLoc=*/NoLoc, - /*RestrictQualifierLoc=*/NoLoc, /*MutableLoc=*/NoLoc, EST_None, /*ESpecRange=*/SourceRange(), /*Exceptions=*/nullptr, @@ -681,8 +733,7 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state, /*NumExceptions=*/0, /*NoexceptExpr=*/nullptr, /*ExceptionSpecTokens=*/nullptr, - /*DeclsInPrototype=*/None, - loc, loc, declarator)); + /*DeclsInPrototype=*/None, loc, loc, declarator)); // For consistency, make sure the state still has us as processing // the decl spec. @@ -808,17 +859,17 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, rangeToRemove = attr.getLocalSourceRange(); if (attr.getTypePtr()->getImmediateNullability()) { typeArg = attr.getTypePtr()->getModifiedType(); - S.Diag(attr.getLocStart(), + S.Diag(attr.getBeginLoc(), diag::err_objc_type_arg_explicit_nullability) - << typeArg << FixItHint::CreateRemoval(rangeToRemove); + << typeArg << FixItHint::CreateRemoval(rangeToRemove); diagnosed = true; } } if (!diagnosed) { - S.Diag(qual.getLocStart(), diag::err_objc_type_arg_qualified) - << typeArg << typeArg.getQualifiers().getAsString() - << FixItHint::CreateRemoval(rangeToRemove); + S.Diag(qual.getBeginLoc(), diag::err_objc_type_arg_qualified) + << typeArg << typeArg.getQualifiers().getAsString() + << FixItHint::CreateRemoval(rangeToRemove); } } @@ -878,9 +929,9 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, } // Diagnose the mismatch. - S.Diag(typeArgInfo->getTypeLoc().getLocStart(), + S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(), diag::err_objc_type_arg_does_not_match_bound) - << typeArg << bound << typeParam->getDeclName(); + << typeArg << bound << typeParam->getDeclName(); S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here) << typeParam->getDeclName(); @@ -906,9 +957,9 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, continue; // Diagnose the mismatch. - S.Diag(typeArgInfo->getTypeLoc().getLocStart(), + S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(), diag::err_objc_type_arg_does_not_match_bound) - << typeArg << bound << typeParam->getDeclName(); + << typeArg << bound << typeParam->getDeclName(); S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here) << typeParam->getDeclName(); @@ -924,10 +975,9 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, } // Diagnose non-id-compatible type arguments. - S.Diag(typeArgInfo->getTypeLoc().getLocStart(), + S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(), diag::err_objc_type_arg_not_id_compatible) - << typeArg - << typeArgInfo->getTypeLoc().getSourceRange(); + << typeArg << typeArgInfo->getTypeLoc().getSourceRange(); if (failOnError) return QualType(); @@ -1186,7 +1236,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { DeclSpec &DS = declarator.getMutableDeclSpec(); SourceLocation DeclLoc = declarator.getIdentifierLoc(); if (DeclLoc.isInvalid()) - DeclLoc = DS.getLocStart(); + DeclLoc = DS.getBeginLoc(); ASTContext &Context = S.Context; @@ -1268,8 +1318,8 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // when one is not allowed. if (DS.isEmpty()) { S.Diag(DeclLoc, diag::ext_missing_declspec) - << DS.getSourceRange() - << FixItHint::CreateInsertion(DS.getLocStart(), "int"); + << DS.getSourceRange() + << FixItHint::CreateInsertion(DS.getBeginLoc(), "int"); } } else if (!DS.hasTypeSpecifier()) { // C99 and C++ require a type specifier. For example, C99 6.7.2p2 says: @@ -1818,8 +1868,7 @@ static QualType inferARCLifetimeForPointee(Sema &S, QualType type, } static std::string getFunctionQualifiersAsString(const FunctionProtoType *FnTy){ - std::string Quals = - Qualifiers::fromCVRMask(FnTy->getTypeQuals()).getAsString(); + std::string Quals = FnTy->getTypeQuals().getAsString(); switch (FnTy->getRefQualifier()) { case RQ_None: @@ -1861,7 +1910,7 @@ static bool checkQualifiedFunction(Sema &S, QualType T, SourceLocation Loc, QualifiedFunctionKind QFK) { // Does T refer to a function type with a cv-qualifier or a ref-qualifier? const FunctionProtoType *FPT = T->getAs<FunctionProtoType>(); - if (!FPT || (FPT->getTypeQuals() == 0 && FPT->getRefQualifier() == RQ_None)) + if (!FPT || (FPT->getTypeQuals().empty() && FPT->getRefQualifier() == RQ_None)) return false; S.Diag(Loc, diag::err_compound_qualified_function_type) @@ -2117,8 +2166,8 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, if (!getLangOpts().CPlusPlus11 && ArraySize && !ArraySize->isTypeDependent() && !ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) { - Diag(ArraySize->getLocStart(), diag::err_array_size_non_int) - << ArraySize->getType() << ArraySize->getSourceRange(); + Diag(ArraySize->getBeginLoc(), diag::err_array_size_non_int) + << ArraySize->getType() << ArraySize->getSourceRange(); return QualType(); } @@ -2137,8 +2186,8 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, // of a VLA. if (getLangOpts().CPlusPlus11 && !ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) { - Diag(ArraySize->getLocStart(), diag::err_array_size_non_int) - << ArraySize->getType() << ArraySize->getSourceRange(); + Diag(ArraySize->getBeginLoc(), diag::err_array_size_non_int) + << ArraySize->getType() << ArraySize->getSourceRange(); return QualType(); } @@ -2151,25 +2200,25 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, // have a value greater than zero. if (ConstVal.isSigned() && ConstVal.isNegative()) { if (Entity) - Diag(ArraySize->getLocStart(), diag::err_decl_negative_array_size) - << getPrintableNameForEntity(Entity) << ArraySize->getSourceRange(); + Diag(ArraySize->getBeginLoc(), diag::err_decl_negative_array_size) + << getPrintableNameForEntity(Entity) << ArraySize->getSourceRange(); else - Diag(ArraySize->getLocStart(), diag::err_typecheck_negative_array_size) - << ArraySize->getSourceRange(); + 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->getLocStart(), - isSFINAEContext()? diag::err_typecheck_zero_array_size - : diag::ext_typecheck_zero_array_size) - << ArraySize->getSourceRange(); + Diag(ArraySize->getBeginLoc(), isSFINAEContext() + ? diag::err_typecheck_zero_array_size + : diag::ext_typecheck_zero_array_size) + << ArraySize->getSourceRange(); if (ASM == ArrayType::Static) { - Diag(ArraySize->getLocStart(), + Diag(ArraySize->getBeginLoc(), diag::warn_typecheck_zero_static_array_size) - << ArraySize->getSourceRange(); + << ArraySize->getSourceRange(); ASM = ArrayType::Normal; } } else if (!T->isDependentType() && !T->isVariablyModifiedType() && @@ -2178,9 +2227,8 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, unsigned ActiveSizeBits = ConstantArrayType::getNumAddressingBits(Context, T, ConstVal); if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) { - Diag(ArraySize->getLocStart(), diag::err_array_too_large) - << ConstVal.toString(10) - << ArraySize->getSourceRange(); + Diag(ArraySize->getBeginLoc(), diag::err_array_too_large) + << ConstVal.toString(10) << ArraySize->getSourceRange(); return QualType(); } } @@ -2842,6 +2890,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, // class template argument deduction)? bool IsCXXAutoType = (Auto && Auto->getKeyword() != AutoTypeKeyword::GNUAutoType); + bool IsDeducedReturnType = false; switch (D.getContext()) { case DeclaratorContext::LambdaExprContext: @@ -2873,9 +2922,9 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, TemplateTypeParmDecl *CorrespondingTemplateParam = TemplateTypeParmDecl::Create( SemaRef.Context, SemaRef.Context.getTranslationUnitDecl(), - /*KeyLoc*/SourceLocation(), /*NameLoc*/D.getLocStart(), + /*KeyLoc*/ SourceLocation(), /*NameLoc*/ D.getBeginLoc(), TemplateParameterDepth, AutoParameterPosition, - /*Identifier*/nullptr, false, IsParameterPack); + /*Identifier*/ nullptr, false, IsParameterPack); LSI->AutoTemplateParams.push_back(CorrespondingTemplateParam); // Replace the 'auto' in the function parameter with this invented // template type parameter. @@ -2933,10 +2982,12 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, case DeclaratorContext::TrailingReturnVarContext: if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType) Error = 13; // Function return type + IsDeducedReturnType = true; break; case DeclaratorContext::ConversionIdContext: if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType) Error = 14; // conversion-type-id + IsDeducedReturnType = true; break; case DeclaratorContext::FunctionalCastContext: if (isa<DeducedTemplateSpecializationType>(Deduced)) @@ -3021,10 +3072,14 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, D.getContext() != DeclaratorContext::LambdaExprContext) { // If there was a trailing return type, we already got // warn_cxx98_compat_trailing_return_type in the parser. - // If this was a lambda, we already warned on that too. SemaRef.Diag(AutoRange.getBegin(), - diag::warn_cxx98_compat_auto_type_specifier) - << AutoRange; + D.getContext() == + DeclaratorContext::LambdaExprParameterContext + ? diag::warn_cxx11_compat_generic_lambda + : IsDeducedReturnType + ? diag::warn_cxx11_compat_deduced_return_type + : diag::warn_cxx98_compat_auto_type_specifier) + << AutoRange; } } @@ -3302,9 +3357,9 @@ static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) { << D.getIdentifier(); // FIXME: A cast to void is probably a better suggestion in cases where it's // valid (when there is no initializer and we're not in a condition). - S.Diag(D.getLocStart(), diag::note_function_style_cast_add_parentheses) - << FixItHint::CreateInsertion(D.getLocStart(), "(") - << FixItHint::CreateInsertion(S.getLocForEndOfToken(D.getLocEnd()), ")"); + S.Diag(D.getBeginLoc(), diag::note_function_style_cast_add_parentheses) + << FixItHint::CreateInsertion(D.getBeginLoc(), "(") + << FixItHint::CreateInsertion(S.getLocForEndOfToken(D.getEndLoc()), ")"); S.Diag(Paren.Loc, diag::note_remove_parens_for_variable_declaration) << FixItHint::CreateRemoval(Paren.Loc) << FixItHint::CreateRemoval(Paren.EndLoc); @@ -3834,6 +3889,37 @@ static bool hasOuterPointerLikeChunk(const Declarator &D, unsigned endIndex) { return false; } +static bool IsNoDerefableChunk(DeclaratorChunk Chunk) { + return (Chunk.Kind == DeclaratorChunk::Pointer || + Chunk.Kind == DeclaratorChunk::Array); +} + +template<typename AttrT> +static AttrT *createSimpleAttr(ASTContext &Ctx, ParsedAttr &Attr) { + Attr.setUsedAsTypeAttr(); + return ::new (Ctx) + AttrT(Attr.getRange(), Ctx, Attr.getAttributeSpellingListIndex()); +} + +static Attr *createNullabilityAttr(ASTContext &Ctx, ParsedAttr &Attr, + NullabilityKind NK) { + switch (NK) { + case NullabilityKind::NonNull: + return createSimpleAttr<TypeNonNullAttr>(Ctx, Attr); + + case NullabilityKind::Nullable: + return createSimpleAttr<TypeNullableAttr>(Ctx, Attr); + + case NullabilityKind::Unspecified: + return createSimpleAttr<TypeNullUnspecifiedAttr>(Ctx, Attr); + } + llvm_unreachable("unknown NullabilityKind"); +} + +static TypeSourceInfo * +GetTypeSourceInfoForDeclarator(TypeProcessingState &State, + QualType T, TypeSourceInfo *ReturnTypeInfo); + static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, QualType declSpecType, TypeSourceInfo *TInfo) { @@ -3858,7 +3944,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // Does T refer to a function type with a cv-qualifier or a ref-qualifier? bool IsQualifiedFunction = T->isFunctionProtoType() && - (T->castAs<FunctionProtoType>()->getTypeQuals() != 0 || + (!T->castAs<FunctionProtoType>()->getTypeQuals().empty() || T->castAs<FunctionProtoType>()->getRefQualifier() != RQ_None); // If T is 'decltype(auto)', the only declarators we can have are parens @@ -4128,7 +4214,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, SourceRange(pointerLoc), nullptr, SourceLocation(), nullptr, 0, syntax); - attrs.addAtStart(nullabilityAttr); + attrs.addAtEnd(nullabilityAttr); if (inferNullabilityCS) { state.getDeclarator().getMutableDeclSpec().getObjCQualifiers() @@ -4184,11 +4270,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, if (auto *attr = inferPointerNullability( pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(), - D.getDeclSpec().getLocEnd(), + D.getDeclSpec().getEndLoc(), D.getMutableDeclSpec().getAttributes())) { - T = Context.getAttributedType( - AttributedType::getNullabilityAttrKind(*inferNullability),T,T); - attr->setUsedAsTypeAttr(); + T = state.getAttributedType( + createNullabilityAttr(Context, *attr, *inferNullability), T, T); } } } @@ -4202,6 +4287,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, } } + bool ExpectNoDerefChunk = + state.getCurrentAttributes().hasAttribute(ParsedAttr::AT_NoDeref); + // Walk the DeclTypeInfo, building the recursive type as we go. // DeclTypeInfos are ordered from the identifier out, which is // opposite of what we want :). @@ -4247,7 +4335,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, inferPointerNullability(SimplePointerKind::Pointer, DeclType.Loc, DeclType.EndLoc, DeclType.getAttrs()); - if (LangOpts.ObjC1 && T->getAs<ObjCObjectType>()) { + if (LangOpts.ObjC && T->getAs<ObjCObjectType>()) { T = Context.getObjCObjectPointerType(T); if (DeclType.Ptr.TypeQuals) T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals); @@ -4367,7 +4455,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // does not have a K&R-style identifier list), then the arguments are part // of the type, otherwise the argument list is (). const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun; - IsQualifiedFunction = FTI.TypeQuals || FTI.hasRefQualifier(); + IsQualifiedFunction = + FTI.hasMethodTypeQualifiers() || FTI.hasRefQualifier(); // Check for auto functions and trailing return type and adjust the // return type accordingly. @@ -4375,25 +4464,28 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // trailing-return-type is only required if we're declaring a function, // and not, for instance, a pointer to a function. if (D.getDeclSpec().hasAutoTypeSpec() && - !FTI.hasTrailingReturnType() && chunkIndex == 0 && - !S.getLangOpts().CPlusPlus14) { - S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(), - D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto - ? diag::err_auto_missing_trailing_return - : diag::err_deduced_return_type); - T = Context.IntTy; - D.setInvalidType(true); + !FTI.hasTrailingReturnType() && chunkIndex == 0) { + if (!S.getLangOpts().CPlusPlus14) { + S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(), + D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto + ? diag::err_auto_missing_trailing_return + : diag::err_deduced_return_type); + T = Context.IntTy; + D.setInvalidType(true); + } else { + S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(), + diag::warn_cxx11_compat_deduced_return_type); + } } else if (FTI.hasTrailingReturnType()) { // T must be exactly 'auto' at this point. See CWG issue 681. if (isa<ParenType>(T)) { - S.Diag(D.getLocStart(), - diag::err_trailing_return_in_parens) - << T << D.getSourceRange(); + S.Diag(D.getBeginLoc(), diag::err_trailing_return_in_parens) + << T << D.getSourceRange(); D.setInvalidType(true); } else if (D.getName().getKind() == UnqualifiedIdKind::IK_DeductionGuideName) { if (T != Context.DependentTy) { - S.Diag(D.getDeclSpec().getLocStart(), + S.Diag(D.getDeclSpec().getBeginLoc(), diag::err_deduction_guide_with_complex_decl) << D.getSourceRange(); D.setInvalidType(true); @@ -4413,6 +4505,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, T = Context.IntTy; D.setInvalidType(true); } + } else { + // This function type is not the type of the entity being declared, + // so checking the 'auto' is not the responsibility of this chunk. } } @@ -4475,11 +4570,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, if (T->isObjCObjectType()) { SourceLocation DiagLoc, FixitLoc; if (TInfo) { - DiagLoc = TInfo->getTypeLoc().getLocStart(); - FixitLoc = S.getLocForEndOfToken(TInfo->getTypeLoc().getLocEnd()); + DiagLoc = TInfo->getTypeLoc().getBeginLoc(); + FixitLoc = S.getLocForEndOfToken(TInfo->getTypeLoc().getEndLoc()); } else { DiagLoc = D.getDeclSpec().getTypeSpecTypeLoc(); - FixitLoc = S.getLocForEndOfToken(D.getDeclSpec().getLocEnd()); + FixitLoc = S.getLocForEndOfToken(D.getDeclSpec().getEndLoc()); } S.Diag(DiagLoc, diag::err_object_cannot_be_passed_returned_by_value) << 0 << T @@ -4599,7 +4694,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, EPI.ExtInfo = EI; EPI.Variadic = FTI.isVariadic; EPI.HasTrailingReturn = FTI.hasTrailingReturnType(); - EPI.TypeQuals = FTI.TypeQuals; + EPI.TypeQuals.addCVRUQualifiers( + FTI.MethodQualifiers ? FTI.MethodQualifiers->getTypeQualifiers() + : 0); EPI.RefQualifier = !FTI.hasRefQualifier()? RQ_None : FTI.RefQualifierIsLValueRef? RQ_LValue : RQ_RValue; @@ -4726,6 +4823,20 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, Exceptions, EPI.ExceptionSpec); + const auto &Spec = D.getCXXScopeSpec(); + // OpenCLCPlusPlus: A class member function has an address space. + if (state.getSema().getLangOpts().OpenCLCPlusPlus && + ((!Spec.isEmpty() && + Spec.getScopeRep()->getKind() == NestedNameSpecifier::TypeSpec) || + state.getDeclarator().getContext() == + DeclaratorContext::MemberContext)) { + LangAS CurAS = EPI.TypeQuals.getAddressSpace(); + // If a class member function's address space is not set, set it to + // __generic. + LangAS AS = + (CurAS == LangAS::Default ? LangAS::opencl_generic : CurAS); + EPI.TypeQuals.addAddressSpace(AS); + } T = Context.getFunctionType(T, ParamTys, EPI); } break; @@ -4805,8 +4916,22 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // See if there are any attributes on this declarator chunk. processTypeAttrs(state, T, TAL_DeclChunk, DeclType.getAttrs()); + + if (DeclType.Kind != DeclaratorChunk::Paren) { + if (ExpectNoDerefChunk) { + if (!IsNoDerefableChunk(DeclType)) + S.Diag(DeclType.Loc, diag::warn_noderef_on_non_pointer_or_array); + ExpectNoDerefChunk = false; + } + + ExpectNoDerefChunk = state.didParseNoDeref(); + } } + if (ExpectNoDerefChunk) + S.Diag(state.getDeclarator().getBeginLoc(), + diag::warn_noderef_on_non_pointer_or_array); + // GNU warning -Wstrict-prototypes // Warn if a function declaration is without a prototype. // This warning is issued for all kinds of unprototyped function @@ -4887,23 +5012,24 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, !IsTypedefName && D.getContext() != DeclaratorContext::TemplateArgContext && D.getContext() != DeclaratorContext::TemplateTypeArgContext) { - SourceLocation Loc = D.getLocStart(); + SourceLocation Loc = D.getBeginLoc(); SourceRange RemovalRange; unsigned I; if (D.isFunctionDeclarator(I)) { SmallVector<SourceLocation, 4> RemovalLocs; const DeclaratorChunk &Chunk = D.getTypeObject(I); assert(Chunk.Kind == DeclaratorChunk::Function); + if (Chunk.Fun.hasRefQualifier()) RemovalLocs.push_back(Chunk.Fun.getRefQualifierLoc()); - if (Chunk.Fun.TypeQuals & Qualifiers::Const) - RemovalLocs.push_back(Chunk.Fun.getConstQualifierLoc()); - if (Chunk.Fun.TypeQuals & Qualifiers::Volatile) - RemovalLocs.push_back(Chunk.Fun.getVolatileQualifierLoc()); - if (Chunk.Fun.TypeQuals & Qualifiers::Restrict) - RemovalLocs.push_back(Chunk.Fun.getRestrictQualifierLoc()); + + if (Chunk.Fun.hasMethodTypeQualifiers()) + Chunk.Fun.MethodQualifiers->forEachQualifier( + [&](DeclSpec::TQ TypeQual, StringRef QualName, + SourceLocation SL) { RemovalLocs.push_back(SL); }); + if (!RemovalLocs.empty()) { - llvm::sort(RemovalLocs.begin(), RemovalLocs.end(), + llvm::sort(RemovalLocs, BeforeThanCompare<SourceLocation>(S.getSourceManager())); RemovalRange = SourceRange(RemovalLocs.front(), RemovalLocs.back()); Loc = RemovalLocs.front(); @@ -4917,7 +5043,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // Strip the cv-qualifiers and ref-qualifiers from the type. FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo(); - EPI.TypeQuals = 0; + EPI.TypeQuals.removeCVRQualifiers(); EPI.RefQualifier = RQ_None; T = Context.getFunctionType(FnTy->getReturnType(), FnTy->getParamTypes(), @@ -5028,7 +5154,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, if (D.isInvalidType()) return Context.getTrivialTypeSourceInfo(T); - return S.GetTypeSourceInfoForDeclarator(D, T, TInfo); + return GetTypeSourceInfoForDeclarator(state, T, TInfo); } /// GetTypeForDeclarator - Convert the type for the specified @@ -5093,7 +5219,7 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state, &S.Context.Idents.get("objc_ownership"), SourceLocation(), /*scope*/ nullptr, SourceLocation(), /*args*/ &Args, 1, ParsedAttr::AS_GNU); - chunk.getAttrs().addAtStart(attr); + chunk.getAttrs().addAtEnd(attr); // TODO: mark whether we did this inference? } @@ -5155,7 +5281,7 @@ TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) { TypeSourceInfo *ReturnTypeInfo = nullptr; QualType declSpecTy = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo); - if (getLangOpts().ObjC1) { + if (getLangOpts().ObjC) { Qualifiers::ObjCLifetime ownership = Context.getInnerObjCOwnership(FromTy); if (ownership != Qualifiers::OCL_None) transferARCOwnership(state, declSpecTy, ownership); @@ -5164,131 +5290,25 @@ TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) { return GetFullTypeForDeclarator(state, declSpecTy, ReturnTypeInfo); } -/// Map an AttributedType::Kind to an ParsedAttr::Kind. -static ParsedAttr::Kind getAttrListKind(AttributedType::Kind kind) { - switch (kind) { - case AttributedType::attr_address_space: - return ParsedAttr::AT_AddressSpace; - case AttributedType::attr_regparm: - return ParsedAttr::AT_Regparm; - case AttributedType::attr_vector_size: - return ParsedAttr::AT_VectorSize; - case AttributedType::attr_neon_vector_type: - return ParsedAttr::AT_NeonVectorType; - case AttributedType::attr_neon_polyvector_type: - return ParsedAttr::AT_NeonPolyVectorType; - case AttributedType::attr_objc_gc: - return ParsedAttr::AT_ObjCGC; - case AttributedType::attr_objc_ownership: - case AttributedType::attr_objc_inert_unsafe_unretained: - return ParsedAttr::AT_ObjCOwnership; - case AttributedType::attr_noreturn: - return ParsedAttr::AT_NoReturn; - case AttributedType::attr_nocf_check: - return ParsedAttr::AT_AnyX86NoCfCheck; - case AttributedType::attr_cdecl: - return ParsedAttr::AT_CDecl; - case AttributedType::attr_fastcall: - return ParsedAttr::AT_FastCall; - case AttributedType::attr_stdcall: - return ParsedAttr::AT_StdCall; - case AttributedType::attr_thiscall: - return ParsedAttr::AT_ThisCall; - case AttributedType::attr_regcall: - return ParsedAttr::AT_RegCall; - case AttributedType::attr_pascal: - return ParsedAttr::AT_Pascal; - case AttributedType::attr_swiftcall: - return ParsedAttr::AT_SwiftCall; - case AttributedType::attr_vectorcall: - return ParsedAttr::AT_VectorCall; - case AttributedType::attr_pcs: - case AttributedType::attr_pcs_vfp: - return ParsedAttr::AT_Pcs; - case AttributedType::attr_inteloclbicc: - return ParsedAttr::AT_IntelOclBicc; - case AttributedType::attr_ms_abi: - return ParsedAttr::AT_MSABI; - case AttributedType::attr_sysv_abi: - return ParsedAttr::AT_SysVABI; - case AttributedType::attr_preserve_most: - return ParsedAttr::AT_PreserveMost; - case AttributedType::attr_preserve_all: - return ParsedAttr::AT_PreserveAll; - case AttributedType::attr_ptr32: - return ParsedAttr::AT_Ptr32; - case AttributedType::attr_ptr64: - return ParsedAttr::AT_Ptr64; - case AttributedType::attr_sptr: - return ParsedAttr::AT_SPtr; - case AttributedType::attr_uptr: - return ParsedAttr::AT_UPtr; - case AttributedType::attr_nonnull: - return ParsedAttr::AT_TypeNonNull; - case AttributedType::attr_nullable: - return ParsedAttr::AT_TypeNullable; - case AttributedType::attr_null_unspecified: - return ParsedAttr::AT_TypeNullUnspecified; - case AttributedType::attr_objc_kindof: - return ParsedAttr::AT_ObjCKindOf; - case AttributedType::attr_ns_returns_retained: - return ParsedAttr::AT_NSReturnsRetained; - case AttributedType::attr_lifetimebound: - return ParsedAttr::AT_LifetimeBound; - } - llvm_unreachable("unexpected attribute kind!"); -} - -static void setAttributedTypeLoc(AttributedTypeLoc TL, const ParsedAttr &attr) { - TL.setAttrNameLoc(attr.getLoc()); - if (TL.hasAttrExprOperand()) { - assert(attr.isArgExpr(0) && "mismatched attribute operand kind"); - TL.setAttrExprOperand(attr.getArgAsExpr(0)); - } else if (TL.hasAttrEnumOperand()) { - assert((attr.isArgIdent(0) || attr.isArgExpr(0)) && - "unexpected attribute operand kind"); - if (attr.isArgIdent(0)) - TL.setAttrEnumOperandLoc(attr.getArgAsIdent(0)->Loc); - else - TL.setAttrEnumOperandLoc(attr.getArgAsExpr(0)->getExprLoc()); - } - - // FIXME: preserve this information to here. - if (TL.hasAttrOperand()) - TL.setAttrOperandParensRange(SourceRange()); -} - static void fillAttributedTypeLoc(AttributedTypeLoc TL, - const ParsedAttributesView &Attrs, - const ParsedAttributesView &DeclAttrs) { - // DeclAttrs and Attrs cannot be both empty. - assert((!Attrs.empty() || !DeclAttrs.empty()) && - "no type attributes in the expected location!"); - - ParsedAttr::Kind parsedKind = getAttrListKind(TL.getAttrKind()); - // Try to search for an attribute of matching kind in Attrs list. - for (const ParsedAttr &AL : Attrs) - if (AL.getKind() == parsedKind) - return setAttributedTypeLoc(TL, AL); - - for (const ParsedAttr &AL : DeclAttrs) - if (AL.isCXX11Attribute() || AL.getKind() == parsedKind) - return setAttributedTypeLoc(TL, AL); - llvm_unreachable("no matching type attribute in expected location!"); + TypeProcessingState &State) { + TL.setAttr(State.takeAttrForAttributedType(TL.getTypePtr())); } namespace { class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> { ASTContext &Context; + TypeProcessingState &State; const DeclSpec &DS; public: - TypeSpecLocFiller(ASTContext &Context, const DeclSpec &DS) - : Context(Context), DS(DS) {} + TypeSpecLocFiller(ASTContext &Context, TypeProcessingState &State, + const DeclSpec &DS) + : Context(Context), State(State), DS(DS) {} void VisitAttributedTypeLoc(AttributedTypeLoc TL) { - fillAttributedTypeLoc(TL, DS.getAttributes(), ParsedAttributesView{}); Visit(TL.getModifiedLoc()); + fillAttributedTypeLoc(TL, State); } void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { Visit(TL.getUnqualifiedLoc()); @@ -5301,7 +5321,7 @@ namespace { // FIXME. We should have DS.getTypeSpecTypeEndLoc(). But, it requires // addition field. What we have is good enough for dispay of location // of 'fixit' on interface name. - TL.setNameEndLoc(DS.getLocEnd()); + TL.setNameEndLoc(DS.getEndLoc()); } void VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { TypeSourceInfo *RepTInfo = nullptr; @@ -5445,11 +5465,13 @@ namespace { class DeclaratorLocFiller : public TypeLocVisitor<DeclaratorLocFiller> { ASTContext &Context; + TypeProcessingState &State; const DeclaratorChunk &Chunk; public: - DeclaratorLocFiller(ASTContext &Context, const DeclaratorChunk &Chunk) - : Context(Context), Chunk(Chunk) {} + DeclaratorLocFiller(ASTContext &Context, TypeProcessingState &State, + const DeclaratorChunk &Chunk) + : Context(Context), State(State), Chunk(Chunk) {} void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { llvm_unreachable("qualified type locs not expected here!"); @@ -5459,7 +5481,7 @@ namespace { } void VisitAttributedTypeLoc(AttributedTypeLoc TL) { - fillAttributedTypeLoc(TL, Chunk.getAttrs(), ParsedAttributesView{}); + fillAttributedTypeLoc(TL, State); } void VisitAdjustedTypeLoc(AdjustedTypeLoc TL) { // nothing @@ -5616,10 +5638,13 @@ fillDependentAddressSpaceTypeLoc(DependentAddressSpaceTypeLoc DASTL, /// up in the normal place in the declaration specifiers (such as a C++ /// conversion function), this pointer will refer to a type source information /// for that return type. -TypeSourceInfo * -Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, - TypeSourceInfo *ReturnTypeInfo) { - TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T); +static TypeSourceInfo * +GetTypeSourceInfoForDeclarator(TypeProcessingState &State, + QualType T, TypeSourceInfo *ReturnTypeInfo) { + Sema &S = State.getSema(); + Declarator &D = State.getDeclarator(); + + TypeSourceInfo *TInfo = S.Context.CreateTypeSourceInfo(T); UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc(); // Handle parameter packs whose type is a pack expansion. @@ -5629,13 +5654,6 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, } for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { - - if (DependentAddressSpaceTypeLoc DASTL = - CurrTL.getAs<DependentAddressSpaceTypeLoc>()) { - fillDependentAddressSpaceTypeLoc(DASTL, D.getTypeObject(i).getAttrs()); - CurrTL = DASTL.getPointeeTypeLoc().getUnqualifiedLoc(); - } - // An AtomicTypeLoc might be produced by an atomic qualifier in this // declarator chunk. if (AtomicTypeLoc ATL = CurrTL.getAs<AtomicTypeLoc>()) { @@ -5644,16 +5662,21 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, } while (AttributedTypeLoc TL = CurrTL.getAs<AttributedTypeLoc>()) { - fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs(), - D.getAttributes()); + fillAttributedTypeLoc(TL, State); CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); } + while (DependentAddressSpaceTypeLoc TL = + CurrTL.getAs<DependentAddressSpaceTypeLoc>()) { + fillDependentAddressSpaceTypeLoc(TL, D.getTypeObject(i).getAttrs()); + CurrTL = TL.getPointeeTypeLoc().getUnqualifiedLoc(); + } + // FIXME: Ordering here? while (AdjustedTypeLoc TL = CurrTL.getAs<AdjustedTypeLoc>()) CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); - DeclaratorLocFiller(Context, D.getTypeObject(i)).Visit(CurrTL); + DeclaratorLocFiller(S.Context, State, D.getTypeObject(i)).Visit(CurrTL); CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc(); } @@ -5664,7 +5687,7 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, assert(TL.getFullDataSize() == CurrTL.getFullDataSize()); memcpy(CurrTL.getOpaqueData(), TL.getOpaqueData(), TL.getFullDataSize()); } else { - TypeSpecLocFiller(Context, D.getDeclSpec()).Visit(CurrTL); + TypeSpecLocFiller(S.Context, State, D.getDeclSpec()).Visit(CurrTL); } return TInfo; @@ -5801,7 +5824,10 @@ QualType Sema::BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace, /// specified type. The attribute contains 1 argument, the id of the address /// space for the type. static void HandleAddressSpaceTypeAttribute(QualType &Type, - const ParsedAttr &Attr, Sema &S) { + const ParsedAttr &Attr, + TypeProcessingState &State) { + Sema &S = State.getSema(); + // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "A function type shall not be // qualified by an address-space qualifier." if (Type->isFunctionType()) { @@ -5815,8 +5841,8 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, // Check the attribute arguments. if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << Attr.getName() << 1; + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Attr + << 1; Attr.setInvalid(); return; } @@ -5843,10 +5869,15 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, // the type. QualType T = S.BuildAddressSpaceAttr(Type, ASArgExpr, Attr.getLoc()); - if (!T.isNull()) - Type = T; - else + if (!T.isNull()) { + ASTContext &Ctx = S.Context; + auto *ASAttr = ::new (Ctx) AddressSpaceAttr( + Attr.getRange(), Ctx, Attr.getAttributeSpellingListIndex(), + static_cast<unsigned>(T.getQualifiers().getAddressSpace())); + Type = State.getAttributedType(ASAttr, T, T); + } else { Attr.setInvalid(); + } } else { // The keyword-based type attributes imply which address space to use. switch (Attr.getKind()) { @@ -5893,7 +5924,7 @@ static bool hasDirectOwnershipQualifier(QualType type) { while (true) { // __strong id if (const AttributedType *attr = dyn_cast<AttributedType>(type)) { - if (attr->getAttrKind() == AttributedType::attr_objc_ownership) + if (attr->getAttrKind() == attr::ObjCOwnership) return true; type = attr->getModifiedType(); @@ -5951,8 +5982,8 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, S.getSourceManager().getImmediateExpansionRange(AttrLoc).getBegin(); if (!attr.isArgIdent(0)) { - S.Diag(AttrLoc, diag::err_attribute_argument_type) - << attr.getName() << AANT_ArgumentString; + S.Diag(AttrLoc, diag::err_attribute_argument_type) << attr + << AANT_ArgumentString; attr.setInvalid(); return true; } @@ -6037,9 +6068,9 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, // the coexistence problems with __unsafe_unretained. if (!S.getLangOpts().ObjCAutoRefCount && lifetime == Qualifiers::OCL_ExplicitNone) { - type = S.Context.getAttributedType( - AttributedType::attr_objc_inert_unsafe_unretained, - type, type); + type = state.getAttributedType( + createSimpleAttr<ObjCInertUnsafeUnretainedAttr>(S.Context, attr), + type, type); return true; } @@ -6049,9 +6080,12 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, // If we have a valid source location for the attribute, use an // AttributedType instead. - if (AttrLoc.isValid()) - type = S.Context.getAttributedType(AttributedType::attr_objc_ownership, - origType, type); + if (AttrLoc.isValid()) { + type = state.getAttributedType(::new (S.Context) ObjCOwnershipAttr( + attr.getRange(), S.Context, II, + attr.getAttributeSpellingListIndex()), + origType, type); + } auto diagnoseOrDelay = [](Sema &S, SourceLocation loc, unsigned diagnostic, QualType type) { @@ -6122,14 +6156,14 @@ static bool handleObjCGCTypeAttr(TypeProcessingState &state, ParsedAttr &attr, // Check the attribute arguments. if (!attr.isArgIdent(0)) { S.Diag(attr.getLoc(), diag::err_attribute_argument_type) - << attr.getName() << AANT_ArgumentString; + << attr << AANT_ArgumentString; attr.setInvalid(); return true; } Qualifiers::GC GCAttr; if (attr.getNumArgs() > 1) { - S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << attr.getName() << 1; + S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << attr + << 1; attr.setInvalid(); return true; } @@ -6151,8 +6185,10 @@ static bool handleObjCGCTypeAttr(TypeProcessingState &state, ParsedAttr &attr, // Make an attributed type to preserve the source information. if (attr.getLoc().isValid()) - type = S.Context.getAttributedType(AttributedType::attr_objc_gc, - origType, type); + type = state.getAttributedType( + ::new (S.Context) ObjCGCAttr(attr.getRange(), S.Context, II, + attr.getAttributeSpellingListIndex()), + origType, type); return true; } @@ -6295,37 +6331,50 @@ namespace { } // end anonymous namespace static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State, - ParsedAttr &Attr, QualType &Type) { + ParsedAttr &PAttr, QualType &Type) { Sema &S = State.getSema(); - ParsedAttr::Kind Kind = Attr.getKind(); + Attr *A; + switch (PAttr.getKind()) { + default: llvm_unreachable("Unknown attribute kind"); + case ParsedAttr::AT_Ptr32: + A = createSimpleAttr<Ptr32Attr>(S.Context, PAttr); + break; + case ParsedAttr::AT_Ptr64: + A = createSimpleAttr<Ptr64Attr>(S.Context, PAttr); + break; + case ParsedAttr::AT_SPtr: + A = createSimpleAttr<SPtrAttr>(S.Context, PAttr); + break; + case ParsedAttr::AT_UPtr: + A = createSimpleAttr<UPtrAttr>(S.Context, PAttr); + break; + } + + attr::Kind NewAttrKind = A->getKind(); QualType Desugared = Type; const AttributedType *AT = dyn_cast<AttributedType>(Type); while (AT) { - AttributedType::Kind CurAttrKind = AT->getAttrKind(); + attr::Kind CurAttrKind = AT->getAttrKind(); // You cannot specify duplicate type attributes, so if the attribute has // already been applied, flag it. - if (getAttrListKind(CurAttrKind) == Kind) { - S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute_exact) - << Attr.getName(); + if (NewAttrKind == CurAttrKind) { + S.Diag(PAttr.getLoc(), diag::warn_duplicate_attribute_exact) + << PAttr.getName(); return true; } // You cannot have both __sptr and __uptr on the same type, nor can you // have __ptr32 and __ptr64. - if ((CurAttrKind == AttributedType::attr_ptr32 && - Kind == ParsedAttr::AT_Ptr64) || - (CurAttrKind == AttributedType::attr_ptr64 && - Kind == ParsedAttr::AT_Ptr32)) { - S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) + if ((CurAttrKind == attr::Ptr32 && NewAttrKind == attr::Ptr64) || + (CurAttrKind == attr::Ptr64 && NewAttrKind == attr::Ptr32)) { + S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible) << "'__ptr32'" << "'__ptr64'"; return true; - } else if ((CurAttrKind == AttributedType::attr_sptr && - Kind == ParsedAttr::AT_UPtr) || - (CurAttrKind == AttributedType::attr_uptr && - Kind == ParsedAttr::AT_SPtr)) { - S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) + } else if ((CurAttrKind == attr::SPtr && NewAttrKind == attr::UPtr) || + (CurAttrKind == attr::UPtr && NewAttrKind == attr::SPtr)) { + S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible) << "'__sptr'" << "'__uptr'"; return true; } @@ -6336,43 +6385,64 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State, // Pointer type qualifiers can only operate on pointer types, but not // pointer-to-member types. + // + // FIXME: Should we really be disallowing this attribute if there is any + // type sugar between it and the pointer (other than attributes)? Eg, this + // disallows the attribute on a parenthesized pointer. + // And if so, should we really allow *any* type attribute? if (!isa<PointerType>(Desugared)) { if (Type->isMemberPointerType()) - S.Diag(Attr.getLoc(), diag::err_attribute_no_member_pointers) - << Attr.getName(); + S.Diag(PAttr.getLoc(), diag::err_attribute_no_member_pointers) << PAttr; else - S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only) - << Attr.getName() << 0; + S.Diag(PAttr.getLoc(), diag::err_attribute_pointers_only) << PAttr << 0; return true; } - AttributedType::Kind TAK; - switch (Kind) { - default: llvm_unreachable("Unknown attribute kind"); - case ParsedAttr::AT_Ptr32: - TAK = AttributedType::attr_ptr32; - break; - case ParsedAttr::AT_Ptr64: - TAK = AttributedType::attr_ptr64; - break; - case ParsedAttr::AT_SPtr: - TAK = AttributedType::attr_sptr; - break; - case ParsedAttr::AT_UPtr: - TAK = AttributedType::attr_uptr; - break; - } - - Type = S.Context.getAttributedType(TAK, Type, Type); + Type = State.getAttributedType(A, Type, Type); return false; } -bool Sema::checkNullabilityTypeSpecifier(QualType &type, - NullabilityKind nullability, - SourceLocation nullabilityLoc, - bool isContextSensitive, - bool allowOnArrayType) { - recordNullabilitySeen(*this, nullabilityLoc); +/// Map a nullability attribute kind to a nullability kind. +static NullabilityKind mapNullabilityAttrKind(ParsedAttr::Kind kind) { + switch (kind) { + case ParsedAttr::AT_TypeNonNull: + return NullabilityKind::NonNull; + + case ParsedAttr::AT_TypeNullable: + return NullabilityKind::Nullable; + + case ParsedAttr::AT_TypeNullUnspecified: + return NullabilityKind::Unspecified; + + default: + llvm_unreachable("not a nullability attribute kind"); + } +} + +/// Applies a nullability type specifier to the given type, if possible. +/// +/// \param state The type processing state. +/// +/// \param type The type to which the nullability specifier will be +/// added. On success, this type will be updated appropriately. +/// +/// \param attr The attribute as written on the type. +/// +/// \param allowOnArrayType Whether to accept nullability specifiers on an +/// array type (e.g., because it will decay to a pointer). +/// +/// \returns true if a problem has been diagnosed, false on success. +static bool checkNullabilityTypeSpecifier(TypeProcessingState &state, + QualType &type, + ParsedAttr &attr, + bool allowOnArrayType) { + Sema &S = state.getSema(); + + NullabilityKind nullability = mapNullabilityAttrKind(attr.getKind()); + SourceLocation nullabilityLoc = attr.getLoc(); + bool isContextSensitive = attr.isContextSensitiveKeywordAttribute(); + + recordNullabilitySeen(S, nullabilityLoc); // Check for existing nullability attributes on the type. QualType desugared = type; @@ -6381,7 +6451,7 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type, if (auto existingNullability = attributed->getImmediateNullability()) { // Duplicated nullability. if (nullability == *existingNullability) { - Diag(nullabilityLoc, diag::warn_nullability_duplicate) + S.Diag(nullabilityLoc, diag::warn_nullability_duplicate) << DiagNullabilityKind(nullability, isContextSensitive) << FixItHint::CreateRemoval(nullabilityLoc); @@ -6389,7 +6459,7 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type, } // Conflicting nullability. - Diag(nullabilityLoc, diag::err_nullability_conflicting) + S.Diag(nullabilityLoc, diag::err_nullability_conflicting) << DiagNullabilityKind(nullability, isContextSensitive) << DiagNullabilityKind(*existingNullability, false); return true; @@ -6402,9 +6472,9 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type, // This (unlike the code above) looks through typedefs that might // have nullability specifiers on them, which means we cannot // provide a useful Fix-It. - if (auto existingNullability = desugared->getNullability(Context)) { + if (auto existingNullability = desugared->getNullability(S.Context)) { if (nullability != *existingNullability) { - Diag(nullabilityLoc, diag::err_nullability_conflicting) + S.Diag(nullabilityLoc, diag::err_nullability_conflicting) << DiagNullabilityKind(nullability, isContextSensitive) << DiagNullabilityKind(*existingNullability, false); @@ -6415,7 +6485,7 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type, if (auto typedefNullability = AttributedType::stripOuterNullability(underlyingType)) { if (*typedefNullability == *existingNullability) { - Diag(typedefDecl->getLocation(), diag::note_nullability_here) + S.Diag(typedefDecl->getLocation(), diag::note_nullability_here) << DiagNullabilityKind(*existingNullability, false); } } @@ -6428,7 +6498,7 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type, // If this definitely isn't a pointer type, reject the specifier. if (!desugared->canHaveNullability() && !(allowOnArrayType && desugared->isArrayType())) { - Diag(nullabilityLoc, diag::err_nullability_nonpointer) + S.Diag(nullabilityLoc, diag::err_nullability_nonpointer) << DiagNullabilityKind(nullability, isContextSensitive) << type; return true; } @@ -6446,10 +6516,10 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type, if (pointeeType->isAnyPointerType() || pointeeType->isObjCObjectPointerType() || pointeeType->isMemberPointerType()) { - Diag(nullabilityLoc, diag::err_nullability_cs_multilevel) + S.Diag(nullabilityLoc, diag::err_nullability_cs_multilevel) << DiagNullabilityKind(nullability, true) << type; - Diag(nullabilityLoc, diag::note_nullability_type_specifier) + S.Diag(nullabilityLoc, diag::note_nullability_type_specifier) << DiagNullabilityKind(nullability, false) << type << FixItHint::CreateReplacement(nullabilityLoc, @@ -6459,16 +6529,21 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type, } // Form the attributed type. - type = Context.getAttributedType( - AttributedType::getNullabilityAttrKind(nullability), type, type); + type = state.getAttributedType( + createNullabilityAttr(S.Context, attr, nullability), type, type); return false; } -bool Sema::checkObjCKindOfType(QualType &type, SourceLocation loc) { +/// Check the application of the Objective-C '__kindof' qualifier to +/// the given type. +static bool checkObjCKindOfType(TypeProcessingState &state, QualType &type, + ParsedAttr &attr) { + Sema &S = state.getSema(); + if (isa<ObjCTypeParamType>(type)) { // Build the attributed type to record where __kindof occurred. - type = Context.getAttributedType(AttributedType::attr_objc_kindof, - type, type); + type = state.getAttributedType( + createSimpleAttr<ObjCKindOfAttr>(S.Context, attr), type, type); return false; } @@ -6480,7 +6555,7 @@ bool Sema::checkObjCKindOfType(QualType &type, SourceLocation loc) { // If not, we can't apply __kindof. if (!objType) { // FIXME: Handle dependent types that aren't yet object types. - Diag(loc, diag::err_objc_kindof_nonobject) + S.Diag(attr.getLoc(), diag::err_objc_kindof_nonobject) << type; return true; } @@ -6488,45 +6563,31 @@ bool Sema::checkObjCKindOfType(QualType &type, SourceLocation loc) { // Rebuild the "equivalent" type, which pushes __kindof down into // the object type. // There is no need to apply kindof on an unqualified id type. - QualType equivType = Context.getObjCObjectType( + QualType equivType = S.Context.getObjCObjectType( objType->getBaseType(), objType->getTypeArgsAsWritten(), objType->getProtocols(), /*isKindOf=*/objType->isObjCUnqualifiedId() ? false : true); // If we started with an object pointer type, rebuild it. if (ptrType) { - equivType = Context.getObjCObjectPointerType(equivType); - if (auto nullability = type->getNullability(Context)) { - auto attrKind = AttributedType::getNullabilityAttrKind(*nullability); - equivType = Context.getAttributedType(attrKind, equivType, equivType); + equivType = S.Context.getObjCObjectPointerType(equivType); + if (auto nullability = type->getNullability(S.Context)) { + // We create a nullability attribute from the __kindof attribute. + // Make sure that will make sense. + assert(attr.getAttributeSpellingListIndex() == 0 && + "multiple spellings for __kindof?"); + Attr *A = createNullabilityAttr(S.Context, attr, *nullability); + A->setImplicit(true); + equivType = state.getAttributedType(A, equivType, equivType); } } // Build the attributed type to record where __kindof occurred. - type = Context.getAttributedType(AttributedType::attr_objc_kindof, - type, - equivType); - + type = state.getAttributedType( + createSimpleAttr<ObjCKindOfAttr>(S.Context, attr), type, equivType); return false; } -/// Map a nullability attribute kind to a nullability kind. -static NullabilityKind mapNullabilityAttrKind(ParsedAttr::Kind kind) { - switch (kind) { - case ParsedAttr::AT_TypeNonNull: - return NullabilityKind::NonNull; - - case ParsedAttr::AT_TypeNullable: - return NullabilityKind::Nullable; - - case ParsedAttr::AT_TypeNullUnspecified: - return NullabilityKind::Unspecified; - - default: - llvm_unreachable("not a nullability attribute kind"); - } -} - /// Distribute a nullability type attribute that cannot be applied to /// the type specifier to a pointer, block pointer, or member pointer /// declarator, complaining if necessary. @@ -6614,27 +6675,29 @@ static bool distributeNullabilityTypeAttr(TypeProcessingState &state, return false; } -static AttributedType::Kind getCCTypeAttrKind(ParsedAttr &Attr) { +static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) { assert(!Attr.isInvalid()); switch (Attr.getKind()) { default: llvm_unreachable("not a calling convention attribute"); case ParsedAttr::AT_CDecl: - return AttributedType::attr_cdecl; + return createSimpleAttr<CDeclAttr>(Ctx, Attr); case ParsedAttr::AT_FastCall: - return AttributedType::attr_fastcall; + return createSimpleAttr<FastCallAttr>(Ctx, Attr); case ParsedAttr::AT_StdCall: - return AttributedType::attr_stdcall; + return createSimpleAttr<StdCallAttr>(Ctx, Attr); case ParsedAttr::AT_ThisCall: - return AttributedType::attr_thiscall; + return createSimpleAttr<ThisCallAttr>(Ctx, Attr); case ParsedAttr::AT_RegCall: - return AttributedType::attr_regcall; + return createSimpleAttr<RegCallAttr>(Ctx, Attr); case ParsedAttr::AT_Pascal: - return AttributedType::attr_pascal; + return createSimpleAttr<PascalAttr>(Ctx, Attr); case ParsedAttr::AT_SwiftCall: - return AttributedType::attr_swiftcall; + return createSimpleAttr<SwiftCallAttr>(Ctx, Attr); case ParsedAttr::AT_VectorCall: - return AttributedType::attr_vectorcall; + return createSimpleAttr<VectorCallAttr>(Ctx, Attr); + case ParsedAttr::AT_AArch64VectorPcs: + return createSimpleAttr<AArch64VectorPcsAttr>(Ctx, Attr); case ParsedAttr::AT_Pcs: { // The attribute may have had a fixit applied where we treated an // identifier as a string literal. The contents of the string are valid, @@ -6644,20 +6707,22 @@ static AttributedType::Kind getCCTypeAttrKind(ParsedAttr &Attr) { Str = cast<StringLiteral>(Attr.getArgAsExpr(0))->getString(); else Str = Attr.getArgAsIdent(0)->Ident->getName(); - return llvm::StringSwitch<AttributedType::Kind>(Str) - .Case("aapcs", AttributedType::attr_pcs) - .Case("aapcs-vfp", AttributedType::attr_pcs_vfp); + PcsAttr::PCSType Type; + if (!PcsAttr::ConvertStrToPCSType(Str, Type)) + llvm_unreachable("already validated the attribute"); + return ::new (Ctx) PcsAttr(Attr.getRange(), Ctx, Type, + Attr.getAttributeSpellingListIndex()); } case ParsedAttr::AT_IntelOclBicc: - return AttributedType::attr_inteloclbicc; + return createSimpleAttr<IntelOclBiccAttr>(Ctx, Attr); case ParsedAttr::AT_MSABI: - return AttributedType::attr_ms_abi; + return createSimpleAttr<MSABIAttr>(Ctx, Attr); case ParsedAttr::AT_SysVABI: - return AttributedType::attr_sysv_abi; + return createSimpleAttr<SysVABIAttr>(Ctx, Attr); case ParsedAttr::AT_PreserveMost: - return AttributedType::attr_preserve_most; + return createSimpleAttr<PreserveMostAttr>(Ctx, Attr); case ParsedAttr::AT_PreserveAll: - return AttributedType::attr_preserve_all; + return createSimpleAttr<PreserveAllAttr>(Ctx, Attr); } llvm_unreachable("unexpected attribute kind!"); } @@ -6705,8 +6770,9 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr, = unwrapped.get()->getExtInfo().withProducesResult(true); type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI)); } - type = S.Context.getAttributedType(AttributedType::attr_ns_returns_retained, - origType, type); + type = state.getAttributedType( + createSimpleAttr<NSReturnsRetainedAttr>(S.Context, attr), + origType, type); return true; } @@ -6781,13 +6847,12 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr, const FunctionType *fn = unwrapped.get(); CallingConv CCOld = fn->getCallConv(); - AttributedType::Kind CCAttrKind = getCCTypeAttrKind(attr); + Attr *CCAttr = getCCTypeAttr(S.Context, attr); if (CCOld != CC) { // Error out on when there's already an attribute on the type // and the CCs don't match. - const AttributedType *AT = S.getCallingConvAttributedType(type); - if (AT && AT->getAttrKind() != CCAttrKind) { + if (S.getCallingConvAttributedType(type)) { S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible) << FunctionType::getNameForCallConv(CC) << FunctionType::getNameForCallConv(CCOld); @@ -6841,7 +6906,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr, Equivalent = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI)); } - type = S.Context.getAttributedType(CCAttrKind, type, Equivalent); + type = state.getAttributedType(CCAttr, type, Equivalent); return true; } @@ -6906,8 +6971,8 @@ static void HandleVectorSizeAttr(QualType &CurType, const ParsedAttr &Attr, Sema &S) { // Check the attribute arguments. if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << Attr.getName() << 1; + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Attr + << 1; Attr.setInvalid(); return; } @@ -6943,8 +7008,8 @@ static void HandleExtVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr, Sema &S) { // check the attribute arguments. if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << Attr.getName() << 1; + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Attr + << 1; return; } @@ -7032,14 +7097,14 @@ static void HandleNeonVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr, Sema &S, VectorType::VectorKind VecKind) { // Target must have NEON if (!S.Context.getTargetInfo().hasFeature("neon")) { - S.Diag(Attr.getLoc(), diag::err_attribute_unsupported) << Attr.getName(); + S.Diag(Attr.getLoc(), diag::err_attribute_unsupported) << Attr; Attr.setInvalid(); return; } // Check the attribute arguments. if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << Attr.getName() << 1; + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Attr + << 1; Attr.setInvalid(); return; } @@ -7049,8 +7114,8 @@ static void HandleNeonVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr, if (numEltsExpr->isTypeDependent() || numEltsExpr->isValueDependent() || !numEltsExpr->isIntegerConstantExpr(numEltsInt, S.Context)) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) - << Attr.getName() << AANT_ArgumentIntegerConstant - << numEltsExpr->getSourceRange(); + << Attr << AANT_ArgumentIntegerConstant + << numEltsExpr->getSourceRange(); Attr.setInvalid(); return; } @@ -7085,22 +7150,43 @@ static void HandleOpenCLAccessAttr(QualType &CurType, const ParsedAttr &Attr, } if (const TypedefType* TypedefTy = CurType->getAs<TypedefType>()) { - QualType PointeeTy = TypedefTy->desugar(); - S.Diag(Attr.getLoc(), diag::err_opencl_multiple_access_qualifiers); + QualType BaseTy = TypedefTy->desugar(); std::string PrevAccessQual; - switch (cast<BuiltinType>(PointeeTy.getTypePtr())->getKind()) { - #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ - case BuiltinType::Id: \ - PrevAccessQual = #Access; \ - break; - #include "clang/Basic/OpenCLImageTypes.def" - default: - assert(0 && "Unable to find corresponding image type."); + if (BaseTy->isPipeType()) { + if (TypedefTy->getDecl()->hasAttr<OpenCLAccessAttr>()) { + OpenCLAccessAttr *Attr = + TypedefTy->getDecl()->getAttr<OpenCLAccessAttr>(); + PrevAccessQual = Attr->getSpelling(); + } else { + PrevAccessQual = "read_only"; + } + } else if (const BuiltinType* ImgType = BaseTy->getAs<BuiltinType>()) { + + switch (ImgType->getKind()) { + #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + case BuiltinType::Id: \ + PrevAccessQual = #Access; \ + break; + #include "clang/Basic/OpenCLImageTypes.def" + default: + llvm_unreachable("Unable to find corresponding image type."); + } + } else { + llvm_unreachable("unexpected type"); + } + StringRef AttrName = Attr.getName()->getName(); + if (PrevAccessQual == AttrName.ltrim("_")) { + // Duplicated qualifiers + S.Diag(Attr.getLoc(), diag::warn_duplicate_declspec) + << AttrName << Attr.getRange(); + } else { + // Contradicting qualifiers + S.Diag(Attr.getLoc(), diag::err_opencl_multiple_access_qualifiers); } - S.Diag(TypedefTy->getDecl()->getLocStart(), - diag::note_opencl_typedef_access_qualifier) << PrevAccessQual; + S.Diag(TypedefTy->getDecl()->getBeginLoc(), + diag::note_opencl_typedef_access_qualifier) << PrevAccessQual; } else if (CurType->isPipeType()) { if (Attr.getSemanticSpelling() == OpenCLAccessAttr::Keyword_write_only) { QualType ElemType = CurType->getAs<PipeType>()->getElementType(); @@ -7136,7 +7222,8 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State, bool IsPointee = ChunkIndex > 0 && (D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Pointer || - D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::BlockPointer); + D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::BlockPointer || + D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Reference); bool IsFuncReturnType = ChunkIndex > 0 && D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Function; @@ -7156,10 +7243,13 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State, !IsPointee) || // Do not deduce addr space of the void type, e.g. in f(void), otherwise // it will fail some sema check. - (T->isVoidType() && !IsPointee)) + (T->isVoidType() && !IsPointee) || + // Do not deduce address spaces for dependent types because they might end + // up instantiating to a type with an explicit address space qualifier. + T->isDependentType()) return; - LangAS ImpAddr; + LangAS ImpAddr = LangAS::Default; // Put OpenCL automatic variable in private address space. // OpenCL v1.2 s6.5: // The default address space name for arguments to a function in a @@ -7181,7 +7271,9 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State, if (IsPointee) { ImpAddr = LangAS::opencl_generic; } else { - if (D.getContext() == DeclaratorContext::FileContext) { + if (D.getContext() == DeclaratorContext::TemplateArgContext) { + // Do not deduce address space for non-pointee type in template arg. + } else if (D.getContext() == DeclaratorContext::FileContext) { ImpAddr = LangAS::opencl_global; } else { if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static || @@ -7196,14 +7288,15 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State, T = State.getSema().Context.getAddrSpaceQualType(T, ImpAddr); } -static void HandleLifetimeBoundAttr(QualType &CurType, - const ParsedAttr &Attr, - Sema &S, Declarator &D) { - if (D.isDeclarationOfFunction()) { - CurType = S.Context.getAttributedType(AttributedType::attr_lifetimebound, - CurType, CurType); +static void HandleLifetimeBoundAttr(TypeProcessingState &State, + QualType &CurType, + ParsedAttr &Attr) { + if (State.getDeclarator().isDeclarationOfFunction()) { + CurType = State.getAttributedType( + createSimpleAttr<LifetimeBoundAttr>(State.getSema().Context, Attr), + CurType, CurType); } else { - Attr.diagnoseAppertainsTo(S, nullptr); + Attr.diagnoseAppertainsTo(State.getSema(), nullptr); } } @@ -7220,6 +7313,9 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, // sure we visit every element once. Copy the attributes list, and iterate // over that. ParsedAttributesView AttrsCopy{attrs}; + + state.setParsedNoDeref(false); + for (ParsedAttr &attr : AttrsCopy) { // Skip attributes that were marked to be invalid. @@ -7231,7 +7327,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, // not appertain to a DeclaratorChunk. If we handle them as type // attributes, accept them in that position and diagnose the GCC // incompatibility. - if (attr.getScopeName() && attr.getScopeName()->isStr("gnu")) { + if (attr.isGNUScope()) { bool IsTypeAttr = attr.isTypeAttr(); if (TAL == TAL_DeclChunk) { state.getSema().Diag(attr.getLoc(), @@ -7256,7 +7352,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, // A C++11 attribute on a declarator chunk must appertain to a type. if (attr.isCXX11Attribute() && TAL == TAL_DeclChunk) { state.getSema().Diag(attr.getLoc(), diag::err_attribute_not_type_attr) - << attr.getName(); + << attr; attr.setUsedAsTypeAttr(); } break; @@ -7282,7 +7378,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, case ParsedAttr::AT_OpenCLConstantAddressSpace: case ParsedAttr::AT_OpenCLGenericAddressSpace: case ParsedAttr::AT_AddressSpace: - HandleAddressSpaceTypeAttribute(type, attr, state.getSema()); + HandleAddressSpaceTypeAttribute(type, attr, state); attr.setUsedAsTypeAttr(); break; OBJC_POINTER_TYPE_ATTRS_CASELIST: @@ -7313,12 +7409,18 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, attr.setUsedAsTypeAttr(); break; case ParsedAttr::AT_LifetimeBound: - if (TAL == TAL_DeclChunk) { - HandleLifetimeBoundAttr(type, attr, state.getSema(), - state.getDeclarator()); - attr.setUsedAsTypeAttr(); - } + if (TAL == TAL_DeclChunk) + HandleLifetimeBoundAttr(state, type, attr); + break; + + case ParsedAttr::AT_NoDeref: { + ASTContext &Ctx = state.getSema().Context; + type = state.getAttributedType(createSimpleAttr<NoDerefAttr>(Ctx, attr), + type, type); + attr.setUsedAsTypeAttr(); + state.setParsedNoDeref(true); break; + } MS_TYPE_ATTRS_CASELIST: if (!handleMSPointerTypeQualifierAttr(state, attr, type)) @@ -7341,11 +7443,10 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, bool allowOnArrayType = state.getDeclarator().isPrototypeContext() && !hasOuterPointerLikeChunk(state.getDeclarator(), endIndex); - if (state.getSema().checkNullabilityTypeSpecifier( + if (checkNullabilityTypeSpecifier( + state, type, - mapNullabilityAttrKind(attr.getKind()), - attr.getLoc(), - attr.isContextSensitiveKeywordAttribute(), + attr, allowOnArrayType)) { attr.setInvalid(); } @@ -7364,16 +7465,16 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, case TAL_DeclName: state.getSema().Diag(attr.getLoc(), diag::err_objc_kindof_wrong_position) - << FixItHint::CreateRemoval(attr.getLoc()) - << FixItHint::CreateInsertion( - state.getDeclarator().getDeclSpec().getLocStart(), "__kindof "); + << FixItHint::CreateRemoval(attr.getLoc()) + << FixItHint::CreateInsertion( + state.getDeclarator().getDeclSpec().getBeginLoc(), + "__kindof "); break; } // Apply it regardless. - if (state.getSema().checkObjCKindOfType(type, attr.getLoc())) + if (checkObjCKindOfType(state, type, attr)) attr.setInvalid(); - attr.setUsedAsTypeAttr(); break; FUNCTION_TYPE_ATTRS_CASELIST: @@ -7577,14 +7678,35 @@ bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested, assert(D && "missing definition for pattern of instantiated definition"); *Suggested = D; - if (isVisible(D)) + + auto DefinitionIsVisible = [&] { + // The (primary) definition might be in a visible module. + if (isVisible(D)) + return true; + + // A visible module might have a merged definition instead. + if (D->isModulePrivate() ? hasMergedDefinitionInCurrentModule(D) + : hasVisibleMergedDefinition(D)) { + if (CodeSynthesisContexts.empty() && + !getLangOpts().ModulesLocalVisibility) { + // Cache the fact that this definition is implicitly visible because + // there is a visible merged definition. + D->setVisibleDespiteOwningModule(); + } + return true; + } + + return false; + }; + + if (DefinitionIsVisible()) return true; // The external source may have additional definitions of this entity that are // visible, so complete the redeclaration chain now and ask again. if (auto *Source = Context.getExternalSource()) { Source->CompleteRedeclChain(D); - return isVisible(D); + return DefinitionIsVisible(); } return false; @@ -7684,39 +7806,24 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, return false; } - const TagType *Tag = T->getAs<TagType>(); - const ObjCInterfaceType *IFace = T->getAs<ObjCInterfaceType>(); + TagDecl *Tag = dyn_cast_or_null<TagDecl>(Def); + ObjCInterfaceDecl *IFace = dyn_cast_or_null<ObjCInterfaceDecl>(Def); - // If there's an unimported definition of this type in a module (for - // instance, because we forward declared it, then imported the definition), - // import that definition now. - // - // FIXME: What about other cases where an import extends a redeclaration - // chain for a declaration that can be accessed through a mechanism other - // than name lookup (eg, referenced in a template, or a variable whose type - // could be completed by the module)? - // - // FIXME: Should we map through to the base array element type before - // checking for a tag type? + // Give the external source a chance to provide a definition of the type. + // This is kept separate from completing the redeclaration chain so that + // external sources such as LLDB can avoid synthesizing a type definition + // unless it's actually needed. if (Tag || IFace) { - NamedDecl *D = - Tag ? static_cast<NamedDecl *>(Tag->getDecl()) : IFace->getDecl(); - // Avoid diagnosing invalid decls as incomplete. - if (D->isInvalidDecl()) + if (Def->isInvalidDecl()) return true; // Give the external AST source a chance to complete the type. if (auto *Source = Context.getExternalSource()) { - if (Tag) { - TagDecl *TagD = Tag->getDecl(); - if (TagD->hasExternalLexicalStorage()) - Source->CompleteType(TagD); - } else { - ObjCInterfaceDecl *IFaceD = IFace->getDecl(); - if (IFaceD->hasExternalLexicalStorage()) - Source->CompleteType(IFace->getDecl()); - } + if (Tag && Tag->hasExternalLexicalStorage()) + Source->CompleteType(Tag); + if (IFace && IFace->hasExternalLexicalStorage()) + Source->CompleteType(IFace); // If the external source completed the type, go through the motions // again to ensure we're allowed to use the completed type. if (!T->isIncompleteType()) @@ -7727,32 +7834,31 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, // If we have a class template specialization or a class member of a // class template specialization, or an array with known size of such, // try to instantiate it. - QualType MaybeTemplate = T; - while (const ConstantArrayType *Array - = Context.getAsConstantArrayType(MaybeTemplate)) - MaybeTemplate = Array->getElementType(); - if (const RecordType *Record = MaybeTemplate->getAs<RecordType>()) { + if (auto *RD = dyn_cast_or_null<CXXRecordDecl>(Tag)) { bool Instantiated = false; bool Diagnosed = false; - if (ClassTemplateSpecializationDecl *ClassTemplateSpec - = dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) { + if (RD->isDependentContext()) { + // Don't try to instantiate a dependent class (eg, a member template of + // an instantiated class template specialization). + // FIXME: Can this ever happen? + } else if (auto *ClassTemplateSpec = + dyn_cast<ClassTemplateSpecializationDecl>(RD)) { if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared) { Diagnosed = InstantiateClassTemplateSpecialization( Loc, ClassTemplateSpec, TSK_ImplicitInstantiation, /*Complain=*/Diagnoser); Instantiated = true; } - } else if (CXXRecordDecl *Rec - = dyn_cast<CXXRecordDecl>(Record->getDecl())) { - CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass(); - if (!Rec->isBeingDefined() && Pattern) { - MemberSpecializationInfo *MSI = Rec->getMemberSpecializationInfo(); + } else { + CXXRecordDecl *Pattern = RD->getInstantiatedFromMemberClass(); + if (!RD->isBeingDefined() && Pattern) { + MemberSpecializationInfo *MSI = RD->getMemberSpecializationInfo(); assert(MSI && "Missing member specialization information?"); // This record was instantiated from a class within a template. if (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) { - Diagnosed = InstantiateClass(Loc, Rec, Pattern, - getTemplateInstantiationArgs(Rec), + Diagnosed = InstantiateClass(Loc, RD, Pattern, + getTemplateInstantiationArgs(RD), TSK_ImplicitInstantiation, /*Complain=*/Diagnoser); Instantiated = true; @@ -7783,15 +7889,15 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, // If the type was a forward declaration of a class/struct/union // type, produce a note. - if (Tag && !Tag->getDecl()->isInvalidDecl()) - Diag(Tag->getDecl()->getLocation(), + if (Tag && !Tag->isInvalidDecl()) + Diag(Tag->getLocation(), Tag->isBeingDefined() ? diag::note_type_being_defined : diag::note_forward_declaration) - << QualType(Tag, 0); + << Context.getTagDeclType(Tag); // If the Objective-C class was a forward declaration, produce a note. - if (IFace && !IFace->getDecl()->isInvalidDecl()) - Diag(IFace->getDecl()->getLocation(), diag::note_forward_class); + if (IFace && !IFace->isInvalidDecl()) + Diag(IFace->getLocation(), diag::note_forward_class); // If we have external information that we can use to suggest a fix, // produce a note. @@ -7880,7 +7986,7 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, Diag(RD->getLocation(), diag::note_non_literal_virtual_base) << getLiteralDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases(); for (const auto &I : RD->vbases()) - Diag(I.getLocStart(), diag::note_constexpr_virtual_base_here) + Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here) << I.getSourceRange(); } else if (!RD->isAggregate() && !RD->hasConstexprNonCopyMoveConstructor() && !RD->hasTrivialDefaultConstructor()) { @@ -7888,9 +7994,8 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, } else if (RD->hasNonLiteralTypeFieldsOrBases()) { for (const auto &I : RD->bases()) { if (!I.getType()->isLiteralType(Context)) { - Diag(I.getLocStart(), - diag::note_non_literal_base_class) - << RD << I.getType() << I.getSourceRange(); + Diag(I.getBeginLoc(), diag::note_non_literal_base_class) + << RD << I.getType() << I.getSourceRange(); return true; } } @@ -7947,9 +8052,7 @@ QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword, } QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) { - ExprResult ER = CheckPlaceholderExpr(E); - if (ER.isInvalid()) return QualType(); - E = ER.get(); + assert(!E->hasPlaceholderType() && "unexpected placeholder"); if (!getLangOpts().CPlusPlus && E->refersToBitField()) Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield) << 2; @@ -8034,9 +8137,7 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) { QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc, bool AsUnevaluated) { - ExprResult ER = CheckPlaceholderExpr(E); - if (ER.isInvalid()) return QualType(); - E = ER.get(); + assert(!E->hasPlaceholderType() && "unexpected placeholder"); if (AsUnevaluated && CodeSynthesisContexts.empty() && E->HasSideEffects(Context, false)) { diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index de962d775d73b..df14768cbe812 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -328,7 +328,7 @@ public: /// other mechanism. /// /// \returns the transformed statement. - StmtResult TransformStmt(Stmt *S); + StmtResult TransformStmt(Stmt *S, bool DiscardedValue = false); /// Transform the given statement. /// @@ -597,7 +597,7 @@ public: QualType TransformFunctionProtoType(TypeLocBuilder &TLB, FunctionProtoTypeLoc TL, CXXRecordDecl *ThisContext, - unsigned ThisTypeQuals, + Qualifiers ThisTypeQuals, Fn TransformExceptionSpec); bool TransformExceptionSpec(SourceLocation Loc, @@ -684,15 +684,13 @@ public: OMPClause *Transform ## Class(Class *S); #include "clang/Basic/OpenMPKinds.def" - /// Build a new qualified type given its unqualified type and type - /// qualifiers. + /// Build a new qualified type given its unqualified type and type location. /// /// By default, this routine adds type qualifiers only to types that can /// have qualifiers, and silently suppresses those qualifiers that are not /// permitted. Subclasses may override this routine to provide different /// behavior. - QualType RebuildQualifiedType(QualType T, SourceLocation Loc, - Qualifiers Quals); + QualType RebuildQualifiedType(QualType T, QualifiedTypeLoc TL); /// Build a new pointer type given its pointee type. /// @@ -1798,14 +1796,16 @@ public: /// By default, performs semantic analysis to build the new OpenMP clause. /// Subclasses may override this routine to provide different behavior. OMPClause * - RebuildOMPMapClause(OpenMPMapClauseKind MapTypeModifier, + RebuildOMPMapClause(ArrayRef<OpenMPMapModifierKind> MapTypeModifiers, + ArrayRef<SourceLocation> MapTypeModifiersLoc, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { - return getSema().ActOnOpenMPMapClause(MapTypeModifier, MapType, - IsMapTypeImplicit, MapLoc, ColonLoc, - VarList, StartLoc, LParenLoc, EndLoc); + return getSema().ActOnOpenMPMapClause(MapTypeModifiers, MapTypeModifiersLoc, + MapType, IsMapTypeImplicit, MapLoc, + ColonLoc, VarList, StartLoc, + LParenLoc, EndLoc); } /// Build a new OpenMP 'num_teams' clause. @@ -2021,11 +2021,10 @@ public: /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. StmtResult RebuildCXXForRangeStmt(SourceLocation ForLoc, - SourceLocation CoawaitLoc, - SourceLocation ColonLoc, - Stmt *Range, Stmt *Begin, Stmt *End, - Expr *Cond, Expr *Inc, - Stmt *LoopVar, + SourceLocation CoawaitLoc, Stmt *Init, + SourceLocation ColonLoc, Stmt *Range, + Stmt *Begin, Stmt *End, Expr *Cond, + Expr *Inc, Stmt *LoopVar, SourceLocation RParenLoc) { // If we've just learned that the range is actually an Objective-C // collection, treat this as an Objective-C fast enumeration loop. @@ -2037,17 +2036,24 @@ public: Expr *RangeExpr = RangeVar->getInit(); if (!RangeExpr->isTypeDependent() && - RangeExpr->getType()->isObjCObjectPointerType()) - return getSema().ActOnObjCForCollectionStmt(ForLoc, LoopVar, RangeExpr, - RParenLoc); + RangeExpr->getType()->isObjCObjectPointerType()) { + // FIXME: Support init-statements in Objective-C++20 ranged for + // statement. + if (Init) { + return SemaRef.Diag(Init->getBeginLoc(), + diag::err_objc_for_range_init_stmt) + << Init->getSourceRange(); + } + return getSema().ActOnObjCForCollectionStmt(ForLoc, LoopVar, + RangeExpr, RParenLoc); + } } } } - return getSema().BuildCXXForRangeStmt(ForLoc, CoawaitLoc, ColonLoc, - Range, Begin, End, - Cond, Inc, LoopVar, RParenLoc, - Sema::BFRK_Rebuild); + return getSema().BuildCXXForRangeStmt(ForLoc, CoawaitLoc, Init, ColonLoc, + Range, Begin, End, Cond, Inc, LoopVar, + RParenLoc, Sema::BFRK_Rebuild); } /// Build a new C++0x range-based for statement. @@ -2090,8 +2096,8 @@ public: /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. ExprResult RebuildPredefinedExpr(SourceLocation Loc, - PredefinedExpr::IdentType IT) { - return getSema().BuildPredefinedExpr(Loc, IT); + PredefinedExpr::IdentKind IK) { + return getSema().BuildPredefinedExpr(Loc, IK); } /// Build a new expression that references a declaration. @@ -3124,15 +3130,15 @@ public: // Build a reference to the __builtin_shufflevector builtin FunctionDecl *Builtin = cast<FunctionDecl>(Lookup.front()); - Expr *Callee = new (SemaRef.Context) DeclRefExpr(Builtin, false, - SemaRef.Context.BuiltinFnTy, - VK_RValue, BuiltinLoc); + Expr *Callee = new (SemaRef.Context) + DeclRefExpr(SemaRef.Context, Builtin, false, + SemaRef.Context.BuiltinFnTy, VK_RValue, BuiltinLoc); QualType CalleePtrTy = SemaRef.Context.getPointerType(Builtin->getType()); Callee = SemaRef.ImpCastExprToType(Callee, CalleePtrTy, CK_BuiltinFnToFnPtr).get(); // Build the CallExpr - ExprResult TheCall = new (SemaRef.Context) CallExpr( + ExprResult TheCall = CallExpr::Create( SemaRef.Context, Callee, SubExprs, Builtin->getCallResultType(), Expr::getValueKindForType(Builtin->getReturnType()), RParenLoc); @@ -3263,8 +3269,8 @@ private: bool DeducibleTSTContext); }; -template<typename Derived> -StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) { +template <typename Derived> +StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S, bool DiscardedValue) { if (!S) return S; @@ -3288,7 +3294,7 @@ StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) { if (E.isInvalid()) return StmtError(); - return getSema().ActOnExprStmt(E); + return getSema().ActOnExprStmt(E, DiscardedValue); } } @@ -3338,8 +3344,8 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init, if (!Init) return Init; - if (ExprWithCleanups *ExprTemp = dyn_cast<ExprWithCleanups>(Init)) - Init = ExprTemp->getSubExpr(); + if (auto *FE = dyn_cast<FullExpr>(Init)) + Init = FE->getSubExpr(); if (auto *AIL = dyn_cast<ArrayInitLoopExpr>(Init)) Init = AIL->getCommonExpr(); @@ -3386,6 +3392,11 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init, if (Construct && Construct->isStdInitListInitialization()) return TransformInitializer(Construct->getArg(0), NotCopyInit); + // Enter a list-init context if this was list initialization. + EnterExpressionEvaluationContext Context( + getSema(), EnterExpressionEvaluationContext::InitList, + Construct->isListInitialization()); + SmallVector<Expr*, 8> NewArgs; bool ArgChanged = false; if (getDerived().TransformExprs(Construct->getArgs(), Construct->getNumArgs(), @@ -3394,8 +3405,8 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init, // If this was list initialization, revert to syntactic list form. if (Construct->isListInitialization()) - return getDerived().RebuildInitList(Construct->getLocStart(), NewArgs, - Construct->getLocEnd()); + return getDerived().RebuildInitList(Construct->getBeginLoc(), NewArgs, + Construct->getEndLoc()); // Build a ParenListExpr to represent anything else. SourceRange Parens = Construct->getParenOrBraceRange(); @@ -4217,8 +4228,9 @@ TreeTransform<Derived>::TransformTypeWithDeducedTST(TypeSourceInfo *DI) { return nullptr; if (QTL) { - Result = getDerived().RebuildQualifiedType( - Result, QTL.getBeginLoc(), QTL.getType().getLocalQualifiers()); + Result = getDerived().RebuildQualifiedType(Result, QTL); + if (Result.isNull()) + return nullptr; TLB.TypeWasModifiedSafely(Result); } @@ -4229,13 +4241,14 @@ template<typename Derived> QualType TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB, QualifiedTypeLoc T) { - Qualifiers Quals = T.getType().getLocalQualifiers(); - QualType Result = getDerived().TransformType(TLB, T.getUnqualifiedLoc()); if (Result.isNull()) return QualType(); - Result = getDerived().RebuildQualifiedType(Result, T.getBeginLoc(), Quals); + Result = getDerived().RebuildQualifiedType(Result, T); + + if (Result.isNull()) + return QualType(); // RebuildQualifiedType might have updated the type, but not in a way // that invalidates the TypeLoc. (There's no location information for @@ -4245,21 +4258,41 @@ TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB, return Result; } -template<typename Derived> +template <typename Derived> QualType TreeTransform<Derived>::RebuildQualifiedType(QualType T, - SourceLocation Loc, - Qualifiers Quals) { + QualifiedTypeLoc TL) { + + SourceLocation Loc = TL.getBeginLoc(); + Qualifiers Quals = TL.getType().getLocalQualifiers(); + + if (((T.getAddressSpace() != LangAS::Default && + Quals.getAddressSpace() != LangAS::Default)) && + T.getAddressSpace() != Quals.getAddressSpace()) { + SemaRef.Diag(Loc, diag::err_address_space_mismatch_templ_inst) + << TL.getType() << T; + return QualType(); + } + // C++ [dcl.fct]p7: // [When] adding cv-qualifications on top of the function type [...] the // cv-qualifiers are ignored. + if (T->isFunctionType()) { + T = SemaRef.getASTContext().getAddrSpaceQualType(T, + Quals.getAddressSpace()); + return T; + } + // C++ [dcl.ref]p1: // when the cv-qualifiers are introduced through the use of a typedef-name // or decltype-specifier [...] the cv-qualifiers are ignored. // Note that [dcl.ref]p1 lists all cases in which cv-qualifiers can be // applied to a reference type. - // FIXME: This removes all qualifiers, not just cv-qualifiers! - if (T->isFunctionType() || T->isReferenceType()) - return T; + if (T->isReferenceType()) { + // The only qualifier that applies to a reference type is restrict. + if (!Quals.hasRestrict()) + return T; + Quals = Qualifiers::fromCVRMask(Qualifiers::Restrict); + } // Suppress Objective-C lifetime qualifiers if they don't make sense for the // resulting type. @@ -4682,7 +4715,8 @@ TreeTransform<Derived>::TransformVariableArrayType(TypeLocBuilder &TLB, } if (SizeResult.isInvalid()) return QualType(); - SizeResult = SemaRef.ActOnFinishFullExpr(SizeResult.get()); + SizeResult = + SemaRef.ActOnFinishFullExpr(SizeResult.get(), /*DiscardedValue*/ false); if (SizeResult.isInvalid()) return QualType(); @@ -5214,7 +5248,7 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB, SmallVector<QualType, 4> ExceptionStorage; TreeTransform *This = this; // Work around gcc.gnu.org/PR56135. return getDerived().TransformFunctionProtoType( - TLB, TL, nullptr, 0, + TLB, TL, nullptr, Qualifiers(), [&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) { return This->TransformExceptionSpec(TL.getBeginLoc(), ESI, ExceptionStorage, Changed); @@ -5224,7 +5258,7 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB, template<typename Derived> template<typename Fn> QualType TreeTransform<Derived>::TransformFunctionProtoType( TypeLocBuilder &TLB, FunctionProtoTypeLoc TL, CXXRecordDecl *ThisContext, - unsigned ThisTypeQuals, Fn TransformExceptionSpec) { + Qualifiers ThisTypeQuals, Fn TransformExceptionSpec) { // Transform the parameters and return type. // @@ -5267,6 +5301,13 @@ QualType TreeTransform<Derived>::TransformFunctionProtoType( if (ResultType.isNull()) return QualType(); + // Return type can not be qualified with an address space. + if (ResultType.getAddressSpace() != LangAS::Default) { + SemaRef.Diag(TL.getReturnLoc().getBeginLoc(), + diag::err_attribute_address_function_type); + return QualType(); + } + if (getDerived().TransformFunctionTypeParams( TL.getBeginLoc(), TL.getParams(), TL.getTypePtr()->param_type_begin(), @@ -6058,6 +6099,12 @@ QualType TreeTransform<Derived>::TransformAttributedType( if (modifiedType.isNull()) return QualType(); + // oldAttr can be null if we started with a QualType rather than a TypeLoc. + const Attr *oldAttr = TL.getAttr(); + const Attr *newAttr = oldAttr ? getDerived().TransformAttr(oldAttr) : nullptr; + if (oldAttr && !newAttr) + return QualType(); + QualType result = TL.getType(); // FIXME: dependent operand expressions? @@ -6074,26 +6121,20 @@ QualType TreeTransform<Derived>::TransformAttributedType( // type sugar, and therefore cannot be diagnosed in any other way. if (auto nullability = oldType->getImmediateNullability()) { if (!modifiedType->canHaveNullability()) { - SemaRef.Diag(TL.getAttrNameLoc(), diag::err_nullability_nonpointer) - << DiagNullabilityKind(*nullability, false) << modifiedType; + SemaRef.Diag(TL.getAttr()->getLocation(), + diag::err_nullability_nonpointer) + << DiagNullabilityKind(*nullability, false) << modifiedType; return QualType(); } } - result = SemaRef.Context.getAttributedType(oldType->getAttrKind(), + result = SemaRef.Context.getAttributedType(TL.getAttrKind(), modifiedType, equivalentType); } AttributedTypeLoc newTL = TLB.push<AttributedTypeLoc>(result); - newTL.setAttrNameLoc(TL.getAttrNameLoc()); - if (TL.hasAttrOperand()) - newTL.setAttrOperandParensRange(TL.getAttrOperandParensRange()); - if (TL.hasAttrExprOperand()) - newTL.setAttrExprOperand(TL.getAttrExprOperand()); - else if (TL.hasAttrEnumOperand()) - newTL.setAttrEnumOperandLoc(TL.getAttrEnumOperandLoc()); - + newTL.setAttr(newAttr); return result; } @@ -6411,16 +6452,10 @@ TreeTransform<Derived>::TransformObjCObjectType(TypeLocBuilder &TLB, if (getDerived().AlwaysRebuild() || AnyChanged) { // Rebuild the type. Result = getDerived().RebuildObjCObjectType( - BaseType, - TL.getLocStart(), - TL.getTypeArgsLAngleLoc(), - NewTypeArgInfos, - TL.getTypeArgsRAngleLoc(), - TL.getProtocolLAngleLoc(), - llvm::makeArrayRef(TL.getTypePtr()->qual_begin(), - TL.getNumProtocols()), - TL.getProtocolLocs(), - TL.getProtocolRAngleLoc()); + BaseType, TL.getBeginLoc(), TL.getTypeArgsLAngleLoc(), NewTypeArgInfos, + TL.getTypeArgsRAngleLoc(), TL.getProtocolLAngleLoc(), + llvm::makeArrayRef(TL.getTypePtr()->qual_begin(), TL.getNumProtocols()), + TL.getProtocolLocs(), TL.getProtocolRAngleLoc()); if (Result.isNull()) return QualType(); @@ -6486,7 +6521,9 @@ TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S, bool SubStmtChanged = false; SmallVector<Stmt*, 8> Statements; for (auto *B : S->body()) { - StmtResult Result = getDerived().TransformStmt(B); + StmtResult Result = + getDerived().TransformStmt(B, !IsStmtExpr || B != S->body_back()); + if (Result.isInvalid()) { // Immediately fail if this was a DeclStmt, since it's very // likely that this will cause problems for future statements. @@ -6656,7 +6693,7 @@ TreeTransform<Derived>::TransformIfStmt(IfStmt *S) { if (Then.isInvalid()) return StmtError(); } else { - Then = new (getSema().Context) NullStmt(S->getThen()->getLocStart()); + Then = new (getSema().Context) NullStmt(S->getThen()->getBeginLoc()); } // Transform the "else" branch. @@ -6759,6 +6796,9 @@ TreeTransform<Derived>::TransformDoStmt(DoStmt *S) { template<typename Derived> StmtResult TreeTransform<Derived>::TransformForStmt(ForStmt *S) { + if (getSema().getLangOpts().OpenMP) + getSema().startOpenMPLoop(); + // Transform the initialization statement StmtResult Init = getDerived().TransformStmt(S->getInit()); if (Init.isInvalid()) @@ -6875,7 +6915,7 @@ TreeTransform<Derived>::TransformDeclStmt(DeclStmt *S) { if (!getDerived().AlwaysRebuild() && !DeclChanged) return S; - return getDerived().RebuildDeclStmt(Decls, S->getStartLoc(), S->getEndLoc()); + return getDerived().RebuildDeclStmt(Decls, S->getBeginLoc(), S->getEndLoc()); } template<typename Derived> @@ -7407,6 +7447,11 @@ StmtResult TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) { template<typename Derived> StmtResult TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) { + StmtResult Init = + S->getInit() ? getDerived().TransformStmt(S->getInit()) : StmtResult(); + if (Init.isInvalid()) + return StmtError(); + StmtResult Range = getDerived().TransformStmt(S->getRangeStmt()); if (Range.isInvalid()) return StmtError(); @@ -7440,6 +7485,7 @@ TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) { StmtResult NewStmt = S; if (getDerived().AlwaysRebuild() || + Init.get() != S->getInit() || Range.get() != S->getRangeStmt() || Begin.get() != S->getBeginStmt() || End.get() != S->getEndStmt() || @@ -7447,7 +7493,7 @@ TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) { Inc.get() != S->getInc() || LoopVar.get() != S->getLoopVarStmt()) { NewStmt = getDerived().RebuildCXXForRangeStmt(S->getForLoc(), - S->getCoawaitLoc(), + S->getCoawaitLoc(), Init.get(), S->getColonLoc(), Range.get(), Begin.get(), End.get(), Cond.get(), @@ -7465,7 +7511,7 @@ TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) { // it now so we have a new statement to attach the body to. if (Body.get() != S->getBody() && NewStmt.get() == S) { NewStmt = getDerived().RebuildCXXForRangeStmt(S->getForLoc(), - S->getCoawaitLoc(), + S->getCoawaitLoc(), Init.get(), S->getColonLoc(), Range.get(), Begin.get(), End.get(), Cond.get(), @@ -7708,7 +7754,7 @@ StmtResult TreeTransform<Derived>::TransformOMPExecutableDirective( return getDerived().RebuildOMPExecutableDirective( D->getDirectiveKind(), DirName, CancelRegion, TClauses, - AssociatedStmt.get(), D->getLocStart(), D->getLocEnd()); + AssociatedStmt.get(), D->getBeginLoc(), D->getEndLoc()); } template <typename Derived> @@ -7716,7 +7762,7 @@ StmtResult TreeTransform<Derived>::TransformOMPParallelDirective(OMPParallelDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7727,7 +7773,7 @@ StmtResult TreeTransform<Derived>::TransformOMPSimdDirective(OMPSimdDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_simd, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7738,7 +7784,7 @@ StmtResult TreeTransform<Derived>::TransformOMPForDirective(OMPForDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_for, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7749,7 +7795,7 @@ StmtResult TreeTransform<Derived>::TransformOMPForSimdDirective(OMPForSimdDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_for_simd, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7760,7 +7806,7 @@ StmtResult TreeTransform<Derived>::TransformOMPSectionsDirective(OMPSectionsDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_sections, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7771,7 +7817,7 @@ StmtResult TreeTransform<Derived>::TransformOMPSectionDirective(OMPSectionDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_section, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7782,7 +7828,7 @@ StmtResult TreeTransform<Derived>::TransformOMPSingleDirective(OMPSingleDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_single, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7793,7 +7839,7 @@ StmtResult TreeTransform<Derived>::TransformOMPMasterDirective(OMPMasterDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_master, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7803,7 +7849,7 @@ template <typename Derived> StmtResult TreeTransform<Derived>::TransformOMPCriticalDirective(OMPCriticalDirective *D) { getDerived().getSema().StartOpenMPDSABlock( - OMPD_critical, D->getDirectiveName(), nullptr, D->getLocStart()); + OMPD_critical, D->getDirectiveName(), nullptr, D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7814,7 +7860,7 @@ StmtResult TreeTransform<Derived>::TransformOMPParallelForDirective( OMPParallelForDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel_for, DirName, - nullptr, D->getLocStart()); + nullptr, D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7825,7 +7871,7 @@ StmtResult TreeTransform<Derived>::TransformOMPParallelForSimdDirective( OMPParallelForSimdDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel_for_simd, DirName, - nullptr, D->getLocStart()); + nullptr, D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7836,7 +7882,7 @@ StmtResult TreeTransform<Derived>::TransformOMPParallelSectionsDirective( OMPParallelSectionsDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel_sections, DirName, - nullptr, D->getLocStart()); + nullptr, D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7847,7 +7893,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTaskDirective(OMPTaskDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_task, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7858,7 +7904,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTaskyieldDirective( OMPTaskyieldDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_taskyield, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7869,7 +7915,7 @@ StmtResult TreeTransform<Derived>::TransformOMPBarrierDirective(OMPBarrierDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_barrier, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7880,7 +7926,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTaskwaitDirective(OMPTaskwaitDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_taskwait, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7891,7 +7937,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTaskgroupDirective( OMPTaskgroupDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_taskgroup, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7902,7 +7948,7 @@ StmtResult TreeTransform<Derived>::TransformOMPFlushDirective(OMPFlushDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_flush, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7913,7 +7959,7 @@ StmtResult TreeTransform<Derived>::TransformOMPOrderedDirective(OMPOrderedDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_ordered, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7924,7 +7970,7 @@ StmtResult TreeTransform<Derived>::TransformOMPAtomicDirective(OMPAtomicDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_atomic, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7935,7 +7981,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTargetDirective(OMPTargetDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_target, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7946,7 +7992,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTargetDataDirective( OMPTargetDataDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_target_data, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7957,7 +8003,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTargetEnterDataDirective( OMPTargetEnterDataDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_target_enter_data, DirName, - nullptr, D->getLocStart()); + nullptr, D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7968,7 +8014,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTargetExitDataDirective( OMPTargetExitDataDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_target_exit_data, DirName, - nullptr, D->getLocStart()); + nullptr, D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7979,7 +8025,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTargetParallelDirective( OMPTargetParallelDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_target_parallel, DirName, - nullptr, D->getLocStart()); + nullptr, D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -7990,7 +8036,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTargetParallelForDirective( OMPTargetParallelForDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_target_parallel_for, DirName, - nullptr, D->getLocStart()); + nullptr, D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -8001,7 +8047,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTargetUpdateDirective( OMPTargetUpdateDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_target_update, DirName, - nullptr, D->getLocStart()); + nullptr, D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -8012,7 +8058,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTeamsDirective(OMPTeamsDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_teams, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -8023,7 +8069,7 @@ StmtResult TreeTransform<Derived>::TransformOMPCancellationPointDirective( OMPCancellationPointDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_cancellation_point, DirName, - nullptr, D->getLocStart()); + nullptr, D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -8034,7 +8080,7 @@ StmtResult TreeTransform<Derived>::TransformOMPCancelDirective(OMPCancelDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_cancel, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -8045,7 +8091,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTaskLoopDirective(OMPTaskLoopDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_taskloop, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -8056,7 +8102,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTaskLoopSimdDirective( OMPTaskLoopSimdDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_taskloop_simd, DirName, - nullptr, D->getLocStart()); + nullptr, D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -8067,7 +8113,7 @@ StmtResult TreeTransform<Derived>::TransformOMPDistributeDirective( OMPDistributeDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_distribute, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -8078,7 +8124,7 @@ StmtResult TreeTransform<Derived>::TransformOMPDistributeParallelForDirective( OMPDistributeParallelForDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock( - OMPD_distribute_parallel_for, DirName, nullptr, D->getLocStart()); + OMPD_distribute_parallel_for, DirName, nullptr, D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -8090,7 +8136,7 @@ TreeTransform<Derived>::TransformOMPDistributeParallelForSimdDirective( OMPDistributeParallelForSimdDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock( - OMPD_distribute_parallel_for_simd, DirName, nullptr, D->getLocStart()); + OMPD_distribute_parallel_for_simd, DirName, nullptr, D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -8101,7 +8147,7 @@ StmtResult TreeTransform<Derived>::TransformOMPDistributeSimdDirective( OMPDistributeSimdDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_distribute_simd, DirName, - nullptr, D->getLocStart()); + nullptr, D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -8111,9 +8157,8 @@ template <typename Derived> StmtResult TreeTransform<Derived>::TransformOMPTargetParallelForSimdDirective( OMPTargetParallelForSimdDirective *D) { DeclarationNameInfo DirName; - getDerived().getSema().StartOpenMPDSABlock(OMPD_target_parallel_for_simd, - DirName, nullptr, - D->getLocStart()); + getDerived().getSema().StartOpenMPDSABlock( + OMPD_target_parallel_for_simd, DirName, nullptr, D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -8124,7 +8169,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTargetSimdDirective( OMPTargetSimdDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_target_simd, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -8135,7 +8180,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTeamsDistributeDirective( OMPTeamsDistributeDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_teams_distribute, DirName, - nullptr, D->getLocStart()); + nullptr, D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -8146,7 +8191,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTeamsDistributeSimdDirective( OMPTeamsDistributeSimdDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock( - OMPD_teams_distribute_simd, DirName, nullptr, D->getLocStart()); + OMPD_teams_distribute_simd, DirName, nullptr, D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -8157,7 +8202,8 @@ StmtResult TreeTransform<Derived>::TransformOMPTeamsDistributeParallelForSimdDir OMPTeamsDistributeParallelForSimdDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock( - OMPD_teams_distribute_parallel_for_simd, DirName, nullptr, D->getLocStart()); + OMPD_teams_distribute_parallel_for_simd, DirName, nullptr, + D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -8167,8 +8213,8 @@ template <typename Derived> StmtResult TreeTransform<Derived>::TransformOMPTeamsDistributeParallelForDirective( OMPTeamsDistributeParallelForDirective *D) { DeclarationNameInfo DirName; - getDerived().getSema().StartOpenMPDSABlock(OMPD_teams_distribute_parallel_for, - DirName, nullptr, D->getLocStart()); + getDerived().getSema().StartOpenMPDSABlock( + OMPD_teams_distribute_parallel_for, DirName, nullptr, D->getBeginLoc()); StmtResult Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -8179,7 +8225,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTargetTeamsDirective( OMPTargetTeamsDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_target_teams, DirName, - nullptr, D->getLocStart()); + nullptr, D->getBeginLoc()); auto Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -8189,8 +8235,8 @@ template <typename Derived> StmtResult TreeTransform<Derived>::TransformOMPTargetTeamsDistributeDirective( OMPTargetTeamsDistributeDirective *D) { DeclarationNameInfo DirName; - getDerived().getSema().StartOpenMPDSABlock(OMPD_target_teams_distribute, - DirName, nullptr, D->getLocStart()); + getDerived().getSema().StartOpenMPDSABlock( + OMPD_target_teams_distribute, DirName, nullptr, D->getBeginLoc()); auto Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -8203,7 +8249,7 @@ TreeTransform<Derived>::TransformOMPTargetTeamsDistributeParallelForDirective( DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock( OMPD_target_teams_distribute_parallel_for, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); auto Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -8216,7 +8262,7 @@ StmtResult TreeTransform<Derived>:: DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock( OMPD_target_teams_distribute_parallel_for_simd, DirName, nullptr, - D->getLocStart()); + D->getBeginLoc()); auto Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -8228,7 +8274,7 @@ TreeTransform<Derived>::TransformOMPTargetTeamsDistributeSimdDirective( OMPTargetTeamsDistributeSimdDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock( - OMPD_target_teams_distribute_simd, DirName, nullptr, D->getLocStart()); + OMPD_target_teams_distribute_simd, DirName, nullptr, D->getBeginLoc()); auto Res = getDerived().TransformOMPExecutableDirective(D); getDerived().getSema().EndOpenMPDSABlock(Res.get()); return Res; @@ -8244,8 +8290,8 @@ OMPClause *TreeTransform<Derived>::TransformOMPIfClause(OMPIfClause *C) { if (Cond.isInvalid()) return nullptr; return getDerived().RebuildOMPIfClause( - C->getNameModifier(), Cond.get(), C->getLocStart(), C->getLParenLoc(), - C->getNameModifierLoc(), C->getColonLoc(), C->getLocEnd()); + C->getNameModifier(), Cond.get(), C->getBeginLoc(), C->getLParenLoc(), + C->getNameModifierLoc(), C->getColonLoc(), C->getEndLoc()); } template <typename Derived> @@ -8253,8 +8299,8 @@ OMPClause *TreeTransform<Derived>::TransformOMPFinalClause(OMPFinalClause *C) { ExprResult Cond = getDerived().TransformExpr(C->getCondition()); if (Cond.isInvalid()) return nullptr; - return getDerived().RebuildOMPFinalClause(Cond.get(), C->getLocStart(), - C->getLParenLoc(), C->getLocEnd()); + return getDerived().RebuildOMPFinalClause(Cond.get(), C->getBeginLoc(), + C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> @@ -8264,7 +8310,7 @@ TreeTransform<Derived>::TransformOMPNumThreadsClause(OMPNumThreadsClause *C) { if (NumThreads.isInvalid()) return nullptr; return getDerived().RebuildOMPNumThreadsClause( - NumThreads.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); + NumThreads.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> @@ -8274,7 +8320,7 @@ TreeTransform<Derived>::TransformOMPSafelenClause(OMPSafelenClause *C) { if (E.isInvalid()) return nullptr; return getDerived().RebuildOMPSafelenClause( - E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); + E.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> @@ -8284,7 +8330,7 @@ TreeTransform<Derived>::TransformOMPSimdlenClause(OMPSimdlenClause *C) { if (E.isInvalid()) return nullptr; return getDerived().RebuildOMPSimdlenClause( - E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); + E.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> @@ -8294,23 +8340,23 @@ TreeTransform<Derived>::TransformOMPCollapseClause(OMPCollapseClause *C) { if (E.isInvalid()) return nullptr; return getDerived().RebuildOMPCollapseClause( - E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); + E.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> OMPClause * TreeTransform<Derived>::TransformOMPDefaultClause(OMPDefaultClause *C) { return getDerived().RebuildOMPDefaultClause( - C->getDefaultKind(), C->getDefaultKindKwLoc(), C->getLocStart(), - C->getLParenLoc(), C->getLocEnd()); + C->getDefaultKind(), C->getDefaultKindKwLoc(), C->getBeginLoc(), + C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> OMPClause * TreeTransform<Derived>::TransformOMPProcBindClause(OMPProcBindClause *C) { return getDerived().RebuildOMPProcBindClause( - C->getProcBindKind(), C->getProcBindKindKwLoc(), C->getLocStart(), - C->getLParenLoc(), C->getLocEnd()); + C->getProcBindKind(), C->getProcBindKindKwLoc(), C->getBeginLoc(), + C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> @@ -8321,9 +8367,9 @@ TreeTransform<Derived>::TransformOMPScheduleClause(OMPScheduleClause *C) { return nullptr; return getDerived().RebuildOMPScheduleClause( C->getFirstScheduleModifier(), C->getSecondScheduleModifier(), - C->getScheduleKind(), E.get(), C->getLocStart(), C->getLParenLoc(), + C->getScheduleKind(), E.get(), C->getBeginLoc(), C->getLParenLoc(), C->getFirstScheduleModifierLoc(), C->getSecondScheduleModifierLoc(), - C->getScheduleKindLoc(), C->getCommaLoc(), C->getLocEnd()); + C->getScheduleKindLoc(), C->getCommaLoc(), C->getEndLoc()); } template <typename Derived> @@ -8335,7 +8381,7 @@ TreeTransform<Derived>::TransformOMPOrderedClause(OMPOrderedClause *C) { if (E.isInvalid()) return nullptr; } - return getDerived().RebuildOMPOrderedClause(C->getLocStart(), C->getLocEnd(), + return getDerived().RebuildOMPOrderedClause(C->getBeginLoc(), C->getEndLoc(), C->getLParenLoc(), E.get()); } @@ -8414,6 +8460,39 @@ TreeTransform<Derived>::TransformOMPNogroupClause(OMPNogroupClause *C) { } template <typename Derived> +OMPClause *TreeTransform<Derived>::TransformOMPUnifiedAddressClause( + OMPUnifiedAddressClause *C) { + llvm_unreachable("unified_address clause cannot appear in dependent context"); +} + +template <typename Derived> +OMPClause *TreeTransform<Derived>::TransformOMPUnifiedSharedMemoryClause( + OMPUnifiedSharedMemoryClause *C) { + llvm_unreachable( + "unified_shared_memory clause cannot appear in dependent context"); +} + +template <typename Derived> +OMPClause *TreeTransform<Derived>::TransformOMPReverseOffloadClause( + OMPReverseOffloadClause *C) { + llvm_unreachable("reverse_offload clause cannot appear in dependent context"); +} + +template <typename Derived> +OMPClause *TreeTransform<Derived>::TransformOMPDynamicAllocatorsClause( + OMPDynamicAllocatorsClause *C) { + llvm_unreachable( + "dynamic_allocators clause cannot appear in dependent context"); +} + +template <typename Derived> +OMPClause *TreeTransform<Derived>::TransformOMPAtomicDefaultMemOrderClause( + OMPAtomicDefaultMemOrderClause *C) { + llvm_unreachable( + "atomic_default_mem_order clause cannot appear in dependent context"); +} + +template <typename Derived> OMPClause * TreeTransform<Derived>::TransformOMPPrivateClause(OMPPrivateClause *C) { llvm::SmallVector<Expr *, 16> Vars; @@ -8425,7 +8504,7 @@ TreeTransform<Derived>::TransformOMPPrivateClause(OMPPrivateClause *C) { Vars.push_back(EVar.get()); } return getDerived().RebuildOMPPrivateClause( - Vars, C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); + Vars, C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> @@ -8440,7 +8519,7 @@ OMPClause *TreeTransform<Derived>::TransformOMPFirstprivateClause( Vars.push_back(EVar.get()); } return getDerived().RebuildOMPFirstprivateClause( - Vars, C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); + Vars, C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> @@ -8455,7 +8534,7 @@ TreeTransform<Derived>::TransformOMPLastprivateClause(OMPLastprivateClause *C) { Vars.push_back(EVar.get()); } return getDerived().RebuildOMPLastprivateClause( - Vars, C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); + Vars, C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> @@ -8469,8 +8548,8 @@ TreeTransform<Derived>::TransformOMPSharedClause(OMPSharedClause *C) { return nullptr; Vars.push_back(EVar.get()); } - return getDerived().RebuildOMPSharedClause(Vars, C->getLocStart(), - C->getLParenLoc(), C->getLocEnd()); + return getDerived().RebuildOMPSharedClause(Vars, C->getBeginLoc(), + C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> @@ -8516,8 +8595,8 @@ TreeTransform<Derived>::TransformOMPReductionClause(OMPReductionClause *C) { UnresolvedReductions.push_back(nullptr); } return getDerived().RebuildOMPReductionClause( - Vars, C->getLocStart(), C->getLParenLoc(), C->getColonLoc(), - C->getLocEnd(), ReductionIdScopeSpec, NameInfo, UnresolvedReductions); + Vars, C->getBeginLoc(), C->getLParenLoc(), C->getColonLoc(), + C->getEndLoc(), ReductionIdScopeSpec, NameInfo, UnresolvedReductions); } template <typename Derived> @@ -8561,8 +8640,8 @@ OMPClause *TreeTransform<Derived>::TransformOMPTaskReductionClause( UnresolvedReductions.push_back(nullptr); } return getDerived().RebuildOMPTaskReductionClause( - Vars, C->getLocStart(), C->getLParenLoc(), C->getColonLoc(), - C->getLocEnd(), ReductionIdScopeSpec, NameInfo, UnresolvedReductions); + Vars, C->getBeginLoc(), C->getLParenLoc(), C->getColonLoc(), + C->getEndLoc(), ReductionIdScopeSpec, NameInfo, UnresolvedReductions); } template <typename Derived> @@ -8606,8 +8685,8 @@ TreeTransform<Derived>::TransformOMPInReductionClause(OMPInReductionClause *C) { UnresolvedReductions.push_back(nullptr); } return getDerived().RebuildOMPInReductionClause( - Vars, C->getLocStart(), C->getLParenLoc(), C->getColonLoc(), - C->getLocEnd(), ReductionIdScopeSpec, NameInfo, UnresolvedReductions); + Vars, C->getBeginLoc(), C->getLParenLoc(), C->getColonLoc(), + C->getEndLoc(), ReductionIdScopeSpec, NameInfo, UnresolvedReductions); } template <typename Derived> @@ -8625,8 +8704,8 @@ TreeTransform<Derived>::TransformOMPLinearClause(OMPLinearClause *C) { if (Step.isInvalid()) return nullptr; return getDerived().RebuildOMPLinearClause( - Vars, Step.get(), C->getLocStart(), C->getLParenLoc(), C->getModifier(), - C->getModifierLoc(), C->getColonLoc(), C->getLocEnd()); + Vars, Step.get(), C->getBeginLoc(), C->getLParenLoc(), C->getModifier(), + C->getModifierLoc(), C->getColonLoc(), C->getEndLoc()); } template <typename Derived> @@ -8644,8 +8723,8 @@ TreeTransform<Derived>::TransformOMPAlignedClause(OMPAlignedClause *C) { if (Alignment.isInvalid()) return nullptr; return getDerived().RebuildOMPAlignedClause( - Vars, Alignment.get(), C->getLocStart(), C->getLParenLoc(), - C->getColonLoc(), C->getLocEnd()); + Vars, Alignment.get(), C->getBeginLoc(), C->getLParenLoc(), + C->getColonLoc(), C->getEndLoc()); } template <typename Derived> @@ -8659,8 +8738,8 @@ TreeTransform<Derived>::TransformOMPCopyinClause(OMPCopyinClause *C) { return nullptr; Vars.push_back(EVar.get()); } - return getDerived().RebuildOMPCopyinClause(Vars, C->getLocStart(), - C->getLParenLoc(), C->getLocEnd()); + return getDerived().RebuildOMPCopyinClause(Vars, C->getBeginLoc(), + C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> @@ -8675,7 +8754,7 @@ TreeTransform<Derived>::TransformOMPCopyprivateClause(OMPCopyprivateClause *C) { Vars.push_back(EVar.get()); } return getDerived().RebuildOMPCopyprivateClause( - Vars, C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); + Vars, C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> @@ -8688,8 +8767,8 @@ OMPClause *TreeTransform<Derived>::TransformOMPFlushClause(OMPFlushClause *C) { return nullptr; Vars.push_back(EVar.get()); } - return getDerived().RebuildOMPFlushClause(Vars, C->getLocStart(), - C->getLParenLoc(), C->getLocEnd()); + return getDerived().RebuildOMPFlushClause(Vars, C->getBeginLoc(), + C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> @@ -8705,7 +8784,7 @@ TreeTransform<Derived>::TransformOMPDependClause(OMPDependClause *C) { } return getDerived().RebuildOMPDependClause( C->getDependencyKind(), C->getDependencyLoc(), C->getColonLoc(), Vars, - C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); + C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> @@ -8714,8 +8793,8 @@ TreeTransform<Derived>::TransformOMPDeviceClause(OMPDeviceClause *C) { ExprResult E = getDerived().TransformExpr(C->getDevice()); if (E.isInvalid()) return nullptr; - return getDerived().RebuildOMPDeviceClause( - E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); + return getDerived().RebuildOMPDeviceClause(E.get(), C->getBeginLoc(), + C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> @@ -8729,9 +8808,9 @@ OMPClause *TreeTransform<Derived>::TransformOMPMapClause(OMPMapClause *C) { Vars.push_back(EVar.get()); } return getDerived().RebuildOMPMapClause( - C->getMapTypeModifier(), C->getMapType(), C->isImplicitMapType(), - C->getMapLoc(), C->getColonLoc(), Vars, C->getLocStart(), - C->getLParenLoc(), C->getLocEnd()); + C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(), C->getMapType(), + C->isImplicitMapType(), C->getMapLoc(), C->getColonLoc(), Vars, + C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> @@ -8741,7 +8820,7 @@ TreeTransform<Derived>::TransformOMPNumTeamsClause(OMPNumTeamsClause *C) { if (E.isInvalid()) return nullptr; return getDerived().RebuildOMPNumTeamsClause( - E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); + E.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> @@ -8751,7 +8830,7 @@ TreeTransform<Derived>::TransformOMPThreadLimitClause(OMPThreadLimitClause *C) { if (E.isInvalid()) return nullptr; return getDerived().RebuildOMPThreadLimitClause( - E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); + E.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> @@ -8761,7 +8840,7 @@ TreeTransform<Derived>::TransformOMPPriorityClause(OMPPriorityClause *C) { if (E.isInvalid()) return nullptr; return getDerived().RebuildOMPPriorityClause( - E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); + E.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> @@ -8771,7 +8850,7 @@ TreeTransform<Derived>::TransformOMPGrainsizeClause(OMPGrainsizeClause *C) { if (E.isInvalid()) return nullptr; return getDerived().RebuildOMPGrainsizeClause( - E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); + E.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> @@ -8781,7 +8860,7 @@ TreeTransform<Derived>::TransformOMPNumTasksClause(OMPNumTasksClause *C) { if (E.isInvalid()) return nullptr; return getDerived().RebuildOMPNumTasksClause( - E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); + E.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> @@ -8789,8 +8868,8 @@ OMPClause *TreeTransform<Derived>::TransformOMPHintClause(OMPHintClause *C) { ExprResult E = getDerived().TransformExpr(C->getHint()); if (E.isInvalid()) return nullptr; - return getDerived().RebuildOMPHintClause(E.get(), C->getLocStart(), - C->getLParenLoc(), C->getLocEnd()); + return getDerived().RebuildOMPHintClause(E.get(), C->getBeginLoc(), + C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> @@ -8800,8 +8879,8 @@ OMPClause *TreeTransform<Derived>::TransformOMPDistScheduleClause( if (E.isInvalid()) return nullptr; return getDerived().RebuildOMPDistScheduleClause( - C->getDistScheduleKind(), E.get(), C->getLocStart(), C->getLParenLoc(), - C->getDistScheduleKindLoc(), C->getCommaLoc(), C->getLocEnd()); + C->getDistScheduleKind(), E.get(), C->getBeginLoc(), C->getLParenLoc(), + C->getDistScheduleKindLoc(), C->getCommaLoc(), C->getEndLoc()); } template <typename Derived> @@ -8820,8 +8899,8 @@ OMPClause *TreeTransform<Derived>::TransformOMPToClause(OMPToClause *C) { return 0; Vars.push_back(EVar.get()); } - return getDerived().RebuildOMPToClause(Vars, C->getLocStart(), - C->getLParenLoc(), C->getLocEnd()); + return getDerived().RebuildOMPToClause(Vars, C->getBeginLoc(), + C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> @@ -8834,8 +8913,8 @@ OMPClause *TreeTransform<Derived>::TransformOMPFromClause(OMPFromClause *C) { return 0; Vars.push_back(EVar.get()); } - return getDerived().RebuildOMPFromClause(Vars, C->getLocStart(), - C->getLParenLoc(), C->getLocEnd()); + return getDerived().RebuildOMPFromClause(Vars, C->getBeginLoc(), + C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> @@ -8850,7 +8929,7 @@ OMPClause *TreeTransform<Derived>::TransformOMPUseDevicePtrClause( Vars.push_back(EVar.get()); } return getDerived().RebuildOMPUseDevicePtrClause( - Vars, C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); + Vars, C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> @@ -8865,7 +8944,7 @@ TreeTransform<Derived>::TransformOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) { Vars.push_back(EVar.get()); } return getDerived().RebuildOMPIsDevicePtrClause( - Vars, C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); + Vars, C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); } //===----------------------------------------------------------------------===// @@ -8873,12 +8952,18 @@ TreeTransform<Derived>::TransformOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) { //===----------------------------------------------------------------------===// template<typename Derived> ExprResult +TreeTransform<Derived>::TransformConstantExpr(ConstantExpr *E) { + return TransformExpr(E->getSubExpr()); +} + +template<typename Derived> +ExprResult TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E) { if (!E->isTypeDependent()) return E; return getDerived().RebuildPredefinedExpr(E->getLocation(), - E->getIdentType()); + E->getIdentKind()); } template<typename Derived> @@ -8973,7 +9058,7 @@ template<typename Derived> ExprResult TreeTransform<Derived>::TransformUserDefinedLiteral(UserDefinedLiteral *E) { if (FunctionDecl *FD = E->getDirectCallee()) - SemaRef.MarkFunctionReferenced(E->getLocStart(), FD); + SemaRef.MarkFunctionReferenced(E->getBeginLoc(), FD); return SemaRef.MaybeBindToTemporary(E); } @@ -9227,10 +9312,9 @@ TreeTransform<Derived>::TransformArraySubscriptExpr(ArraySubscriptExpr *E) { RHS.get() == E->getRHS()) return E; - return getDerived().RebuildArraySubscriptExpr(LHS.get(), - /*FIXME:*/E->getLHS()->getLocStart(), - RHS.get(), - E->getRBracketLoc()); + return getDerived().RebuildArraySubscriptExpr( + LHS.get(), + /*FIXME:*/ E->getLHS()->getBeginLoc(), RHS.get(), E->getRBracketLoc()); } template <typename Derived> @@ -9259,7 +9343,7 @@ TreeTransform<Derived>::TransformOMPArraySectionExpr(OMPArraySectionExpr *E) { return E; return getDerived().RebuildOMPArraySectionExpr( - Base.get(), E->getBase()->getLocEnd(), LowerBound.get(), E->getColonLoc(), + Base.get(), E->getBase()->getEndLoc(), LowerBound.get(), E->getColonLoc(), Length.get(), E->getRBracketLoc()); } @@ -9512,9 +9596,9 @@ TreeTransform<Derived>::TransformCompoundLiteralExpr(CompoundLiteralExpr *E) { // type-as-written, but that's okay, because it should always be // derivable from the initializer. - return getDerived().RebuildCompoundLiteralExpr(E->getLParenLoc(), NewT, - /*FIXME:*/E->getInitializer()->getLocEnd(), - Init.get()); + return getDerived().RebuildCompoundLiteralExpr( + E->getLParenLoc(), NewT, + /*FIXME:*/ E->getInitializer()->getEndLoc(), Init.get()); } template<typename Derived> @@ -9530,7 +9614,7 @@ TreeTransform<Derived>::TransformExtVectorElementExpr(ExtVectorElementExpr *E) { // FIXME: Bad source location SourceLocation FakeOperatorLoc = - SemaRef.getLocForEndOfToken(E->getBase()->getLocEnd()); + SemaRef.getLocForEndOfToken(E->getBase()->getEndLoc()); return getDerived().RebuildExtVectorElementExpr(Base.get(), FakeOperatorLoc, E->getAccessorLoc(), E->getAccessor()); @@ -9544,6 +9628,9 @@ TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E) { bool InitChanged = false; + EnterExpressionEvaluationContext Context( + getSema(), EnterExpressionEvaluationContext::InitList); + SmallVector<Expr*, 4> Inits; if (getDerived().TransformExprs(E->getInits(), E->getNumInits(), false, Inits, &InitChanged)) @@ -9676,7 +9763,7 @@ template<typename Derived> ExprResult TreeTransform<Derived>::TransformImplicitValueInitExpr( ImplicitValueInitExpr *E) { - TemporaryBase Rebase(*this, E->getLocStart(), DeclarationName()); + TemporaryBase Rebase(*this, E->getBeginLoc(), DeclarationName()); // FIXME: Will we ever have proper type location here? Will we actually // need to transform the type? @@ -9818,7 +9905,7 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) { // FIXME: Poor location information SourceLocation FakeLParenLoc = SemaRef.getLocForEndOfToken( - static_cast<Expr *>(Object.get())->getLocEnd()); + static_cast<Expr *>(Object.get())->getEndLoc()); // Transform the call arguments. SmallVector<Expr*, 8> Args; @@ -9826,9 +9913,8 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) { Args)) return ExprError(); - return getDerived().RebuildCallExpr(Object.get(), FakeLParenLoc, - Args, - E->getLocEnd()); + return getDerived().RebuildCallExpr(Object.get(), FakeLParenLoc, Args, + E->getEndLoc()); } #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ @@ -10008,10 +10094,8 @@ TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) { TInfo == E->getTypeOperandSourceInfo()) return E; - return getDerived().RebuildCXXTypeidExpr(E->getType(), - E->getLocStart(), - TInfo, - E->getLocEnd()); + return getDerived().RebuildCXXTypeidExpr(E->getType(), E->getBeginLoc(), + TInfo, E->getEndLoc()); } // We don't know whether the subexpression is potentially evaluated until @@ -10030,10 +10114,8 @@ TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) { SubExpr.get() == E->getExprOperand()) return E; - return getDerived().RebuildCXXTypeidExpr(E->getType(), - E->getLocStart(), - SubExpr.get(), - E->getLocEnd()); + return getDerived().RebuildCXXTypeidExpr(E->getType(), E->getBeginLoc(), + SubExpr.get(), E->getEndLoc()); } template<typename Derived> @@ -10049,10 +10131,8 @@ TreeTransform<Derived>::TransformCXXUuidofExpr(CXXUuidofExpr *E) { TInfo == E->getTypeOperandSourceInfo()) return E; - return getDerived().RebuildCXXUuidofExpr(E->getType(), - E->getLocStart(), - TInfo, - E->getLocEnd()); + return getDerived().RebuildCXXUuidofExpr(E->getType(), E->getBeginLoc(), + TInfo, E->getEndLoc()); } EnterExpressionEvaluationContext Unevaluated( @@ -10066,10 +10146,8 @@ TreeTransform<Derived>::TransformCXXUuidofExpr(CXXUuidofExpr *E) { SubExpr.get() == E->getExprOperand()) return E; - return getDerived().RebuildCXXUuidofExpr(E->getType(), - E->getLocStart(), - SubExpr.get(), - E->getLocEnd()); + return getDerived().RebuildCXXUuidofExpr(E->getType(), E->getBeginLoc(), + SubExpr.get(), E->getEndLoc()); } template<typename Derived> @@ -10092,11 +10170,11 @@ TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) { if (!getDerived().AlwaysRebuild() && T == E->getType()) { // Make sure that we capture 'this'. - getSema().CheckCXXThisCapture(E->getLocStart()); + getSema().CheckCXXThisCapture(E->getBeginLoc()); return E; } - return getDerived().RebuildCXXThisExpr(E->getLocStart(), T, E->isImplicit()); + return getDerived().RebuildCXXThisExpr(E->getBeginLoc(), T, E->isImplicit()); } template<typename Derived> @@ -10117,9 +10195,8 @@ TreeTransform<Derived>::TransformCXXThrowExpr(CXXThrowExpr *E) { template<typename Derived> ExprResult TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) { - ParmVarDecl *Param - = cast_or_null<ParmVarDecl>(getDerived().TransformDecl(E->getLocStart(), - E->getParam())); + ParmVarDecl *Param = cast_or_null<ParmVarDecl>( + getDerived().TransformDecl(E->getBeginLoc(), E->getParam())); if (!Param) return ExprError(); @@ -10133,9 +10210,8 @@ TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) { template<typename Derived> ExprResult TreeTransform<Derived>::TransformCXXDefaultInitExpr(CXXDefaultInitExpr *E) { - FieldDecl *Field - = cast_or_null<FieldDecl>(getDerived().TransformDecl(E->getLocStart(), - E->getField())); + FieldDecl *Field = cast_or_null<FieldDecl>( + getDerived().TransformDecl(E->getBeginLoc(), E->getField())); if (!Field) return ExprError(); @@ -10196,8 +10272,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { FunctionDecl *OperatorNew = nullptr; if (E->getOperatorNew()) { OperatorNew = cast_or_null<FunctionDecl>( - getDerived().TransformDecl(E->getLocStart(), - E->getOperatorNew())); + getDerived().TransformDecl(E->getBeginLoc(), E->getOperatorNew())); if (!OperatorNew) return ExprError(); } @@ -10205,8 +10280,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { FunctionDecl *OperatorDelete = nullptr; if (E->getOperatorDelete()) { OperatorDelete = cast_or_null<FunctionDecl>( - getDerived().TransformDecl(E->getLocStart(), - E->getOperatorDelete())); + getDerived().TransformDecl(E->getBeginLoc(), E->getOperatorDelete())); if (!OperatorDelete) return ExprError(); } @@ -10221,9 +10295,9 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { // Mark any declarations we need as referenced. // FIXME: instantiation-specific. if (OperatorNew) - SemaRef.MarkFunctionReferenced(E->getLocStart(), OperatorNew); + SemaRef.MarkFunctionReferenced(E->getBeginLoc(), OperatorNew); if (OperatorDelete) - SemaRef.MarkFunctionReferenced(E->getLocStart(), OperatorDelete); + SemaRef.MarkFunctionReferenced(E->getBeginLoc(), OperatorDelete); if (E->isArray() && !E->getAllocatedType()->isDependentType()) { QualType ElementType @@ -10231,7 +10305,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { if (const RecordType *RecordT = ElementType->getAs<RecordType>()) { CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordT->getDecl()); if (CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(Record)) { - SemaRef.MarkFunctionReferenced(E->getLocStart(), Destructor); + SemaRef.MarkFunctionReferenced(E->getBeginLoc(), Destructor); } } } @@ -10253,7 +10327,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { = dyn_cast<ConstantArrayType>(ArrayT)) { ArraySize = IntegerLiteral::Create(SemaRef.Context, ConsArrayT->getSize(), SemaRef.Context.getSizeType(), - /*FIXME:*/ E->getLocStart()); + /*FIXME:*/ E->getBeginLoc()); AllocType = ConsArrayT->getElementType(); } else if (const DependentSizedArrayType *DepArrayT = dyn_cast<DependentSizedArrayType>(ArrayT)) { @@ -10264,17 +10338,11 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { } } - return getDerived().RebuildCXXNewExpr(E->getLocStart(), - E->isGlobalNew(), - /*FIXME:*/E->getLocStart(), - PlacementArgs, - /*FIXME:*/E->getLocStart(), - E->getTypeIdParens(), - AllocType, - AllocTypeInfo, - ArraySize.get(), - E->getDirectInitRange(), - NewInit.get()); + return getDerived().RebuildCXXNewExpr( + E->getBeginLoc(), E->isGlobalNew(), + /*FIXME:*/ E->getBeginLoc(), PlacementArgs, + /*FIXME:*/ E->getBeginLoc(), E->getTypeIdParens(), AllocType, + AllocTypeInfo, ArraySize.get(), E->getDirectInitRange(), NewInit.get()); } template<typename Derived> @@ -10288,8 +10356,7 @@ TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) { FunctionDecl *OperatorDelete = nullptr; if (E->getOperatorDelete()) { OperatorDelete = cast_or_null<FunctionDecl>( - getDerived().TransformDecl(E->getLocStart(), - E->getOperatorDelete())); + getDerived().TransformDecl(E->getBeginLoc(), E->getOperatorDelete())); if (!OperatorDelete) return ExprError(); } @@ -10300,14 +10367,14 @@ TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) { // Mark any declarations we need as referenced. // FIXME: instantiation-specific. if (OperatorDelete) - SemaRef.MarkFunctionReferenced(E->getLocStart(), OperatorDelete); + SemaRef.MarkFunctionReferenced(E->getBeginLoc(), OperatorDelete); if (!E->getArgument()->isTypeDependent()) { QualType Destroyed = SemaRef.Context.getBaseElementType( E->getDestroyedType()); if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) { CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl()); - SemaRef.MarkFunctionReferenced(E->getLocStart(), + SemaRef.MarkFunctionReferenced(E->getBeginLoc(), SemaRef.LookupDestructor(Record)); } } @@ -10315,10 +10382,8 @@ TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) { return E; } - return getDerived().RebuildCXXDeleteExpr(E->getLocStart(), - E->isGlobalDelete(), - E->isArrayForm(), - Operand.get()); + return getDerived().RebuildCXXDeleteExpr( + E->getBeginLoc(), E->isGlobalDelete(), E->isArrayForm(), Operand.get()); } template<typename Derived> @@ -10651,10 +10716,8 @@ TreeTransform<Derived>::TransformTypeTraitExpr(TypeTraitExpr *E) { if (!getDerived().AlwaysRebuild() && !ArgChanged) return E; - return getDerived().RebuildTypeTrait(E->getTrait(), - E->getLocStart(), - Args, - E->getLocEnd()); + return getDerived().RebuildTypeTrait(E->getTrait(), E->getBeginLoc(), Args, + E->getEndLoc()); } template<typename Derived> @@ -10680,11 +10743,8 @@ TreeTransform<Derived>::TransformArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { return E; } - return getDerived().RebuildArrayTypeTrait(E->getTrait(), - E->getLocStart(), - T, - SubExpr.get(), - E->getLocEnd()); + return getDerived().RebuildArrayTypeTrait(E->getTrait(), E->getBeginLoc(), T, + SubExpr.get(), E->getEndLoc()); } template<typename Derived> @@ -10702,8 +10762,8 @@ TreeTransform<Derived>::TransformExpressionTraitExpr(ExpressionTraitExpr *E) { return E; } - return getDerived().RebuildExpressionTrait( - E->getTrait(), E->getLocStart(), SubExpr.get(), E->getLocEnd()); + return getDerived().RebuildExpressionTrait(E->getTrait(), E->getBeginLoc(), + SubExpr.get(), E->getEndLoc()); } template <typename Derived> @@ -10789,24 +10849,27 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) { !E->isListInitialization()) return getDerived().TransformExpr(E->getArg(0)); - TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName()); + TemporaryBase Rebase(*this, /*FIXME*/ E->getBeginLoc(), DeclarationName()); QualType T = getDerived().TransformType(E->getType()); if (T.isNull()) return ExprError(); - CXXConstructorDecl *Constructor - = cast_or_null<CXXConstructorDecl>( - getDerived().TransformDecl(E->getLocStart(), - E->getConstructor())); + CXXConstructorDecl *Constructor = cast_or_null<CXXConstructorDecl>( + getDerived().TransformDecl(E->getBeginLoc(), E->getConstructor())); if (!Constructor) return ExprError(); bool ArgumentChanged = false; SmallVector<Expr*, 8> Args; - if (getDerived().TransformExprs(E->getArgs(), E->getNumArgs(), true, Args, - &ArgumentChanged)) - return ExprError(); + { + EnterExpressionEvaluationContext Context( + getSema(), EnterExpressionEvaluationContext::InitList, + E->isListInitialization()); + if (getDerived().TransformExprs(E->getArgs(), E->getNumArgs(), true, Args, + &ArgumentChanged)) + return ExprError(); + } if (!getDerived().AlwaysRebuild() && T == E->getType() && @@ -10814,19 +10877,15 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) { !ArgumentChanged) { // Mark the constructor as referenced. // FIXME: Instantiation-specific - SemaRef.MarkFunctionReferenced(E->getLocStart(), Constructor); + SemaRef.MarkFunctionReferenced(E->getBeginLoc(), Constructor); return E; } - return getDerived().RebuildCXXConstructExpr(T, /*FIXME:*/E->getLocStart(), - Constructor, - E->isElidable(), Args, - E->hadMultipleCandidates(), - E->isListInitialization(), - E->isStdInitListInitialization(), - E->requiresZeroInitialization(), - E->getConstructionKind(), - E->getParenOrBraceRange()); + return getDerived().RebuildCXXConstructExpr( + T, /*FIXME:*/ E->getBeginLoc(), Constructor, E->isElidable(), Args, + E->hadMultipleCandidates(), E->isListInitialization(), + E->isStdInitListInitialization(), E->requiresZeroInitialization(), + E->getConstructionKind(), E->getParenOrBraceRange()); } template<typename Derived> @@ -10837,7 +10896,7 @@ ExprResult TreeTransform<Derived>::TransformCXXInheritedCtorInitExpr( return ExprError(); CXXConstructorDecl *Constructor = cast_or_null<CXXConstructorDecl>( - getDerived().TransformDecl(E->getLocStart(), E->getConstructor())); + getDerived().TransformDecl(E->getBeginLoc(), E->getConstructor())); if (!Constructor) return ExprError(); @@ -10846,7 +10905,7 @@ ExprResult TreeTransform<Derived>::TransformCXXInheritedCtorInitExpr( Constructor == E->getConstructor()) { // Mark the constructor as referenced. // FIXME: Instantiation-specific - SemaRef.MarkFunctionReferenced(E->getLocStart(), Constructor); + SemaRef.MarkFunctionReferenced(E->getBeginLoc(), Constructor); return E; } @@ -10885,26 +10944,29 @@ TreeTransform<Derived>::TransformCXXTemporaryObjectExpr( if (!T) return ExprError(); - CXXConstructorDecl *Constructor - = cast_or_null<CXXConstructorDecl>( - getDerived().TransformDecl(E->getLocStart(), - E->getConstructor())); + CXXConstructorDecl *Constructor = cast_or_null<CXXConstructorDecl>( + getDerived().TransformDecl(E->getBeginLoc(), E->getConstructor())); if (!Constructor) return ExprError(); bool ArgumentChanged = false; SmallVector<Expr*, 8> Args; Args.reserve(E->getNumArgs()); - if (TransformExprs(E->getArgs(), E->getNumArgs(), true, Args, - &ArgumentChanged)) - return ExprError(); + { + EnterExpressionEvaluationContext Context( + getSema(), EnterExpressionEvaluationContext::InitList, + E->isListInitialization()); + if (TransformExprs(E->getArgs(), E->getNumArgs(), true, Args, + &ArgumentChanged)) + return ExprError(); + } if (!getDerived().AlwaysRebuild() && T == E->getTypeSourceInfo() && Constructor == E->getConstructor() && !ArgumentChanged) { // FIXME: Instantiation-specific - SemaRef.MarkFunctionReferenced(E->getLocStart(), Constructor); + SemaRef.MarkFunctionReferenced(E->getBeginLoc(), Constructor); return SemaRef.MaybeBindToTemporary(E); } @@ -10912,7 +10974,7 @@ TreeTransform<Derived>::TransformCXXTemporaryObjectExpr( // prepared to handle list-initialization without a child InitListExpr. SourceLocation LParenLoc = T->getTypeLoc().getEndLoc(); return getDerived().RebuildCXXTemporaryObjectExpr( - T, LParenLoc, Args, E->getLocEnd(), + T, LParenLoc, Args, E->getEndLoc(), /*ListInitialization=*/LParenLoc.isInvalid()); } @@ -10970,7 +11032,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { SmallVector<QualType, 4> ExceptionStorage; TreeTransform *This = this; // Work around gcc.gnu.org/PR56135. QualType NewCallOpType = TransformFunctionProtoType( - NewCallOpTLBuilder, OldCallOpFPTL, nullptr, 0, + NewCallOpTLBuilder, OldCallOpFPTL, nullptr, Qualifiers(), [&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) { return This->TransformExceptionSpec(OldCallOpFPTL.getBeginLoc(), ESI, ExceptionStorage, Changed); @@ -10996,7 +11058,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { // Build the call operator. CXXMethodDecl *NewCallOperator = getSema().startLambdaDefinition( Class, E->getIntroducerRange(), NewCallOpTSI, - E->getCallOperator()->getLocEnd(), + E->getCallOperator()->getEndLoc(), NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams(), E->getCallOperator()->isConstexpr()); @@ -11160,7 +11222,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { if (Body.isInvalid()) { SavedContext.pop(); - getSema().ActOnLambdaError(E->getLocStart(), /*CurScope=*/nullptr, + getSema().ActOnLambdaError(E->getBeginLoc(), /*CurScope=*/nullptr, /*IsInstantiation=*/true); return ExprError(); } @@ -11173,7 +11235,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { /*IsInstantiation*/ true); SavedContext.pop(); - return getSema().BuildLambdaExpr(E->getLocStart(), Body.get()->getLocEnd(), + return getSema().BuildLambdaExpr(E->getBeginLoc(), Body.get()->getEndLoc(), &LSICopy); } @@ -11189,9 +11251,14 @@ TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr( bool ArgumentChanged = false; SmallVector<Expr*, 8> Args; Args.reserve(E->arg_size()); - if (getDerived().TransformExprs(E->arg_begin(), E->arg_size(), true, Args, - &ArgumentChanged)) - return ExprError(); + { + EnterExpressionEvaluationContext Context( + getSema(), EnterExpressionEvaluationContext::InitList, + E->isListInitialization()); + if (getDerived().TransformExprs(E->arg_begin(), E->arg_size(), true, Args, + &ArgumentChanged)) + return ExprError(); + } if (!getDerived().AlwaysRebuild() && T == E->getTypeSourceInfo() && @@ -11620,8 +11687,8 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) { return E; return getDerived().RebuildCXXFoldExpr( - E->getLocStart(), LHS.get(), E->getOperator(), E->getEllipsisLoc(), - RHS.get(), E->getLocEnd()); + E->getBeginLoc(), LHS.get(), E->getOperator(), E->getEllipsisLoc(), + RHS.get(), E->getEndLoc()); } // The transform has determined that we should perform an elementwise @@ -11641,8 +11708,8 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) { return true; Result = getDerived().RebuildCXXFoldExpr( - E->getLocStart(), Out.get(), E->getOperator(), E->getEllipsisLoc(), - Result.get(), E->getLocEnd()); + E->getBeginLoc(), Out.get(), E->getOperator(), E->getEllipsisLoc(), + Result.get(), E->getEndLoc()); if (Result.isInvalid()) return true; } @@ -11657,11 +11724,9 @@ 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->getLocStart(), - LeftFold ? Result.get() : Out.get(), + E->getBeginLoc(), LeftFold ? Result.get() : Out.get(), E->getOperator(), E->getEllipsisLoc(), - LeftFold ? Out.get() : Result.get(), - E->getLocEnd()); + LeftFold ? Out.get() : Result.get(), E->getEndLoc()); } else if (Result.isUsable()) { // We've got down to a single element; build a binary operator. Result = getDerived().RebuildBinaryOperator( @@ -11685,9 +11750,8 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) { return true; Result = getDerived().RebuildCXXFoldExpr( - E->getLocStart(), Result.get(), - E->getOperator(), E->getEllipsisLoc(), - Out.get(), E->getLocEnd()); + E->getBeginLoc(), Result.get(), E->getOperator(), E->getEllipsisLoc(), + Out.get(), E->getEndLoc()); if (Result.isInvalid()) return true; } @@ -11775,13 +11839,11 @@ TreeTransform<Derived>::TransformObjCDictionaryLiteral( bool RetainExpansion = false; Optional<unsigned> OrigNumExpansions = OrigElement.NumExpansions; Optional<unsigned> NumExpansions = OrigNumExpansions; - SourceRange PatternRange(OrigElement.Key->getLocStart(), - OrigElement.Value->getLocEnd()); - if (getDerived().TryExpandParameterPacks(OrigElement.EllipsisLoc, - PatternRange, - Unexpanded, - Expand, RetainExpansion, - NumExpansions)) + SourceRange PatternRange(OrigElement.Key->getBeginLoc(), + OrigElement.Value->getEndLoc()); + if (getDerived().TryExpandParameterPacks(OrigElement.EllipsisLoc, + PatternRange, Unexpanded, Expand, + RetainExpansion, NumExpansions)) return ExprError(); if (!Expand) { @@ -12651,9 +12713,8 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, if (Op == OO_Subscript) { if (!First->getType()->isOverloadableType() && !Second->getType()->isOverloadableType()) - return getSema().CreateBuiltinArraySubscriptExpr(First, - Callee->getLocStart(), - Second, OpLoc); + return getSema().CreateBuiltinArraySubscriptExpr( + First, Callee->getBeginLoc(), Second, OpLoc); } else if (Op == OO_Arrow) { // -> is never a builtin operation. return SemaRef.BuildOverloadedArrowExpr(nullptr, First, OpLoc); @@ -12727,8 +12788,8 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, RBrace = SourceLocation::getFromRawEncoding( NameLoc.CXXOperatorName.EndOpNameLoc); } else { - LBrace = Callee->getLocStart(); - RBrace = OpLoc; + LBrace = Callee->getBeginLoc(); + RBrace = OpLoc; } return SemaRef.CreateOverloadedArraySubscriptExpr(LBrace, RBrace, @@ -12799,7 +12860,7 @@ TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(Expr *Base, template<typename Derived> StmtResult TreeTransform<Derived>::TransformCapturedStmt(CapturedStmt *S) { - SourceLocation Loc = S->getLocStart(); + SourceLocation Loc = S->getBeginLoc(); CapturedDecl *CD = S->getCapturedDecl(); unsigned NumParams = CD->getNumParams(); unsigned ContextParamPos = CD->getContextParamPosition(); |