summaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/AnalysisBasedWarnings.cpp135
-rw-r--r--lib/Sema/CMakeLists.txt1
-rw-r--r--lib/Sema/CodeCompleteConsumer.cpp222
-rw-r--r--lib/Sema/DeclSpec.cpp63
-rw-r--r--lib/Sema/IdentifierResolver.cpp14
-rw-r--r--lib/Sema/JumpDiagnostics.cpp16
-rw-r--r--lib/Sema/ParsedAttr.cpp49
-rw-r--r--lib/Sema/ScopeInfo.cpp2
-rw-r--r--lib/Sema/Sema.cpp135
-rw-r--r--lib/Sema/SemaAccess.cpp47
-rw-r--r--lib/Sema/SemaAttr.cpp112
-rw-r--r--lib/Sema/SemaCUDA.cpp2
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp24
-rw-r--r--lib/Sema/SemaCast.cpp105
-rw-r--r--lib/Sema/SemaChecking.cpp2758
-rw-r--r--lib/Sema/SemaCodeComplete.cpp3022
-rw-r--r--lib/Sema/SemaCoroutine.cpp43
-rw-r--r--lib/Sema/SemaDecl.cpp959
-rw-r--r--lib/Sema/SemaDeclAttr.cpp1214
-rw-r--r--lib/Sema/SemaDeclCXX.cpp814
-rw-r--r--lib/Sema/SemaDeclObjC.cpp52
-rw-r--r--lib/Sema/SemaExceptionSpec.cpp54
-rw-r--r--lib/Sema/SemaExpr.cpp1157
-rw-r--r--lib/Sema/SemaExprCXX.cpp389
-rw-r--r--lib/Sema/SemaExprMember.cpp30
-rw-r--r--lib/Sema/SemaExprObjC.cpp240
-rw-r--r--lib/Sema/SemaInit.cpp710
-rw-r--r--lib/Sema/SemaLambda.cpp157
-rw-r--r--lib/Sema/SemaLookup.cpp161
-rw-r--r--lib/Sema/SemaObjCProperty.cpp42
-rw-r--r--lib/Sema/SemaOpenMP.cpp1749
-rw-r--r--lib/Sema/SemaOverload.cpp628
-rw-r--r--lib/Sema/SemaPseudoObject.cpp2
-rw-r--r--lib/Sema/SemaStmt.cpp429
-rw-r--r--lib/Sema/SemaStmtAsm.cpp160
-rw-r--r--lib/Sema/SemaStmtAttr.cpp99
-rw-r--r--lib/Sema/SemaTemplate.cpp396
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp19
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp53
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp352
-rw-r--r--lib/Sema/SemaTemplateVariadic.cpp9
-rw-r--r--lib/Sema/SemaType.cpp1013
-rw-r--r--lib/Sema/TreeTransform.h703
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();