aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/tools/clang/lib/Sema
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-07-31 17:06:31 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-07-31 17:06:31 +0000
commit735bee93f1285c5c55c64d80fdc2ede4c0f23341 (patch)
treee1209c2a0b4880eee15e0ce705016372f7c88724 /contrib/llvm/tools/clang/lib/Sema
parent51315c45ff5643a27f9c84b816db54ee870ba29b (diff)
parent486754660bb926339aefcf012a3f848592babb8b (diff)
Merge clang trunk r338150, and resolve conflicts.
Notes
Notes: svn path=/projects/clang700-import/; revision=336979
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema')
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp270
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp162
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/CoroutineStmtBuilder.h10
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp56
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp21
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp39
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp18
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/ParsedAttr.cpp (renamed from contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp)162
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp1
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/Sema.cpp232
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp29
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp17
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp88
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp21
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp457
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp2519
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp2361
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp326
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp1379
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp4288
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp1031
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp209
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp421
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp1141
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp572
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp150
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp76
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp1027
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp107
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp240
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp24
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp3152
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp698
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp95
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp572
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp27
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp748
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp728
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp329
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp168
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp119
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaType.cpp1208
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TreeTransform.h703
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h6
46 files changed, 15592 insertions, 10431 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 0033edf326ac..82d9df25d934 100644
--- a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -122,7 +122,7 @@ static void CheckUnreachable(Sema &S, AnalysisDeclContext &AC) {
}
namespace {
-/// \brief Warn on logical operator errors in CFGBuilder
+/// Warn on logical operator errors in CFGBuilder
class LogicalErrorHandler : public CFGCallback {
Sema &S;
@@ -200,60 +200,41 @@ static bool hasRecursiveCallInPath(const FunctionDecl *FD, CFGBlock &Block) {
return false;
}
-// All blocks are in one of three states. States are ordered so that blocks
-// can only move to higher states.
-enum RecursiveState {
- FoundNoPath,
- FoundPath,
- FoundPathWithNoRecursiveCall
-};
-
-// Returns true if there exists a path to the exit block and every path
-// to the exit block passes through a call to FD.
+// Returns true if every path from the entry block passes through a call to FD.
static bool checkForRecursiveFunctionCall(const FunctionDecl *FD, CFG *cfg) {
+ llvm::SmallPtrSet<CFGBlock *, 16> Visited;
+ llvm::SmallVector<CFGBlock *, 16> WorkList;
+ // Keep track of whether we found at least one recursive path.
+ bool foundRecursion = false;
const unsigned ExitID = cfg->getExit().getBlockID();
- // Mark all nodes as FoundNoPath, then set the status of the entry block.
- SmallVector<RecursiveState, 16> States(cfg->getNumBlockIDs(), FoundNoPath);
- States[cfg->getEntry().getBlockID()] = FoundPathWithNoRecursiveCall;
-
- // Make the processing stack and seed it with the entry block.
- SmallVector<CFGBlock *, 16> Stack;
- Stack.push_back(&cfg->getEntry());
-
- while (!Stack.empty()) {
- CFGBlock *CurBlock = Stack.back();
- Stack.pop_back();
+ // Seed the work list with the entry block.
+ WorkList.push_back(&cfg->getEntry());
- unsigned ID = CurBlock->getBlockID();
- RecursiveState CurState = States[ID];
+ while (!WorkList.empty()) {
+ CFGBlock *Block = WorkList.pop_back_val();
- if (CurState == FoundPathWithNoRecursiveCall) {
- // Found a path to the exit node without a recursive call.
- if (ExitID == ID)
- return false;
+ for (auto I = Block->succ_begin(), E = Block->succ_end(); I != E; ++I) {
+ if (CFGBlock *SuccBlock = *I) {
+ if (!Visited.insert(SuccBlock).second)
+ continue;
- // Only change state if the block has a recursive call.
- if (hasRecursiveCallInPath(FD, *CurBlock))
- CurState = FoundPath;
- }
+ // Found a path to the exit node without a recursive call.
+ if (ExitID == SuccBlock->getBlockID())
+ return false;
- // Loop over successor blocks and add them to the Stack if their state
- // changes.
- for (auto I = CurBlock->succ_begin(), E = CurBlock->succ_end(); I != E; ++I)
- if (*I) {
- unsigned next_ID = (*I)->getBlockID();
- if (States[next_ID] < CurState) {
- States[next_ID] = CurState;
- Stack.push_back(*I);
+ // If the successor block contains a recursive call, end analysis there.
+ if (hasRecursiveCallInPath(FD, *SuccBlock)) {
+ foundRecursion = true;
+ continue;
}
+
+ WorkList.push_back(SuccBlock);
}
+ }
}
-
- // Return true if the exit node is reachable, and only reachable through
- // a recursive call.
- return States[ExitID] == FoundPath;
+ return foundRecursion;
}
static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,
@@ -269,10 +250,6 @@ static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,
CFG *cfg = AC.getCFG();
if (!cfg) return;
- // If the exit block is unreachable, skip processing the function.
- if (cfg->getExit().pred_empty())
- return;
-
// 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);
@@ -281,114 +258,62 @@ static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,
//===----------------------------------------------------------------------===//
// Check for throw in a non-throwing function.
//===----------------------------------------------------------------------===//
-enum ThrowState {
- FoundNoPathForThrow,
- FoundPathForThrow,
- FoundPathWithNoThrowOutFunction,
-};
-static bool isThrowCaught(const CXXThrowExpr *Throw,
- const CXXCatchStmt *Catch) {
- const Type *CaughtType = Catch->getCaughtType().getTypePtrOrNull();
- if (!CaughtType)
- return true;
- const Type *ThrowType = nullptr;
- if (Throw->getSubExpr())
- ThrowType = Throw->getSubExpr()->getType().getTypePtrOrNull();
- if (!ThrowType)
- return false;
- if (ThrowType->isReferenceType())
- ThrowType = ThrowType->castAs<ReferenceType>()
- ->getPointeeType()
- ->getUnqualifiedDesugaredType();
- if (CaughtType->isReferenceType())
- CaughtType = CaughtType->castAs<ReferenceType>()
- ->getPointeeType()
- ->getUnqualifiedDesugaredType();
- if (ThrowType->isPointerType() && CaughtType->isPointerType()) {
- ThrowType = ThrowType->getPointeeType()->getUnqualifiedDesugaredType();
- CaughtType = CaughtType->getPointeeType()->getUnqualifiedDesugaredType();
- }
- if (CaughtType == ThrowType)
- return true;
- const CXXRecordDecl *CaughtAsRecordType =
- CaughtType->getAsCXXRecordDecl();
- const CXXRecordDecl *ThrowTypeAsRecordType = ThrowType->getAsCXXRecordDecl();
- if (CaughtAsRecordType && ThrowTypeAsRecordType)
- return ThrowTypeAsRecordType->isDerivedFrom(CaughtAsRecordType);
- return false;
-}
+/// Determine whether an exception thrown by E, unwinding from ThrowBlock,
+/// can reach ExitBlock.
+static bool throwEscapes(Sema &S, const CXXThrowExpr *E, CFGBlock &ThrowBlock,
+ CFG *Body) {
+ SmallVector<CFGBlock *, 16> Stack;
+ llvm::BitVector Queued(Body->getNumBlockIDs());
-static bool isThrowCaughtByHandlers(const CXXThrowExpr *CE,
- const CXXTryStmt *TryStmt) {
- for (unsigned H = 0, E = TryStmt->getNumHandlers(); H < E; ++H) {
- if (isThrowCaught(CE, TryStmt->getHandler(H)))
- return true;
- }
- return false;
-}
+ Stack.push_back(&ThrowBlock);
+ Queued[ThrowBlock.getBlockID()] = true;
-static bool doesThrowEscapePath(CFGBlock Block, SourceLocation &OpLoc) {
- for (const auto &B : Block) {
- if (B.getKind() != CFGElement::Statement)
- continue;
- const auto *CE = dyn_cast<CXXThrowExpr>(B.getAs<CFGStmt>()->getStmt());
- if (!CE)
- continue;
+ while (!Stack.empty()) {
+ CFGBlock &UnwindBlock = *Stack.back();
+ Stack.pop_back();
- OpLoc = CE->getThrowLoc();
- for (const auto &I : Block.succs()) {
- if (!I.isReachable())
+ for (auto &Succ : UnwindBlock.succs()) {
+ if (!Succ.isReachable() || Queued[Succ->getBlockID()])
continue;
- if (const auto *Terminator =
- dyn_cast_or_null<CXXTryStmt>(I->getTerminator()))
- if (isThrowCaughtByHandlers(CE, Terminator))
- return false;
+
+ if (Succ->getBlockID() == Body->getExit().getBlockID())
+ return true;
+
+ if (auto *Catch =
+ dyn_cast_or_null<CXXCatchStmt>(Succ->getLabel())) {
+ QualType Caught = Catch->getCaughtType();
+ if (Caught.isNull() || // catch (...) catches everything
+ !E->getSubExpr() || // throw; is considered cuaght by any handler
+ S.handlerCanCatch(Caught, E->getSubExpr()->getType()))
+ // Exception doesn't escape via this path.
+ break;
+ } else {
+ Stack.push_back(Succ);
+ Queued[Succ->getBlockID()] = true;
+ }
}
- return true;
}
+
return false;
}
-static bool hasThrowOutNonThrowingFunc(SourceLocation &OpLoc, CFG *BodyCFG) {
-
- unsigned ExitID = BodyCFG->getExit().getBlockID();
-
- SmallVector<ThrowState, 16> States(BodyCFG->getNumBlockIDs(),
- FoundNoPathForThrow);
- States[BodyCFG->getEntry().getBlockID()] = FoundPathWithNoThrowOutFunction;
-
- SmallVector<CFGBlock *, 16> Stack;
- Stack.push_back(&BodyCFG->getEntry());
- while (!Stack.empty()) {
- CFGBlock *CurBlock = Stack.pop_back_val();
-
- unsigned ID = CurBlock->getBlockID();
- ThrowState CurState = States[ID];
- if (CurState == FoundPathWithNoThrowOutFunction) {
- if (ExitID == ID)
+static void visitReachableThrows(
+ CFG *BodyCFG,
+ llvm::function_ref<void(const CXXThrowExpr *, CFGBlock &)> Visit) {
+ llvm::BitVector Reachable(BodyCFG->getNumBlockIDs());
+ clang::reachable_code::ScanReachableFromBlock(&BodyCFG->getEntry(), Reachable);
+ for (CFGBlock *B : *BodyCFG) {
+ if (!Reachable[B->getBlockID()])
+ continue;
+ for (CFGElement &E : *B) {
+ Optional<CFGStmt> S = E.getAs<CFGStmt>();
+ if (!S)
continue;
-
- if (doesThrowEscapePath(*CurBlock, OpLoc))
- CurState = FoundPathForThrow;
+ if (auto *Throw = dyn_cast<CXXThrowExpr>(S->getStmt()))
+ Visit(Throw, *B);
}
-
- // Loop over successor blocks and add them to the Stack if their state
- // changes.
- for (const auto &I : CurBlock->succs())
- if (I.isReachable()) {
- unsigned NextID = I->getBlockID();
- if (NextID == ExitID && CurState == FoundPathForThrow) {
- States[NextID] = CurState;
- } else if (States[NextID] < CurState) {
- States[NextID] = CurState;
- Stack.push_back(I);
- }
- }
}
- // Return true if the exit node is reachable, and only reachable through
- // a throw expression.
- return States[ExitID] == FoundPathForThrow;
}
static void EmitDiagForCXXThrowInNonThrowingFunc(Sema &S, SourceLocation OpLoc,
@@ -418,14 +343,15 @@ static void checkThrowInNonThrowingFunc(Sema &S, const FunctionDecl *FD,
return;
if (BodyCFG->getExit().pred_empty())
return;
- SourceLocation OpLoc;
- if (hasThrowOutNonThrowingFunc(OpLoc, BodyCFG))
- EmitDiagForCXXThrowInNonThrowingFunc(S, OpLoc, FD);
+ visitReachableThrows(BodyCFG, [&](const CXXThrowExpr *Throw, CFGBlock &Block) {
+ if (throwEscapes(S, Throw, Block, BodyCFG))
+ EmitDiagForCXXThrowInNonThrowingFunc(S, Throw->getThrowLoc(), FD);
+ });
}
static bool isNoexcept(const FunctionDecl *FD) {
const auto *FPT = FD->getType()->castAs<FunctionProtoType>();
- if (FPT->isNothrow(FD->getASTContext()) || FD->hasAttr<NoThrowAttr>())
+ if (FPT->isNothrow() || FD->hasAttr<NoThrowAttr>())
return true;
return false;
}
@@ -491,9 +417,10 @@ static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) {
CFGBlock::FilterOptions FO;
FO.IgnoreDefaultsWithCoveredEnums = 1;
- for (CFGBlock::filtered_pred_iterator
- I = cfg->getExit().filtered_pred_start_end(FO); I.hasMore(); ++I) {
- const CFGBlock& B = **I;
+ for (CFGBlock::filtered_pred_iterator I =
+ cfg->getExit().filtered_pred_start_end(FO);
+ I.hasMore(); ++I) {
+ const CFGBlock &B = **I;
if (!live[B.getBlockID()])
continue;
@@ -683,18 +610,19 @@ struct CheckFallThroughDiagnostics {
} // anonymous namespace
-/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a
+/// CheckFallThroughForBody - Check that we don't fall off the end of a
/// function that should return a value. Check that we don't fall off the end
/// of a noreturn function. We assume that functions and blocks not marked
/// noreturn will return.
static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
const BlockExpr *blkExpr,
- const CheckFallThroughDiagnostics& CD,
- AnalysisDeclContext &AC) {
+ const CheckFallThroughDiagnostics &CD,
+ AnalysisDeclContext &AC,
+ sema::FunctionScopeInfo *FSI) {
bool ReturnsVoid = false;
bool HasNoReturn = false;
- bool IsCoroutine = S.getCurFunction() && S.getCurFunction()->isCoroutine();
+ bool IsCoroutine = FSI->isCoroutine();
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
if (const auto *CBody = dyn_cast<CoroutineBodyStmt>(Body))
@@ -726,10 +654,15 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
SourceLocation LBrace = Body->getLocStart(), RBrace = Body->getLocEnd();
auto EmitDiag = [&](SourceLocation Loc, unsigned DiagID) {
if (IsCoroutine)
- S.Diag(Loc, DiagID) << S.getCurFunction()->CoroutinePromise->getType();
+ S.Diag(Loc, DiagID) << FSI->CoroutinePromise->getType();
else
S.Diag(Loc, DiagID);
};
+
+ // cpu_dispatch functions permit empty function bodies for ICC compatibility.
+ if (D->getAsFunction() && D->getAsFunction()->isCPUDispatchMultiVersion())
+ return;
+
// Either in a function body compound statement, or a function-try-block.
switch (CheckFallThrough(AC)) {
case UnknownFallThrough:
@@ -1461,8 +1394,8 @@ static void diagnoseRepeatedUseOfWeak(Sema &S,
// Sort by first use so that we emit the warnings in a deterministic order.
SourceManager &SM = S.getSourceManager();
- std::sort(UsesByStmt.begin(), UsesByStmt.end(),
- [&SM](const StmtUsesPair &LHS, const StmtUsesPair &RHS) {
+ llvm::sort(UsesByStmt.begin(), UsesByStmt.end(),
+ [&SM](const StmtUsesPair &LHS, const StmtUsesPair &RHS) {
return SM.isBeforeInTranslationUnit(LHS.first->getLocStart(),
RHS.first->getLocStart());
});
@@ -1600,8 +1533,8 @@ public:
// Sort the uses by their SourceLocations. While not strictly
// guaranteed to produce them in line/column order, this will provide
// a stable ordering.
- std::sort(vec->begin(), vec->end(),
- [](const UninitUse &a, const UninitUse &b) {
+ llvm::sort(vec->begin(), vec->end(),
+ [](const UninitUse &a, const UninitUse &b) {
// Prefer a more confident report over a less confident one.
if (a.getKind() != b.getKind())
return a.getKind() > b.getKind();
@@ -1674,7 +1607,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
if (Verbose && CurrentFunction) {
PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(),
S.PDiag(diag::note_thread_warning_in_fun)
- << CurrentFunction->getNameAsString());
+ << CurrentFunction);
return OptionalNotes(1, FNote);
}
return OptionalNotes();
@@ -1685,7 +1618,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
if (Verbose && CurrentFunction) {
PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(),
S.PDiag(diag::note_thread_warning_in_fun)
- << CurrentFunction->getNameAsString());
+ << CurrentFunction);
ONS.push_back(std::move(FNote));
}
return ONS;
@@ -1699,7 +1632,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
if (Verbose && CurrentFunction) {
PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(),
S.PDiag(diag::note_thread_warning_in_fun)
- << CurrentFunction->getNameAsString());
+ << CurrentFunction);
ONS.push_back(std::move(FNote));
}
return ONS;
@@ -1723,7 +1656,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
void setVerbose(bool b) { Verbose = b; }
- /// \brief Emit all buffered diagnostics in order of sourcelocation.
+ /// Emit all buffered diagnostics in order of sourcelocation.
/// We need to output diagnostics produced while iterating through
/// the lockset in deterministic order, so this function orders diagnostics
/// and outputs them.
@@ -1815,7 +1748,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
diag::warn_variable_requires_any_lock:
diag::warn_var_deref_requires_any_lock;
PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID)
- << D->getNameAsString() << getLockKindFromAccessKind(AK));
+ << D << getLockKindFromAccessKind(AK));
Warnings.emplace_back(std::move(Warning), getNotes());
}
@@ -1843,7 +1776,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
break;
}
PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind
- << D->getNameAsString()
+ << D
<< LockName << LK);
PartialDiagnosticAt Note(Loc, S.PDiag(diag::note_found_mutex_near_match)
<< *PossibleMatch);
@@ -1873,12 +1806,11 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
break;
}
PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind
- << D->getNameAsString()
+ << D
<< LockName << LK);
if (Verbose && POK == POK_VarAccess) {
PartialDiagnosticAt Note(D->getLocation(),
- S.PDiag(diag::note_guarded_by_declared_here)
- << D->getNameAsString());
+ S.PDiag(diag::note_guarded_by_declared_here));
Warnings.emplace_back(std::move(Warning), getNotes(Note));
} else
Warnings.emplace_back(std::move(Warning), getNotes());
@@ -2194,7 +2126,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
: (fscope->isCoroutine()
? CheckFallThroughDiagnostics::MakeForCoroutine(D)
: CheckFallThroughDiagnostics::MakeForFunction(D)));
- CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC);
+ CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC, fscope);
}
// Warning: check for unreachable code
diff --git a/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp
index 3431ddcf70a2..9c4d315a692f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp
@@ -1,4 +1,4 @@
-//===--- CodeCompleteConsumer.cpp - Code Completion Interface ---*- C++ -*-===//
+//===- CodeCompleteConsumer.cpp - Code Completion Interface ---------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,21 +10,30 @@
// This file implements the CodeCompleteConsumer class.
//
//===----------------------------------------------------------------------===//
+
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang-c/Index.h"
-#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
-#include "clang/Sema/Scope.h"
+#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 "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
-#include <cstring>
-#include <functional>
+#include <cassert>
+#include <cstdint>
+#include <string>
using namespace clang;
@@ -33,7 +42,7 @@ using namespace clang;
//===----------------------------------------------------------------------===//
bool CodeCompletionContext::wantConstructorResults() const {
- switch (Kind) {
+ switch (CCKind) {
case CCC_Recovery:
case CCC_Statement:
case CCC_Expression:
@@ -76,12 +85,87 @@ bool CodeCompletionContext::wantConstructorResults() const {
llvm_unreachable("Invalid CodeCompletionContext::Kind!");
}
+StringRef clang::getCompletionKindString(CodeCompletionContext::Kind Kind) {
+ using CCKind = CodeCompletionContext::Kind;
+ switch (Kind) {
+ case CCKind::CCC_Other:
+ return "Other";
+ case CCKind::CCC_OtherWithMacros:
+ return "OtherWithMacros";
+ case CCKind::CCC_TopLevel:
+ return "TopLevel";
+ case CCKind::CCC_ObjCInterface:
+ return "ObjCInterface";
+ case CCKind::CCC_ObjCImplementation:
+ return "ObjCImplementation";
+ case CCKind::CCC_ObjCIvarList:
+ return "ObjCIvarList";
+ case CCKind::CCC_ClassStructUnion:
+ return "ClassStructUnion";
+ case CCKind::CCC_Statement:
+ return "Statement";
+ case CCKind::CCC_Expression:
+ return "Expression";
+ case CCKind::CCC_ObjCMessageReceiver:
+ return "ObjCMessageReceiver";
+ case CCKind::CCC_DotMemberAccess:
+ return "DotMemberAccess";
+ case CCKind::CCC_ArrowMemberAccess:
+ return "ArrowMemberAccess";
+ case CCKind::CCC_ObjCPropertyAccess:
+ return "ObjCPropertyAccess";
+ case CCKind::CCC_EnumTag:
+ return "EnumTag";
+ case CCKind::CCC_UnionTag:
+ return "UnionTag";
+ case CCKind::CCC_ClassOrStructTag:
+ return "ClassOrStructTag";
+ case CCKind::CCC_ObjCProtocolName:
+ return "ObjCProtocolName";
+ case CCKind::CCC_Namespace:
+ return "Namespace";
+ case CCKind::CCC_Type:
+ return "Type";
+ case CCKind::CCC_Name:
+ return "Name";
+ case CCKind::CCC_PotentiallyQualifiedName:
+ return "PotentiallyQualifiedName";
+ case CCKind::CCC_MacroName:
+ return "MacroName";
+ case CCKind::CCC_MacroNameUse:
+ return "MacroNameUse";
+ case CCKind::CCC_PreprocessorExpression:
+ return "PreprocessorExpression";
+ case CCKind::CCC_PreprocessorDirective:
+ return "PreprocessorDirective";
+ case CCKind::CCC_NaturalLanguage:
+ return "NaturalLanguage";
+ case CCKind::CCC_SelectorName:
+ return "SelectorName";
+ case CCKind::CCC_TypeQualifiers:
+ return "TypeQualifiers";
+ case CCKind::CCC_ParenthesizedExpression:
+ return "ParenthesizedExpression";
+ case CCKind::CCC_ObjCInstanceMessage:
+ return "ObjCInstanceMessage";
+ case CCKind::CCC_ObjCClassMessage:
+ return "ObjCClassMessage";
+ case CCKind::CCC_ObjCInterfaceName:
+ return "ObjCInterfaceName";
+ case CCKind::CCC_ObjCCategoryName:
+ return "ObjCCategoryName";
+ case CCKind::CCC_Recovery:
+ return "Recovery";
+ }
+ llvm_unreachable("Invalid CodeCompletionContext::Kind!");
+}
+
//===----------------------------------------------------------------------===//
// Code completion string implementation
//===----------------------------------------------------------------------===//
+
CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text)
- : Kind(Kind), Text("")
-{
+ : Kind(Kind), Text("") {
switch (Kind) {
case CK_TypedText:
case CK_Text:
@@ -195,10 +279,9 @@ CodeCompletionString::CodeCompletionString(const Chunk *Chunks,
unsigned NumAnnotations,
StringRef ParentName,
const char *BriefComment)
- : NumChunks(NumChunks), NumAnnotations(NumAnnotations),
- Priority(Priority), Availability(Availability),
- ParentName(ParentName), BriefComment(BriefComment)
-{
+ : NumChunks(NumChunks), NumAnnotations(NumAnnotations),
+ Priority(Priority), Availability(Availability),
+ ParentName(ParentName), BriefComment(BriefComment) {
assert(NumChunks <= 0xffff);
assert(NumAnnotations <= 0xffff);
@@ -222,7 +305,6 @@ const char *CodeCompletionString::getAnnotation(unsigned AnnotationNr) const {
return nullptr;
}
-
std::string CodeCompletionString::getAsString() const {
std::string Result;
llvm::raw_string_ostream OS(Result);
@@ -267,7 +349,7 @@ const char *CodeCompletionAllocator::CopyString(const Twine &String) {
StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) {
const NamedDecl *ND = dyn_cast<NamedDecl>(DC);
if (!ND)
- return StringRef();
+ return {};
// Check whether we've already cached the parent name.
StringRef &CachedParentName = ParentNames[DC];
@@ -277,7 +359,7 @@ StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) {
// If we already processed this DeclContext and assigned empty to it, the
// data pointer will be non-null.
if (CachedParentName.data() != nullptr)
- return StringRef();
+ return {};
// Find the interesting names.
SmallVector<const DeclContext *, 2> Contexts;
@@ -311,7 +393,7 @@ StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) {
// Assign an empty StringRef but with non-null data to distinguish
// between empty because we didn't process the DeclContext yet.
CachedParentName = StringRef((const char *)(uintptr_t)~0U, 0);
- return StringRef();
+ return {};
}
OS << Interface->getName() << '(' << Cat->getName() << ')';
@@ -375,9 +457,8 @@ void CodeCompletionBuilder::AddChunk(CodeCompletionString::ChunkKind CK,
}
void CodeCompletionBuilder::addParentContext(const DeclContext *DC) {
- if (DC->isTranslationUnit()) {
+ if (DC->isTranslationUnit())
return;
- }
if (DC->isFunctionOrMethod())
return;
@@ -427,25 +508,21 @@ CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
// Code completion consumer implementation
//===----------------------------------------------------------------------===//
-CodeCompleteConsumer::~CodeCompleteConsumer() { }
+CodeCompleteConsumer::~CodeCompleteConsumer() = default;
bool PrintingCodeCompleteConsumer::isResultFilteredOut(StringRef Filter,
CodeCompletionResult Result) {
switch (Result.Kind) {
- case CodeCompletionResult::RK_Declaration: {
+ case CodeCompletionResult::RK_Declaration:
return !(Result.Declaration->getIdentifier() &&
Result.Declaration->getIdentifier()->getName().startswith(Filter));
- }
- case CodeCompletionResult::RK_Keyword: {
+ case CodeCompletionResult::RK_Keyword:
return !StringRef(Result.Keyword).startswith(Filter);
- }
- case CodeCompletionResult::RK_Macro: {
+ case CodeCompletionResult::RK_Macro:
return !Result.Macro->getName().startswith(Filter);
- }
- case CodeCompletionResult::RK_Pattern: {
+ case CodeCompletionResult::RK_Pattern:
return !StringRef(Result.Pattern->getAsString()).startswith(Filter);
}
- }
llvm_unreachable("Unknown code completion result Kind.");
}
@@ -477,7 +554,24 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
if (const char *BriefComment = CCS->getBriefComment())
OS << " : " << BriefComment;
}
-
+ for (const FixItHint &FixIt : Results[I].FixIts) {
+ const SourceLocation BLoc = FixIt.RemoveRange.getBegin();
+ const SourceLocation ELoc = FixIt.RemoveRange.getEnd();
+
+ SourceManager &SM = SemaRef.SourceMgr;
+ std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(BLoc);
+ std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(ELoc);
+ // Adjust for token ranges.
+ if (FixIt.RemoveRange.isTokenRange())
+ EInfo.second += Lexer::MeasureTokenLength(ELoc, SM, SemaRef.LangOpts);
+
+ OS << " (requires fix-it:"
+ << " {" << SM.getLineNumber(BInfo.first, BInfo.second) << ':'
+ << SM.getColumnNumber(BInfo.first, BInfo.second) << '-'
+ << SM.getLineNumber(EInfo.first, EInfo.second) << ':'
+ << SM.getColumnNumber(EInfo.first, EInfo.second) << "}"
+ << " to \"" << FixIt.CodeToInsert << "\")";
+ }
OS << '\n';
break;
@@ -485,7 +579,7 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
OS << Results[I].Keyword << '\n';
break;
- case CodeCompletionResult::RK_Macro: {
+ case CodeCompletionResult::RK_Macro:
OS << Results[I].Macro->getName();
if (CodeCompletionString *CCS
= Results[I].CreateCodeCompletionString(SemaRef, Context,
@@ -496,14 +590,12 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
}
OS << '\n';
break;
- }
- case CodeCompletionResult::RK_Pattern: {
+ case CodeCompletionResult::RK_Pattern:
OS << "Pattern : "
<< Results[I].Pattern->getAsString() << '\n';
break;
}
- }
}
}
@@ -547,7 +639,7 @@ PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
}
}
-/// \brief Retrieve the effective availability of the given declaration.
+/// Retrieve the effective availability of the given declaration.
static AvailabilityResult getDeclAvailability(const Decl *D) {
AvailabilityResult AR = D->getAvailability();
if (isa<EnumConstantDecl>(D))
@@ -609,7 +701,7 @@ void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) {
Availability = CXAvailability_NotAccessible;
}
-/// \brief Retrieve the name that should be used to order a result.
+/// Retrieve the name that should be used to order a result.
///
/// If the name needs to be constructed as a string, that string will be
/// saved into Saved and the returned StringRef will refer to it.
diff --git a/contrib/llvm/tools/clang/lib/Sema/CoroutineStmtBuilder.h b/contrib/llvm/tools/clang/lib/Sema/CoroutineStmtBuilder.h
index 33a368d92ff4..d15cf0b756e7 100644
--- a/contrib/llvm/tools/clang/lib/Sema/CoroutineStmtBuilder.h
+++ b/contrib/llvm/tools/clang/lib/Sema/CoroutineStmtBuilder.h
@@ -33,16 +33,16 @@ class CoroutineStmtBuilder : public CoroutineBodyStmt::CtorArgs {
CXXRecordDecl *PromiseRecordDecl = nullptr;
public:
- /// \brief Construct a CoroutineStmtBuilder and initialize the promise
+ /// Construct a CoroutineStmtBuilder and initialize the promise
/// statement and initial/final suspends from the FunctionScopeInfo.
CoroutineStmtBuilder(Sema &S, FunctionDecl &FD, sema::FunctionScopeInfo &Fn,
Stmt *Body);
- /// \brief Build the coroutine body statements, including the
+ /// Build the coroutine body statements, including the
/// "promise dependent" statements when the promise type is not dependent.
bool buildStatements();
- /// \brief Build the coroutine body statements that require a non-dependent
+ /// Build the coroutine body statements that require a non-dependent
/// promise type in order to construct.
///
/// For example different new/delete overloads are selected depending on
@@ -51,9 +51,6 @@ public:
/// name lookup.
bool buildDependentStatements();
- /// \brief Build just parameter moves. To use for rebuilding in TreeTransform.
- bool buildParameterMoves();
-
bool isInvalid() const { return !this->IsValid; }
private:
@@ -65,7 +62,6 @@ private:
bool makeReturnObject();
bool makeGroDeclAndReturnStmt();
bool makeReturnOnAllocFailure();
- bool makeParamMoves();
};
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
index 2fad5a18ba6b..ccca5d37ea39 100644
--- a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
@@ -186,7 +186,6 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
I.Kind = Function;
I.Loc = LocalRangeBegin;
I.EndLoc = LocalRangeEnd;
- I.Fun.AttrList = nullptr;
I.Fun.hasPrototype = hasProto;
I.Fun.isVariadic = EllipsisLoc.isValid();
I.Fun.isAmbiguous = isAmbiguous;
@@ -251,7 +250,9 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
}
break;
- case EST_ComputedNoexcept:
+ case EST_DependentNoexcept:
+ case EST_NoexceptFalse:
+ case EST_NoexceptTrue:
I.Fun.NoexceptExpr = NoexceptExpr;
break;
@@ -329,6 +330,7 @@ bool Declarator::isDeclarationOfFunction() const {
case TST_auto_type:
case TST_bool:
case TST_char:
+ case TST_char8:
case TST_char16:
case TST_char32:
case TST_class:
@@ -336,6 +338,8 @@ bool Declarator::isDeclarationOfFunction() const {
case TST_decimal32:
case TST_decimal64:
case TST_double:
+ case TST_Accum:
+ case TST_Fract:
case TST_Float16:
case TST_float128:
case TST_enum:
@@ -499,6 +503,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T,
case DeclSpec::TST_void: return "void";
case DeclSpec::TST_char: return "char";
case DeclSpec::TST_wchar: return Policy.MSWChar ? "__wchar_t" : "wchar_t";
+ case DeclSpec::TST_char8: return "char8_t";
case DeclSpec::TST_char16: return "char16_t";
case DeclSpec::TST_char32: return "char32_t";
case DeclSpec::TST_int: return "int";
@@ -506,6 +511,8 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T,
case DeclSpec::TST_half: return "half";
case DeclSpec::TST_float: return "float";
case DeclSpec::TST_double: return "double";
+ case DeclSpec::TST_accum: return "_Accum";
+ case DeclSpec::TST_fract: return "_Fract";
case DeclSpec::TST_float16: return "_Float16";
case DeclSpec::TST_float128: return "__float128";
case DeclSpec::TST_bool: return Policy.Bool ? "bool" : "_Bool";
@@ -761,6 +768,19 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
return false;
}
+bool DeclSpec::SetTypeSpecSat(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID) {
+ // Cannot set twice
+ if (TypeSpecSat) {
+ DiagID = diag::warn_duplicate_declspec;
+ PrevSpec = "_Sat";
+ return true;
+ }
+ TypeSpecSat = true;
+ TSSatLoc = Loc;
+ return false;
+}
+
bool DeclSpec::SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc,
const char *&PrevSpec, unsigned &DiagID,
const PrintingPolicy &Policy) {
@@ -974,15 +994,7 @@ void DeclSpec::SaveWrittenBuiltinSpecs() {
writtenBS.Width = getTypeSpecWidth();
writtenBS.Type = getTypeSpecType();
// Search the list of attributes for the presence of a mode attribute.
- writtenBS.ModeAttr = false;
- AttributeList* attrs = getAttributes().getList();
- while (attrs) {
- if (attrs->getKind() == AttributeList::AT_Mode) {
- writtenBS.ModeAttr = true;
- break;
- }
- attrs = attrs->getNext();
- }
+ writtenBS.ModeAttr = getAttributes().hasAttribute(ParsedAttr::AT_Mode);
}
/// Finish - This does final analysis of the declspec, rejecting things like
@@ -1096,12 +1108,16 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
}
}
- // signed/unsigned are only valid with int/char/wchar_t.
+ bool IsFixedPointType =
+ TypeSpecType == TST_accum || TypeSpecType == TST_fract;
+
+ // signed/unsigned are only valid with int/char/wchar_t/_Accum.
if (TypeSpecSign != TSS_unspecified) {
if (TypeSpecType == TST_unspecified)
TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int.
- else if (TypeSpecType != TST_int && TypeSpecType != TST_int128 &&
- TypeSpecType != TST_char && TypeSpecType != TST_wchar) {
+ else if (TypeSpecType != TST_int && TypeSpecType != TST_int128 &&
+ TypeSpecType != TST_char && TypeSpecType != TST_wchar &&
+ !IsFixedPointType) {
S.Diag(TSSLoc, diag::err_invalid_sign_spec)
<< getSpecifierName((TST)TypeSpecType, Policy);
// signed double -> double.
@@ -1116,20 +1132,24 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
case TSW_longlong: // long long int
if (TypeSpecType == TST_unspecified)
TypeSpecType = TST_int; // short -> short int, long long -> long long int.
- else if (TypeSpecType != TST_int) {
+ else if (!(TypeSpecType == TST_int ||
+ (IsFixedPointType && TypeSpecWidth != TSW_longlong))) {
S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec)
<< (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy);
TypeSpecType = TST_int;
+ TypeSpecSat = false;
TypeSpecOwned = false;
}
break;
case TSW_long: // long double, long int
if (TypeSpecType == TST_unspecified)
TypeSpecType = TST_int; // long -> long int.
- else if (TypeSpecType != TST_int && TypeSpecType != TST_double) {
+ else if (TypeSpecType != TST_int && TypeSpecType != TST_double &&
+ !IsFixedPointType) {
S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec)
<< (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy);
TypeSpecType = TST_int;
+ TypeSpecSat = false;
TypeSpecOwned = false;
}
break;
@@ -1202,7 +1222,9 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
StorageClassSpec == SCS_auto)
S.Diag(StorageClassSpecLoc, diag::warn_auto_storage_class)
<< FixItHint::CreateRemoval(StorageClassSpecLoc);
- if (TypeSpecType == TST_char16 || TypeSpecType == TST_char32)
+ if (TypeSpecType == TST_char8)
+ S.Diag(TSTLoc, diag::warn_cxx17_compat_unicode_type);
+ else if (TypeSpecType == TST_char16 || TypeSpecType == TST_char32)
S.Diag(TSTLoc, diag::warn_cxx98_compat_unicode_type)
<< (TypeSpecType == TST_char16 ? "char16_t" : "char32_t");
if (Constexpr_specified)
diff --git a/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp b/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp
index 3d321d561e60..122b477d5522 100644
--- a/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp
@@ -1,4 +1,4 @@
-//===--- DelayedDiagnostic.cpp - Delayed declarator diagnostics -*- C++ -*-===//
+//===- DelayedDiagnostic.cpp - Delayed declarator diagnostics -------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,36 +14,44 @@
// This file also defines AccessedEntity.
//
//===----------------------------------------------------------------------===//
+
#include "clang/Sema/DelayedDiagnostic.h"
-#include <string.h>
+#include <cstring>
+
using namespace clang;
using namespace sema;
DelayedDiagnostic
DelayedDiagnostic::makeAvailability(AvailabilityResult AR,
- SourceLocation Loc,
+ ArrayRef<SourceLocation> Locs,
const NamedDecl *ReferringDecl,
const NamedDecl *OffendingDecl,
const ObjCInterfaceDecl *UnknownObjCClass,
const ObjCPropertyDecl *ObjCProperty,
StringRef Msg,
bool ObjCPropertyAccess) {
+ assert(!Locs.empty());
DelayedDiagnostic DD;
DD.Kind = Availability;
DD.Triggered = false;
- DD.Loc = Loc;
+ DD.Loc = Locs.front();
DD.AvailabilityData.ReferringDecl = ReferringDecl;
DD.AvailabilityData.OffendingDecl = OffendingDecl;
DD.AvailabilityData.UnknownObjCClass = UnknownObjCClass;
DD.AvailabilityData.ObjCProperty = ObjCProperty;
char *MessageData = nullptr;
- if (Msg.size()) {
+ if (!Msg.empty()) {
MessageData = new char [Msg.size()];
memcpy(MessageData, Msg.data(), Msg.size());
}
-
DD.AvailabilityData.Message = MessageData;
DD.AvailabilityData.MessageLen = Msg.size();
+
+ DD.AvailabilityData.SelectorLocs = new SourceLocation[Locs.size()];
+ memcpy(DD.AvailabilityData.SelectorLocs, Locs.data(),
+ sizeof(SourceLocation) * Locs.size());
+ DD.AvailabilityData.NumSelectorLocs = Locs.size();
+
DD.AvailabilityData.AR = AR;
DD.AvailabilityData.ObjCPropertyAccess = ObjCPropertyAccess;
return DD;
@@ -57,6 +65,7 @@ void DelayedDiagnostic::Destroy() {
case Availability:
delete[] AvailabilityData.Message;
+ delete[] AvailabilityData.SelectorLocs;
break;
case ForbiddenType:
diff --git a/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp
index 0bdb19490bc5..dbd52dee1eea 100644
--- a/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp
@@ -1,4 +1,4 @@
-//===- IdentifierResolver.cpp - Lexical Scope Name lookup -------*- C++ -*-===//
+//===- IdentifierResolver.cpp - Lexical Scope Name lookup -----------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,10 +14,16 @@
#include "clang/Sema/IdentifierResolver.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Lex/ExternalPreprocessorSource.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Scope.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
+#include <cstdint>
using namespace clang;
@@ -35,17 +41,17 @@ class IdentifierResolver::IdDeclInfoMap {
/// impossible to add something to a pre-C++0x STL container without
/// a completely unnecessary copy.
struct IdDeclInfoPool {
- IdDeclInfoPool(IdDeclInfoPool *Next) : Next(Next) {}
-
IdDeclInfoPool *Next;
IdDeclInfo Pool[POOL_SIZE];
+
+ IdDeclInfoPool(IdDeclInfoPool *Next) : Next(Next) {}
};
- IdDeclInfoPool *CurPool;
- unsigned int CurIndex;
+ IdDeclInfoPool *CurPool = nullptr;
+ unsigned int CurIndex = POOL_SIZE;
public:
- IdDeclInfoMap() : CurPool(nullptr), CurIndex(POOL_SIZE) {}
+ IdDeclInfoMap() = default;
~IdDeclInfoMap() {
IdDeclInfoPool *Cur = CurPool;
@@ -60,7 +66,6 @@ public:
IdDeclInfo &operator[](DeclarationName Name);
};
-
//===----------------------------------------------------------------------===//
// IdDeclInfo Implementation
//===----------------------------------------------------------------------===//
@@ -83,9 +88,7 @@ void IdentifierResolver::IdDeclInfo::RemoveDecl(NamedDecl *D) {
//===----------------------------------------------------------------------===//
IdentifierResolver::IdentifierResolver(Preprocessor &PP)
- : LangOpt(PP.getLangOpts()), PP(PP),
- IdDeclInfos(new IdDeclInfoMap) {
-}
+ : LangOpt(PP.getLangOpts()), PP(PP), IdDeclInfos(new IdDeclInfoMap) {}
IdentifierResolver::~IdentifierResolver() {
delete IdDeclInfos;
@@ -245,14 +248,16 @@ IdentifierResolver::begin(DeclarationName Name) {
}
namespace {
- enum DeclMatchKind {
- DMK_Different,
- DMK_Replace,
- DMK_Ignore
- };
-}
-/// \brief Compare two declarations to see whether they are different or,
+enum DeclMatchKind {
+ DMK_Different,
+ DMK_Replace,
+ DMK_Ignore
+};
+
+} // namespace
+
+/// Compare two declarations to see whether they are different or,
/// if they are the same, whether the new declaration should replace the
/// existing declaration.
static DeclMatchKind compareDeclarations(NamedDecl *Existing, NamedDecl *New) {
diff --git a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp
index 64fa2c34b238..58a7862370cc 100644
--- a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp
@@ -154,6 +154,10 @@ static ScopePair GetDiagForGotoScopeDecl(Sema &S, const Decl *D) {
return ScopePair(diag::note_protected_by_objc_weak_init,
diag::note_exits_objc_weak);
+ case QualType::DK_nontrivial_c_struct:
+ return ScopePair(diag::note_protected_by_non_trivial_c_struct_init,
+ diag::note_exits_dtor);
+
case QualType::DK_cxx_destructor:
OutDiag = diag::note_exits_dtor;
break;
@@ -212,7 +216,7 @@ static ScopePair GetDiagForGotoScopeDecl(Sema &S, const Decl *D) {
return ScopePair(0U, 0U);
}
-/// \brief Build scope information for a declaration that is part of a DeclStmt.
+/// Build scope information for a declaration that is part of a DeclStmt.
void JumpScopeChecker::BuildScopeInformation(Decl *D, unsigned &ParentScope) {
// If this decl causes a new scope, push and switch to it.
std::pair<unsigned,unsigned> Diags = GetDiagForGotoScopeDecl(S, D);
@@ -229,7 +233,7 @@ void JumpScopeChecker::BuildScopeInformation(Decl *D, unsigned &ParentScope) {
BuildScopeInformation(Init, ParentScope);
}
-/// \brief Build scope information for a captured block literal variables.
+/// Build scope information for a captured block literal variables.
void JumpScopeChecker::BuildScopeInformation(VarDecl *D,
const BlockDecl *BDecl,
unsigned &ParentScope) {
@@ -254,6 +258,10 @@ void JumpScopeChecker::BuildScopeInformation(VarDecl *D,
Diags = ScopePair(diag::note_enters_block_captures_weak,
diag::note_exits_block_captures_weak);
break;
+ case QualType::DK_nontrivial_c_struct:
+ Diags = ScopePair(diag::note_enters_block_captures_non_trivial_c_struct,
+ diag::note_exits_block_captures_non_trivial_c_struct);
+ break;
case QualType::DK_none:
llvm_unreachable("non-lifetime captured variable");
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp
index 77ace0cfa579..7e61ccbb1068 100644
--- a/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp
@@ -16,7 +16,7 @@
using namespace clang;
-///\brief Constructs a new multiplexing external sema source and appends the
+///Constructs a new multiplexing external sema source and appends the
/// given element to it.
///
MultiplexExternalSemaSource::MultiplexExternalSemaSource(ExternalSemaSource &s1,
@@ -28,7 +28,7 @@ MultiplexExternalSemaSource::MultiplexExternalSemaSource(ExternalSemaSource &s1,
// pin the vtable here.
MultiplexExternalSemaSource::~MultiplexExternalSemaSource() {}
-///\brief Appends new source to the source list.
+///Appends new source to the source list.
///
///\param[in] source - An ExternalSemaSource.
///
@@ -164,6 +164,20 @@ void MultiplexExternalSemaSource::PrintStats() {
Sources[i]->PrintStats();
}
+Module *MultiplexExternalSemaSource::getModule(unsigned ID) {
+ for (size_t i = 0; i < Sources.size(); ++i)
+ if (auto M = Sources[i]->getModule(ID))
+ return M;
+ return nullptr;
+}
+
+bool MultiplexExternalSemaSource::DeclIsFromPCHWithObjectFile(const Decl *D) {
+ for (auto *S : Sources)
+ if (S->DeclIsFromPCHWithObjectFile(D))
+ return true;
+ return false;
+}
+
bool MultiplexExternalSemaSource::layoutRecordType(const RecordDecl *Record,
uint64_t &Size,
uint64_t &Alignment,
diff --git a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp b/contrib/llvm/tools/clang/lib/Sema/ParsedAttr.cpp
index 14d334746f1f..6509df9985ef 100644
--- a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/ParsedAttr.cpp
@@ -1,4 +1,4 @@
-//===--- AttributeList.cpp --------------------------------------*- C++ -*-===//
+//======- ParsedAttr.cpp --------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,20 +7,23 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines the AttributeList class implementation
+// This file defines the ParsedAttr class implementation
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/AttributeList.h"
+#include "clang/Sema/ParsedAttr.h"
#include "clang/AST/ASTContext.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclTemplate.h"
-#include "clang/AST/Expr.h"
#include "clang/Basic/AttrSubjectMatchRules.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include <cassert>
+#include <cstddef>
+#include <utility>
+
using namespace clang;
IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc,
@@ -31,91 +34,79 @@ IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc,
return Result;
}
-size_t AttributeList::allocated_size() const {
+size_t ParsedAttr::allocated_size() const {
if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
else if (IsTypeTagForDatatype)
return AttributeFactory::TypeTagForDatatypeAllocSize;
else if (IsProperty)
return AttributeFactory::PropertyAllocSize;
- return (sizeof(AttributeList) + NumArgs * sizeof(ArgsUnion));
+ else if (HasParsedType)
+ return sizeof(ParsedAttr) + sizeof(void *);
+ return (sizeof(ParsedAttr) + NumArgs * sizeof(ArgsUnion));
}
AttributeFactory::AttributeFactory() {
// Go ahead and configure all the inline capacity. This is just a memset.
FreeLists.resize(InlineFreeListsCapacity);
}
-AttributeFactory::~AttributeFactory() {}
+AttributeFactory::~AttributeFactory() = default;
static size_t getFreeListIndexForSize(size_t size) {
- assert(size >= sizeof(AttributeList));
+ assert(size >= sizeof(ParsedAttr));
assert((size % sizeof(void*)) == 0);
- return ((size - sizeof(AttributeList)) / sizeof(void*));
+ return ((size - sizeof(ParsedAttr)) / sizeof(void *));
}
void *AttributeFactory::allocate(size_t size) {
// Check for a previously reclaimed attribute.
size_t index = getFreeListIndexForSize(size);
- if (index < FreeLists.size()) {
- if (AttributeList *attr = FreeLists[index]) {
- FreeLists[index] = attr->NextInPool;
- return attr;
- }
+ if (index < FreeLists.size() && !FreeLists[index].empty()) {
+ ParsedAttr *attr = FreeLists[index].back();
+ FreeLists[index].pop_back();
+ return attr;
}
// Otherwise, allocate something new.
return Alloc.Allocate(size, alignof(AttributeFactory));
}
-void AttributeFactory::reclaimPool(AttributeList *cur) {
- assert(cur && "reclaiming empty pool!");
- do {
- // Read this here, because we're going to overwrite NextInPool
- // when we toss 'cur' into the appropriate queue.
- AttributeList *next = cur->NextInPool;
+void AttributeFactory::deallocate(ParsedAttr *Attr) {
+ size_t size = Attr->allocated_size();
+ size_t freeListIndex = getFreeListIndexForSize(size);
- size_t size = cur->allocated_size();
- size_t freeListIndex = getFreeListIndexForSize(size);
+ // Expand FreeLists to the appropriate size, if required.
+ if (freeListIndex >= FreeLists.size())
+ FreeLists.resize(freeListIndex + 1);
- // Expand FreeLists to the appropriate size, if required.
- if (freeListIndex >= FreeLists.size())
- FreeLists.resize(freeListIndex+1);
+#if !NDEBUG
+ // In debug mode, zero out the attribute to help find memory overwriting.
+ memset(Attr, 0, size);
+#endif
- // Add 'cur' to the appropriate free-list.
- cur->NextInPool = FreeLists[freeListIndex];
- FreeLists[freeListIndex] = cur;
-
- cur = next;
- } while (cur);
+ // Add 'Attr' to the appropriate free-list.
+ FreeLists[freeListIndex].push_back(Attr);
}
-void AttributePool::takePool(AttributeList *pool) {
- assert(pool);
-
- // Fast path: this pool is empty.
- if (!Head) {
- Head = pool;
- return;
- }
+void AttributeFactory::reclaimPool(AttributePool &cur) {
+ for (ParsedAttr *AL : cur.Attrs)
+ deallocate(AL);
+}
- // Reverse the pool onto the current head. This optimizes for the
- // pattern of pulling a lot of pools into a single pool.
- do {
- AttributeList *next = pool->NextInPool;
- pool->NextInPool = Head;
- Head = pool;
- pool = next;
- } while (pool);
+void AttributePool::takePool(AttributePool &pool) {
+ Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end());
+ pool.Attrs.clear();
}
#include "clang/Sema/AttrParsedAttrKinds.inc"
static StringRef normalizeAttrName(StringRef AttrName, StringRef ScopeName,
- AttributeList::Syntax SyntaxUsed) {
+ ParsedAttr::Syntax SyntaxUsed) {
// Normalize the attribute name, __foo__ becomes foo. This is only allowable
// for GNU attributes.
- bool IsGNU = SyntaxUsed == AttributeList::AS_GNU ||
- ((SyntaxUsed == AttributeList::AS_CXX11 ||
- SyntaxUsed == AttributeList::AS_C2x) && ScopeName == "gnu");
+ bool IsGNU = SyntaxUsed == ParsedAttr::AS_GNU ||
+ ((SyntaxUsed == ParsedAttr::AS_CXX11 ||
+ SyntaxUsed == ParsedAttr::AS_C2x) &&
+ ScopeName == "gnu");
if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") &&
AttrName.endswith("__"))
AttrName = AttrName.slice(2, AttrName.size() - 2);
@@ -123,9 +114,9 @@ static StringRef normalizeAttrName(StringRef AttrName, StringRef ScopeName,
return AttrName;
}
-AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name,
- const IdentifierInfo *ScopeName,
- Syntax SyntaxUsed) {
+ParsedAttr::Kind ParsedAttr::getKind(const IdentifierInfo *Name,
+ const IdentifierInfo *ScopeName,
+ Syntax SyntaxUsed) {
StringRef AttrName = Name->getName();
SmallString<64> FullName;
@@ -143,12 +134,12 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name,
return ::getAttrKind(FullName, SyntaxUsed);
}
-unsigned AttributeList::getAttributeSpellingListIndex() const {
+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,
- (AttributeList::Syntax)SyntaxUsed);
+ (ParsedAttr::Syntax)SyntaxUsed);
#include "clang/Sema/AttrSpellingListIndex.inc"
@@ -164,85 +155,78 @@ struct ParsedAttrInfo {
unsigned IsKnownToGCC : 1;
unsigned IsSupportedByPragmaAttribute : 1;
- bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr,
- const Decl *);
- bool (*DiagLangOpts)(Sema &S, const AttributeList &Attr);
+ bool (*DiagAppertainsToDecl)(Sema &S, const ParsedAttr &Attr, const Decl *);
+ bool (*DiagLangOpts)(Sema &S, const ParsedAttr &Attr);
bool (*ExistsInTarget)(const TargetInfo &Target);
- unsigned (*SpellingIndexToSemanticSpelling)(const AttributeList &Attr);
+ unsigned (*SpellingIndexToSemanticSpelling)(const ParsedAttr &Attr);
void (*GetPragmaAttributeMatchRules)(
llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &Rules,
const LangOptions &LangOpts);
};
namespace {
- #include "clang/Sema/AttrParsedAttrImpl.inc"
-}
-static const ParsedAttrInfo &getInfo(const AttributeList &A) {
+#include "clang/Sema/AttrParsedAttrImpl.inc"
+
+} // namespace
+
+static const ParsedAttrInfo &getInfo(const ParsedAttr &A) {
return AttrInfoMap[A.getKind()];
}
-unsigned AttributeList::getMinArgs() const {
- return getInfo(*this).NumArgs;
-}
+unsigned ParsedAttr::getMinArgs() const { return getInfo(*this).NumArgs; }
-unsigned AttributeList::getMaxArgs() const {
+unsigned ParsedAttr::getMaxArgs() const {
return getMinArgs() + getInfo(*this).OptArgs;
}
-bool AttributeList::hasCustomParsing() const {
+bool ParsedAttr::hasCustomParsing() const {
return getInfo(*this).HasCustomParsing;
}
-bool AttributeList::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
+bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
return getInfo(*this).DiagAppertainsToDecl(S, *this, D);
}
-bool AttributeList::appliesToDecl(const Decl *D,
- attr::SubjectMatchRule MatchRule) const {
+bool ParsedAttr::appliesToDecl(const Decl *D,
+ attr::SubjectMatchRule MatchRule) const {
return checkAttributeMatchRuleAppliesTo(D, MatchRule);
}
-void AttributeList::getMatchRules(
+void ParsedAttr::getMatchRules(
const LangOptions &LangOpts,
SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
const {
return getInfo(*this).GetPragmaAttributeMatchRules(MatchRules, LangOpts);
}
-bool AttributeList::diagnoseLangOpts(Sema &S) const {
+bool ParsedAttr::diagnoseLangOpts(Sema &S) const {
return getInfo(*this).DiagLangOpts(S, *this);
}
-bool AttributeList::isTargetSpecificAttr() const {
+bool ParsedAttr::isTargetSpecificAttr() const {
return getInfo(*this).IsTargetSpecific;
}
-bool AttributeList::isTypeAttr() const {
- return getInfo(*this).IsType;
-}
+bool ParsedAttr::isTypeAttr() const { return getInfo(*this).IsType; }
-bool AttributeList::isStmtAttr() const {
- return getInfo(*this).IsStmt;
-}
+bool ParsedAttr::isStmtAttr() const { return getInfo(*this).IsStmt; }
-bool AttributeList::existsInTarget(const TargetInfo &Target) const {
+bool ParsedAttr::existsInTarget(const TargetInfo &Target) const {
return getInfo(*this).ExistsInTarget(Target);
}
-bool AttributeList::isKnownToGCC() const {
- return getInfo(*this).IsKnownToGCC;
-}
+bool ParsedAttr::isKnownToGCC() const { return getInfo(*this).IsKnownToGCC; }
-bool AttributeList::isSupportedByPragmaAttribute() const {
+bool ParsedAttr::isSupportedByPragmaAttribute() const {
return getInfo(*this).IsSupportedByPragmaAttribute;
}
-unsigned AttributeList::getSemanticSpelling() const {
+unsigned ParsedAttr::getSemanticSpelling() const {
return getInfo(*this).SpellingIndexToSemanticSpelling(*this);
}
-bool AttributeList::hasVariadicArg() const {
+bool ParsedAttr::hasVariadicArg() const {
// If the attribute has the maximum number of optional arguments, we will
// claim that as being variadic. If we someday get an attribute that
// legitimately bumps up against that maximum, we can use another bit to track
diff --git a/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp b/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp
index b309a36a30a3..62a83ccb70aa 100644
--- a/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp
@@ -43,6 +43,7 @@ void FunctionScopeInfo::Clear() {
// Coroutine state
FirstCoroutineStmtLoc = SourceLocation();
CoroutinePromise = nullptr;
+ CoroutineParameterMoves.clear();
NeedsCoroutineSuspends = true;
CoroutineSuspends.first = nullptr;
CoroutineSuspends.second = nullptr;
diff --git a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
index 4e57e5ef81c6..d57473c5616f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
@@ -19,6 +19,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/AST/StmtCXX.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/PartialDiagnostic.h"
@@ -31,12 +32,12 @@
#include "clang/Sema/Initialization.h"
#include "clang/Sema/MultiplexExternalSemaSource.h"
#include "clang/Sema/ObjCMethodList.h"
-#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaConsumer.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/TemplateDeduction.h"
+#include "clang/Sema/TemplateInstCallback.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
using namespace clang;
@@ -51,8 +52,8 @@ ModuleLoader &Sema::getModuleLoader() const { return PP.getModuleLoader(); }
PrintingPolicy Sema::getPrintingPolicy(const ASTContext &Context,
const Preprocessor &PP) {
PrintingPolicy Policy = Context.getPrintingPolicy();
- // Our printing policy is copied over the ASTContext printing policy whenever
- // a diagnostic is emitted, so recompute it.
+ // In diagnostics, we print _Bool as bool if the latter is defined as the
+ // former.
Policy.Bool = Context.getLangOpts().Bool;
if (!Policy.Bool) {
if (const MacroInfo *BoolMacro = PP.getMacroInfo(Context.getBoolName())) {
@@ -130,16 +131,19 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
IsBuildingRecoveryCallExpr(false), Cleanup{}, LateTemplateParser(nullptr),
LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp),
StdExperimentalNamespaceCache(nullptr), StdInitializerList(nullptr),
- CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr), NSNumberDecl(nullptr),
- NSValueDecl(nullptr), NSStringDecl(nullptr),
- StringWithUTF8StringMethod(nullptr),
+ StdCoroutineTraitsCache(nullptr), CXXTypeInfoDecl(nullptr),
+ MSVCGuidDecl(nullptr), NSNumberDecl(nullptr), NSValueDecl(nullptr),
+ NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr),
ValueWithBytesObjCTypeMethod(nullptr), NSArrayDecl(nullptr),
ArrayWithObjectsMethod(nullptr), NSDictionaryDecl(nullptr),
DictionaryWithObjectsMethod(nullptr), GlobalNewDeleteDeclared(false),
- TUKind(TUKind), NumSFINAEErrors(0), AccessCheckingSFINAE(false),
- InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0),
- ArgumentPackSubstitutionIndex(-1), CurrentInstantiationScope(nullptr),
- DisableTypoCorrection(false), TyposCorrected(0), AnalysisWarnings(*this),
+ TUKind(TUKind), NumSFINAEErrors(0),
+ FullyCheckedComparisonCategories(
+ static_cast<unsigned>(ComparisonCategoryType::Last) + 1),
+ AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false),
+ NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1),
+ CurrentInstantiationScope(nullptr), DisableTypoCorrection(false),
+ TyposCorrected(0), AnalysisWarnings(*this),
ThreadSafetyDeclCache(nullptr), VarDataSharingAttributesStack(nullptr),
CurScope(nullptr), Ident_super(nullptr), Ident___float128(nullptr) {
TUScope = nullptr;
@@ -159,9 +163,9 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
ExprEvalContexts.emplace_back(
ExpressionEvaluationContext::PotentiallyEvaluated, 0, CleanupInfo{},
- nullptr, false);
+ nullptr, ExpressionEvaluationContextRecord::EK_Other);
- FunctionScopes.push_back(new FunctionScopeInfo(Diags));
+ PreallocatedFunctionScope.reset(new FunctionScopeInfo(Diags));
// Initilization of data sharing attributes stack for OpenMP
InitDataSharingAttributesStack();
@@ -331,11 +335,11 @@ void Sema::Initialize() {
Sema::~Sema() {
if (VisContext) FreeVisContext();
+
// Kill all the active scopes.
- for (unsigned I = 1, E = FunctionScopes.size(); I != E; ++I)
- delete FunctionScopes[I];
- if (FunctionScopes.size() == 1)
- delete FunctionScopes[0];
+ for (sema::FunctionScopeInfo *FSI : FunctionScopes)
+ if (FSI != PreallocatedFunctionScope.get())
+ delete FSI;
// Tell the SemaConsumer to forget about us; we're going out of scope.
if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer))
@@ -391,7 +395,7 @@ ASTMutationListener *Sema::getASTMutationListener() const {
return getASTConsumer().GetASTMutationListener();
}
-///\brief Registers an external source. If an external source already exists,
+///Registers an external source. If an external source already exists,
/// creates a multiplex external source and appends to it.
///
///\param[in] E - A non-null external sema source.
@@ -412,7 +416,7 @@ void Sema::addExternalSource(ExternalSemaSource *E) {
}
}
-/// \brief Print out statistics about the semantic analysis.
+/// Print out statistics about the semantic analysis.
void Sema::PrintStats() const {
llvm::errs() << "\n*** Semantic Analysis Stats:\n";
llvm::errs() << NumSFINAEErrors << " SFINAE diagnostics trapped.\n";
@@ -477,6 +481,7 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
case CK_ArrayToPointerDecay:
case CK_FunctionToPointerDecay:
case CK_ToVoid:
+ case CK_NonAtomicToAtomic:
break;
}
}
@@ -532,7 +537,7 @@ CastKind Sema::ScalarTypeToBooleanCastKind(QualType ScalarTy) {
llvm_unreachable("unknown scalar type kind");
}
-/// \brief Used to prune the decls of Sema's UnusedFileScopedDecls vector.
+/// Used to prune the decls of Sema's UnusedFileScopedDecls vector.
static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
if (D->getMostRecentDecl()->isUsed())
return true;
@@ -641,6 +646,8 @@ void Sema::getUndefinedButUsed(
!isExternalWithNoLinkageType(FD) &&
!FD->getMostRecentDecl()->isInlined())
continue;
+ if (FD->getBuiltinID())
+ continue;
} else {
auto *VD = cast<VarDecl>(ND);
if (VD->hasDefinition() != VarDecl::DeclarationOnly)
@@ -649,6 +656,11 @@ void Sema::getUndefinedButUsed(
!isExternalWithNoLinkageType(VD) &&
!VD->getMostRecentDecl()->isInline())
continue;
+
+ // Skip VarDecls that lack formal definitions but which we know are in
+ // fact defined somewhere.
+ if (VD->isKnownToBeDefined())
+ continue;
}
Undefined.push_back(std::make_pair(ND, UndefinedUse.second));
@@ -720,7 +732,7 @@ void Sema::LoadExternalWeakUndeclaredIdentifiers() {
typedef llvm::DenseMap<const CXXRecordDecl*, bool> RecordCompleteMap;
-/// \brief Returns true, if all methods and nested classes of the given
+/// Returns true, if all methods and nested classes of the given
/// CXXRecordDecl are defined in this translation unit.
///
/// Should only be called from ActOnEndOfTranslationUnit so that all
@@ -760,7 +772,7 @@ static bool MethodsAndNestedClassesComplete(const CXXRecordDecl *RD,
return Complete;
}
-/// \brief Returns true, if the given CXXRecordDecl is fully defined in this
+/// Returns true, if the given CXXRecordDecl is fully defined in this
/// translation unit, i.e. all methods are defined or pure virtual and all
/// friends, friend functions and nested classes are fully defined in this
/// translation unit.
@@ -849,6 +861,20 @@ void Sema::ActOnEndOfTranslationUnit() {
if (PP.isCodeCompletionEnabled())
return;
+ // Transfer late parsed template instantiations over to the pending template
+ // instantiation list. During normal compliation, the late template parser
+ // will be installed and instantiating these templates will succeed.
+ //
+ // If we are building a TU prefix for serialization, it is also safe to
+ // transfer these over, even though they are not parsed. The end of the TU
+ // should be outside of any eager template instantiation scope, so when this
+ // AST is deserialized, these templates will not be parsed until the end of
+ // the combined TU.
+ PendingInstantiations.insert(PendingInstantiations.end(),
+ LateParsedInstantiations.begin(),
+ LateParsedInstantiations.end());
+ LateParsedInstantiations.clear();
+
// Complete translation units and modules define vtables and perform implicit
// instantiations. PCH files do not.
if (TUKind != TU_Prefix) {
@@ -878,8 +904,13 @@ void Sema::ActOnEndOfTranslationUnit() {
PendingInstantiations.insert(PendingInstantiations.begin(),
Pending.begin(), Pending.end());
}
+
PerformPendingInstantiations();
+ assert(LateParsedInstantiations.empty() &&
+ "end of TU template instantiation should not create more "
+ "late-parsed templates");
+
if (LateTemplateParserCleanup)
LateTemplateParserCleanup(OpaqueParser);
@@ -980,11 +1011,6 @@ void Sema::ActOnEndOfTranslationUnit() {
// Warnings emitted in ActOnEndOfTranslationUnit() should be emitted for
// modules when they are built, not every time they are used.
emitAndClearUnusedLocalTypedefWarnings();
-
- // Modules don't need any of the checking below.
- if (!PP.isIncrementalProcessingEnabled())
- TUScope = nullptr;
- return;
}
// C99 6.9.2p2:
@@ -1002,8 +1028,7 @@ void Sema::ActOnEndOfTranslationUnit() {
for (TentativeDefinitionsType::iterator
T = TentativeDefinitions.begin(ExternalSource),
TEnd = TentativeDefinitions.end();
- T != TEnd; ++T)
- {
+ T != TEnd; ++T) {
VarDecl *VD = (*T)->getActingDefinition();
// If the tentative definition was completed, getActingDefinition() returns
@@ -1030,12 +1055,13 @@ void Sema::ActOnEndOfTranslationUnit() {
// Notify the consumer that we've completed a tentative definition.
if (!VD->isInvalidDecl())
Consumer.CompleteTentativeDefinition(VD);
-
}
// If there were errors, disable 'unused' warnings since they will mostly be
- // noise.
- if (!Diags.hasErrorOccurred()) {
+ // noise. Don't warn for a use from a module: either we should warn on all
+ // file-scope declarations in modules or not at all, but whether the
+ // declaration is used is immaterial.
+ if (!Diags.hasErrorOccurred() && TUKind != TU_Module) {
// Output warning for unused file scoped decls.
for (UnusedFileScopedDeclsType::iterator
I = UnusedFileScopedDecls.begin(ExternalSource),
@@ -1103,6 +1129,8 @@ void Sema::ActOnEndOfTranslationUnit() {
}
if (!Diags.isIgnored(diag::warn_unused_private_field, SourceLocation())) {
+ // FIXME: Load additional unused private field candidates from the external
+ // source.
RecordCompleteMap RecordsComplete;
RecordCompleteMap MNCComplete;
for (NamedDeclSetType::iterator I = UnusedPrivateFields.begin(),
@@ -1264,7 +1292,8 @@ void Sema::EmitCurrentDiagnostic(unsigned DiagID) {
}
}
- // Set up the context's printing policy based on our current state.
+ // Copy the diagnostic printing policy over the ASTContext printing policy.
+ // TODO: Stop doing that. See: https://reviews.llvm.org/D45093#1090292
Context.setPrintingPolicy(getPrintingPolicy());
// Emit the diagnostic.
@@ -1287,7 +1316,7 @@ Sema::Diag(SourceLocation Loc, const PartialDiagnostic& PD) {
return Builder;
}
-/// \brief Looks through the macro-expansion chain for the given
+/// Looks through the macro-expansion chain for the given
/// location, looking for a macro expansion with the given name.
/// If one is found, returns true and sets the location to that
/// expansion loc.
@@ -1308,7 +1337,7 @@ bool Sema::findMacroSpelling(SourceLocation &locref, StringRef name) {
return false;
}
-/// \brief Determines the active Scope associated with the given declaration
+/// Determines the active Scope associated with the given declaration
/// context.
///
/// This routine maps a declaration context to the active Scope object that
@@ -1337,19 +1366,15 @@ Scope *Sema::getScopeForContext(DeclContext *Ctx) {
return nullptr;
}
-/// \brief Enter a new function scope
+/// Enter a new function scope
void Sema::PushFunctionScope() {
- if (FunctionScopes.size() == 1) {
- // Use the "top" function scope rather than having to allocate
- // memory for a new scope.
- FunctionScopes.back()->Clear();
- FunctionScopes.push_back(FunctionScopes.back());
- if (LangOpts.OpenMP)
- pushOpenMPFunctionRegion();
- return;
+ if (FunctionScopes.empty()) {
+ // Use PreallocatedFunctionScope to avoid allocating memory when possible.
+ PreallocatedFunctionScope->Clear();
+ FunctionScopes.push_back(PreallocatedFunctionScope.get());
+ } else {
+ FunctionScopes.push_back(new FunctionScopeInfo(getDiagnostics()));
}
-
- FunctionScopes.push_back(new FunctionScopeInfo(getDiagnostics()));
if (LangOpts.OpenMP)
pushOpenMPFunctionRegion();
}
@@ -1369,15 +1394,15 @@ void Sema::RecordParsingTemplateParameterDepth(unsigned Depth) {
if (LambdaScopeInfo *const LSI = getCurLambda()) {
LSI->AutoTemplateParameterDepth = Depth;
return;
- }
- llvm_unreachable(
+ }
+ llvm_unreachable(
"Remove assertion if intentionally called in a non-lambda context.");
}
void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
const Decl *D, const BlockExpr *blkExpr) {
- FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();
assert(!FunctionScopes.empty() && "mismatched push/pop!");
+ FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();
if (LangOpts.OpenMP)
popOpenMPFunctionRegion(Scope);
@@ -1389,12 +1414,13 @@ void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
for (const auto &PUD : Scope->PossiblyUnreachableDiags)
Diag(PUD.Loc, PUD.PD);
- if (FunctionScopes.back() != Scope)
+ // Delete the scope unless its our preallocated scope.
+ if (Scope != PreallocatedFunctionScope.get())
delete Scope;
}
-void Sema::PushCompoundScope() {
- getCurFunction()->CompoundScopes.push_back(CompoundScopeInfo());
+void Sema::PushCompoundScope(bool IsStmtExpr) {
+ getCurFunction()->CompoundScopes.push_back(CompoundScopeInfo(IsStmtExpr));
}
void Sema::PopCompoundScope() {
@@ -1404,12 +1430,27 @@ void Sema::PopCompoundScope() {
CurFunction->CompoundScopes.pop_back();
}
-/// \brief Determine whether any errors occurred within this function/method/
+/// Determine whether any errors occurred within this function/method/
/// block.
bool Sema::hasAnyUnrecoverableErrorsInThisFunction() const {
return getCurFunction()->ErrorTrap.hasUnrecoverableErrorOccurred();
}
+void Sema::setFunctionHasBranchIntoScope() {
+ if (!FunctionScopes.empty())
+ FunctionScopes.back()->setHasBranchIntoScope();
+}
+
+void Sema::setFunctionHasBranchProtectedScope() {
+ if (!FunctionScopes.empty())
+ FunctionScopes.back()->setHasBranchProtectedScope();
+}
+
+void Sema::setFunctionHasIndirectGoto() {
+ if (!FunctionScopes.empty())
+ FunctionScopes.back()->setHasIndirectGoto();
+}
+
BlockScopeInfo *Sema::getCurBlock() {
if (FunctionScopes.empty())
return nullptr;
@@ -1425,6 +1466,18 @@ BlockScopeInfo *Sema::getCurBlock() {
return CurBSI;
}
+FunctionScopeInfo *Sema::getEnclosingFunction() const {
+ if (FunctionScopes.empty())
+ return nullptr;
+
+ for (int e = FunctionScopes.size() - 1; e >= 0; --e) {
+ if (isa<sema::BlockScopeInfo>(FunctionScopes[e]))
+ continue;
+ return FunctionScopes[e];
+ }
+ return nullptr;
+}
+
LambdaScopeInfo *Sema::getCurLambda(bool IgnoreNonLambdaCapturingScope) {
if (FunctionScopes.empty())
return nullptr;
@@ -1462,8 +1515,7 @@ void Sema::ActOnComment(SourceRange Comment) {
if (!LangOpts.RetainCommentsFromSystemHeaders &&
SourceMgr.isInSystemHeader(Comment.getBegin()))
return;
- RawComment RC(SourceMgr, Comment, false,
- LangOpts.CommentOpts.ParseAllComments);
+ RawComment RC(SourceMgr, Comment, LangOpts.CommentOpts, false);
if (RC.isAlmostTrailingComment()) {
SourceRange MagicMarkerRange(Comment.getBegin(),
Comment.getBegin().getLocWithOffset(3));
@@ -1501,25 +1553,7 @@ void ExternalSemaSource::ReadUndefinedButUsed(
void ExternalSemaSource::ReadMismatchingDeleteExpressions(llvm::MapVector<
FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &) {}
-void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const {
- SourceLocation Loc = this->Loc;
- if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation();
- if (Loc.isValid()) {
- Loc.print(OS, S.getSourceManager());
- OS << ": ";
- }
- OS << Message;
-
- if (auto *ND = dyn_cast_or_null<NamedDecl>(TheDecl)) {
- OS << " '";
- ND->getNameForDiagnostic(OS, ND->getASTContext().getPrintingPolicy(), true);
- OS << "'";
- }
-
- OS << '\n';
-}
-
-/// \brief Figure out if an expression could be turned into a call.
+/// Figure out if an expression could be turned into a call.
///
/// Use this when trying to recover from an error where the programmer may have
/// written just the name of a function instead of actually calling it.
@@ -1551,6 +1585,7 @@ bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
}
bool Ambiguous = false;
+ bool IsMV = false;
if (Overloads) {
for (OverloadExpr::decls_iterator it = Overloads->decls_begin(),
@@ -1564,11 +1599,16 @@ bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
if (const FunctionDecl *OverloadDecl
= dyn_cast<FunctionDecl>((*it)->getUnderlyingDecl())) {
if (OverloadDecl->getMinRequiredArguments() == 0) {
- if (!ZeroArgCallReturnTy.isNull() && !Ambiguous) {
+ if (!ZeroArgCallReturnTy.isNull() && !Ambiguous &&
+ (!IsMV || !(OverloadDecl->isCPUDispatchMultiVersion() ||
+ OverloadDecl->isCPUSpecificMultiVersion()))) {
ZeroArgCallReturnTy = QualType();
Ambiguous = true;
- } else
+ } else {
ZeroArgCallReturnTy = OverloadDecl->getReturnType();
+ IsMV = OverloadDecl->isCPUDispatchMultiVersion() ||
+ OverloadDecl->isCPUSpecificMultiVersion();
+ }
}
}
}
@@ -1621,7 +1661,7 @@ bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
return false;
}
-/// \brief Give notes for a set of overloads.
+/// Give notes for a set of overloads.
///
/// A companion to tryExprAsCall. In cases when the name that the programmer
/// wrote was an overloaded function, we may be able to make some guesses about
@@ -1647,6 +1687,12 @@ static void noteOverloads(Sema &S, const UnresolvedSetImpl &Overloads,
}
NamedDecl *Fn = (*It)->getUnderlyingDecl();
+ // Don't print overloads for non-default multiversioned functions.
+ if (const auto *FD = Fn->getAsFunction()) {
+ if (FD->isMultiVersion() && FD->hasAttr<TargetAttr>() &&
+ !FD->getAttr<TargetAttr>()->isDefaultVersion())
+ continue;
+ }
S.Diag(Fn->getLocation(), diag::note_possible_target_of_call);
++ShownOverloads;
}
@@ -1685,6 +1731,21 @@ static bool IsCallableWithAppend(Expr *E) {
!isa<CXXOperatorCallExpr>(E));
}
+static bool IsCPUDispatchCPUSpecificMultiVersion(const Expr *E) {
+ if (const auto *UO = dyn_cast<UnaryOperator>(E))
+ E = UO->getSubExpr();
+
+ if (const auto *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
+ if (ULE->getNumDecls() == 0)
+ return false;
+
+ const NamedDecl *ND = *ULE->decls_begin();
+ if (const auto *FD = dyn_cast<FunctionDecl>(ND))
+ return FD->isCPUDispatchMultiVersion() || FD->isCPUSpecificMultiVersion();
+ }
+ return false;
+}
+
bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
bool ForceComplain,
bool (*IsPlausibleResult)(QualType)) {
@@ -1701,12 +1762,13 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
// so we can emit a fixit and carry on pretending that E was
// actually a CallExpr.
SourceLocation ParenInsertionLoc = getLocForEndOfToken(Range.getEnd());
- Diag(Loc, PD)
- << /*zero-arg*/ 1 << Range
- << (IsCallableWithAppend(E.get())
- ? FixItHint::CreateInsertion(ParenInsertionLoc, "()")
- : FixItHint());
- notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
+ bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get());
+ Diag(Loc, PD) << /*zero-arg*/ 1 << IsMV << Range
+ << (IsCallableWithAppend(E.get())
+ ? FixItHint::CreateInsertion(ParenInsertionLoc, "()")
+ : FixItHint());
+ if (!IsMV)
+ notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
// FIXME: Try this before emitting the fixit, and suppress diagnostics
// while doing so.
@@ -1717,8 +1779,10 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
if (!ForceComplain) return false;
- Diag(Loc, PD) << /*not zero-arg*/ 0 << Range;
- notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
+ bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get());
+ Diag(Loc, PD) << /*not zero-arg*/ 0 << IsMV << Range;
+ if (!IsMV)
+ notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
E = ExprError();
return true;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp
index 98a918bd7d63..9fbae2ca297f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Basic/Specifiers.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
@@ -1712,7 +1713,7 @@ Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc,
return CheckAccess(*this, OpLoc, Entity);
}
-/// \brief Checks access to a member.
+/// Checks access to a member.
Sema::AccessResult Sema::CheckMemberAccess(SourceLocation UseLoc,
CXXRecordDecl *NamingClass,
DeclAccessPair Found) {
@@ -1856,29 +1857,31 @@ void Sema::CheckLookupAccess(const LookupResult &R) {
}
}
-/// Checks access to Decl from the given class. The check will take access
+/// Checks access to Target from the given class. The check will take access
/// specifiers into account, but no member access expressions and such.
///
-/// \param Decl the declaration to check if it can be accessed
+/// \param Target the declaration to check if it can be accessed
/// \param Ctx the class/context from which to start the search
-/// \return true if the Decl is accessible from the Class, false otherwise.
-bool Sema::IsSimplyAccessible(NamedDecl *Decl, DeclContext *Ctx) {
+/// \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 (!Decl->isCXXClassMember())
+ if (!Target->isCXXClassMember())
return true;
+ if (Target->getAccess() == AS_public)
+ return true;
QualType qType = Class->getTypeForDecl()->getCanonicalTypeInternal();
+ // 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(Decl, Decl->getAccess()),
- qType);
- if (Entity.getAccess() == AS_public)
- return true;
-
+ DeclAccessPair::make(Target, AS_none), qType);
EffectiveContext EC(CurContext);
return ::IsAccessible(*this, EC, Entity) != ::AR_inaccessible;
}
-
- if (ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(Decl)) {
+
+ if (ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(Target)) {
// @public and @package ivars are always accessible.
if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Public ||
Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Package)
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp
index 4ba2a317e1f9..4f3cf4633c80 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp
@@ -205,7 +205,7 @@ void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action,
// "#pragma pack(pop, identifier, n) is undefined"
if (Action & Sema::PSK_Pop) {
if (Alignment && !SlotLabel.empty())
- Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
+ Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifier_and_alignment);
if (PackStack.Stack.empty())
Diag(PragmaLoc, diag::warn_pragma_pop_failed) << "pack" << "stack empty";
}
@@ -330,7 +330,7 @@ void Sema::PragmaStack<ValueType>::Act(SourceLocation PragmaLocation,
Stack.erase(std::prev(I.base()), Stack.end());
}
} else if (!Stack.empty()) {
- // We don't have a label, just pop the last entry.
+ // We do not have a label, just pop the last entry.
CurrentValue = Stack.back().Value;
CurrentPragmaLocation = Stack.back().PragmaLocation;
Stack.pop_back();
@@ -389,7 +389,7 @@ bool Sema::UnifySection(StringRef SectionName,
return false;
}
-/// \brief Called on well formed \#pragma bss_seg().
+/// Called on well formed \#pragma bss_seg().
void Sema::ActOnPragmaMSSeg(SourceLocation PragmaLocation,
PragmaMsStackAction Action,
llvm::StringRef StackSlotLabel,
@@ -410,7 +410,7 @@ void Sema::ActOnPragmaMSSeg(SourceLocation PragmaLocation,
Stack->Act(PragmaLocation, Action, StackSlotLabel, SegmentName);
}
-/// \brief Called on well formed \#pragma bss_seg().
+/// Called on well formed \#pragma bss_seg().
void Sema::ActOnPragmaMSSection(SourceLocation PragmaLocation,
int SectionFlags, StringLiteral *SegmentName) {
UnifySection(SegmentName->getString(), SectionFlags, PragmaLocation);
@@ -520,7 +520,7 @@ attrMatcherRuleListToString(ArrayRef<attr::SubjectMatchRule> Rules) {
} // end anonymous namespace
-void Sema::ActOnPragmaAttributePush(AttributeList &Attribute,
+void Sema::ActOnPragmaAttributePush(ParsedAttr &Attribute,
SourceLocation PragmaLoc,
attr::ParsedSubjectMatchRuleSet Rules) {
SmallVector<attr::SubjectMatchRule, 4> SubjectMatchRules;
@@ -645,7 +645,7 @@ void Sema::AddPragmaAttributes(Scope *S, Decl *D) {
if (PragmaAttributeStack.empty())
return;
for (auto &Entry : PragmaAttributeStack) {
- const AttributeList *Attribute = Entry.Attribute;
+ ParsedAttr *Attribute = Entry.Attribute;
assert(Attribute && "Expected an attribute");
// Ensure that the attribute can be applied to the given declaration.
@@ -659,9 +659,10 @@ void Sema::AddPragmaAttributes(Scope *S, Decl *D) {
if (!Applies)
continue;
Entry.IsUsed = true;
- assert(!Attribute->getNext() && "Expected just one attribute");
PragmaAttributeCurrentTargetDecl = D;
- ProcessDeclAttributeList(S, D, Attribute);
+ ParsedAttributesView Attrs;
+ Attrs.addAtStart(Attribute);
+ ProcessDeclAttributeList(S, D, Attrs);
PragmaAttributeCurrentTargetDecl = nullptr;
}
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp
index cac5f682275e..13dd8d936fd2 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
/// \file
-/// \brief This file implements semantic analysis for CUDA constructs.
+/// This file implements semantic analysis for CUDA constructs.
///
//===----------------------------------------------------------------------===//
@@ -42,8 +42,9 @@ ExprResult Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
SourceLocation GGGLoc) {
FunctionDecl *ConfigDecl = Context.getcudaConfigureCallDecl();
if (!ConfigDecl)
- return ExprError(Diag(LLLLoc, diag::err_undeclared_var_use)
- << "cudaConfigureCall");
+ return ExprError(
+ Diag(LLLLoc, diag::err_undeclared_var_use)
+ << (getLangOpts().HIP ? "hipConfigureCall" : "cudaConfigureCall"));
QualType ConfigQTy = ConfigDecl->getType();
DeclRefExpr *ConfigDR = new (Context)
@@ -54,30 +55,31 @@ ExprResult Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
/*IsExecConfig=*/true);
}
-Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const AttributeList *Attr) {
+Sema::CUDAFunctionTarget
+Sema::IdentifyCUDATarget(const ParsedAttributesView &Attrs) {
bool HasHostAttr = false;
bool HasDeviceAttr = false;
bool HasGlobalAttr = false;
bool HasInvalidTargetAttr = false;
- while (Attr) {
- switch(Attr->getKind()){
- case AttributeList::AT_CUDAGlobal:
+ for (const ParsedAttr &AL : Attrs) {
+ switch (AL.getKind()) {
+ case ParsedAttr::AT_CUDAGlobal:
HasGlobalAttr = true;
break;
- case AttributeList::AT_CUDAHost:
+ case ParsedAttr::AT_CUDAHost:
HasHostAttr = true;
break;
- case AttributeList::AT_CUDADevice:
+ case ParsedAttr::AT_CUDADevice:
HasDeviceAttr = true;
break;
- case AttributeList::AT_CUDAInvalidTarget:
+ case ParsedAttr::AT_CUDAInvalidTarget:
HasInvalidTargetAttr = true;
break;
default:
break;
}
- Attr = Attr->getNext();
}
+
if (HasInvalidTargetAttr)
return CFT_InvalidTarget;
@@ -471,6 +473,59 @@ bool Sema::isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *DD) {
return true;
}
+void Sema::checkAllowedCUDAInitializer(VarDecl *VD) {
+ if (VD->isInvalidDecl() || !VD->hasInit() || !VD->hasGlobalStorage())
+ return;
+ const Expr *Init = VD->getInit();
+ if (VD->hasAttr<CUDADeviceAttr>() || VD->hasAttr<CUDAConstantAttr>() ||
+ VD->hasAttr<CUDASharedAttr>()) {
+ assert(!VD->isStaticLocal() || VD->hasAttr<CUDASharedAttr>());
+ bool AllowedInit = false;
+ if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(Init))
+ AllowedInit =
+ isEmptyCudaConstructor(VD->getLocation(), CE->getConstructor());
+ // We'll allow constant initializers even if it's a non-empty
+ // constructor according to CUDA rules. This deviates from NVCC,
+ // but allows us to handle things like constexpr constructors.
+ if (!AllowedInit &&
+ (VD->hasAttr<CUDADeviceAttr>() || VD->hasAttr<CUDAConstantAttr>()))
+ AllowedInit = VD->getInit()->isConstantInitializer(
+ Context, VD->getType()->isReferenceType());
+
+ // Also make sure that destructor, if there is one, is empty.
+ if (AllowedInit)
+ if (CXXRecordDecl *RD = VD->getType()->getAsCXXRecordDecl())
+ AllowedInit =
+ isEmptyCudaDestructor(VD->getLocation(), RD->getDestructor());
+
+ if (!AllowedInit) {
+ Diag(VD->getLocation(), VD->hasAttr<CUDASharedAttr>()
+ ? diag::err_shared_var_init
+ : diag::err_dynamic_var_init)
+ << Init->getSourceRange();
+ VD->setInvalidDecl();
+ }
+ } else {
+ // This is a host-side global variable. Check that the initializer is
+ // callable from the host side.
+ const FunctionDecl *InitFn = nullptr;
+ if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(Init)) {
+ InitFn = CE->getConstructor();
+ } else if (const CallExpr *CE = dyn_cast<CallExpr>(Init)) {
+ InitFn = CE->getDirectCallee();
+ }
+ if (InitFn) {
+ CUDAFunctionTarget InitFnTarget = IdentifyCUDATarget(InitFn);
+ if (InitFnTarget != CFT_Host && InitFnTarget != CFT_HostDevice) {
+ Diag(VD->getLocation(), diag::err_ref_bad_target_global_initializer)
+ << InitFnTarget << InitFn;
+ Diag(InitFn->getLocation(), diag::note_previous_decl) << InitFn;
+ VD->setInvalidDecl();
+ }
+ }
+ }
+}
+
// With -fcuda-host-device-constexpr, an unattributed constexpr function is
// treated as implicitly __host__ __device__, unless:
// * it is a variadic function (device-side variadic functions are not
@@ -521,7 +576,7 @@ void Sema::maybeAddCUDAHostDeviceAttrs(FunctionDecl *NewD,
if (!getSourceManager().isInSystemHeader(Match->getLocation())) {
Diag(NewD->getLocation(),
diag::err_cuda_unattributed_constexpr_cannot_overload_device)
- << NewD->getName();
+ << NewD;
Diag(Match->getLocation(),
diag::note_cuda_conflicting_device_function_declared_here);
}
@@ -790,9 +845,12 @@ bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) {
// If the caller is known-emitted, mark the callee as known-emitted.
// Otherwise, mark the call in our call graph so we can traverse it later.
bool CallerKnownEmitted = IsKnownEmitted(*this, Caller);
- if (CallerKnownEmitted)
- MarkKnownEmitted(*this, Caller, Callee, Loc);
- else {
+ if (CallerKnownEmitted) {
+ // Host-side references to a __global__ function refer to the stub, so the
+ // function itself is never emitted and therefore should not be marked.
+ if (getLangOpts().CUDAIsDevice || IdentifyCUDATarget(Callee) != CFT_Global)
+ MarkKnownEmitted(*this, Caller, Callee, Loc);
+ } else {
// If we have
// host fn calls kernel fn calls host+device,
// the HD function does not get instantiated on the host. We model this by
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
index 6da4d2a26191..f2fad825c3e7 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -24,7 +24,7 @@
#include "llvm/ADT/STLExtras.h"
using namespace clang;
-/// \brief Find the current instantiation that associated with the given type.
+/// Find the current instantiation that associated with the given type.
static CXXRecordDecl *getCurrentInstantiationOf(QualType T,
DeclContext *CurContext) {
if (T.isNull())
@@ -44,7 +44,7 @@ static CXXRecordDecl *getCurrentInstantiationOf(QualType T,
return nullptr;
}
-/// \brief Compute the DeclContext that is associated with the given type.
+/// Compute the DeclContext that is associated with the given type.
///
/// \param T the type for which we are attempting to find a DeclContext.
///
@@ -59,7 +59,7 @@ DeclContext *Sema::computeDeclContext(QualType T) {
return ::getCurrentInstantiationOf(T, CurContext);
}
-/// \brief Compute the DeclContext that is associated with the given
+/// Compute the DeclContext that is associated with the given
/// scope specifier.
///
/// \param SS the C++ scope specifier as it appears in the source
@@ -172,7 +172,7 @@ bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) {
return SS.getScopeRep()->isDependent();
}
-/// \brief If the given nested name specifier refers to the current
+/// If the given nested name specifier refers to the current
/// instantiation, return the declaration that corresponds to that
/// current instantiation (C++0x [temp.dep.type]p1).
///
@@ -188,7 +188,7 @@ CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier *NNS) {
return ::getCurrentInstantiationOf(T, CurContext);
}
-/// \brief Require that the context specified by SS be complete.
+/// Require that the context specified by SS be complete.
///
/// If SS refers to a type, this routine checks whether the type is
/// complete enough (or can be made complete enough) for name lookup
@@ -305,7 +305,7 @@ bool Sema::ActOnSuperScopeSpecifier(SourceLocation SuperLoc,
return false;
}
-/// \brief Determines whether the given declaration is an valid acceptable
+/// Determines whether the given declaration is an valid acceptable
/// result for name lookup of a nested-name-specifier.
/// \param SD Declaration checked for nested-name-specifier.
/// \param IsExtension If not null and the declaration is accepted as an
@@ -350,7 +350,7 @@ bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD,
return false;
}
-/// \brief If the given nested-name-specifier begins with a bare identifier
+/// If the given nested-name-specifier begins with a bare identifier
/// (e.g., Base::), perform name lookup for that identifier as a
/// nested-name-specifier within the given scope, and return the result of that
/// name lookup.
@@ -443,7 +443,7 @@ class NestedNameSpecifierValidatorCCC : public CorrectionCandidateCallback {
}
-/// \brief Build a new nested-name-specifier for "identifier::", as described
+/// Build a new nested-name-specifier for "identifier::", as described
/// by ActOnCXXNestedNameSpecifier.
///
/// \param S Scope in which the nested-name-specifier occurs.
@@ -846,6 +846,9 @@ bool Sema::ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS,
assert(DS.getTypeSpecType() == DeclSpec::TST_decltype);
QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
+ if (T.isNull())
+ return true;
+
if (!T->isDependentType() && !T->getAs<TagType>()) {
Diag(DS.getTypeSpecTypeLoc(), diag::err_expected_class_or_namespace)
<< T << getLangOpts().CPlusPlus;
@@ -967,7 +970,7 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
}
namespace {
- /// \brief A structure that stores a nested-name-specifier annotation,
+ /// A structure that stores a nested-name-specifier annotation,
/// including both the nested-name-specifier
struct NestedNameSpecifierAnnotation {
NestedNameSpecifier *NNS;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
index ad6348685b64..b7f4629fbab7 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
@@ -33,10 +33,16 @@ using namespace clang;
enum TryCastResult {
TC_NotApplicable, ///< The cast method is not applicable.
TC_Success, ///< The cast method is appropriate and successful.
+ TC_Extension, ///< The cast method is appropriate and accepted as a
+ ///< language extension.
TC_Failed ///< The cast method is appropriate, but failed. A
///< diagnostic has been emitted.
};
+static bool isValidCast(TryCastResult TCR) {
+ return TCR == TC_Success || TCR == TC_Extension;
+}
+
enum CastType {
CT_Const, ///< const_cast
CT_Static, ///< static_cast
@@ -83,6 +89,14 @@ namespace {
void CheckCXXCStyleCast(bool FunctionalCast, bool ListInitialization);
void CheckCStyleCast();
+ void updatePartOfExplicitCastFlags(CastExpr *CE) {
+ // Walk down from the CE to the OrigSrcExpr, and mark all immediate
+ // ImplicitCastExpr's as being part of ExplicitCastExpr. The original CE
+ // (which is a ExplicitCastExpr), and the OrigSrcExpr are not touched.
+ for (; auto *ICE = dyn_cast<ImplicitCastExpr>(CE->getSubExpr()); CE = ICE)
+ ICE->setIsPartOfExplicitCast(true);
+ }
+
/// Complete an apparently-successful cast operation that yields
/// the given expression.
ExprResult complete(CastExpr *castExpr) {
@@ -94,6 +108,7 @@ namespace {
CK_Dependent, castExpr, nullptr,
castExpr->getValueKind());
}
+ updatePartOfExplicitCastFlags(castExpr);
return castExpr;
}
@@ -267,6 +282,12 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
AngleBrackets));
case tok::kw_dynamic_cast: {
+ // OpenCL C++ 1.0 s2.9: dynamic_cast is not supported.
+ if (getLangOpts().OpenCLCPlusPlus) {
+ return ExprError(Diag(OpLoc, diag::err_openclcxx_not_supported)
+ << "dynamic_cast");
+ }
+
if (!TypeDependent) {
Op.CheckDynamicCast();
if (Op.SrcExpr.isInvalid())
@@ -425,95 +446,114 @@ static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType,
}
}
-/// UnwrapDissimilarPointerTypes - Like Sema::UnwrapSimilarPointerTypes,
-/// this removes one level of indirection from both types, provided that they're
-/// the same kind of pointer (plain or to-member). Unlike the Sema function,
-/// this one doesn't care if the two pointers-to-member don't point into the
-/// same class. This is because CastsAwayConstness doesn't care.
-/// And additionally, it handles C++ references. If both the types are
-/// references, then their pointee types are returned,
-/// else if only one of them is reference, it's pointee type is returned,
-/// and the other type is returned as-is.
-static bool UnwrapDissimilarPointerTypes(QualType& T1, QualType& T2) {
- const PointerType *T1PtrType = T1->getAs<PointerType>(),
- *T2PtrType = T2->getAs<PointerType>();
- if (T1PtrType && T2PtrType) {
- T1 = T1PtrType->getPointeeType();
- T2 = T2PtrType->getPointeeType();
- return true;
- }
- const ObjCObjectPointerType *T1ObjCPtrType =
- T1->getAs<ObjCObjectPointerType>(),
- *T2ObjCPtrType =
- T2->getAs<ObjCObjectPointerType>();
- if (T1ObjCPtrType) {
- if (T2ObjCPtrType) {
- T1 = T1ObjCPtrType->getPointeeType();
- T2 = T2ObjCPtrType->getPointeeType();
- return true;
- }
- else if (T2PtrType) {
- T1 = T1ObjCPtrType->getPointeeType();
- T2 = T2PtrType->getPointeeType();
- return true;
- }
- }
- else if (T2ObjCPtrType) {
- if (T1PtrType) {
- T2 = T2ObjCPtrType->getPointeeType();
- T1 = T1PtrType->getPointeeType();
- return true;
- }
- }
-
- const MemberPointerType *T1MPType = T1->getAs<MemberPointerType>(),
- *T2MPType = T2->getAs<MemberPointerType>();
- if (T1MPType && T2MPType) {
- T1 = T1MPType->getPointeeType();
- T2 = T2MPType->getPointeeType();
- return true;
- }
-
- const BlockPointerType *T1BPType = T1->getAs<BlockPointerType>(),
- *T2BPType = T2->getAs<BlockPointerType>();
- if (T1BPType && T2BPType) {
- T1 = T1BPType->getPointeeType();
- T2 = T2BPType->getPointeeType();
- return true;
- }
-
- const LValueReferenceType *T1RefType = T1->getAs<LValueReferenceType>(),
- *T2RefType = T2->getAs<LValueReferenceType>();
- if (T1RefType && T2RefType) {
- T1 = T1RefType->getPointeeType();
- T2 = T2RefType->getPointeeType();
- return true;
- }
+namespace {
+/// The kind of unwrapping we did when determining whether a conversion casts
+/// away constness.
+enum CastAwayConstnessKind {
+ /// The conversion does not cast away constness.
+ CACK_None = 0,
+ /// We unwrapped similar types.
+ CACK_Similar = 1,
+ /// We unwrapped dissimilar types with similar representations (eg, a pointer
+ /// versus an Objective-C object pointer).
+ CACK_SimilarKind = 2,
+ /// We unwrapped representationally-unrelated types, such as a pointer versus
+ /// a pointer-to-member.
+ CACK_Incoherent = 3,
+};
+}
- if (T1RefType) {
- T1 = T1RefType->getPointeeType();
- // T2 = T2;
- return true;
+/// Unwrap one level of types for CastsAwayConstness.
+///
+/// Like Sema::UnwrapSimilarTypes, this removes one level of indirection from
+/// both types, provided that they're both pointer-like or array-like. Unlike
+/// the Sema function, doesn't care if the unwrapped pieces are related.
+///
+/// This function may remove additional levels as necessary for correctness:
+/// the resulting T1 is unwrapped sufficiently that it is never an array type,
+/// so that its qualifiers can be directly compared to those of T2 (which will
+/// have the combined set of qualifiers from all indermediate levels of T2),
+/// as (effectively) required by [expr.const.cast]p7 replacing T1's qualifiers
+/// with those from T2.
+static CastAwayConstnessKind
+unwrapCastAwayConstnessLevel(ASTContext &Context, QualType &T1, QualType &T2) {
+ enum { None, Ptr, MemPtr, BlockPtr, Array };
+ auto Classify = [](QualType T) {
+ if (T->isAnyPointerType()) return Ptr;
+ if (T->isMemberPointerType()) return MemPtr;
+ if (T->isBlockPointerType()) return BlockPtr;
+ // We somewhat-arbitrarily don't look through VLA types here. This is at
+ // least consistent with the behavior of UnwrapSimilarTypes.
+ if (T->isConstantArrayType() || T->isIncompleteArrayType()) return Array;
+ return None;
+ };
+
+ auto Unwrap = [&](QualType T) {
+ if (auto *AT = Context.getAsArrayType(T))
+ return AT->getElementType();
+ return T->getPointeeType();
+ };
+
+ CastAwayConstnessKind Kind;
+
+ if (T2->isReferenceType()) {
+ // Special case: if the destination type is a reference type, unwrap it as
+ // the first level. (The source will have been an lvalue expression in this
+ // case, so there is no corresponding "reference to" in T1 to remove.) This
+ // simulates removing a "pointer to" from both sides.
+ T2 = T2->getPointeeType();
+ Kind = CastAwayConstnessKind::CACK_Similar;
+ } else if (Context.UnwrapSimilarTypes(T1, T2)) {
+ Kind = CastAwayConstnessKind::CACK_Similar;
+ } else {
+ // Try unwrapping mismatching levels.
+ int T1Class = Classify(T1);
+ if (T1Class == None)
+ return CastAwayConstnessKind::CACK_None;
+
+ int T2Class = Classify(T2);
+ if (T2Class == None)
+ return CastAwayConstnessKind::CACK_None;
+
+ T1 = Unwrap(T1);
+ T2 = Unwrap(T2);
+ Kind = T1Class == T2Class ? CastAwayConstnessKind::CACK_SimilarKind
+ : CastAwayConstnessKind::CACK_Incoherent;
}
- if (T2RefType) {
- // T1 = T1;
- T2 = T2RefType->getPointeeType();
- return true;
+ // We've unwrapped at least one level. If the resulting T1 is a (possibly
+ // multidimensional) array type, any qualifier on any matching layer of
+ // T2 is considered to correspond to T1. Decompose down to the element
+ // type of T1 so that we can compare properly.
+ while (true) {
+ Context.UnwrapSimilarArrayTypes(T1, T2);
+
+ if (Classify(T1) != Array)
+ break;
+
+ auto T2Class = Classify(T2);
+ if (T2Class == None)
+ break;
+
+ if (T2Class != Array)
+ Kind = CastAwayConstnessKind::CACK_Incoherent;
+ else if (Kind != CastAwayConstnessKind::CACK_Incoherent)
+ Kind = CastAwayConstnessKind::CACK_SimilarKind;
+
+ T1 = Unwrap(T1);
+ T2 = Unwrap(T2).withCVRQualifiers(T2.getCVRQualifiers());
}
- return false;
+ return Kind;
}
-/// CastsAwayConstness - Check if the pointer conversion from SrcType to
-/// DestType casts away constness as defined in C++ 5.2.11p8ff. This is used by
-/// the cast checkers. Both arguments must denote pointer (possibly to member)
-/// types.
+/// Check if the pointer conversion from SrcType to DestType casts away
+/// constness as defined in C++ [expr.const.cast]. This is used by the cast
+/// checkers. Both arguments must denote pointer (possibly to member) types.
///
/// \param CheckCVR Whether to check for const/volatile/restrict qualifiers.
-///
/// \param CheckObjCLifetime Whether to check Objective-C lifetime qualifiers.
-static bool
+static CastAwayConstnessKind
CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
bool CheckCVR, bool CheckObjCLifetime,
QualType *TheOffendingSrcType = nullptr,
@@ -521,33 +561,35 @@ 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)
- return false;
-
- // Casting away constness is defined in C++ 5.2.11p8 with reference to
- // C++ 4.4. We piggyback on Sema::IsQualificationConversion for this, since
- // the rules are non-trivial. So first we construct Tcv *...cv* as described
- // in C++ 5.2.11p8.
- assert((SrcType->isAnyPointerType() || SrcType->isMemberPointerType() ||
- SrcType->isBlockPointerType() ||
- DestType->isLValueReferenceType()) &&
- "Source type is not pointer or pointer to member.");
- assert((DestType->isAnyPointerType() || DestType->isMemberPointerType() ||
- DestType->isBlockPointerType() ||
- DestType->isLValueReferenceType()) &&
- "Destination type is not pointer or pointer to member, or reference.");
+ if (!CheckCVR && CheckObjCLifetime && !Self.Context.getLangOpts().ObjC1)
+ return CastAwayConstnessKind::CACK_None;
+
+ if (!DestType->isReferenceType()) {
+ assert((SrcType->isAnyPointerType() || SrcType->isMemberPointerType() ||
+ SrcType->isBlockPointerType()) &&
+ "Source type is not pointer or pointer to member.");
+ assert((DestType->isAnyPointerType() || DestType->isMemberPointerType() ||
+ DestType->isBlockPointerType()) &&
+ "Destination type is not pointer or pointer to member.");
+ }
QualType UnwrappedSrcType = Self.Context.getCanonicalType(SrcType),
UnwrappedDestType = Self.Context.getCanonicalType(DestType);
- SmallVector<Qualifiers, 8> cv1, cv2;
// Find the qualifiers. We only care about cvr-qualifiers for the
// purpose of this check, because other qualifiers (address spaces,
// Objective-C GC, etc.) are part of the type's identity.
QualType PrevUnwrappedSrcType = UnwrappedSrcType;
QualType PrevUnwrappedDestType = UnwrappedDestType;
- while (UnwrapDissimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) {
+ auto WorstKind = CastAwayConstnessKind::CACK_Similar;
+ bool AllConstSoFar = true;
+ while (auto Kind = unwrapCastAwayConstnessLevel(
+ Self.Context, UnwrappedSrcType, UnwrappedDestType)) {
+ // Track the worst kind of unwrap we needed to do before we found a
+ // problem.
+ if (Kind > WorstKind)
+ WorstKind = Kind;
+
// Determine the relevant qualifiers at this level.
Qualifiers SrcQuals, DestQuals;
Self.Context.getUnqualifiedArrayType(UnwrappedSrcType, SrcQuals);
@@ -560,51 +602,71 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
UnwrappedDestType->isObjCObjectType())
SrcQuals.removeConst();
- Qualifiers RetainedSrcQuals, RetainedDestQuals;
if (CheckCVR) {
- RetainedSrcQuals.setCVRQualifiers(SrcQuals.getCVRQualifiers());
- RetainedDestQuals.setCVRQualifiers(DestQuals.getCVRQualifiers());
+ Qualifiers SrcCvrQuals =
+ Qualifiers::fromCVRMask(SrcQuals.getCVRQualifiers());
+ Qualifiers DestCvrQuals =
+ Qualifiers::fromCVRMask(DestQuals.getCVRQualifiers());
+
+ if (SrcCvrQuals != DestCvrQuals) {
+ if (CastAwayQualifiers)
+ *CastAwayQualifiers = SrcCvrQuals - DestCvrQuals;
+
+ // If we removed a cvr-qualifier, this is casting away 'constness'.
+ if (!DestCvrQuals.compatiblyIncludes(SrcCvrQuals)) {
+ if (TheOffendingSrcType)
+ *TheOffendingSrcType = PrevUnwrappedSrcType;
+ if (TheOffendingDestType)
+ *TheOffendingDestType = PrevUnwrappedDestType;
+ return WorstKind;
+ }
- if (RetainedSrcQuals != RetainedDestQuals && TheOffendingSrcType &&
- TheOffendingDestType && CastAwayQualifiers) {
- *TheOffendingSrcType = PrevUnwrappedSrcType;
- *TheOffendingDestType = PrevUnwrappedDestType;
- *CastAwayQualifiers = RetainedSrcQuals - RetainedDestQuals;
+ // If any prior level was not 'const', this is also casting away
+ // 'constness'. We noted the outermost type missing a 'const' already.
+ if (!AllConstSoFar)
+ return WorstKind;
}
}
-
+
if (CheckObjCLifetime &&
!DestQuals.compatiblyIncludesObjCLifetime(SrcQuals))
- return true;
-
- cv1.push_back(RetainedSrcQuals);
- cv2.push_back(RetainedDestQuals);
+ return WorstKind;
+
+ // If we found our first non-const-qualified type, this may be the place
+ // where things start to go wrong.
+ if (AllConstSoFar && !DestQuals.hasConst()) {
+ AllConstSoFar = false;
+ if (TheOffendingSrcType)
+ *TheOffendingSrcType = PrevUnwrappedSrcType;
+ if (TheOffendingDestType)
+ *TheOffendingDestType = PrevUnwrappedDestType;
+ }
PrevUnwrappedSrcType = UnwrappedSrcType;
PrevUnwrappedDestType = UnwrappedDestType;
}
- if (cv1.empty())
- return false;
- // Construct void pointers with those qualifiers (in reverse order of
- // unwrapping, of course).
- QualType SrcConstruct = Self.Context.VoidTy;
- QualType DestConstruct = Self.Context.VoidTy;
- ASTContext &Context = Self.Context;
- for (SmallVectorImpl<Qualifiers>::reverse_iterator i1 = cv1.rbegin(),
- i2 = cv2.rbegin();
- i1 != cv1.rend(); ++i1, ++i2) {
- SrcConstruct
- = Context.getPointerType(Context.getQualifiedType(SrcConstruct, *i1));
- DestConstruct
- = Context.getPointerType(Context.getQualifiedType(DestConstruct, *i2));
- }
-
- // Test if they're compatible.
- bool ObjCLifetimeConversion;
- return SrcConstruct != DestConstruct &&
- !Self.IsQualificationConversion(SrcConstruct, DestConstruct, false,
- ObjCLifetimeConversion);
+ return CastAwayConstnessKind::CACK_None;
+}
+
+static TryCastResult getCastAwayConstnessCastKind(CastAwayConstnessKind CACK,
+ unsigned &DiagID) {
+ switch (CACK) {
+ case CastAwayConstnessKind::CACK_None:
+ llvm_unreachable("did not cast away constness");
+
+ case CastAwayConstnessKind::CACK_Similar:
+ // FIXME: Accept these as an extension too?
+ case CastAwayConstnessKind::CACK_SimilarKind:
+ DiagID = diag::err_bad_cxx_cast_qualifiers_away;
+ return TC_Failed;
+
+ case CastAwayConstnessKind::CACK_Incoherent:
+ DiagID = diag::ext_bad_cxx_cast_qualifiers_away_incoherent;
+ return TC_Extension;
+ }
+
+ llvm_unreachable("unexpected cast away constness kind");
}
/// CheckDynamicCast - Check that a dynamic_cast\<DestType\>(SrcExpr) is valid.
@@ -772,12 +834,13 @@ void CastOperation::CheckConstCast() {
return;
unsigned msg = diag::err_bad_cxx_cast_generic;
- if (TryConstCast(Self, SrcExpr, DestType, /*CStyle*/false, msg) != TC_Success
- && msg != 0) {
+ auto TCR = TryConstCast(Self, SrcExpr, DestType, /*CStyle*/ false, msg);
+ if (TCR != TC_Success && msg != 0) {
Self.Diag(OpRange.getBegin(), msg) << CT_Const
<< SrcExpr.get()->getType() << DestType << OpRange;
- SrcExpr = ExprError();
}
+ if (!isValidCast(TCR))
+ SrcExpr = ExprError();
}
/// Check that a reinterpret_cast\<DestType\>(SrcExpr) is not used as upcast
@@ -890,8 +953,7 @@ void CastOperation::CheckReinterpretCast() {
TryCastResult tcr =
TryReinterpretCast(Self, SrcExpr, DestType,
/*CStyle*/false, OpRange, msg, Kind);
- if (tcr != TC_Success && msg != 0)
- {
+ if (tcr != TC_Success && msg != 0) {
if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
return;
if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
@@ -905,11 +967,14 @@ void CastOperation::CheckReinterpretCast() {
diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr.get(),
DestType, /*listInitialization=*/false);
}
- SrcExpr = ExprError();
- } else if (tcr == TC_Success) {
+ }
+
+ if (isValidCast(tcr)) {
if (Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers())
checkObjCConversion(Sema::CCK_OtherCast);
DiagnoseReinterpretUpDownCast(Self, SrcExpr.get(), DestType, OpRange);
+ } else {
+ SrcExpr = ExprError();
}
}
@@ -967,14 +1032,15 @@ void CastOperation::CheckStaticCast() {
diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr.get(), DestType,
/*listInitialization=*/false);
}
- SrcExpr = ExprError();
- } else if (tcr == TC_Success) {
+ }
+
+ if (isValidCast(tcr)) {
if (Kind == CK_BitCast)
checkCastAlign();
if (Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers())
checkObjCConversion(Sema::CCK_OtherCast);
- } else if (Kind == CK_BitCast) {
- checkCastAlign();
+ } else {
+ SrcExpr = ExprError();
}
}
@@ -1145,7 +1211,7 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
}
}
}
- // Allow arbitray objective-c pointer conversion with static casts.
+ // Allow arbitrary objective-c pointer conversion with static casts.
if (SrcType->isObjCObjectPointerType() &&
DestType->isObjCObjectPointerType()) {
Kind = CK_BitCast;
@@ -1663,29 +1729,14 @@ static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr,
msg = diag::err_bad_const_cast_dest;
return TC_NotApplicable;
}
- SrcType = Self.Context.getCanonicalType(SrcType);
-
- // Unwrap the pointers. Ignore qualifiers. Terminate early if the types are
- // completely equal.
- // C++ 5.2.11p3 describes the core semantics of const_cast. All cv specifiers
- // in multi-level pointers may change, but the level count must be the same,
- // as must be the final pointee type.
- while (SrcType != DestType &&
- Self.Context.UnwrapSimilarPointerTypes(SrcType, DestType)) {
- Qualifiers SrcQuals, DestQuals;
- SrcType = Self.Context.getUnqualifiedArrayType(SrcType, SrcQuals);
- DestType = Self.Context.getUnqualifiedArrayType(DestType, DestQuals);
-
- // const_cast is permitted to strip cvr-qualifiers, only. Make sure that
- // the other qualifiers (e.g., address spaces) are identical.
- SrcQuals.removeCVRQualifiers();
- DestQuals.removeCVRQualifiers();
- if (SrcQuals != DestQuals)
- return TC_NotApplicable;
- }
- // Since we're dealing in canonical types, the remainder must be the same.
- if (SrcType != DestType)
+ // C++ [expr.const.cast]p3:
+ // "For two similar types T1 and T2, [...]"
+ //
+ // We only allow a const_cast to change cvr-qualifiers, not other kinds of
+ // type qualifiers. (Likewise, we ignore other changes when determining
+ // whether a cast casts away constness.)
+ if (!Self.Context.hasCvrSimilarType(SrcType, DestType))
return TC_NotApplicable;
if (NeedToMaterializeTemporary)
@@ -1913,6 +1964,12 @@ 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,
@@ -1994,16 +2051,6 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
SrcMemPtr->isMemberFunctionPointer())
return TC_NotApplicable;
- // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away
- // constness.
- // A reinterpret_cast followed by a const_cast can, though, so in C-style,
- // we accept it.
- if (CastsAwayConstness(Self, SrcType, DestType, /*CheckCVR=*/!CStyle,
- /*CheckObjCLifetime=*/CStyle)) {
- msg = diag::err_bad_cxx_cast_qualifiers_away;
- return TC_Failed;
- }
-
if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
// We need to determine the inheritance model that the class will use if
// haven't yet.
@@ -2018,6 +2065,15 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
return TC_Failed;
}
+ // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away
+ // constness.
+ // A reinterpret_cast followed by a const_cast can, though, so in C-style,
+ // we accept it.
+ if (auto CACK =
+ CastsAwayConstness(Self, SrcType, DestType, /*CheckCVR=*/!CStyle,
+ /*CheckObjCLifetime=*/CStyle))
+ return getCastAwayConstnessCastKind(CACK, msg);
+
// A valid member pointer cast.
assert(!IsLValueCast);
Kind = CK_ReinterpretMemberPointer;
@@ -2134,19 +2190,19 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
return TC_NotApplicable;
}
- // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away constness.
- // The C-style cast operator can.
- if (CastsAwayConstness(Self, SrcType, DestType, /*CheckCVR=*/!CStyle,
- /*CheckObjCLifetime=*/CStyle)) {
- msg = diag::err_bad_cxx_cast_qualifiers_away;
- return TC_Failed;
- }
-
// Cannot convert between block pointers and Objective-C object pointers.
if ((SrcType->isBlockPointerType() && DestType->isObjCObjectPointerType()) ||
(DestType->isBlockPointerType() && SrcType->isObjCObjectPointerType()))
return TC_NotApplicable;
+ // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away constness.
+ // The C-style cast operator can.
+ TryCastResult SuccessResult = TC_Success;
+ if (auto CACK =
+ CastsAwayConstness(Self, SrcType, DestType, /*CheckCVR=*/!CStyle,
+ /*CheckObjCLifetime=*/CStyle))
+ SuccessResult = getCastAwayConstnessCastKind(CACK, msg);
+
if (IsLValueCast) {
Kind = CK_LValueBitCast;
} else if (DestType->isObjCObjectPointerType()) {
@@ -2157,6 +2213,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
} else {
Kind = CK_BitCast;
}
+ } else if (IsAddressSpaceConversion(SrcType, DestType)) {
+ Kind = CK_AddressSpaceConversion;
} else {
Kind = CK_BitCast;
}
@@ -2164,7 +2222,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
// Any pointer can be cast to an Objective-C pointer type with a C-style
// cast.
if (CStyle && DestType->isObjCObjectPointerType()) {
- return TC_Success;
+ return SuccessResult;
}
if (CStyle)
DiagnoseCastOfObjCSEL(Self, SrcExpr, DestType);
@@ -2178,7 +2236,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
if (DestType->isFunctionPointerType()) {
// C++ 5.2.10p6: A pointer to a function can be explicitly converted to
// a pointer to a function of a different type.
- return TC_Success;
+ return SuccessResult;
}
// C++0x 5.2.10p8: Converting a pointer to a function into a pointer to
@@ -2191,7 +2249,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
Self.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_cast_fn_obj : diag::ext_cast_fn_obj)
<< OpRange;
- return TC_Success;
+ return SuccessResult;
}
if (DestType->isFunctionPointerType()) {
@@ -2200,7 +2258,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
Self.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_cast_fn_obj : diag::ext_cast_fn_obj)
<< OpRange;
- return TC_Success;
+ return SuccessResult;
}
// C++ 5.2.10p7: A pointer to an object can be explicitly converted to
@@ -2208,8 +2266,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
// Void pointers are not specified, but supported by every compiler out there.
// So we finish by allowing everything that remains - it's got to be two
// object pointers.
- return TC_Success;
-}
+ return SuccessResult;
+}
void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
bool ListInitialization) {
@@ -2289,7 +2347,7 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
/*CStyle*/true, msg);
if (SrcExpr.isInvalid())
return;
- if (tcr == TC_Success)
+ if (isValidCast(tcr))
Kind = CK_NoOp;
Sema::CheckedConversionKind CCK
@@ -2312,7 +2370,7 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
}
if (Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() &&
- tcr == TC_Success)
+ isValidCast(tcr))
checkObjCConversion(CCK);
if (tcr != TC_Success && msg != 0) {
@@ -2336,13 +2394,14 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
diagnoseBadCast(Self, msg, (FunctionalStyle ? CT_Functional : CT_CStyle),
OpRange, SrcExpr.get(), DestType, ListInitialization);
}
- } else if (Kind == CK_BitCast) {
- checkCastAlign();
}
- // Clear out SrcExpr if there was a fatal error.
- if (tcr != TC_Success)
+ if (isValidCast(tcr)) {
+ if (Kind == CK_BitCast)
+ checkCastAlign();
+ } else {
SrcExpr = ExprError();
+ }
}
/// DiagnoseBadFunctionCast - Warn whenever a function call is cast to a
@@ -2627,11 +2686,13 @@ static void DiagnoseCastQual(Sema &Self, const ExprResult &SrcExpr,
QualType TheOffendingSrcType, TheOffendingDestType;
Qualifiers CastAwayQualifiers;
- if (!CastsAwayConstness(Self, SrcType, DestType, true, false,
- &TheOffendingSrcType, &TheOffendingDestType,
- &CastAwayQualifiers))
+ if (CastsAwayConstness(Self, SrcType, DestType, true, false,
+ &TheOffendingSrcType, &TheOffendingDestType,
+ &CastAwayQualifiers) !=
+ CastAwayConstnessKind::CACK_Similar)
return;
+ // FIXME: 'restrict' is not properly handled here.
int qualifiers = -1;
if (CastAwayQualifiers.hasConst() && CastAwayQualifiers.hasVolatile()) {
qualifiers = 0;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
index 57af6b86bf80..8d953b6ef341 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
@@ -28,6 +28,7 @@
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/NSAPI.h"
+#include "clang/AST/NonTrivialTypeVisitor.h"
#include "clang/AST/OperationKinds.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/TemplateBase.h"
@@ -196,35 +197,47 @@ static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall) {
// First two arguments should be integers.
for (unsigned I = 0; I < 2; ++I) {
- Expr *Arg = TheCall->getArg(I);
- QualType Ty = Arg->getType();
+ ExprResult Arg = TheCall->getArg(I);
+ QualType Ty = Arg.get()->getType();
if (!Ty->isIntegerType()) {
- S.Diag(Arg->getLocStart(), diag::err_overflow_builtin_must_be_int)
- << Ty << Arg->getSourceRange();
+ S.Diag(Arg.get()->getLocStart(), diag::err_overflow_builtin_must_be_int)
+ << Ty << Arg.get()->getSourceRange();
return true;
}
+ InitializedEntity Entity = InitializedEntity::InitializeParameter(
+ S.getASTContext(), Ty, /*consume*/ false);
+ Arg = S.PerformCopyInitialization(Entity, SourceLocation(), Arg);
+ if (Arg.isInvalid())
+ return true;
+ TheCall->setArg(I, Arg.get());
}
// Third argument should be a pointer to a non-const integer.
// IRGen correctly handles volatile, restrict, and address spaces, and
// the other qualifiers aren't possible.
{
- Expr *Arg = TheCall->getArg(2);
- QualType Ty = Arg->getType();
+ ExprResult Arg = TheCall->getArg(2);
+ QualType Ty = Arg.get()->getType();
const auto *PtrTy = Ty->getAs<PointerType>();
if (!(PtrTy && PtrTy->getPointeeType()->isIntegerType() &&
!PtrTy->getPointeeType().isConstQualified())) {
- S.Diag(Arg->getLocStart(), diag::err_overflow_builtin_must_be_ptr_int)
- << Ty << Arg->getSourceRange();
+ S.Diag(Arg.get()->getLocStart(),
+ diag::err_overflow_builtin_must_be_ptr_int)
+ << Ty << Arg.get()->getSourceRange();
return true;
}
+ InitializedEntity Entity = InitializedEntity::InitializeParameter(
+ S.getASTContext(), Ty, /*consume*/ false);
+ Arg = S.PerformCopyInitialization(Entity, SourceLocation(), Arg);
+ if (Arg.isInvalid())
+ return true;
+ TheCall->setArg(2, Arg.get());
}
-
return false;
}
static void SemaBuiltinMemChkCall(Sema &S, FunctionDecl *FDecl,
- CallExpr *TheCall, unsigned SizeIdx,
+ CallExpr *TheCall, unsigned SizeIdx,
unsigned DstSizeIdx) {
if (TheCall->getNumArgs() <= SizeIdx ||
TheCall->getNumArgs() <= DstSizeIdx)
@@ -683,7 +696,7 @@ static bool checkOpenCLPipePacketType(Sema &S, CallExpr *Call, unsigned Idx) {
return false;
}
-// \brief Performs semantic analysis for the read/write_pipe call.
+// Performs semantic analysis for the read/write_pipe call.
// \param S Reference to the semantic analyzer.
// \param Call A pointer to the builtin call.
// \return True if a semantic error has been found, false otherwise.
@@ -737,7 +750,7 @@ static bool SemaBuiltinRWPipe(Sema &S, CallExpr *Call) {
return false;
}
-// \brief Performs a semantic analysis on the {work_group_/sub_group_
+// Performs a semantic analysis on the {work_group_/sub_group_
// /_}reserve_{read/write}_pipe
// \param S Reference to the semantic analyzer.
// \param Call The call to the builtin function to be analyzed.
@@ -766,7 +779,7 @@ static bool SemaBuiltinReserveRWPipe(Sema &S, CallExpr *Call) {
return false;
}
-// \brief Performs a semantic analysis on {work_group_/sub_group_
+// Performs a semantic analysis on {work_group_/sub_group_
// /_}commit_{read/write}_pipe
// \param S Reference to the semantic analyzer.
// \param Call The call to the builtin function to be analyzed.
@@ -789,7 +802,7 @@ static bool SemaBuiltinCommitRWPipe(Sema &S, CallExpr *Call) {
return false;
}
-// \brief Performs a semantic analysis on the call to built-in Pipe
+// Performs a semantic analysis on the call to built-in Pipe
// Query Functions.
// \param S Reference to the semantic analyzer.
// \param Call The call to the builtin function to be analyzed.
@@ -807,8 +820,8 @@ static bool SemaBuiltinPipePackets(Sema &S, CallExpr *Call) {
return false;
}
-// \brief OpenCL v2.0 s6.13.9 - Address space qualifier functions.
-// \brief Performs semantic analysis for the to_global/local/private call.
+// OpenCL v2.0 s6.13.9 - Address space qualifier functions.
+// Performs semantic analysis for the to_global/local/private call.
// \param S Reference to the semantic analyzer.
// \param BuiltinID ID of the builtin function.
// \param Call A pointer to the builtin call.
@@ -850,6 +863,20 @@ static bool SemaOpenCLBuiltinToAddr(Sema &S, unsigned BuiltinID,
return false;
}
+// Emit an error and return true if the current architecture is not in the list
+// of supported architectures.
+static bool
+CheckBuiltinTargetSupport(Sema &S, unsigned BuiltinID, CallExpr *TheCall,
+ ArrayRef<llvm::Triple::ArchType> SupportedArchs) {
+ llvm::Triple::ArchType CurArch =
+ S.getASTContext().getTargetInfo().getTriple().getArch();
+ if (llvm::is_contained(SupportedArchs, CurArch))
+ return false;
+ S.Diag(TheCall->getLocStart(), diag::err_builtin_target_unsupported)
+ << TheCall->getSourceRange();
+ return true;
+}
+
ExprResult
Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
CallExpr *TheCall) {
@@ -900,6 +927,33 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
}
break;
}
+
+ // The acquire, release, and no fence variants are ARM and AArch64 only.
+ case Builtin::BI_interlockedbittestandset_acq:
+ case Builtin::BI_interlockedbittestandset_rel:
+ case Builtin::BI_interlockedbittestandset_nf:
+ case Builtin::BI_interlockedbittestandreset_acq:
+ case Builtin::BI_interlockedbittestandreset_rel:
+ case Builtin::BI_interlockedbittestandreset_nf:
+ if (CheckBuiltinTargetSupport(
+ *this, BuiltinID, TheCall,
+ {llvm::Triple::arm, llvm::Triple::thumb, llvm::Triple::aarch64}))
+ return ExprError();
+ break;
+
+ // The 64-bit bittest variants are x64, ARM, and AArch64 only.
+ case Builtin::BI_bittest64:
+ case Builtin::BI_bittestandcomplement64:
+ case Builtin::BI_bittestandreset64:
+ case Builtin::BI_bittestandset64:
+ case Builtin::BI_interlockedbittestandreset64:
+ case Builtin::BI_interlockedbittestandset64:
+ if (CheckBuiltinTargetSupport(*this, BuiltinID, TheCall,
+ {llvm::Triple::x86_64, llvm::Triple::arm,
+ llvm::Triple::thumb, llvm::Triple::aarch64}))
+ return ExprError();
+ break;
+
case Builtin::BI__builtin_isgreater:
case Builtin::BI__builtin_isgreaterequal:
case Builtin::BI__builtin_isless:
@@ -918,6 +972,9 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
case Builtin::BI__builtin_isinf_sign:
case Builtin::BI__builtin_isnan:
case Builtin::BI__builtin_isnormal:
+ case Builtin::BI__builtin_signbit:
+ case Builtin::BI__builtin_signbitf:
+ case Builtin::BI__builtin_signbitl:
if (SemaBuiltinFPClassification(TheCall, 1))
return ExprError();
break;
@@ -1097,19 +1154,70 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
return ExprError();
break;
case Builtin::BI__builtin_operator_new:
- case Builtin::BI__builtin_operator_delete:
- if (!getLangOpts().CPlusPlus) {
- Diag(TheCall->getExprLoc(), diag::err_builtin_requires_language)
- << (BuiltinID == Builtin::BI__builtin_operator_new
- ? "__builtin_operator_new"
- : "__builtin_operator_delete")
- << "C++";
+ case Builtin::BI__builtin_operator_delete: {
+ bool IsDelete = BuiltinID == Builtin::BI__builtin_operator_delete;
+ ExprResult Res =
+ SemaBuiltinOperatorNewDeleteOverloaded(TheCallResult, IsDelete);
+ if (Res.isInvalid())
+ CorrectDelayedTyposInExpr(TheCallResult.get());
+ return Res;
+ }
+ case Builtin::BI__builtin_dump_struct: {
+ // We first want to ensure we are called with 2 arguments
+ if (checkArgCount(*this, TheCall, 2))
+ return ExprError();
+ // Ensure that the first argument is of type 'struct XX *'
+ const Expr *PtrArg = TheCall->getArg(0)->IgnoreParenImpCasts();
+ const QualType PtrArgType = PtrArg->getType();
+ if (!PtrArgType->isPointerType() ||
+ !PtrArgType->getPointeeType()->isRecordType()) {
+ Diag(PtrArg->getLocStart(), diag::err_typecheck_convert_incompatible)
+ << PtrArgType << "structure pointer" << 1 << 0 << 3 << 1 << PtrArgType
+ << "structure pointer";
+ return ExprError();
+ }
+
+ // Ensure that the second argument is of type 'FunctionType'
+ 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 *, ...)'";
return ExprError();
}
- // CodeGen assumes it can find the global new and delete to call,
- // so ensure that they are declared.
- DeclareGlobalNewDelete();
+
+ const auto *FuncType =
+ 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 *, ...)'";
+ return ExprError();
+ }
+
+ if (const auto *FT = dyn_cast<FunctionProtoType>(FuncType)) {
+ if (!FT->getNumParams()) {
+ Diag(FnPtrArg->getLocStart(), diag::err_typecheck_convert_incompatible)
+ << FnPtrArgType << "'int (*)(const char *, ...)'" << 1 << 0 << 3
+ << 2 << FnPtrArgType << "'int (*)(const char *, ...)'";
+ return ExprError();
+ }
+ QualType PT = FT->getParamType(0);
+ if (!FT->isVariadic() || FT->getReturnType() != Context.IntTy ||
+ !PT->isPointerType() || !PT->getPointeeType()->isCharType() ||
+ !PT->getPointeeType().isConstQualified()) {
+ Diag(FnPtrArg->getLocStart(), diag::err_typecheck_convert_incompatible)
+ << FnPtrArgType << "'int (*)(const char *, ...)'" << 1 << 0 << 3
+ << 2 << FnPtrArgType << "'int (*)(const char *, ...)'";
+ return ExprError();
+ }
+ }
+
+ TheCall->setType(Context.IntTy);
break;
+ }
// check secure string manipulation functions where overflows
// are detectable at compile time
@@ -1215,7 +1323,6 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
if (SemaOpenCLBuiltinKernelWorkGroupSize(*this, TheCall))
return ExprError();
break;
- break;
case Builtin::BIget_kernel_max_sub_group_size_for_ndrange:
case Builtin::BIget_kernel_sub_group_count_for_ndrange:
if (SemaOpenCLBuiltinNDRangeAndBlock(*this, TheCall))
@@ -1244,6 +1351,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
if (CheckAArch64BuiltinFunctionCall(BuiltinID, TheCall))
return ExprError();
break;
+ case llvm::Triple::hexagon:
+ if (CheckHexagonBuiltinFunctionCall(BuiltinID, TheCall))
+ return ExprError();
+ break;
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
@@ -1353,6 +1464,7 @@ bool Sema::CheckNeonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
switch (BuiltinID) {
#define GET_NEON_OVERLOAD_CHECK
#include "clang/Basic/arm_neon.inc"
+#include "clang/Basic/arm_fp16.inc"
#undef GET_NEON_OVERLOAD_CHECK
}
@@ -1402,9 +1514,10 @@ bool Sema::CheckNeonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
switch (BuiltinID) {
default:
return false;
-#define GET_NEON_IMMEDIATE_CHECK
-#include "clang/Basic/arm_neon.inc"
-#undef GET_NEON_IMMEDIATE_CHECK
+ #define GET_NEON_IMMEDIATE_CHECK
+ #include "clang/Basic/arm_neon.inc"
+ #include "clang/Basic/arm_fp16.inc"
+ #undef GET_NEON_IMMEDIATE_CHECK
}
return SemaBuiltinConstantArgRange(TheCall, i, l, u + l);
@@ -1618,6 +1731,1015 @@ bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID,
return SemaBuiltinConstantArgRange(TheCall, i, l, u + l);
}
+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"} },
+ };
+
+ 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"} },
+ };
+
+ const TargetInfo &TI = Context.getTargetInfo();
+
+ auto FC = ValidCPU.find(BuiltinID);
+ if (FC != ValidCPU.end()) {
+ 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(),
+ diag::err_hexagon_builtin_unsupported_cpu);
+ }
+ }
+
+ auto FH = ValidHVX.find(BuiltinID);
+ if (FH != ValidHVX.end()) {
+ if (!TI.hasFeature("hvx"))
+ return Diag(TheCall->getLocStart(),
+ diag::err_hexagon_builtin_requires_hvx);
+
+ bool IsValid = llvm::any_of(FH->second,
+ [&TI] (StringRef V) {
+ std::string F = "hvx" + V.str();
+ return TI.hasFeature(F);
+ });
+ if (!IsValid)
+ return Diag(TheCall->getLocStart(),
+ diag::err_hexagon_builtin_unsupported_hvx);
+ }
+
+ return false;
+}
+
+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;
+ };
+
+ static const std::map<unsigned, std::vector<ArgInfo>> 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 }} },
+ { Hexagon::BI__builtin_circ_lduh, {{ 3, true, 4, 0 }} },
+ { Hexagon::BI__builtin_circ_ldb, {{ 3, true, 4, 0 }} },
+ { Hexagon::BI__builtin_circ_ldub, {{ 3, true, 4, 0 }} },
+ { Hexagon::BI__builtin_circ_std, {{ 3, true, 4, 3 }} },
+ { Hexagon::BI__builtin_circ_stw, {{ 3, true, 4, 2 }} },
+ { Hexagon::BI__builtin_circ_sth, {{ 3, true, 4, 1 }} },
+ { Hexagon::BI__builtin_circ_sthhi, {{ 3, true, 4, 1 }} },
+ { Hexagon::BI__builtin_circ_stb, {{ 3, true, 4, 0 }} },
+
+ { Hexagon::BI__builtin_HEXAGON_L2_loadrub_pci, {{ 1, true, 4, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_L2_loadrb_pci, {{ 1, true, 4, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_L2_loadruh_pci, {{ 1, true, 4, 1 }} },
+ { Hexagon::BI__builtin_HEXAGON_L2_loadrh_pci, {{ 1, true, 4, 1 }} },
+ { Hexagon::BI__builtin_HEXAGON_L2_loadri_pci, {{ 1, true, 4, 2 }} },
+ { Hexagon::BI__builtin_HEXAGON_L2_loadrd_pci, {{ 1, true, 4, 3 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_storerb_pci, {{ 1, true, 4, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_storerh_pci, {{ 1, true, 4, 1 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_storerf_pci, {{ 1, true, 4, 1 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_storeri_pci, {{ 1, true, 4, 2 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_storerd_pci, {{ 1, true, 4, 3 }} },
+
+ { Hexagon::BI__builtin_HEXAGON_A2_combineii, {{ 1, true, 8, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A2_tfrih, {{ 1, false, 16, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A2_tfril, {{ 1, false, 16, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A2_tfrpi, {{ 0, true, 8, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_bitspliti, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_cmpbeqi, {{ 1, false, 8, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_cmpbgti, {{ 1, true, 8, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_cround_ri, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_round_ri, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_round_ri_sat, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_vcmpbeqi, {{ 1, false, 8, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_vcmpbgti, {{ 1, true, 8, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_vcmpbgtui, {{ 1, false, 7, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_vcmpheqi, {{ 1, true, 8, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_vcmphgti, {{ 1, true, 8, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_vcmphgtui, {{ 1, false, 7, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_vcmpweqi, {{ 1, true, 8, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_vcmpwgti, {{ 1, true, 8, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_A4_vcmpwgtui, {{ 1, false, 7, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_C2_bitsclri, {{ 1, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_C2_muxii, {{ 2, true, 8, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_C4_nbitsclri, {{ 1, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_F2_dfclass, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_F2_dfimm_n, {{ 0, false, 10, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_F2_dfimm_p, {{ 0, false, 10, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_F2_sfclass, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_F2_sfimm_n, {{ 0, false, 10, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_F2_sfimm_p, {{ 0, false, 10, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_M4_mpyri_addi, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_M4_mpyri_addr_u2, {{ 1, false, 6, 2 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_addasl_rrri, {{ 2, false, 3, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_p_acc, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_p_and, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_p, {{ 1, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_p_nac, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_p_or, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_p_xacc, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_r_acc, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_r_and, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_r, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_r_nac, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_r_or, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_r_sat, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_r_xacc, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_vh, {{ 1, false, 4, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asl_i_vw, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_p_acc, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_p_and, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_p, {{ 1, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_p_nac, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_p_or, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_p_rnd_goodsyntax,
+ {{ 1, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_p_rnd, {{ 1, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_r_acc, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_r_and, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_r, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_r_nac, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_r_or, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_r_rnd_goodsyntax,
+ {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_r_rnd, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_svw_trun, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_vh, {{ 1, false, 4, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_asr_i_vw, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_clrbit_i, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_extractu, {{ 1, false, 5, 0 },
+ { 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_extractup, {{ 1, false, 6, 0 },
+ { 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_insert, {{ 2, false, 5, 0 },
+ { 3, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_insertp, {{ 2, false, 6, 0 },
+ { 3, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_p_acc, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_p_and, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_p, {{ 1, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_p_nac, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_p_or, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_p_xacc, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_r_acc, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_r_and, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_r, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_r_nac, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_r_or, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_r_xacc, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_vh, {{ 1, false, 4, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_vw, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_setbit_i, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_tableidxb_goodsyntax,
+ {{ 2, false, 4, 0 },
+ { 3, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_tableidxd_goodsyntax,
+ {{ 2, false, 4, 0 },
+ { 3, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_tableidxh_goodsyntax,
+ {{ 2, false, 4, 0 },
+ { 3, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_tableidxw_goodsyntax,
+ {{ 2, false, 4, 0 },
+ { 3, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_togglebit_i, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_tstbit_i, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_valignib, {{ 2, false, 3, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S2_vspliceib, {{ 2, false, 3, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_addi_asl_ri, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_addi_lsr_ri, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_andi_asl_ri, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_andi_lsr_ri, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_clbaddi, {{ 1, true , 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_clbpaddi, {{ 1, true, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_extract, {{ 1, false, 5, 0 },
+ { 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_extractp, {{ 1, false, 6, 0 },
+ { 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_lsli, {{ 0, true, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_ntstbit_i, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_ori_asl_ri, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_ori_lsr_ri, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_subi_asl_ri, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_subi_lsr_ri, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_vrcrotate_acc, {{ 3, false, 2, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S4_vrcrotate, {{ 2, false, 2, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S5_asrhub_rnd_sat_goodsyntax,
+ {{ 1, false, 4, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S5_asrhub_sat, {{ 1, false, 4, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S5_vasrhrnd_goodsyntax,
+ {{ 1, false, 4, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p, {{ 1, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_acc, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_and, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_nac, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_or, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_xacc, {{ 2, false, 6, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r, {{ 1, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_acc, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_and, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_nac, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_or, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_xacc, {{ 2, false, 5, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_valignbi, {{ 2, false, 3, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_valignbi_128B, {{ 2, false, 3, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlalignbi, {{ 2, false, 3, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlalignbi_128B, {{ 2, false, 3, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi, {{ 2, false, 1, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_128B, {{ 2, false, 1, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_acc, {{ 3, false, 1, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_acc_128B,
+ {{ 3, false, 1, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi, {{ 2, false, 1, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_128B, {{ 2, false, 1, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_acc, {{ 3, false, 1, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_acc_128B,
+ {{ 3, false, 1, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi, {{ 2, false, 1, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_128B, {{ 2, false, 1, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_acc, {{ 3, false, 1, 0 }} },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_acc_128B,
+ {{ 3, false, 1, 0 }} },
+ };
+
+ auto F = Infos.find(BuiltinID);
+ if (F == Infos.end())
+ 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;
+ if (!A.Align) {
+ Error |= SemaBuiltinConstantArgRange(TheCall, A.OpNum, Min, Max);
+ } else {
+ unsigned M = 1 << A.Align;
+ Min *= M;
+ Max *= M;
+ Error |= SemaBuiltinConstantArgRange(TheCall, A.OpNum, Min, Max) |
+ SemaBuiltinConstantArgMultiple(TheCall, A.OpNum, M);
+ }
+ }
+ return Error;
+}
+
+bool Sema::CheckHexagonBuiltinFunctionCall(unsigned BuiltinID,
+ CallExpr *TheCall) {
+ return CheckHexagonBuiltinCpu(BuiltinID, TheCall) ||
+ CheckHexagonBuiltinArgument(BuiltinID, TheCall);
+}
+
+
// CheckMipsBuiltinFunctionCall - Checks the constant value passed to the
// intrinsic is correct. The switch statement is ordered by DSP, MSA. The
// ordering for DSP is unspecified. MSA is ordered by the data format used
@@ -1666,7 +2788,7 @@ bool Sema::CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case Mips::BI__builtin_msa_srlri_h: i = 1; l = 0; u = 15; break;
case Mips::BI__builtin_msa_binsli_h:
case Mips::BI__builtin_msa_binsri_h: i = 2; l = 0; u = 15; break;
- // These intrinsics take an unsigned 5 bit immedate.
+ // These intrinsics take an unsigned 5 bit immediate.
// The first block of intrinsics actually have an unsigned 5 bit field,
// not a df/n field.
case Mips::BI__builtin_msa_clei_u_b:
@@ -1966,6 +3088,12 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_vcvttss2usi64:
ArgNum = 1;
break;
+ case X86::BI__builtin_ia32_maxpd512:
+ case X86::BI__builtin_ia32_maxps512:
+ case X86::BI__builtin_ia32_minpd512:
+ case X86::BI__builtin_ia32_minps512:
+ ArgNum = 2;
+ break;
case X86::BI__builtin_ia32_cvtps2pd512_mask:
case X86::BI__builtin_ia32_cvttpd2dq512_mask:
case X86::BI__builtin_ia32_cvttpd2qq512_mask:
@@ -1995,12 +3123,8 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_cvtss2sd_round_mask:
case X86::BI__builtin_ia32_getexpsd128_round_mask:
case X86::BI__builtin_ia32_getexpss128_round_mask:
- case X86::BI__builtin_ia32_maxpd512_mask:
- case X86::BI__builtin_ia32_maxps512_mask:
case X86::BI__builtin_ia32_maxsd_round_mask:
case X86::BI__builtin_ia32_maxss_round_mask:
- case X86::BI__builtin_ia32_minpd512_mask:
- case X86::BI__builtin_ia32_minps512_mask:
case X86::BI__builtin_ia32_minsd_round_mask:
case X86::BI__builtin_ia32_minss_round_mask:
case X86::BI__builtin_ia32_rcp28sd_round_mask:
@@ -2039,9 +3163,19 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_vcvtss2si64:
case X86::BI__builtin_ia32_vcvtss2usi32:
case X86::BI__builtin_ia32_vcvtss2usi64:
+ case X86::BI__builtin_ia32_sqrtpd512:
+ case X86::BI__builtin_ia32_sqrtps512:
ArgNum = 1;
HasRC = true;
break;
+ case X86::BI__builtin_ia32_addpd512:
+ case X86::BI__builtin_ia32_addps512:
+ case X86::BI__builtin_ia32_divpd512:
+ case X86::BI__builtin_ia32_divps512:
+ case X86::BI__builtin_ia32_mulpd512:
+ case X86::BI__builtin_ia32_mulps512:
+ case X86::BI__builtin_ia32_subpd512:
+ case X86::BI__builtin_ia32_subps512:
case X86::BI__builtin_ia32_cvtsi2sd64:
case X86::BI__builtin_ia32_cvtsi2ss32:
case X86::BI__builtin_ia32_cvtsi2ss64:
@@ -2062,19 +3196,9 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_cvtqq2ps512_mask:
case X86::BI__builtin_ia32_cvtuqq2pd512_mask:
case X86::BI__builtin_ia32_cvtuqq2ps512_mask:
- case X86::BI__builtin_ia32_sqrtpd512_mask:
- case X86::BI__builtin_ia32_sqrtps512_mask:
ArgNum = 3;
HasRC = true;
break;
- case X86::BI__builtin_ia32_addpd512_mask:
- case X86::BI__builtin_ia32_addps512_mask:
- case X86::BI__builtin_ia32_divpd512_mask:
- case X86::BI__builtin_ia32_divps512_mask:
- case X86::BI__builtin_ia32_mulpd512_mask:
- case X86::BI__builtin_ia32_mulps512_mask:
- case X86::BI__builtin_ia32_subpd512_mask:
- case X86::BI__builtin_ia32_subps512_mask:
case X86::BI__builtin_ia32_addss_round_mask:
case X86::BI__builtin_ia32_addsd_round_mask:
case X86::BI__builtin_ia32_divss_round_mask:
@@ -2092,34 +3216,28 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_cvtsd2ss_round_mask:
case X86::BI__builtin_ia32_sqrtsd_round_mask:
case X86::BI__builtin_ia32_sqrtss_round_mask:
+ case X86::BI__builtin_ia32_vfmaddsd3_mask:
+ case X86::BI__builtin_ia32_vfmaddsd3_maskz:
+ case X86::BI__builtin_ia32_vfmaddsd3_mask3:
+ case X86::BI__builtin_ia32_vfmaddss3_mask:
+ case X86::BI__builtin_ia32_vfmaddss3_maskz:
+ case X86::BI__builtin_ia32_vfmaddss3_mask3:
case X86::BI__builtin_ia32_vfmaddpd512_mask:
- case X86::BI__builtin_ia32_vfmaddpd512_mask3:
case X86::BI__builtin_ia32_vfmaddpd512_maskz:
+ case X86::BI__builtin_ia32_vfmaddpd512_mask3:
+ case X86::BI__builtin_ia32_vfmsubpd512_mask3:
case X86::BI__builtin_ia32_vfmaddps512_mask:
- case X86::BI__builtin_ia32_vfmaddps512_mask3:
case X86::BI__builtin_ia32_vfmaddps512_maskz:
+ case X86::BI__builtin_ia32_vfmaddps512_mask3:
+ case X86::BI__builtin_ia32_vfmsubps512_mask3:
case X86::BI__builtin_ia32_vfmaddsubpd512_mask:
- case X86::BI__builtin_ia32_vfmaddsubpd512_mask3:
case X86::BI__builtin_ia32_vfmaddsubpd512_maskz:
+ case X86::BI__builtin_ia32_vfmaddsubpd512_mask3:
+ case X86::BI__builtin_ia32_vfmsubaddpd512_mask3:
case X86::BI__builtin_ia32_vfmaddsubps512_mask:
- case X86::BI__builtin_ia32_vfmaddsubps512_mask3:
case X86::BI__builtin_ia32_vfmaddsubps512_maskz:
- case X86::BI__builtin_ia32_vfmsubpd512_mask3:
- case X86::BI__builtin_ia32_vfmsubps512_mask3:
- case X86::BI__builtin_ia32_vfmsubaddpd512_mask3:
+ case X86::BI__builtin_ia32_vfmaddsubps512_mask3:
case X86::BI__builtin_ia32_vfmsubaddps512_mask3:
- case X86::BI__builtin_ia32_vfnmaddpd512_mask:
- case X86::BI__builtin_ia32_vfnmaddps512_mask:
- case X86::BI__builtin_ia32_vfnmsubpd512_mask:
- case X86::BI__builtin_ia32_vfnmsubpd512_mask3:
- case X86::BI__builtin_ia32_vfnmsubps512_mask:
- case X86::BI__builtin_ia32_vfnmsubps512_mask3:
- case X86::BI__builtin_ia32_vfmaddsd3_mask:
- case X86::BI__builtin_ia32_vfmaddsd3_maskz:
- case X86::BI__builtin_ia32_vfmaddsd3_mask3:
- case X86::BI__builtin_ia32_vfmaddss3_mask:
- case X86::BI__builtin_ia32_vfmaddss3_maskz:
- case X86::BI__builtin_ia32_vfmaddss3_mask3:
ArgNum = 4;
HasRC = true;
break;
@@ -2256,6 +3374,17 @@ bool Sema::CheckX86BuiltinGatherScatterScale(unsigned BuiltinID,
<< Arg->getSourceRange();
}
+static bool isX86_32Builtin(unsigned BuiltinID) {
+ // These builtins only work on x86-32 targets.
+ switch (BuiltinID) {
+ case X86::BI__builtin_ia32_readeflags_u32:
+ case X86::BI__builtin_ia32_writeeflags_u32:
+ return true;
+ }
+
+ return false;
+}
+
bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
if (BuiltinID == X86::BI__builtin_cpu_supports)
return SemaBuiltinCpuSupports(*this, TheCall);
@@ -2263,6 +3392,12 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
if (BuiltinID == X86::BI__builtin_cpu_is)
return SemaBuiltinCpuIs(*this, 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(),
+ diag::err_32_bit_builtin_64_bit_tgt);
+
// If the intrinsic has rounding or SAE make sure its valid.
if (CheckX86BuiltinRoundingOrSAE(BuiltinID, TheCall))
return true;
@@ -2277,14 +3412,67 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
switch (BuiltinID) {
default:
return false;
+ case X86::BI__builtin_ia32_vec_ext_v2si:
+ case X86::BI__builtin_ia32_vec_ext_v2di:
+ case X86::BI__builtin_ia32_vextractf128_pd256:
+ case X86::BI__builtin_ia32_vextractf128_ps256:
+ case X86::BI__builtin_ia32_vextractf128_si256:
+ case X86::BI__builtin_ia32_extract128i256:
+ case X86::BI__builtin_ia32_extractf64x4_mask:
+ case X86::BI__builtin_ia32_extracti64x4_mask:
+ case X86::BI__builtin_ia32_extractf32x8_mask:
+ case X86::BI__builtin_ia32_extracti32x8_mask:
+ case X86::BI__builtin_ia32_extractf64x2_256_mask:
+ case X86::BI__builtin_ia32_extracti64x2_256_mask:
+ case X86::BI__builtin_ia32_extractf32x4_256_mask:
+ case X86::BI__builtin_ia32_extracti32x4_256_mask:
+ i = 1; l = 0; u = 1;
+ break;
+ case X86::BI__builtin_ia32_vec_set_v2di:
+ case X86::BI__builtin_ia32_vinsertf128_pd256:
+ case X86::BI__builtin_ia32_vinsertf128_ps256:
+ case X86::BI__builtin_ia32_vinsertf128_si256:
+ case X86::BI__builtin_ia32_insert128i256:
+ case X86::BI__builtin_ia32_insertf32x8:
+ case X86::BI__builtin_ia32_inserti32x8:
+ case X86::BI__builtin_ia32_insertf64x4:
+ case X86::BI__builtin_ia32_inserti64x4:
+ case X86::BI__builtin_ia32_insertf64x2_256:
+ case X86::BI__builtin_ia32_inserti64x2_256:
+ case X86::BI__builtin_ia32_insertf32x4_256:
+ case X86::BI__builtin_ia32_inserti32x4_256:
+ i = 2; l = 0; u = 1;
+ break;
+ case X86::BI__builtin_ia32_vpermilpd:
+ case X86::BI__builtin_ia32_vec_ext_v4hi:
+ case X86::BI__builtin_ia32_vec_ext_v4si:
+ case X86::BI__builtin_ia32_vec_ext_v4sf:
+ case X86::BI__builtin_ia32_vec_ext_v4di:
+ case X86::BI__builtin_ia32_extractf32x4_mask:
+ case X86::BI__builtin_ia32_extracti32x4_mask:
+ case X86::BI__builtin_ia32_extractf64x2_512_mask:
+ case X86::BI__builtin_ia32_extracti64x2_512_mask:
+ i = 1; l = 0; u = 3;
+ break;
case X86::BI_mm_prefetch:
+ case X86::BI__builtin_ia32_vec_ext_v8hi:
+ case X86::BI__builtin_ia32_vec_ext_v8si:
i = 1; l = 0; u = 7;
break;
case X86::BI__builtin_ia32_sha1rnds4:
- case X86::BI__builtin_ia32_shuf_f32x4_256_mask:
- case X86::BI__builtin_ia32_shuf_f64x2_256_mask:
- case X86::BI__builtin_ia32_shuf_i32x4_256_mask:
- case X86::BI__builtin_ia32_shuf_i64x2_256_mask:
+ case X86::BI__builtin_ia32_blendpd:
+ case X86::BI__builtin_ia32_shufpd:
+ case X86::BI__builtin_ia32_vec_set_v4hi:
+ case X86::BI__builtin_ia32_vec_set_v4si:
+ case X86::BI__builtin_ia32_vec_set_v4di:
+ case X86::BI__builtin_ia32_shuf_f32x4_256:
+ case X86::BI__builtin_ia32_shuf_f64x2_256:
+ case X86::BI__builtin_ia32_shuf_i32x4_256:
+ case X86::BI__builtin_ia32_shuf_i64x2_256:
+ case X86::BI__builtin_ia32_insertf64x2_512:
+ case X86::BI__builtin_ia32_inserti64x2_512:
+ case X86::BI__builtin_ia32_insertf32x4:
+ case X86::BI__builtin_ia32_inserti32x4:
i = 2; l = 0; u = 3;
break;
case X86::BI__builtin_ia32_vpermil2pd:
@@ -2325,14 +3513,29 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_vpcomw:
case X86::BI__builtin_ia32_vpcomd:
case X86::BI__builtin_ia32_vpcomq:
+ case X86::BI__builtin_ia32_vec_set_v8hi:
+ case X86::BI__builtin_ia32_vec_set_v8si:
i = 2; l = 0; u = 7;
break;
+ case X86::BI__builtin_ia32_vpermilpd256:
case X86::BI__builtin_ia32_roundps:
case X86::BI__builtin_ia32_roundpd:
case X86::BI__builtin_ia32_roundps256:
case X86::BI__builtin_ia32_roundpd256:
+ case X86::BI__builtin_ia32_getmantpd128_mask:
+ case X86::BI__builtin_ia32_getmantpd256_mask:
+ case X86::BI__builtin_ia32_getmantps128_mask:
+ case X86::BI__builtin_ia32_getmantps256_mask:
+ case X86::BI__builtin_ia32_getmantpd512_mask:
+ case X86::BI__builtin_ia32_getmantps512_mask:
+ case X86::BI__builtin_ia32_vec_ext_v16qi:
+ case X86::BI__builtin_ia32_vec_ext_v16hi:
i = 1; l = 0; u = 15;
break;
+ case X86::BI__builtin_ia32_pblendd128:
+ case X86::BI__builtin_ia32_blendps:
+ case X86::BI__builtin_ia32_blendpd256:
+ case X86::BI__builtin_ia32_shufpd256:
case X86::BI__builtin_ia32_roundss:
case X86::BI__builtin_ia32_roundsd:
case X86::BI__builtin_ia32_rangepd128_mask:
@@ -2343,8 +3546,13 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_rangeps512_mask:
case X86::BI__builtin_ia32_getmantsd_round_mask:
case X86::BI__builtin_ia32_getmantss_round_mask:
+ case X86::BI__builtin_ia32_vec_set_v16qi:
+ case X86::BI__builtin_ia32_vec_set_v16hi:
i = 2; l = 0; u = 15;
break;
+ case X86::BI__builtin_ia32_vec_ext_v32qi:
+ i = 1; l = 0; u = 31;
+ break;
case X86::BI__builtin_ia32_cmpps:
case X86::BI__builtin_ia32_cmpss:
case X86::BI__builtin_ia32_cmppd:
@@ -2359,15 +3567,26 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_cmppd512_mask:
case X86::BI__builtin_ia32_cmpsd_mask:
case X86::BI__builtin_ia32_cmpss_mask:
+ case X86::BI__builtin_ia32_vec_set_v32qi:
i = 2; l = 0; u = 31;
break;
- case X86::BI__builtin_ia32_xabort:
- i = 0; l = -128; u = 255;
- break;
- case X86::BI__builtin_ia32_pshufw:
- case X86::BI__builtin_ia32_aeskeygenassist128:
- i = 1; l = -128; u = 255;
- break;
+ case X86::BI__builtin_ia32_permdf256:
+ case X86::BI__builtin_ia32_permdi256:
+ case X86::BI__builtin_ia32_permdf512:
+ case X86::BI__builtin_ia32_permdi512:
+ case X86::BI__builtin_ia32_vpermilps:
+ case X86::BI__builtin_ia32_vpermilps256:
+ case X86::BI__builtin_ia32_vpermilpd512:
+ case X86::BI__builtin_ia32_vpermilps512:
+ case X86::BI__builtin_ia32_pshufd:
+ case X86::BI__builtin_ia32_pshufd256:
+ case X86::BI__builtin_ia32_pshufd512:
+ case X86::BI__builtin_ia32_pshufhw:
+ case X86::BI__builtin_ia32_pshufhw256:
+ case X86::BI__builtin_ia32_pshufhw512:
+ case X86::BI__builtin_ia32_pshuflw:
+ case X86::BI__builtin_ia32_pshuflw256:
+ case X86::BI__builtin_ia32_pshuflw512:
case X86::BI__builtin_ia32_vcvtps2ph:
case X86::BI__builtin_ia32_vcvtps2ph_mask:
case X86::BI__builtin_ia32_vcvtps2ph256:
@@ -2385,16 +3604,18 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_reduceps128_mask:
case X86::BI__builtin_ia32_reduceps256_mask:
case X86::BI__builtin_ia32_reduceps512_mask:
- case X86::BI__builtin_ia32_prold512_mask:
- case X86::BI__builtin_ia32_prolq512_mask:
- case X86::BI__builtin_ia32_prold128_mask:
- case X86::BI__builtin_ia32_prold256_mask:
- case X86::BI__builtin_ia32_prolq128_mask:
- case X86::BI__builtin_ia32_prolq256_mask:
- case X86::BI__builtin_ia32_prord128_mask:
- case X86::BI__builtin_ia32_prord256_mask:
- case X86::BI__builtin_ia32_prorq128_mask:
- case X86::BI__builtin_ia32_prorq256_mask:
+ case X86::BI__builtin_ia32_prold512:
+ case X86::BI__builtin_ia32_prolq512:
+ case X86::BI__builtin_ia32_prold128:
+ case X86::BI__builtin_ia32_prold256:
+ case X86::BI__builtin_ia32_prolq128:
+ case X86::BI__builtin_ia32_prolq256:
+ case X86::BI__builtin_ia32_prord512:
+ case X86::BI__builtin_ia32_prorq512:
+ case X86::BI__builtin_ia32_prord128:
+ case X86::BI__builtin_ia32_prord256:
+ case X86::BI__builtin_ia32_prorq128:
+ case X86::BI__builtin_ia32_prorq256:
case X86::BI__builtin_ia32_fpclasspd128_mask:
case X86::BI__builtin_ia32_fpclasspd256_mask:
case X86::BI__builtin_ia32_fpclassps128_mask:
@@ -2403,41 +3624,62 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_fpclasspd512_mask:
case X86::BI__builtin_ia32_fpclasssd_mask:
case X86::BI__builtin_ia32_fpclassss_mask:
+ case X86::BI__builtin_ia32_pslldqi128_byteshift:
+ case X86::BI__builtin_ia32_pslldqi256_byteshift:
+ case X86::BI__builtin_ia32_pslldqi512_byteshift:
+ case X86::BI__builtin_ia32_psrldqi128_byteshift:
+ case X86::BI__builtin_ia32_psrldqi256_byteshift:
+ case X86::BI__builtin_ia32_psrldqi512_byteshift:
i = 1; l = 0; u = 255;
break;
- case X86::BI__builtin_ia32_palignr:
- case X86::BI__builtin_ia32_insertps128:
- case X86::BI__builtin_ia32_dpps:
- case X86::BI__builtin_ia32_dppd:
- case X86::BI__builtin_ia32_dpps256:
- case X86::BI__builtin_ia32_mpsadbw128:
- case X86::BI__builtin_ia32_mpsadbw256:
- case X86::BI__builtin_ia32_pcmpistrm128:
- case X86::BI__builtin_ia32_pcmpistri128:
- case X86::BI__builtin_ia32_pcmpistria128:
- case X86::BI__builtin_ia32_pcmpistric128:
- case X86::BI__builtin_ia32_pcmpistrio128:
- case X86::BI__builtin_ia32_pcmpistris128:
- case X86::BI__builtin_ia32_pcmpistriz128:
- case X86::BI__builtin_ia32_pclmulqdq128:
case X86::BI__builtin_ia32_vperm2f128_pd256:
case X86::BI__builtin_ia32_vperm2f128_ps256:
case X86::BI__builtin_ia32_vperm2f128_si256:
case X86::BI__builtin_ia32_permti256:
- i = 2; l = -128; u = 255;
- break;
+ case X86::BI__builtin_ia32_pblendw128:
+ case X86::BI__builtin_ia32_pblendw256:
+ case X86::BI__builtin_ia32_blendps256:
+ case X86::BI__builtin_ia32_pblendd256:
case X86::BI__builtin_ia32_palignr128:
case X86::BI__builtin_ia32_palignr256:
- case X86::BI__builtin_ia32_palignr512_mask:
+ case X86::BI__builtin_ia32_palignr512:
+ case X86::BI__builtin_ia32_alignq512:
+ case X86::BI__builtin_ia32_alignd512:
+ case X86::BI__builtin_ia32_alignd128:
+ case X86::BI__builtin_ia32_alignd256:
+ case X86::BI__builtin_ia32_alignq128:
+ case X86::BI__builtin_ia32_alignq256:
case X86::BI__builtin_ia32_vcomisd:
case X86::BI__builtin_ia32_vcomiss:
- case X86::BI__builtin_ia32_shuf_f32x4_mask:
- case X86::BI__builtin_ia32_shuf_f64x2_mask:
- case X86::BI__builtin_ia32_shuf_i32x4_mask:
- case X86::BI__builtin_ia32_shuf_i64x2_mask:
- case X86::BI__builtin_ia32_dbpsadbw128_mask:
- case X86::BI__builtin_ia32_dbpsadbw256_mask:
- case X86::BI__builtin_ia32_dbpsadbw512_mask:
+ case X86::BI__builtin_ia32_shuf_f32x4:
+ case X86::BI__builtin_ia32_shuf_f64x2:
+ case X86::BI__builtin_ia32_shuf_i32x4:
+ case X86::BI__builtin_ia32_shuf_i64x2:
+ case X86::BI__builtin_ia32_shufpd512:
+ case X86::BI__builtin_ia32_shufps:
+ case X86::BI__builtin_ia32_shufps256:
+ case X86::BI__builtin_ia32_shufps512:
+ case X86::BI__builtin_ia32_dbpsadbw128:
+ case X86::BI__builtin_ia32_dbpsadbw256:
+ case X86::BI__builtin_ia32_dbpsadbw512:
+ case X86::BI__builtin_ia32_vpshldd128:
+ case X86::BI__builtin_ia32_vpshldd256:
+ case X86::BI__builtin_ia32_vpshldd512:
+ case X86::BI__builtin_ia32_vpshldq128:
+ case X86::BI__builtin_ia32_vpshldq256:
+ case X86::BI__builtin_ia32_vpshldq512:
+ case X86::BI__builtin_ia32_vpshldw128:
+ case X86::BI__builtin_ia32_vpshldw256:
+ case X86::BI__builtin_ia32_vpshldw512:
+ case X86::BI__builtin_ia32_vpshrdd128:
+ case X86::BI__builtin_ia32_vpshrdd256:
+ case X86::BI__builtin_ia32_vpshrdd512:
+ case X86::BI__builtin_ia32_vpshrdq128:
+ case X86::BI__builtin_ia32_vpshrdq256:
+ case X86::BI__builtin_ia32_vpshrdq512:
+ case X86::BI__builtin_ia32_vpshrdw128:
+ case X86::BI__builtin_ia32_vpshrdw256:
+ case X86::BI__builtin_ia32_vpshrdw512:
i = 2; l = 0; u = 255;
break;
case X86::BI__builtin_ia32_fixupimmpd512_mask:
@@ -2480,21 +3722,17 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_scatterpfqps:
i = 4; l = 2; u = 3;
break;
- case X86::BI__builtin_ia32_pcmpestrm128:
- case X86::BI__builtin_ia32_pcmpestri128:
- case X86::BI__builtin_ia32_pcmpestria128:
- case X86::BI__builtin_ia32_pcmpestric128:
- case X86::BI__builtin_ia32_pcmpestrio128:
- case X86::BI__builtin_ia32_pcmpestris128:
- case X86::BI__builtin_ia32_pcmpestriz128:
- i = 4; l = -128; u = 255;
- break;
case X86::BI__builtin_ia32_rndscalesd_round_mask:
case X86::BI__builtin_ia32_rndscaless_round_mask:
i = 4; l = 0; u = 255;
break;
}
- return SemaBuiltinConstantArgRange(TheCall, i, l, u);
+
+ // Note that we don't force a hard error on the range check here, allowing
+ // template-generated or macro-generated dead code to potentially have out-of-
+ // range values. These need to code generate, but don't need to necessarily
+ // make any sense. We use a warning that defaults to an error.
+ return SemaBuiltinConstantArgRange(TheCall, i, l, u, /*RangeIsError*/ false);
}
/// Given a FunctionDecl's FormatAttr, attempts to populate the FomatStringInfo
@@ -2522,7 +3760,7 @@ bool Sema::getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
/// Checks if a the given expression evaluates to null.
///
-/// \brief Returns true if the value evaluates to null.
+/// Returns true if the value evaluates to null.
static bool CheckNonNullExpr(Sema &S, const Expr *Expr) {
// If the expression has non-null type, it doesn't evaluate to null.
if (auto nullability
@@ -2566,7 +3804,7 @@ bool Sema::GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx) {
return false;
}
-/// \brief Diagnose use of %s directive in an NSString which is being passed
+/// Diagnose use of %s directive in an NSString which is being passed
/// as formatting string to formatting method.
static void
DiagnoseCStringFormatDirectiveInCFAPI(Sema &S,
@@ -2636,12 +3874,13 @@ static void CheckNonNullArguments(Sema &S,
return;
}
- for (unsigned Val : NonNull->args()) {
- if (Val >= Args.size())
+ for (const ParamIdx &Idx : NonNull->args()) {
+ unsigned IdxAST = Idx.getASTIndex();
+ if (IdxAST >= Args.size())
continue;
if (NonNullArgs.empty())
NonNullArgs.resize(Args.size());
- NonNullArgs.set(Val);
+ NonNullArgs.set(IdxAST);
}
}
}
@@ -2985,6 +4224,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
Op == AtomicExpr::AO__atomic_exchange_n ||
Op == AtomicExpr::AO__atomic_compare_exchange_n;
bool IsAddSub = false;
+ bool IsMinMax = false;
switch (Op) {
case AtomicExpr::AO__c11_atomic_init:
@@ -3038,6 +4278,12 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
Form = Arithmetic;
break;
+ case AtomicExpr::AO__atomic_fetch_min:
+ case AtomicExpr::AO__atomic_fetch_max:
+ IsMinMax = true;
+ Form = Arithmetic;
+ break;
+
case AtomicExpr::AO__c11_atomic_exchange:
case AtomicExpr::AO__opencl_atomic_exchange:
case AtomicExpr::AO__atomic_exchange_n:
@@ -3120,12 +4366,21 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
// For an arithmetic operation, the implied arithmetic must be well-formed.
if (Form == Arithmetic) {
// gcc does not enforce these rules for GNU atomics, but we do so for sanity.
- if (IsAddSub && !ValType->isIntegerType() && !ValType->isPointerType()) {
+ if (IsAddSub && !ValType->isIntegerType()
+ && !ValType->isPointerType()) {
Diag(DRE->getLocStart(), diag::err_atomic_op_needs_atomic_int_or_ptr)
<< IsC11 << Ptr->getType() << Ptr->getSourceRange();
return ExprError();
}
- if (!IsAddSub && !ValType->isIntegerType()) {
+ 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);
+ return ExprError();
+ }
+ }
+ if (!IsAddSub && !IsMinMax && !ValType->isIntegerType()) {
Diag(DRE->getLocStart(), diag::err_atomic_op_bitwise_needs_atomic_int)
<< IsC11 << Ptr->getType() << Ptr->getSourceRange();
return ExprError();
@@ -3168,9 +4423,10 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
return ExprError();
}
- // atomic_fetch_or takes a pointer to a volatile 'A'. We shouldn't let the
- // volatile-ness of the pointee-type inject itself into the result or the
- // other operands. Similarly atomic_load can take a pointer to a const 'A'.
+ // All atomic operations have an overload which takes a pointer to a volatile
+ // 'A'. We shouldn't let the volatile-ness of the pointee-type inject itself
+ // into the result or the other operands. Similarly atomic_load takes a
+ // pointer to a const 'A'.
ValType.removeLocalVolatile();
ValType.removeLocalConst();
QualType ResultType = ValType;
@@ -3183,16 +4439,27 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
// The type of a parameter passed 'by value'. In the GNU atomics, such
// arguments are actually passed as pointers.
QualType ByValType = ValType; // 'CP'
- if (!IsC11 && !IsN)
+ bool IsPassedByAddress = false;
+ if (!IsC11 && !IsN) {
ByValType = Ptr->getType();
+ IsPassedByAddress = true;
+ }
- // The first argument --- the pointer --- has a fixed type; we
- // deduce the types of the rest of the arguments accordingly. Walk
- // the remaining arguments, converting them to the deduced value type.
- for (unsigned i = 1; i != TheCall->getNumArgs(); ++i) {
+ // The first argument's non-CV pointer type is used to deduce the type of
+ // subsequent arguments, except for:
+ // - weak flag (always converted to bool)
+ // - memory order (always converted to int)
+ // - scope (always converted to int)
+ for (unsigned i = 0; i != TheCall->getNumArgs(); ++i) {
QualType Ty;
if (i < NumVals[Form] + 1) {
switch (i) {
+ 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());
+ // Nothing else to do: we already know all we want about this pointer.
+ continue;
case 1:
// The second argument is the non-atomic operand. For arithmetic, this
// is always passed by value, and for a compare_exchange it is always
@@ -3201,14 +4468,16 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
assert(Form != Load);
if (Form == Init || (Form == Arithmetic && ValType->isIntegerType()))
Ty = ValType;
- else if (Form == Copy || Form == Xchg)
+ 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());
Ty = ByValType;
- else if (Form == Arithmetic)
+ } else if (Form == Arithmetic)
Ty = Context.getPointerDiffType();
else {
Expr *ValArg = TheCall->getArg(i);
- // Treat this argument as _Nonnull as we want to show a warning if
- // NULL is passed into it.
+ // The value pointer is always dereferenced, a nullptr is undefined.
CheckNonNullArgument(*this, ValArg, DRE->getLocStart());
LangAS AS = LangAS::Default;
// Keep address space of non-atomic pointer type.
@@ -3221,8 +4490,10 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
}
break;
case 2:
- // The third argument to compare_exchange / GNU exchange is a
- // (pointer to a) desired value.
+ // 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());
Ty = ByValType;
break;
case 3:
@@ -3393,6 +4664,12 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
return ExprError();
}
+ if (ValType.isConstQualified()) {
+ Diag(DRE->getLocStart(), diag::err_atomic_builtin_cannot_be_const)
+ << FirstArg->getType() << FirstArg->getSourceRange();
+ return ExprError();
+ }
+
switch (ValType.getObjCLifetime()) {
case Qualifiers::OCL_None:
case Qualifiers::OCL_ExplicitNone:
@@ -3598,7 +4875,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
ResultType = Context.BoolTy;
break;
- case Builtin::BI__sync_lock_test_and_set:
+ case Builtin::BI__sync_lock_test_and_set:
case Builtin::BI__sync_lock_test_and_set_1:
case Builtin::BI__sync_lock_test_and_set_2:
case Builtin::BI__sync_lock_test_and_set_4:
@@ -4115,15 +5392,19 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) {
diag::err_typecheck_call_invalid_unary_fp)
<< OrigArg->getType() << OrigArg->getSourceRange();
- // If this is an implicit conversion from float -> float or double, remove it.
+ // If this is an implicit conversion from float -> float, double, or
+ // long double, remove it.
if (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(OrigArg)) {
// Only remove standard FloatCasts, leaving other casts inplace
if (Cast->getCastKind() == CK_FloatingCast) {
Expr *CastArg = Cast->getSubExpr();
if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Float)) {
- assert((Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) ||
- Cast->getType()->isSpecificBuiltinType(BuiltinType::Float)) &&
- "promotion from float to either float or double is the only expected cast here");
+ assert(
+ (Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) ||
+ Cast->getType()->isSpecificBuiltinType(BuiltinType::Float) ||
+ Cast->getType()->isSpecificBuiltinType(BuiltinType::LongDouble)) &&
+ "promotion from float to either float, double, or long double is "
+ "the only expected cast here");
Cast->setSubExpr(nullptr);
TheCall->setArg(NumArgs-1, CastArg);
}
@@ -4519,7 +5800,7 @@ bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum,
/// SemaBuiltinConstantArgRange - Handle a check if argument ArgNum of CallExpr
/// TheCall is a constant expression in the range [Low, High].
bool Sema::SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum,
- int Low, int High) {
+ int Low, int High, bool RangeIsError) {
llvm::APSInt Result;
// We can't check the value of a dependent argument.
@@ -4531,9 +5812,18 @@ bool Sema::SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum,
if (SemaBuiltinConstantArg(TheCall, ArgNum, Result))
return true;
- if (Result.getSExtValue() < Low || Result.getSExtValue() > High)
- return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
- << Low << High << Arg->getSourceRange();
+ if (Result.getSExtValue() < Low || Result.getSExtValue() > High) {
+ if (RangeIsError)
+ return Diag(TheCall->getLocStart(), 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());
+ }
return false;
}
@@ -5018,18 +6308,22 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
case Stmt::CXXMemberCallExprClass: {
const CallExpr *CE = cast<CallExpr>(E);
if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl())) {
- if (const FormatArgAttr *FA = ND->getAttr<FormatArgAttr>()) {
- unsigned ArgIndex = FA->getFormatIdx();
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND))
- if (MD->isInstance())
- --ArgIndex;
- const Expr *Arg = CE->getArg(ArgIndex - 1);
-
- return checkFormatStringExpr(S, Arg, Args,
- HasVAListArg, format_idx, firstDataArg,
- Type, CallType, InFunctionCall,
- CheckedVarArgs, UncoveredArg, Offset);
- } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
+ bool IsFirst = true;
+ StringLiteralCheckType CommonResult;
+ for (const auto *FA : ND->specific_attrs<FormatArgAttr>()) {
+ const Expr *Arg = CE->getArg(FA->getFormatIdx().getASTIndex());
+ StringLiteralCheckType Result = checkFormatStringExpr(
+ S, Arg, Args, HasVAListArg, format_idx, firstDataArg, Type,
+ CallType, InFunctionCall, CheckedVarArgs, UncoveredArg, Offset);
+ if (IsFirst) {
+ CommonResult = Result;
+ IsFirst = false;
+ }
+ }
+ if (!IsFirst)
+ return CommonResult;
+
+ if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
unsigned BuiltinID = FD->getBuiltinID();
if (BuiltinID == Builtin::BI__builtin___CFStringMakeConstantString ||
BuiltinID == Builtin::BI__builtin___NSStringMakeConstantString) {
@@ -5049,8 +6343,7 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
const auto *ME = cast<ObjCMessageExpr>(E);
if (const auto *ND = ME->getMethodDecl()) {
if (const auto *FA = ND->getAttr<FormatArgAttr>()) {
- unsigned ArgIndex = FA->getFormatIdx();
- const Expr *Arg = ME->getArg(ArgIndex - 1);
+ const Expr *Arg = ME->getArg(FA->getFormatIdx().getASTIndex());
return checkFormatStringExpr(
S, Arg, Args, HasVAListArg, format_idx, firstDataArg, Type,
CallType, InFunctionCall, CheckedVarArgs, UncoveredArg, Offset);
@@ -5654,7 +6947,7 @@ void CheckFormatHandler::EmitFormatDiagnostic(PartialDiagnostic PDiag,
Loc, IsStringLocation, StringRange, FixIt);
}
-/// \brief If the format string is not within the funcion call, emit a note
+/// If the format string is not within the function call, emit a note
/// so that the function call and string are in diagnostic messages.
///
/// \param InFunctionCall if true, the format string is within the function
@@ -6311,11 +7604,11 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
ExprTy = TET->getUnderlyingExpr()->getType();
}
- analyze_printf::ArgType::MatchKind match = AT.matchesType(S.Context, ExprTy);
-
- if (match == analyze_printf::ArgType::Match) {
+ const analyze_printf::ArgType::MatchKind Match =
+ AT.matchesType(S.Context, ExprTy);
+ bool Pedantic = Match == analyze_printf::ArgType::NoMatchPedantic;
+ if (Match == analyze_printf::ArgType::Match)
return true;
- }
// Look through argument promotions for our error message's reported type.
// This includes the integral and floating promotions, but excludes array
@@ -6391,6 +7684,12 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
QualType CastTy;
std::tie(CastTy, CastTyName) = shouldNotPrintDirectly(S.Context, IntendedTy, E);
if (!CastTy.isNull()) {
+ // %zi/%zu and %td/%tu are OK to use for NSInteger/NSUInteger of type int
+ // (long in ASTContext). Only complain to pedants.
+ if ((CastTyName == "NSInteger" || CastTyName == "NSUInteger") &&
+ (AT.isSizeT() || AT.isPtrdiffT()) &&
+ AT.matchesType(S.Context, CastTy))
+ Pedantic = true;
IntendedTy = CastTy;
ShouldNotPrintDirectly = true;
}
@@ -6398,10 +7697,10 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
// We may be able to offer a FixItHint if it is a supported type.
PrintfSpecifier fixedFS = FS;
- bool success =
+ bool Success =
fixedFS.fixType(IntendedTy, S.getLangOpts(), S.Context, isObjCContext());
- if (success) {
+ if (Success) {
// Get the fix string from the fixed format specifier
SmallString<16> buf;
llvm::raw_svector_ostream os(buf);
@@ -6410,13 +7709,13 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
CharSourceRange SpecRange = getSpecifierRange(StartSpecifier, SpecifierLen);
if (IntendedTy == ExprTy && !ShouldNotPrintDirectly) {
- unsigned diag = diag::warn_format_conversion_argument_type_mismatch;
- if (match == analyze_format_string::ArgType::NoMatchPedantic) {
- diag = diag::warn_format_conversion_argument_type_mismatch_pedantic;
- }
+ unsigned Diag =
+ Pedantic
+ ? diag::warn_format_conversion_argument_type_mismatch_pedantic
+ : diag::warn_format_conversion_argument_type_mismatch;
// In this case, the specifier is wrong and should be changed to match
// the argument.
- EmitFormatDiagnostic(S.PDiag(diag)
+ EmitFormatDiagnostic(S.PDiag(Diag)
<< AT.getRepresentativeTypeName(S.Context)
<< IntendedTy << IsEnum << E->getSourceRange(),
E->getLocStart(),
@@ -6469,9 +7768,11 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
Name = TypedefTy->getDecl()->getName();
else
Name = CastTyName;
- EmitFormatDiagnostic(S.PDiag(diag::warn_format_argument_needs_cast)
- << Name << IntendedTy << IsEnum
- << E->getSourceRange(),
+ unsigned Diag = Pedantic
+ ? diag::warn_format_argument_needs_cast_pedantic
+ : diag::warn_format_argument_needs_cast;
+ EmitFormatDiagnostic(S.PDiag(Diag) << Name << IntendedTy << IsEnum
+ << E->getSourceRange(),
E->getLocStart(), /*IsStringLocation=*/false,
SpecRange, Hints);
} else {
@@ -6495,13 +7796,13 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
switch (S.isValidVarArgType(ExprTy)) {
case Sema::VAK_Valid:
case Sema::VAK_ValidInCXX11: {
- unsigned diag = diag::warn_format_conversion_argument_type_mismatch;
- if (match == analyze_printf::ArgType::NoMatchPedantic) {
- diag = diag::warn_format_conversion_argument_type_mismatch_pedantic;
- }
+ unsigned Diag =
+ Pedantic
+ ? diag::warn_format_conversion_argument_type_mismatch_pedantic
+ : diag::warn_format_conversion_argument_type_mismatch;
EmitFormatDiagnostic(
- S.PDiag(diag) << AT.getRepresentativeTypeName(S.Context) << ExprTy
+ S.PDiag(Diag) << AT.getRepresentativeTypeName(S.Context) << ExprTy
<< IsEnum << CSR << E->getSourceRange(),
E->getLocStart(), /*IsStringLocation*/ false, CSR);
break;
@@ -6684,29 +7985,28 @@ bool CheckScanfHandler::HandleScanfSpecifier(
return true;
}
- analyze_format_string::ArgType::MatchKind match =
+ analyze_format_string::ArgType::MatchKind Match =
AT.matchesType(S.Context, Ex->getType());
- if (match == analyze_format_string::ArgType::Match) {
+ bool Pedantic = Match == analyze_format_string::ArgType::NoMatchPedantic;
+ if (Match == analyze_format_string::ArgType::Match)
return true;
- }
ScanfSpecifier fixedFS = FS;
- bool success = fixedFS.fixType(Ex->getType(), Ex->IgnoreImpCasts()->getType(),
+ bool Success = fixedFS.fixType(Ex->getType(), Ex->IgnoreImpCasts()->getType(),
S.getLangOpts(), S.Context);
- unsigned diag = diag::warn_format_conversion_argument_type_mismatch;
- if (match == analyze_format_string::ArgType::NoMatchPedantic) {
- diag = diag::warn_format_conversion_argument_type_mismatch_pedantic;
- }
+ unsigned Diag =
+ Pedantic ? diag::warn_format_conversion_argument_type_mismatch_pedantic
+ : diag::warn_format_conversion_argument_type_mismatch;
- if (success) {
+ if (Success) {
// Get the fix string from the fixed format specifier.
SmallString<128> buf;
llvm::raw_svector_ostream os(buf);
fixedFS.toString(os);
EmitFormatDiagnostic(
- S.PDiag(diag) << AT.getRepresentativeTypeName(S.Context)
+ S.PDiag(Diag) << AT.getRepresentativeTypeName(S.Context)
<< Ex->getType() << false << Ex->getSourceRange(),
Ex->getLocStart(),
/*IsStringLocation*/ false,
@@ -6714,7 +8014,7 @@ bool CheckScanfHandler::HandleScanfSpecifier(
FixItHint::CreateReplacement(
getSpecifierRange(startSpecifier, specifierLen), os.str()));
} else {
- EmitFormatDiagnostic(S.PDiag(diag)
+ EmitFormatDiagnostic(S.PDiag(Diag)
<< AT.getRepresentativeTypeName(S.Context)
<< Ex->getType() << false << Ex->getSourceRange(),
Ex->getLocStart(),
@@ -7267,7 +8567,7 @@ void Sema::CheckMaxUnsignedZero(const CallExpr *Call,
//===--- CHECK: Standard memory functions ---------------------------------===//
-/// \brief Takes the expression passed to the size_t parameter of functions
+/// Takes the expression passed to the size_t parameter of functions
/// such as memcmp, strncat, etc and warns if it's a comparison.
///
/// This is to catch typos like `if (memcmp(&a, &b, sizeof(a) > 0))`.
@@ -7298,7 +8598,7 @@ static bool CheckMemorySizeofForComparison(Sema &S, const Expr *E,
return true;
}
-/// \brief Determine whether the given type is or contains a dynamic class type
+/// Determine whether the given type is or contains a dynamic class type
/// (e.g., whether it has a vtable).
static const CXXRecordDecl *getContainedDynamicClass(QualType T,
bool &IsContained) {
@@ -7329,28 +8629,205 @@ static const CXXRecordDecl *getContainedDynamicClass(QualType T,
return nullptr;
}
-/// \brief If E is a sizeof expression, returns its argument expression,
+static const UnaryExprOrTypeTraitExpr *getAsSizeOfExpr(const Expr *E) {
+ if (const auto *Unary = dyn_cast<UnaryExprOrTypeTraitExpr>(E))
+ if (Unary->getKind() == UETT_SizeOf)
+ return Unary;
+ return nullptr;
+}
+
+/// If E is a sizeof expression, returns its argument expression,
/// otherwise returns NULL.
static const Expr *getSizeOfExprArg(const Expr *E) {
- if (const UnaryExprOrTypeTraitExpr *SizeOf =
- dyn_cast<UnaryExprOrTypeTraitExpr>(E))
- if (SizeOf->getKind() == UETT_SizeOf && !SizeOf->isArgumentType())
+ if (const UnaryExprOrTypeTraitExpr *SizeOf = getAsSizeOfExpr(E))
+ if (!SizeOf->isArgumentType())
return SizeOf->getArgumentExpr()->IgnoreParenImpCasts();
-
return nullptr;
}
-/// \brief If E is a sizeof expression, returns its argument type.
+/// If E is a sizeof expression, returns its argument type.
static QualType getSizeOfArgType(const Expr *E) {
- if (const UnaryExprOrTypeTraitExpr *SizeOf =
- dyn_cast<UnaryExprOrTypeTraitExpr>(E))
- if (SizeOf->getKind() == UETT_SizeOf)
- return SizeOf->getTypeOfArgument();
-
+ if (const UnaryExprOrTypeTraitExpr *SizeOf = getAsSizeOfExpr(E))
+ return SizeOf->getTypeOfArgument();
return QualType();
}
-/// \brief Check for dangerous or invalid arguments to memset().
+namespace {
+
+struct SearchNonTrivialToInitializeField
+ : DefaultInitializedTypeVisitor<SearchNonTrivialToInitializeField> {
+ using Super =
+ DefaultInitializedTypeVisitor<SearchNonTrivialToInitializeField>;
+
+ SearchNonTrivialToInitializeField(const Expr *E, Sema &S) : E(E), S(S) {}
+
+ void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
+ SourceLocation SL) {
+ if (const auto *AT = asDerived().getContext().getAsArrayType(FT)) {
+ asDerived().visitArray(PDIK, AT, SL);
+ return;
+ }
+
+ Super::visitWithKind(PDIK, FT, SL);
+ }
+
+ void visitARCStrong(QualType FT, SourceLocation SL) {
+ S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 1);
+ }
+ void visitARCWeak(QualType FT, SourceLocation SL) {
+ S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 1);
+ }
+ void visitStruct(QualType FT, SourceLocation SL) {
+ for (const FieldDecl *FD : FT->castAs<RecordType>()->getDecl()->fields())
+ visit(FD->getType(), FD->getLocation());
+ }
+ void visitArray(QualType::PrimitiveDefaultInitializeKind PDIK,
+ const ArrayType *AT, SourceLocation SL) {
+ visit(getContext().getBaseElementType(AT), SL);
+ }
+ void visitTrivial(QualType FT, SourceLocation SL) {}
+
+ static void diag(QualType RT, const Expr *E, Sema &S) {
+ SearchNonTrivialToInitializeField(E, S).visitStruct(RT, SourceLocation());
+ }
+
+ ASTContext &getContext() { return S.getASTContext(); }
+
+ const Expr *E;
+ Sema &S;
+};
+
+struct SearchNonTrivialToCopyField
+ : CopiedTypeVisitor<SearchNonTrivialToCopyField, false> {
+ using Super = CopiedTypeVisitor<SearchNonTrivialToCopyField, false>;
+
+ SearchNonTrivialToCopyField(const Expr *E, Sema &S) : E(E), S(S) {}
+
+ void visitWithKind(QualType::PrimitiveCopyKind PCK, QualType FT,
+ SourceLocation SL) {
+ if (const auto *AT = asDerived().getContext().getAsArrayType(FT)) {
+ asDerived().visitArray(PCK, AT, SL);
+ return;
+ }
+
+ Super::visitWithKind(PCK, FT, SL);
+ }
+
+ void visitARCStrong(QualType FT, SourceLocation SL) {
+ S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 0);
+ }
+ void visitARCWeak(QualType FT, SourceLocation SL) {
+ S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 0);
+ }
+ void visitStruct(QualType FT, SourceLocation SL) {
+ for (const FieldDecl *FD : FT->castAs<RecordType>()->getDecl()->fields())
+ visit(FD->getType(), FD->getLocation());
+ }
+ void visitArray(QualType::PrimitiveCopyKind PCK, const ArrayType *AT,
+ SourceLocation SL) {
+ visit(getContext().getBaseElementType(AT), SL);
+ }
+ void preVisit(QualType::PrimitiveCopyKind PCK, QualType FT,
+ SourceLocation SL) {}
+ void visitTrivial(QualType FT, SourceLocation SL) {}
+ void visitVolatileTrivial(QualType FT, SourceLocation SL) {}
+
+ static void diag(QualType RT, const Expr *E, Sema &S) {
+ SearchNonTrivialToCopyField(E, S).visitStruct(RT, SourceLocation());
+ }
+
+ ASTContext &getContext() { return S.getASTContext(); }
+
+ const Expr *E;
+ Sema &S;
+};
+
+}
+
+/// Detect if \c SizeofExpr is likely to calculate the sizeof an object.
+static bool doesExprLikelyComputeSize(const Expr *SizeofExpr) {
+ SizeofExpr = SizeofExpr->IgnoreParenImpCasts();
+
+ if (const auto *BO = dyn_cast<BinaryOperator>(SizeofExpr)) {
+ if (BO->getOpcode() != BO_Mul && BO->getOpcode() != BO_Add)
+ return false;
+
+ return doesExprLikelyComputeSize(BO->getLHS()) ||
+ doesExprLikelyComputeSize(BO->getRHS());
+ }
+
+ return getAsSizeOfExpr(SizeofExpr) != nullptr;
+}
+
+/// Check if the ArgLoc originated from a macro passed to the call at CallLoc.
+///
+/// \code
+/// #define MACRO 0
+/// foo(MACRO);
+/// foo(0);
+/// \endcode
+///
+/// This should return true for the first call to foo, but not for the second
+/// (regardless of whether foo is a macro or function).
+static bool isArgumentExpandedFromMacro(SourceManager &SM,
+ SourceLocation CallLoc,
+ SourceLocation ArgLoc) {
+ if (!CallLoc.isMacroID())
+ return SM.getFileID(CallLoc) != SM.getFileID(ArgLoc);
+
+ return SM.getFileID(SM.getImmediateMacroCallerLoc(CallLoc)) !=
+ SM.getFileID(SM.getImmediateMacroCallerLoc(ArgLoc));
+}
+
+/// Diagnose cases like 'memset(buf, sizeof(buf), 0)', which should have the
+/// last two arguments transposed.
+static void CheckMemaccessSize(Sema &S, unsigned BId, const CallExpr *Call) {
+ if (BId != Builtin::BImemset && BId != Builtin::BIbzero)
+ return;
+
+ const Expr *SizeArg =
+ Call->getArg(BId == Builtin::BImemset ? 2 : 1)->IgnoreImpCasts();
+
+ auto isLiteralZero = [](const Expr *E) {
+ return isa<IntegerLiteral>(E) && cast<IntegerLiteral>(E)->getValue() == 0;
+ };
+
+ // If we're memsetting or bzeroing 0 bytes, then this is likely an error.
+ SourceLocation CallLoc = Call->getRParenLoc();
+ SourceManager &SM = S.getSourceManager();
+ if (isLiteralZero(SizeArg) &&
+ !isArgumentExpandedFromMacro(SM, CallLoc, SizeArg->getExprLoc())) {
+
+ SourceLocation DiagLoc = SizeArg->getExprLoc();
+
+ // Some platforms #define bzero to __builtin_memset. See if this is the
+ // case, and if so, emit a better diagnostic.
+ if (BId == Builtin::BIbzero ||
+ (CallLoc.isMacroID() && Lexer::getImmediateMacroName(
+ CallLoc, SM, S.getLangOpts()) == "bzero")) {
+ S.Diag(DiagLoc, diag::warn_suspicious_bzero_size);
+ S.Diag(DiagLoc, diag::note_suspicious_bzero_size_silence);
+ } else if (!isLiteralZero(Call->getArg(1)->IgnoreImpCasts())) {
+ S.Diag(DiagLoc, diag::warn_suspicious_sizeof_memset) << 0;
+ S.Diag(DiagLoc, diag::note_suspicious_sizeof_memset_silence) << 0;
+ }
+ return;
+ }
+
+ // If the second argument to a memset is a sizeof expression and the third
+ // isn't, this is also likely an error. This should catch
+ // 'memset(buf, sizeof(buf), 0xff)'.
+ if (BId == Builtin::BImemset &&
+ doesExprLikelyComputeSize(Call->getArg(1)) &&
+ !doesExprLikelyComputeSize(Call->getArg(2))) {
+ SourceLocation DiagLoc = Call->getArg(1)->getExprLoc();
+ S.Diag(DiagLoc, diag::warn_suspicious_sizeof_memset) << 1;
+ S.Diag(DiagLoc, diag::note_suspicious_sizeof_memset_silence) << 1;
+ return;
+ }
+}
+
+/// Check for dangerous or invalid arguments to memset().
///
/// This issues warnings on known problematic, dangerous or unspecified
/// arguments to the standard 'memset', 'memcpy', 'memmove', and 'memcmp'
@@ -7379,6 +8856,9 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
Call->getLocStart(), Call->getRParenLoc()))
return;
+ // Catch cases like 'memset(buf, sizeof(buf), 0)'.
+ CheckMemaccessSize(*this, BId, Call);
+
// We have special checking when the length is a sizeof expression.
QualType SizeOfArgTy = getSizeOfArgType(LenExpr);
const Expr *SizeOfArg = getSizeOfExprArg(LenExpr);
@@ -7515,7 +8995,23 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
PDiag(diag::warn_arc_object_memaccess)
<< ArgIdx << FnName << PointeeTy
<< Call->getCallee()->getSourceRange());
- else
+ else if (const auto *RT = PointeeTy->getAs<RecordType>()) {
+ if ((BId == Builtin::BImemset || BId == Builtin::BIbzero) &&
+ RT->getDecl()->isNonTrivialToPrimitiveDefaultInitialize()) {
+ DiagRuntimeBehavior(Dest->getExprLoc(), Dest,
+ PDiag(diag::warn_cstruct_memaccess)
+ << ArgIdx << FnName << PointeeTy << 0);
+ SearchNonTrivialToInitializeField::diag(PointeeTy, Dest, *this);
+ } else if ((BId == Builtin::BImemcpy || BId == Builtin::BImemmove) &&
+ RT->getDecl()->isNonTrivialToPrimitiveCopy()) {
+ DiagRuntimeBehavior(Dest->getExprLoc(), Dest,
+ PDiag(diag::warn_cstruct_memaccess)
+ << ArgIdx << FnName << PointeeTy << 1);
+ SearchNonTrivialToCopyField::diag(PointeeTy, Dest, *this);
+ } else {
+ continue;
+ }
+ } else
continue;
DiagRuntimeBehavior(
@@ -7736,421 +9232,12 @@ void Sema::CheckStrncatArguments(const CallExpr *CE,
<< FixItHint::CreateReplacement(SR, OS.str());
}
-//===--- CHECK: Return Address of Stack Variable --------------------------===//
-
-static const Expr *EvalVal(const Expr *E,
- SmallVectorImpl<const DeclRefExpr *> &refVars,
- const Decl *ParentDecl);
-static const Expr *EvalAddr(const Expr *E,
- SmallVectorImpl<const DeclRefExpr *> &refVars,
- const Decl *ParentDecl);
-
-/// CheckReturnStackAddr - Check if a return statement returns the address
-/// of a stack variable.
-static void
-CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType,
- SourceLocation ReturnLoc) {
- const Expr *stackE = nullptr;
- SmallVector<const DeclRefExpr *, 8> refVars;
-
- // Perform checking for returned stack addresses, local blocks,
- // label addresses or references to temporaries.
- if (lhsType->isPointerType() ||
- (!S.getLangOpts().ObjCAutoRefCount && lhsType->isBlockPointerType())) {
- stackE = EvalAddr(RetValExp, refVars, /*ParentDecl=*/nullptr);
- } else if (lhsType->isReferenceType()) {
- stackE = EvalVal(RetValExp, refVars, /*ParentDecl=*/nullptr);
- }
-
- if (!stackE)
- return; // Nothing suspicious was found.
-
- // Parameters are initialized in the calling scope, so taking the address
- // of a parameter reference doesn't need a warning.
- for (auto *DRE : refVars)
- if (isa<ParmVarDecl>(DRE->getDecl()))
- return;
-
- SourceLocation diagLoc;
- SourceRange diagRange;
- if (refVars.empty()) {
- diagLoc = stackE->getLocStart();
- diagRange = stackE->getSourceRange();
- } else {
- // We followed through a reference variable. 'stackE' contains the
- // problematic expression but we will warn at the return statement pointing
- // at the reference variable. We will later display the "trail" of
- // reference variables using notes.
- diagLoc = refVars[0]->getLocStart();
- diagRange = refVars[0]->getSourceRange();
- }
-
- if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(stackE)) {
- // address of local var
- S.Diag(diagLoc, diag::warn_ret_stack_addr_ref) << lhsType->isReferenceType()
- << DR->getDecl()->getDeclName() << diagRange;
- } else if (isa<BlockExpr>(stackE)) { // local block.
- S.Diag(diagLoc, diag::err_ret_local_block) << diagRange;
- } else if (isa<AddrLabelExpr>(stackE)) { // address of label.
- S.Diag(diagLoc, diag::warn_ret_addr_label) << diagRange;
- } else { // local temporary.
- // If there is an LValue->RValue conversion, then the value of the
- // reference type is used, not the reference.
- if (auto *ICE = dyn_cast<ImplicitCastExpr>(RetValExp)) {
- if (ICE->getCastKind() == CK_LValueToRValue) {
- return;
- }
- }
- S.Diag(diagLoc, diag::warn_ret_local_temp_addr_ref)
- << lhsType->isReferenceType() << diagRange;
- }
-
- // Display the "trail" of reference variables that we followed until we
- // found the problematic expression using notes.
- for (unsigned i = 0, e = refVars.size(); i != e; ++i) {
- const VarDecl *VD = cast<VarDecl>(refVars[i]->getDecl());
- // If this var binds to another reference var, show the range of the next
- // var, otherwise the var binds to the problematic expression, in which case
- // show the range of the expression.
- SourceRange range = (i < e - 1) ? refVars[i + 1]->getSourceRange()
- : stackE->getSourceRange();
- S.Diag(VD->getLocation(), diag::note_ref_var_local_bind)
- << VD->getDeclName() << range;
- }
-}
-
-/// EvalAddr - EvalAddr and EvalVal are mutually recursive functions that
-/// check if the expression in a return statement evaluates to an address
-/// to a location on the stack, a local block, an address of a label, or a
-/// reference to local temporary. The recursion is used to traverse the
-/// AST of the return expression, with recursion backtracking when we
-/// encounter a subexpression that (1) clearly does not lead to one of the
-/// above problematic expressions (2) is something we cannot determine leads to
-/// a problematic expression based on such local checking.
-///
-/// Both EvalAddr and EvalVal follow through reference variables to evaluate
-/// the expression that they point to. Such variables are added to the
-/// 'refVars' vector so that we know what the reference variable "trail" was.
-///
-/// EvalAddr processes expressions that are pointers that are used as
-/// references (and not L-values). EvalVal handles all other values.
-/// At the base case of the recursion is a check for the above problematic
-/// expressions.
-///
-/// This implementation handles:
-///
-/// * pointer-to-pointer casts
-/// * implicit conversions from array references to pointers
-/// * taking the address of fields
-/// * arbitrary interplay between "&" and "*" operators
-/// * pointer arithmetic from an address of a stack variable
-/// * taking the address of an array element where the array is on the stack
-static const Expr *EvalAddr(const Expr *E,
- SmallVectorImpl<const DeclRefExpr *> &refVars,
- const Decl *ParentDecl) {
- if (E->isTypeDependent())
- return nullptr;
-
- // We should only be called for evaluating pointer expressions.
- assert((E->getType()->isAnyPointerType() ||
- E->getType()->isBlockPointerType() ||
- E->getType()->isObjCQualifiedIdType()) &&
- "EvalAddr only works on pointers");
-
- E = E->IgnoreParens();
-
- // Our "symbolic interpreter" is just a dispatch off the currently
- // viewed AST node. We then recursively traverse the AST by calling
- // EvalAddr and EvalVal appropriately.
- switch (E->getStmtClass()) {
- case Stmt::DeclRefExprClass: {
- const DeclRefExpr *DR = cast<DeclRefExpr>(E);
-
- // If we leave the immediate function, the lifetime isn't about to end.
- if (DR->refersToEnclosingVariableOrCapture())
- return nullptr;
-
- if (const VarDecl *V = dyn_cast<VarDecl>(DR->getDecl()))
- // If this is a reference variable, follow through to the expression that
- // it points to.
- if (V->hasLocalStorage() &&
- V->getType()->isReferenceType() && V->hasInit()) {
- // Add the reference variable to the "trail".
- refVars.push_back(DR);
- return EvalAddr(V->getInit(), refVars, ParentDecl);
- }
-
- return nullptr;
- }
-
- case Stmt::UnaryOperatorClass: {
- // The only unary operator that make sense to handle here
- // is AddrOf. All others don't make sense as pointers.
- const UnaryOperator *U = cast<UnaryOperator>(E);
-
- if (U->getOpcode() == UO_AddrOf)
- return EvalVal(U->getSubExpr(), refVars, ParentDecl);
- return nullptr;
- }
-
- case Stmt::BinaryOperatorClass: {
- // Handle pointer arithmetic. All other binary operators are not valid
- // in this context.
- const BinaryOperator *B = cast<BinaryOperator>(E);
- BinaryOperatorKind op = B->getOpcode();
-
- if (op != BO_Add && op != BO_Sub)
- return nullptr;
-
- const Expr *Base = B->getLHS();
-
- // Determine which argument is the real pointer base. It could be
- // the RHS argument instead of the LHS.
- if (!Base->getType()->isPointerType())
- Base = B->getRHS();
-
- assert(Base->getType()->isPointerType());
- return EvalAddr(Base, refVars, ParentDecl);
- }
-
- // For conditional operators we need to see if either the LHS or RHS are
- // valid DeclRefExpr*s. If one of them is valid, we return it.
- case Stmt::ConditionalOperatorClass: {
- const ConditionalOperator *C = cast<ConditionalOperator>(E);
-
- // Handle the GNU extension for missing LHS.
- // FIXME: That isn't a ConditionalOperator, so doesn't get here.
- if (const Expr *LHSExpr = C->getLHS()) {
- // In C++, we can have a throw-expression, which has 'void' type.
- if (!LHSExpr->getType()->isVoidType())
- if (const Expr *LHS = EvalAddr(LHSExpr, refVars, ParentDecl))
- return LHS;
- }
-
- // In C++, we can have a throw-expression, which has 'void' type.
- if (C->getRHS()->getType()->isVoidType())
- return nullptr;
-
- return EvalAddr(C->getRHS(), refVars, ParentDecl);
- }
-
- case Stmt::BlockExprClass:
- if (cast<BlockExpr>(E)->getBlockDecl()->hasCaptures())
- return E; // local block.
- return nullptr;
-
- case Stmt::AddrLabelExprClass:
- return E; // address of label.
-
- case Stmt::ExprWithCleanupsClass:
- return EvalAddr(cast<ExprWithCleanups>(E)->getSubExpr(), refVars,
- ParentDecl);
-
- // For casts, we need to handle conversions from arrays to
- // pointer values, and pointer-to-pointer conversions.
- case Stmt::ImplicitCastExprClass:
- case Stmt::CStyleCastExprClass:
- case Stmt::CXXFunctionalCastExprClass:
- case Stmt::ObjCBridgedCastExprClass:
- case Stmt::CXXStaticCastExprClass:
- case Stmt::CXXDynamicCastExprClass:
- case Stmt::CXXConstCastExprClass:
- case Stmt::CXXReinterpretCastExprClass: {
- const Expr* SubExpr = cast<CastExpr>(E)->getSubExpr();
- switch (cast<CastExpr>(E)->getCastKind()) {
- case CK_LValueToRValue:
- case CK_NoOp:
- case CK_BaseToDerived:
- case CK_DerivedToBase:
- case CK_UncheckedDerivedToBase:
- case CK_Dynamic:
- case CK_CPointerToObjCPointerCast:
- case CK_BlockPointerToObjCPointerCast:
- case CK_AnyPointerToBlockPointerCast:
- return EvalAddr(SubExpr, refVars, ParentDecl);
-
- case CK_ArrayToPointerDecay:
- return EvalVal(SubExpr, refVars, ParentDecl);
-
- case CK_BitCast:
- if (SubExpr->getType()->isAnyPointerType() ||
- SubExpr->getType()->isBlockPointerType() ||
- SubExpr->getType()->isObjCQualifiedIdType())
- return EvalAddr(SubExpr, refVars, ParentDecl);
- else
- return nullptr;
-
- default:
- return nullptr;
- }
- }
-
- case Stmt::MaterializeTemporaryExprClass:
- if (const Expr *Result =
- EvalAddr(cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(),
- refVars, ParentDecl))
- return Result;
- return E;
-
- // Everything else: we simply don't reason about them.
- default:
- return nullptr;
- }
-}
-
-/// EvalVal - This function is complements EvalAddr in the mutual recursion.
-/// See the comments for EvalAddr for more details.
-static const Expr *EvalVal(const Expr *E,
- SmallVectorImpl<const DeclRefExpr *> &refVars,
- const Decl *ParentDecl) {
- do {
- // We should only be called for evaluating non-pointer expressions, or
- // expressions with a pointer type that are not used as references but
- // instead
- // are l-values (e.g., DeclRefExpr with a pointer type).
-
- // Our "symbolic interpreter" is just a dispatch off the currently
- // viewed AST node. We then recursively traverse the AST by calling
- // EvalAddr and EvalVal appropriately.
-
- E = E->IgnoreParens();
- switch (E->getStmtClass()) {
- case Stmt::ImplicitCastExprClass: {
- const ImplicitCastExpr *IE = cast<ImplicitCastExpr>(E);
- if (IE->getValueKind() == VK_LValue) {
- E = IE->getSubExpr();
- continue;
- }
- return nullptr;
- }
-
- case Stmt::ExprWithCleanupsClass:
- return EvalVal(cast<ExprWithCleanups>(E)->getSubExpr(), refVars,
- ParentDecl);
-
- case Stmt::DeclRefExprClass: {
- // When we hit a DeclRefExpr we are looking at code that refers to a
- // variable's name. If it's not a reference variable we check if it has
- // local storage within the function, and if so, return the expression.
- const DeclRefExpr *DR = cast<DeclRefExpr>(E);
-
- // If we leave the immediate function, the lifetime isn't about to end.
- if (DR->refersToEnclosingVariableOrCapture())
- return nullptr;
-
- if (const VarDecl *V = dyn_cast<VarDecl>(DR->getDecl())) {
- // Check if it refers to itself, e.g. "int& i = i;".
- if (V == ParentDecl)
- return DR;
-
- if (V->hasLocalStorage()) {
- if (!V->getType()->isReferenceType())
- return DR;
-
- // Reference variable, follow through to the expression that
- // it points to.
- if (V->hasInit()) {
- // Add the reference variable to the "trail".
- refVars.push_back(DR);
- return EvalVal(V->getInit(), refVars, V);
- }
- }
- }
-
- return nullptr;
- }
-
- case Stmt::UnaryOperatorClass: {
- // The only unary operator that make sense to handle here
- // is Deref. All others don't resolve to a "name." This includes
- // handling all sorts of rvalues passed to a unary operator.
- const UnaryOperator *U = cast<UnaryOperator>(E);
-
- if (U->getOpcode() == UO_Deref)
- return EvalAddr(U->getSubExpr(), refVars, ParentDecl);
-
- return nullptr;
- }
-
- case Stmt::ArraySubscriptExprClass: {
- // Array subscripts are potential references to data on the stack. We
- // retrieve the DeclRefExpr* for the array variable if it indeed
- // has local storage.
- const auto *ASE = cast<ArraySubscriptExpr>(E);
- if (ASE->isTypeDependent())
- return nullptr;
- return EvalAddr(ASE->getBase(), refVars, ParentDecl);
- }
-
- case Stmt::OMPArraySectionExprClass: {
- return EvalAddr(cast<OMPArraySectionExpr>(E)->getBase(), refVars,
- ParentDecl);
- }
-
- case Stmt::ConditionalOperatorClass: {
- // For conditional operators we need to see if either the LHS or RHS are
- // non-NULL Expr's. If one is non-NULL, we return it.
- const ConditionalOperator *C = cast<ConditionalOperator>(E);
-
- // Handle the GNU extension for missing LHS.
- if (const Expr *LHSExpr = C->getLHS()) {
- // In C++, we can have a throw-expression, which has 'void' type.
- if (!LHSExpr->getType()->isVoidType())
- if (const Expr *LHS = EvalVal(LHSExpr, refVars, ParentDecl))
- return LHS;
- }
-
- // In C++, we can have a throw-expression, which has 'void' type.
- if (C->getRHS()->getType()->isVoidType())
- return nullptr;
-
- return EvalVal(C->getRHS(), refVars, ParentDecl);
- }
-
- // Accesses to members are potential references to data on the stack.
- case Stmt::MemberExprClass: {
- const MemberExpr *M = cast<MemberExpr>(E);
-
- // Check for indirect access. We only want direct field accesses.
- if (M->isArrow())
- return nullptr;
-
- // Check whether the member type is itself a reference, in which case
- // we're not going to refer to the member, but to what the member refers
- // to.
- if (M->getMemberDecl()->getType()->isReferenceType())
- return nullptr;
-
- return EvalVal(M->getBase(), refVars, ParentDecl);
- }
-
- case Stmt::MaterializeTemporaryExprClass:
- if (const Expr *Result =
- EvalVal(cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(),
- refVars, ParentDecl))
- return Result;
- return E;
-
- default:
- // Check that we don't return or take the address of a reference to a
- // temporary. This is only useful in C++.
- if (!E->isTypeDependent() && E->isRValue())
- return E;
-
- // Everything else: we simply don't reason about them.
- return nullptr;
- }
- } while (true);
-}
-
void
Sema::CheckReturnValExpr(Expr *RetValExp, QualType lhsType,
SourceLocation ReturnLoc,
bool isObjCMethod,
const AttrVec *Attrs,
const FunctionDecl *FD) {
- CheckReturnStackAddr(*this, RetValExp, lhsType, ReturnLoc);
-
// Check if the return value is null but should not be.
if (((Attrs && hasSpecificAttr<ReturnsNonNullAttr>(*Attrs)) ||
(!isObjCMethod && isNonNullType(Context, lhsType))) &&
@@ -8168,7 +9255,7 @@ Sema::CheckReturnValExpr(Expr *RetValExp, QualType lhsType,
if (Op == OO_New || Op == OO_Array_New) {
const FunctionProtoType *Proto
= FD->getType()->castAs<FunctionProtoType>();
- if (!Proto->isNothrow(Context, /*ResultIfDependent*/true) &&
+ if (!Proto->isNothrow(/*ResultIfDependent*/true) &&
CheckNonNullExpr(*this, RetValExp))
Diag(ReturnLoc, diag::warn_operator_new_returns_null)
<< FD << getLangOpts().CPlusPlus11;
@@ -8917,7 +10004,7 @@ static void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) {
AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc());
}
-/// \brief Implements -Wsign-compare.
+/// Implements -Wsign-compare.
///
/// \param E the binary operator to check for warnings
static void AnalyzeComparison(Sema &S, BinaryOperator *E) {
@@ -9205,6 +10292,32 @@ 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,
@@ -9233,14 +10346,24 @@ static void DiagnoseFloatingImpCast(Sema &S, Expr *E, QualType T,
llvm::APSInt IntegerValue(S.Context.getIntWidth(T),
T->hasUnsignedIntegerRepresentation());
- if (Value.convertToInteger(IntegerValue, llvm::APFloat::rmTowardZero,
- &isExact) == llvm::APFloat::opOK &&
- isExact) {
+ llvm::APFloat::opStatus Result = Value.convertToInteger(
+ IntegerValue, llvm::APFloat::rmTowardZero, &isExact);
+
+ if (Result == llvm::APFloat::opOK && isExact) {
if (IsLiteral) return;
return DiagnoseImpCast(S, E, T, CContext, diag::warn_impcast_float_integer,
PruneWarnings);
}
+ // Conversion of a floating-point value to a non-bool integer where the
+ // integral part cannot be represented by the integer type is undefined.
+ if (!IsBool && Result == llvm::APFloat::opInvalidOp)
+ return DiagnoseImpCast(
+ S, E, T, CContext,
+ IsLiteral ? diag::warn_impcast_literal_float_to_integer_out_of_range
+ : diag::warn_impcast_float_to_integer_out_of_range,
+ PruneWarnings);
+
unsigned DiagID = 0;
if (IsLiteral) {
// Warn on floating point literal to integer.
@@ -9374,18 +10497,15 @@ static void DiagnoseNullConversion(Sema &S, Expr *E, QualType T,
// Venture through the macro stacks to get to the source of macro arguments.
// The new location is a better location than the complete location that was
// passed in.
- while (S.SourceMgr.isMacroArgExpansion(Loc))
- Loc = S.SourceMgr.getImmediateMacroCallerLoc(Loc);
-
- while (S.SourceMgr.isMacroArgExpansion(CC))
- CC = S.SourceMgr.getImmediateMacroCallerLoc(CC);
+ Loc = S.SourceMgr.getTopMacroCallerLoc(Loc);
+ CC = S.SourceMgr.getTopMacroCallerLoc(CC);
// __null is usually wrapped in a macro. Go up a macro if that is the case.
if (NullKind == Expr::NPCK_GNUNull && Loc.isMacroID()) {
StringRef MacroName = Lexer::getImmediateMacroNameForDiagnostics(
Loc, S.SourceMgr, S.getLangOpts());
if (MacroName == "NULL")
- Loc = S.SourceMgr.getImmediateExpansionRange(Loc).first;
+ Loc = S.SourceMgr.getImmediateExpansionRange(Loc).getBegin();
}
// Only warn if the null and context location are in the same macro expansion.
@@ -9575,7 +10695,7 @@ CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC,
return;
return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_vector_scalar);
}
-
+
// If the vector cast is cast between two vectors of the same size, it is
// a bitcast, not a conversion.
if (S.Context.getTypeSize(Source) == S.Context.getTypeSize(Target))
@@ -9852,7 +10972,7 @@ static void AnalyzeImplicitConversions(Sema &S, Expr *OrigE,
if (E->isTypeDependent() || E->isValueDependent())
return;
-
+
// For conditional operators, we analyze the arguments as if they
// were being fed directly into the output.
if (isa<ConditionalOperator>(E)) {
@@ -9896,6 +11016,9 @@ static void AnalyzeImplicitConversions(Sema &S, Expr *OrigE,
// And with simple assignments.
if (BO->getOpcode() == BO_Assign)
return AnalyzeAssignment(S, BO);
+ // And with compound assignments.
+ if (BO->isAssignmentOp())
+ return AnalyzeCompoundAssignment(S, BO);
}
// These break the otherwise-useful invariant below. Fortunately,
@@ -9939,7 +11062,7 @@ static void AnalyzeImplicitConversions(Sema &S, Expr *OrigE,
::CheckBoolLikeConversion(S, U->getSubExpr(), CC);
}
-/// Diagnose integer type and any valid implicit convertion to it.
+/// Diagnose integer type and any valid implicit conversion to it.
static bool checkOpenCLEnqueueIntType(Sema &S, Expr *E, const QualType &IntT) {
// Taking into account implicit conversions,
// allow any integer.
@@ -10002,7 +11125,7 @@ static bool IsInAnyMacroBody(const SourceManager &SM, SourceLocation Loc) {
return false;
}
-/// \brief Diagnose pointers that are always non-null.
+/// Diagnose pointers that are always non-null.
/// \param E the expression containing the pointer
/// \param NullKind NPCK_NotNull if E is a cast to bool, otherwise, E is
/// compared to a null pointer
@@ -10106,8 +11229,8 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E,
return;
}
- for (unsigned ArgNo : NonNull->args()) {
- if (ArgNo == ParamNo) {
+ for (const ParamIdx &ArgNo : NonNull->args()) {
+ if (ArgNo.getASTIndex() == ParamNo) {
ComplainAboutNonnullParamOrCall(NonNull);
return;
}
@@ -10228,29 +11351,33 @@ void Sema::CheckForIntOverflow (Expr *E) {
SmallVector<Expr *, 2> Exprs(1, E);
do {
- Expr *E = Exprs.pop_back_val();
+ Expr *OriginalE = Exprs.pop_back_val();
+ Expr *E = OriginalE->IgnoreParenCasts();
- if (isa<BinaryOperator>(E->IgnoreParenCasts())) {
- E->IgnoreParenCasts()->EvaluateForOverflow(Context);
+ if (isa<BinaryOperator>(E)) {
+ E->EvaluateForOverflow(Context);
continue;
}
- if (auto InitList = dyn_cast<InitListExpr>(E))
+ if (auto InitList = dyn_cast<InitListExpr>(OriginalE))
Exprs.append(InitList->inits().begin(), InitList->inits().end());
-
- if (isa<ObjCBoxedExpr>(E))
- E->IgnoreParenCasts()->EvaluateForOverflow(Context);
+ else if (isa<ObjCBoxedExpr>(OriginalE))
+ E->EvaluateForOverflow(Context);
+ else if (auto Call = dyn_cast<CallExpr>(E))
+ Exprs.append(Call->arg_begin(), Call->arg_end());
+ else if (auto Message = dyn_cast<ObjCMessageExpr>(E))
+ Exprs.append(Message->arg_begin(), Message->arg_end());
} while (!Exprs.empty());
}
namespace {
-/// \brief Visitor for expressions which looks for unsequenced operations on the
+/// Visitor for expressions which looks for unsequenced operations on the
/// same object.
class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
using Base = EvaluatedExprVisitor<SequenceChecker>;
- /// \brief A tree of sequenced regions within an expression. Two regions are
+ /// A tree of sequenced regions within an expression. Two regions are
/// unsequenced if one is an ancestor or a descendent of the other. When we
/// finish processing an expression with sequencing, such as a comma
/// expression, we fold its tree nodes into its parent, since they are
@@ -10264,7 +11391,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
SmallVector<Value, 8> Values;
public:
- /// \brief A region within an expression which may be sequenced with respect
+ /// A region within an expression which may be sequenced with respect
/// to some other region.
class Seq {
friend class SequenceTree;
@@ -10280,7 +11407,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
SequenceTree() { Values.push_back(Value(0)); }
Seq root() const { return Seq(0); }
- /// \brief Create a new sequence of operations, which is an unsequenced
+ /// Create a new sequence of operations, which is an unsequenced
/// subset of \p Parent. This sequence of operations is sequenced with
/// respect to other children of \p Parent.
Seq allocate(Seq Parent) {
@@ -10288,12 +11415,12 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
return Seq(Values.size() - 1);
}
- /// \brief Merge a sequence of operations into its parent.
+ /// Merge a sequence of operations into its parent.
void merge(Seq S) {
Values[S.Index].Merged = true;
}
- /// \brief Determine whether two operations are unsequenced. This operation
+ /// Determine whether two operations are unsequenced. This operation
/// is asymmetric: \p Cur should be the more recent sequence, and \p Old
/// should have been merged into its parent as appropriate.
bool isUnsequenced(Seq Cur, Seq Old) {
@@ -10308,7 +11435,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
}
private:
- /// \brief Pick a representative for a sequence.
+ /// Pick a representative for a sequence.
unsigned representative(unsigned K) {
if (Values[K].Merged)
// Perform path compression as we go.
@@ -10429,7 +11556,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
bool EvalOK = true;
} *EvalTracker = nullptr;
- /// \brief Find the object which is produced by the specified expression,
+ /// Find the object which is produced by the specified expression,
/// if any.
Object getObject(Expr *E, bool Mod) const {
E = E->IgnoreParenCasts();
@@ -10451,7 +11578,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
return nullptr;
}
- /// \brief Note that an object was modified or used by an expression.
+ /// Note that an object was modified or used by an expression.
void addUsage(UsageInfo &UI, Object O, Expr *Ref, UsageKind UK) {
Usage &U = UI.Uses[UK];
if (!U.Use || !Tree.isUnsequenced(Region, U.Seq)) {
@@ -10462,7 +11589,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
}
}
- /// \brief Check whether a modification or use conflicts with a prior usage.
+ /// Check whether a modification or use conflicts with a prior usage.
void checkUsage(Object O, UsageInfo &UI, Expr *Ref, UsageKind OtherKind,
bool IsModMod) {
if (UI.Diagnosed)
@@ -10841,23 +11968,18 @@ bool Sema::CheckParmsForFunctionDef(ArrayRef<ParmVarDecl *> Parameters,
// information is added for it.
diagnoseArrayStarInParamType(*this, PType, Param->getLocation());
- // MSVC destroys objects passed by value in the callee. Therefore a
- // function definition which takes such a parameter must be able to call the
- // object's destructor. However, we don't perform any direct access check
- // on the dtor.
- if (getLangOpts().CPlusPlus && Context.getTargetInfo()
- .getCXXABI()
- .areArgsDestroyedLeftToRightInCallee()) {
- if (!Param->isInvalidDecl()) {
- if (const RecordType *RT = Param->getType()->getAs<RecordType>()) {
- CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RT->getDecl());
- if (!ClassDecl->isInvalidDecl() &&
- !ClassDecl->hasIrrelevantDestructor() &&
- !ClassDecl->isDependentContext()) {
- CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl);
- MarkFunctionReferenced(Param->getLocation(), Destructor);
- DiagnoseUseOfDecl(Destructor, Param->getLocation());
- }
+ // If the parameter is a c++ class type and it has to be destructed in the
+ // callee function, declare the destructor so that it can be called by the
+ // callee function. Do not perform any direct access check on the dtor here.
+ if (!Param->isInvalidDecl()) {
+ if (CXXRecordDecl *ClassDecl = Param->getType()->getAsCXXRecordDecl()) {
+ if (!ClassDecl->isInvalidDecl() &&
+ !ClassDecl->hasIrrelevantDestructor() &&
+ !ClassDecl->isDependentContext() &&
+ ClassDecl->isParamDestroyedInCallee()) {
+ CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl);
+ MarkFunctionReferenced(Param->getLocation(), Destructor);
+ DiagnoseUseOfDecl(Destructor, Param->getLocation());
}
}
}
@@ -10940,7 +12062,7 @@ void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) {
<< TRange << Op->getSourceRange();
}
-/// \brief Check whether this array fits the idiom of a size-one tail padded
+/// Check whether this array fits the idiom of a size-one tail padded
/// array member of a struct.
///
/// We avoid emitting out-of-bounds access warnings for such arrays as they are
@@ -11010,9 +12132,9 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
const NamedDecl *ND = nullptr;
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
- ND = dyn_cast<NamedDecl>(DRE->getDecl());
+ ND = DRE->getDecl();
if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr))
- ND = dyn_cast<NamedDecl>(ME->getMemberDecl());
+ ND = ME->getMemberDecl();
if (index.isUnsigned() || !index.isNegative()) {
llvm::APInt size = ArrayTy->getSize();
@@ -11095,9 +12217,9 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
dyn_cast<ArraySubscriptExpr>(BaseExpr))
BaseExpr = ASE->getBase()->IgnoreParenCasts();
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
- ND = dyn_cast<NamedDecl>(DRE->getDecl());
+ ND = DRE->getDecl();
if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr))
- ND = dyn_cast<NamedDecl>(ME->getMemberDecl());
+ ND = ME->getMemberDecl();
}
if (ND)
@@ -11115,7 +12237,12 @@ void Sema::CheckArrayAccess(const Expr *expr) {
const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(expr);
CheckArrayAccess(ASE->getBase(), ASE->getIdx(), ASE,
AllowOnePastEnd > 0);
- return;
+ expr = ASE->getBase();
+ break;
+ }
+ case Stmt::MemberExprClass: {
+ expr = cast<MemberExpr>(expr)->getBase();
+ break;
}
case Stmt::OMPArraySectionExprClass: {
const OMPArraySectionExpr *ASE = cast<OMPArraySectionExpr>(expr);
@@ -11525,7 +12652,7 @@ void Sema::CheckObjCCircularContainer(ObjCMessageExpr *Message) {
if (ArgRE->isObjCSelfExpr()) {
Diag(Message->getSourceRange().getBegin(),
diag::warn_objc_circular_container)
- << ArgRE->getDecl()->getName() << StringRef("super");
+ << ArgRE->getDecl() << StringRef("'super'");
}
}
} else {
@@ -11541,11 +12668,11 @@ void Sema::CheckObjCCircularContainer(ObjCMessageExpr *Message) {
ValueDecl *Decl = ReceiverRE->getDecl();
Diag(Message->getSourceRange().getBegin(),
diag::warn_objc_circular_container)
- << Decl->getName() << Decl->getName();
+ << Decl << Decl;
if (!ArgRE->isObjCSelfExpr()) {
Diag(Decl->getLocation(),
diag::note_objc_circular_container_declared_here)
- << Decl->getName();
+ << Decl;
}
}
}
@@ -11555,10 +12682,10 @@ void Sema::CheckObjCCircularContainer(ObjCMessageExpr *Message) {
ObjCIvarDecl *Decl = IvarRE->getDecl();
Diag(Message->getSourceRange().getBegin(),
diag::warn_objc_circular_container)
- << Decl->getName() << Decl->getName();
+ << Decl << Decl;
Diag(Decl->getLocation(),
diag::note_objc_circular_container_declared_here)
- << Decl->getName();
+ << Decl;
}
}
}
@@ -11951,7 +13078,7 @@ void Sema::DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
static bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2);
-/// \brief Check if two enumeration types are layout-compatible.
+/// Check if two enumeration types are layout-compatible.
static bool isLayoutCompatible(ASTContext &C, EnumDecl *ED1, EnumDecl *ED2) {
// C++11 [dcl.enum] p8:
// Two enumeration types are layout-compatible if they have the same
@@ -11960,7 +13087,7 @@ static bool isLayoutCompatible(ASTContext &C, EnumDecl *ED1, EnumDecl *ED2) {
C.hasSameType(ED1->getIntegerType(), ED2->getIntegerType());
}
-/// \brief Check if two fields are layout-compatible.
+/// Check if two fields are layout-compatible.
static bool isLayoutCompatible(ASTContext &C, FieldDecl *Field1,
FieldDecl *Field2) {
if (!isLayoutCompatible(C, Field1->getType(), Field2->getType()))
@@ -11981,7 +13108,7 @@ static bool isLayoutCompatible(ASTContext &C, FieldDecl *Field1,
return true;
}
-/// \brief Check if two standard-layout structs are layout-compatible.
+/// Check if two standard-layout structs are layout-compatible.
/// (C++11 [class.mem] p17)
static bool isLayoutCompatibleStruct(ASTContext &C, RecordDecl *RD1,
RecordDecl *RD2) {
@@ -12025,7 +13152,7 @@ static bool isLayoutCompatibleStruct(ASTContext &C, RecordDecl *RD1,
return true;
}
-/// \brief Check if two standard-layout unions are layout-compatible.
+/// Check if two standard-layout unions are layout-compatible.
/// (C++11 [class.mem] p18)
static bool isLayoutCompatibleUnion(ASTContext &C, RecordDecl *RD1,
RecordDecl *RD2) {
@@ -12064,7 +13191,7 @@ static bool isLayoutCompatible(ASTContext &C, RecordDecl *RD1,
return isLayoutCompatibleStruct(C, RD1, RD2);
}
-/// \brief Check if two types are layout-compatible in C++11 sense.
+/// Check if two types are layout-compatible in C++11 sense.
static bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2) {
if (T1.isNull() || T2.isNull())
return false;
@@ -12102,7 +13229,7 @@ static bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2) {
//===--- CHECK: pointer_with_type_tag attribute: datatypes should match ----//
-/// \brief Given a type tag expression find the type tag itself.
+/// Given a type tag expression find the type tag itself.
///
/// \param TypeExpr Type tag expression, as it appears in user's code.
///
@@ -12173,7 +13300,7 @@ static bool FindTypeTagExpr(const Expr *TypeExpr, const ASTContext &Ctx,
}
}
-/// \brief Retrieve the C type corresponding to type tag TypeExpr.
+/// Retrieve the C type corresponding to type tag TypeExpr.
///
/// \param TypeExpr Expression that specifies a type tag.
///
@@ -12267,13 +13394,13 @@ void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr,
bool IsPointerAttr = Attr->getIsPointer();
// Retrieve the argument representing the 'type_tag'.
- if (Attr->getTypeTagIdx() >= ExprArgs.size()) {
- // Add 1 to display the user's specified value.
+ unsigned TypeTagIdxAST = Attr->getTypeTagIdx().getASTIndex();
+ if (TypeTagIdxAST >= ExprArgs.size()) {
Diag(CallSiteLoc, diag::err_tag_index_out_of_range)
- << 0 << Attr->getTypeTagIdx() + 1;
+ << 0 << Attr->getTypeTagIdx().getSourceIndex();
return;
}
- const Expr *TypeTagExpr = ExprArgs[Attr->getTypeTagIdx()];
+ const Expr *TypeTagExpr = ExprArgs[TypeTagIdxAST];
bool FoundWrongKind;
TypeTagData TypeInfo;
if (!GetMatchingCType(ArgumentKind, TypeTagExpr, Context,
@@ -12287,13 +13414,13 @@ void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr,
}
// Retrieve the argument representing the 'arg_idx'.
- if (Attr->getArgumentIdx() >= ExprArgs.size()) {
- // Add 1 to display the user's specified value.
+ unsigned ArgumentIdxAST = Attr->getArgumentIdx().getASTIndex();
+ if (ArgumentIdxAST >= ExprArgs.size()) {
Diag(CallSiteLoc, diag::err_tag_index_out_of_range)
- << 1 << Attr->getArgumentIdx() + 1;
+ << 1 << Attr->getArgumentIdx().getSourceIndex();
return;
}
- const Expr *ArgumentExpr = ExprArgs[Attr->getArgumentIdx()];
+ const Expr *ArgumentExpr = ExprArgs[ArgumentIdxAST];
if (IsPointerAttr) {
// Skip implicit cast of pointer to `void *' (as a function argument).
if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(ArgumentExpr))
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
index 2acc896d53d7..4e571eba17e9 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
@@ -40,39 +40,39 @@ using namespace clang;
using namespace sema;
namespace {
- /// \brief A container of code-completion results.
+ /// A container of code-completion results.
class ResultBuilder {
public:
- /// \brief The type of a name-lookup filter, which can be provided to the
+ /// 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;
-
+
private:
- /// \brief The actual results we have found.
+ /// The actual results we have found.
std::vector<Result> Results;
-
- /// \brief A record of all of the declarations we have found and placed
+
+ /// 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;
-
+
typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;
- /// \brief An entry in the shadow map, which is optimized to store
+ /// 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;
- /// \brief Contains either the solitary NamedDecl * or a vector
+ /// Contains either the solitary NamedDecl * or a vector
/// of (declaration, index) pairs.
llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector*> DeclOrVector;
- /// \brief When the entry contains a single declaration, this is
+ /// When the entry contains a single declaration, this is
/// the index associated with that entry.
unsigned SingleDeclIndex;
@@ -115,72 +115,72 @@ namespace {
iterator end() const;
};
- /// \brief A mapping from declaration names to the declarations that have
+ /// 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;
-
- /// \brief The semantic analysis object for which results are being
+
+ /// The semantic analysis object for which results are being
/// produced.
Sema &SemaRef;
- /// \brief The allocator used to allocate new code-completion strings.
+ /// The allocator used to allocate new code-completion strings.
CodeCompletionAllocator &Allocator;
CodeCompletionTUInfo &CCTUInfo;
-
- /// \brief If non-NULL, a filter function used to remove any code-completion
+
+ /// If non-NULL, a filter function used to remove any code-completion
/// results that are not desirable.
LookupFilter Filter;
- /// \brief Whether we should allow declarations as
+ /// Whether we should allow declarations as
/// nested-name-specifiers that would otherwise be filtered out.
bool AllowNestedNameSpecifiers;
- /// \brief If set, the type that we would prefer our resulting value
+ /// 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
+ /// Closely matching the preferred type gives a boost to a result's
/// priority.
CanQualType PreferredType;
-
- /// \brief A list of shadow maps, which is used to model name hiding at
+
+ /// 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;
-
- /// \brief If we're potentially referring to a C++ member function, the set
+
+ /// If we're potentially referring to a C++ member function, the set
/// of qualifiers applied to the object type.
Qualifiers ObjectTypeQualifiers;
-
- /// \brief Whether the \p ObjectTypeQualifiers field is active.
+
+ /// Whether the \p ObjectTypeQualifiers field is active.
bool HasObjectTypeQualifiers;
-
- /// \brief The selector that we prefer.
+
+ /// The selector that we prefer.
Selector PreferredSelector;
-
- /// \brief The completion context in which we are gathering results.
+
+ /// The completion context in which we are gathering results.
CodeCompletionContext CompletionContext;
-
- /// \brief If we are in an instance method definition, the \@implementation
+
+ /// If we are in an instance method definition, the \@implementation
/// object.
ObjCImplementationDecl *ObjCImplementation;
void AdjustResultPriorityForDecl(Result &R);
void MaybeAddConstructorResults(Result R);
-
+
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),
+ Filter(Filter),
+ AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
CompletionContext(CompletionContext),
ObjCImplementation(nullptr)
- {
- // If this is an Objective-C instance method definition, dig out the
+ {
+ // If this is an Objective-C instance method definition, dig out the
// corresponding implementation.
switch (CompletionContext.getKind()) {
case CodeCompletionContext::CCC_Expression:
@@ -193,23 +193,23 @@ namespace {
if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
ObjCImplementation = Interface->getImplementation();
break;
-
+
default:
break;
}
}
- /// \brief Determine the priority for a reference to the given declaration.
+ /// Determine the priority for a reference to the given declaration.
unsigned getBasePriority(const NamedDecl *D);
- /// \brief Whether we should include code patterns in the completion
+ /// Whether we should include code patterns in the completion
/// results.
bool includeCodePatterns() const {
- return SemaRef.CodeCompleter &&
+ return SemaRef.CodeCompleter &&
SemaRef.CodeCompleter->includeCodePatterns();
}
-
- /// \brief Set the filter used for code-completion results.
+
+ /// Set the filter used for code-completion results.
void setFilter(LookupFilter Filter) {
this->Filter = Filter;
}
@@ -217,25 +217,25 @@ namespace {
Result *data() { return Results.empty()? nullptr : &Results.front(); }
unsigned size() const { return Results.size(); }
bool empty() const { return Results.empty(); }
-
- /// \brief Specify the preferred type.
- void setPreferredType(QualType T) {
- PreferredType = SemaRef.Context.getCanonicalType(T);
+
+ /// Specify the preferred type.
+ void setPreferredType(QualType T) {
+ PreferredType = SemaRef.Context.getCanonicalType(T);
}
-
- /// \brief Set the cv-qualifiers on the object type, for us in filtering
+
+ /// 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
+ /// 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;
}
-
- /// \brief Set the preferred selector.
+
+ /// 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
@@ -243,28 +243,28 @@ namespace {
void setPreferredSelector(Selector Sel) {
PreferredSelector = Sel;
}
-
- /// \brief Retrieve the code-completion context for which results are
+
+ /// Retrieve the code-completion context for which results are
/// being collected.
- const CodeCompletionContext &getCompletionContext() const {
- return CompletionContext;
+ const CodeCompletionContext &getCompletionContext() const {
+ return CompletionContext;
}
-
- /// \brief Specify whether nested-name-specifiers are allowed.
+
+ /// Specify whether nested-name-specifiers are allowed.
void allowNestedNameSpecifiers(bool Allow = true) {
AllowNestedNameSpecifiers = Allow;
}
- /// \brief Return the semantic analysis object for which we are collecting
+ /// Return the semantic analysis object for which we are collecting
/// code completion results.
Sema &getSema() const { return SemaRef; }
-
- /// \brief Retrieve the allocator used to allocate code completion strings.
+
+ /// Retrieve the allocator used to allocate code completion strings.
CodeCompletionAllocator &getAllocator() const { return Allocator; }
CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
-
- /// \brief Determine whether the given declaration is at all interesting
+
+ /// Determine whether the given declaration is at all interesting
/// as a code-completion result.
///
/// \param ND the declaration that we are inspecting.
@@ -273,8 +273,8 @@ namespace {
/// only interesting when it is a nested-name-specifier.
bool isInterestingDecl(const NamedDecl *ND,
bool &AsNestedNameSpecifier) const;
-
- /// \brief Check whether the result is hidden by the Hiding declaration.
+
+ /// 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
@@ -282,9 +282,9 @@ namespace {
/// qualification).
bool CheckHiddenResult(Result &R, DeclContext *CurContext,
const NamedDecl *Hiding);
-
- /// \brief 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
+
+ /// 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).
@@ -292,7 +292,7 @@ namespace {
/// \param CurContext the context in which this result will be named.
void MaybeAddResult(Result R, DeclContext *CurContext = nullptr);
- /// \brief Add a new result to this result set, where we already know
+ /// 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).
@@ -305,24 +305,29 @@ namespace {
/// class of the searched context.
void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
bool InBaseClass);
-
- /// \brief Add a new non-declaration result to this result set.
+
+ /// Add a new non-declaration result to this result set.
void AddResult(Result R);
- /// \brief Enter into a new scope.
+ /// Enter into a new scope.
void EnterNewScope();
-
- /// \brief Exit from the current scope.
+
+ /// Exit from the current scope.
void ExitScope();
-
- /// \brief Ignore this declaration, if it is seen again.
+
+ /// 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;
@@ -341,8 +346,8 @@ namespace {
bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;
bool IsObjCCollection(const NamedDecl *ND) const;
bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
- //@}
- };
+ //@}
+ };
}
class ResultBuilder::ShadowMapEntry::iterator {
@@ -354,7 +359,7 @@ public:
typedef value_type reference;
typedef std::ptrdiff_t difference_type;
typedef std::input_iterator_tag iterator_category;
-
+
class pointer {
DeclIndexPair Value;
@@ -415,7 +420,7 @@ public:
}
};
-ResultBuilder::ShadowMapEntry::iterator
+ResultBuilder::ShadowMapEntry::iterator
ResultBuilder::ShadowMapEntry::begin() const {
if (DeclOrVector.isNull())
return iterator();
@@ -426,7 +431,7 @@ ResultBuilder::ShadowMapEntry::begin() const {
return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
}
-ResultBuilder::ShadowMapEntry::iterator
+ResultBuilder::ShadowMapEntry::iterator
ResultBuilder::ShadowMapEntry::end() const {
if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull())
return iterator();
@@ -434,7 +439,7 @@ ResultBuilder::ShadowMapEntry::end() const {
return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
}
-/// \brief Compute the qualification required to get from the current context
+/// Compute the qualification required to get from the current context
/// (\p CurContext) to the target context (\p TargetContext).
///
/// \param Context the AST context in which the qualification will be used.
@@ -442,7 +447,7 @@ ResultBuilder::ShadowMapEntry::end() const {
/// \param CurContext the context where an entity is being named, which is
/// typically based on the current scope.
///
-/// \param TargetContext the context in which the named entity actually
+/// \param TargetContext the context in which the named entity actually
/// resides.
///
/// \returns a nested name specifier that refers into the target context, or
@@ -452,14 +457,14 @@ getRequiredQualification(ASTContext &Context,
const DeclContext *CurContext,
const DeclContext *TargetContext) {
SmallVector<const DeclContext *, 4> TargetParents;
-
+
for (const DeclContext *CommonAncestor = TargetContext;
CommonAncestor && !CommonAncestor->Encloses(CurContext);
CommonAncestor = CommonAncestor->getLookupParent()) {
if (CommonAncestor->isTransparentContext() ||
CommonAncestor->isFunctionOrMethod())
continue;
-
+
TargetParents.push_back(CommonAncestor);
}
@@ -477,7 +482,7 @@ getRequiredQualification(ASTContext &Context,
Result = NestedNameSpecifier::Create(Context, Result,
false,
Context.getTypeDeclType(TD).getTypePtr());
- }
+ }
return Result;
}
@@ -526,17 +531,17 @@ bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
// Skip unnamed entities.
if (!ND->getDeclName())
return false;
-
+
// Friend declarations and declarations introduced due to friends are never
// added as results.
if (ND->getFriendObjectKind() == Decl::FOK_Undeclared)
return false;
-
+
// Class template (partial) specializations are never added as results.
if (isa<ClassTemplateSpecializationDecl>(ND) ||
isa<ClassTemplatePartialSpecializationDecl>(ND))
return false;
-
+
// Using declarations themselves are never added as results.
if (isa<UsingDecl>(ND))
return false;
@@ -554,17 +559,17 @@ bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
// Filter out any unwanted results.
if (Filter && !(this->*Filter)(Named)) {
// Check whether it is interesting as a nested-name-specifier.
- if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
+ if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
IsNestedNameSpecifier(ND) &&
(Filter != &ResultBuilder::IsMember ||
- (isa<CXXRecordDecl>(ND) &&
+ (isa<CXXRecordDecl>(ND) &&
cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
AsNestedNameSpecifier = true;
return true;
}
return false;
- }
+ }
// ... then it must be interesting!
return true;
}
@@ -576,29 +581,29 @@ bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
// name if we introduce the tag type.
if (!SemaRef.getLangOpts().CPlusPlus)
return true;
-
+
const DeclContext *HiddenCtx =
R.Declaration->getDeclContext()->getRedeclContext();
-
+
// There is no way to qualify a name declared in a function or method.
if (HiddenCtx->isFunctionOrMethod())
return true;
-
+
if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
return true;
-
+
// We can refer to the result with the appropriate qualification. Do it.
R.Hidden = true;
R.QualifierIsInformative = false;
-
+
if (!R.Qualifier)
- R.Qualifier = getRequiredQualification(SemaRef.Context,
- CurContext,
+ R.Qualifier = getRequiredQualification(SemaRef.Context,
+ CurContext,
R.Declaration->getDeclContext());
return false;
}
-/// \brief A simplified classification of types used to determine whether two
+/// A simplified classification of types used to determine whether two
/// types are "similar enough" when adjusting priorities.
SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
switch (T->getTypeClass()) {
@@ -606,77 +611,77 @@ SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
switch (cast<BuiltinType>(T)->getKind()) {
case BuiltinType::Void:
return STC_Void;
-
+
case BuiltinType::NullPtr:
return STC_Pointer;
-
+
case BuiltinType::Overload:
case BuiltinType::Dependent:
return STC_Other;
-
+
case BuiltinType::ObjCId:
case BuiltinType::ObjCClass:
case BuiltinType::ObjCSel:
return STC_ObjectiveC;
-
+
default:
return STC_Arithmetic;
}
case Type::Complex:
return STC_Arithmetic;
-
+
case Type::Pointer:
return STC_Pointer;
-
+
case Type::BlockPointer:
return STC_Block;
-
+
case Type::LValueReference:
case Type::RValueReference:
return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
-
+
case Type::ConstantArray:
case Type::IncompleteArray:
case Type::VariableArray:
case Type::DependentSizedArray:
return STC_Array;
-
+
case Type::DependentSizedExtVector:
case Type::Vector:
case Type::ExtVector:
return STC_Arithmetic;
-
+
case Type::FunctionProto:
case Type::FunctionNoProto:
return STC_Function;
-
+
case Type::Record:
return STC_Record;
-
+
case Type::Enum:
return STC_Arithmetic;
-
+
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
return STC_ObjectiveC;
-
+
default:
return STC_Other;
}
}
-/// \brief Get the type that a given expression will have if this declaration
+/// Get the type that a given expression will have if this declaration
/// is used as an expression in its "typical" code-completion form.
QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
- ND = cast<NamedDecl>(ND->getUnderlyingDecl());
-
+ ND = ND->getUnderlyingDecl();
+
if (const TypeDecl *Type = dyn_cast<TypeDecl>(ND))
return C.getTypeDeclType(Type);
if (const ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
return C.getObjCInterfaceType(Iface);
-
+
QualType T;
if (const FunctionDecl *Function = ND->getAsFunction())
T = Function->getCallResultType();
@@ -721,7 +726,7 @@ QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
break;
} while (true);
-
+
return T;
}
@@ -781,7 +786,7 @@ void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
if (PreferredSelector == Method->getSelector())
R.Priority += CCD_SelectorMatch;
-
+
// If we have a preferred type, adjust the priority for results with exactly-
// matching or nearly-matching types.
if (!PreferredType.isNull()) {
@@ -795,16 +800,16 @@ void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
else if ((getSimplifiedTypeClass(PreferredType)
== getSimplifiedTypeClass(TC)) &&
!(PreferredType->isEnumeralType() && TC->isEnumeralType()))
- R.Priority /= CCF_SimilarTypeMatch;
+ R.Priority /= CCF_SimilarTypeMatch;
}
- }
+ }
}
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;
@@ -818,12 +823,12 @@ void ResultBuilder::MaybeAddConstructorResults(Result R) {
// There are no constructors here.
return;
}
-
+
Record = Record->getDefinition();
if (!Record)
return;
-
+
QualType RecordTy = Context.getTypeDeclType(Record);
DeclarationName ConstructorName
= Context.DeclarationNames.getCXXConstructorName(
@@ -838,9 +843,15 @@ void ResultBuilder::MaybeAddConstructorResults(Result R) {
}
}
+static bool isConstructor(const Decl *ND) {
+ if (const auto *Tmpl = dyn_cast<FunctionTemplateDecl>(ND))
+ ND = Tmpl->getTemplatedDecl();
+ return isa<CXXConstructorDecl>(ND);
+}
+
void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
assert(!ShadowMaps.empty() && "Must enter into a results scope");
-
+
if (R.Kind != Result::RK_Declaration) {
// For non-declaration results, just add the result.
Results.push_back(R);
@@ -848,24 +859,24 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
}
// Look through using declarations.
- if (const UsingShadowDecl *Using =
- dyn_cast<UsingShadowDecl>(R.Declaration)) {
- MaybeAddResult(Result(Using->getTargetDecl(),
- getBasePriority(Using->getTargetDecl()),
- R.Qualifier),
- CurContext);
+ if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
+ CodeCompletionResult Result(Using->getTargetDecl(),
+ getBasePriority(Using->getTargetDecl()),
+ R.Qualifier);
+ Result.ShadowDecl = Using;
+ MaybeAddResult(Result, CurContext);
return;
}
-
+
const Decl *CanonDecl = R.Declaration->getCanonicalDecl();
unsigned IDNS = CanonDecl->getIdentifierNamespace();
bool AsNestedNameSpecifier = false;
if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
return;
-
+
// C++ constructors are never found by name lookup.
- if (isa<CXXConstructorDecl>(R.Declaration))
+ if (isConstructor(R.Declaration))
return;
ShadowMap &SMap = ShadowMaps.back();
@@ -882,12 +893,12 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
if (ND->getCanonicalDecl() == CanonDecl) {
// This is a redeclaration. Always pick the newer declaration.
Results[Index].Declaration = R.Declaration;
-
+
// We're done.
return;
}
}
-
+
// This is a new declaration in this scope. However, check whether this
// declaration name is hidden by a similarly-named declaration in an outer
// scope.
@@ -906,21 +917,21 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
(IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol)))
continue;
-
+
// Protocols are in distinct namespaces from everything else.
if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
|| (IDNS & Decl::IDNS_ObjCProtocol)) &&
I->first->getIdentifierNamespace() != IDNS)
continue;
-
+
// The newly-added result is hidden by an entry in the shadow map.
if (CheckHiddenResult(R, CurContext, I->first))
return;
-
+
break;
}
}
-
+
// Make sure that any given declaration only shows up in the result set once.
if (!AllDeclsFound.insert(CanonDecl).second)
return;
@@ -930,9 +941,9 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
if (AsNestedNameSpecifier) {
R.StartsNestedNameSpecifier = true;
R.Priority = CCP_NestedNameSpecifier;
- } else
+ } else
AdjustResultPriorityForDecl(R);
-
+
// If this result is supposed to have an informative qualifier, add one.
if (R.QualifierIsInformative && !R.Qualifier &&
!R.StartsNestedNameSpecifier) {
@@ -946,17 +957,17 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
else
R.QualifierIsInformative = false;
}
-
+
// Insert this result into the set of results and into the current shadow
// map.
SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Results.push_back(R);
-
+
if (!AsNestedNameSpecifier)
MaybeAddConstructorResults(R);
}
-void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
+void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
NamedDecl *Hiding, bool InBaseClass = false) {
if (R.Kind != Result::RK_Declaration) {
// For non-declaration results, just add the result.
@@ -966,19 +977,20 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
// Look through using declarations.
if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
- AddResult(Result(Using->getTargetDecl(),
- getBasePriority(Using->getTargetDecl()),
- R.Qualifier),
- CurContext, Hiding);
+ CodeCompletionResult Result(Using->getTargetDecl(),
+ getBasePriority(Using->getTargetDecl()),
+ R.Qualifier);
+ Result.ShadowDecl = Using;
+ AddResult(Result, CurContext, Hiding);
return;
}
-
+
bool AsNestedNameSpecifier = false;
if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
return;
-
+
// C++ constructors are never found by name lookup.
- if (isa<CXXConstructorDecl>(R.Declaration))
+ if (isConstructor(R.Declaration))
return;
if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
@@ -987,16 +999,16 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
// Make sure that any given declaration only shows up in the result set once.
if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second)
return;
-
+
// If the filter is for nested-name-specifiers, then this result starts a
// nested-name-specifier.
if (AsNestedNameSpecifier) {
R.StartsNestedNameSpecifier = true;
R.Priority = CCP_NestedNameSpecifier;
- }
- else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
- isa<CXXRecordDecl>(R.Declaration->getDeclContext()
- ->getRedeclContext()))
+ } else if (Filter == &ResultBuilder::IsMember && !R.Qualifier &&
+ InBaseClass &&
+ isa<CXXRecordDecl>(
+ R.Declaration->getDeclContext()->getRedeclContext()))
R.QualifierIsInformative = true;
// If this result is supposed to have an informative qualifier, add one.
@@ -1012,13 +1024,13 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
else
R.QualifierIsInformative = false;
}
-
+
// Adjust the priority if this result comes from a base class.
if (InBaseClass)
R.Priority += CCD_InBaseClass;
-
+
AdjustResultPriorityForDecl(R);
-
+
if (HasObjectTypeQualifiers)
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
if (Method->isInstance()) {
@@ -1027,43 +1039,43 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
if (ObjectTypeQualifiers == MethodQuals)
R.Priority += CCD_ObjectQualifierMatch;
else if (ObjectTypeQualifiers - MethodQuals) {
- // The method cannot be invoked, because doing so would drop
+ // The method cannot be invoked, because doing so would drop
// qualifiers.
return;
}
}
-
+
// Insert this result into the set of results.
Results.push_back(R);
-
+
if (!AsNestedNameSpecifier)
MaybeAddConstructorResults(R);
}
void ResultBuilder::AddResult(Result R) {
- assert(R.Kind != Result::RK_Declaration &&
+ assert(R.Kind != Result::RK_Declaration &&
"Declaration results need more context");
Results.push_back(R);
}
-/// \brief Enter into a new scope.
+/// Enter into a new scope.
void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }
-/// \brief Exit from the current scope.
+/// Exit from the current scope.
void ResultBuilder::ExitScope() {
for (ShadowMap::iterator E = ShadowMaps.back().begin(),
EEnd = ShadowMaps.back().end();
E != EEnd;
++E)
E->second.Destroy();
-
+
ShadowMaps.pop_back();
}
-/// \brief Determines whether this given declaration will be found by
+/// Determines whether this given declaration will be found by
/// ordinary name lookup.
bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
- ND = cast<NamedDecl>(ND->getUnderlyingDecl());
+ ND = ND->getUnderlyingDecl();
// If name lookup finds a local extern declaration, then we are in a
// context where it behaves like an ordinary name.
@@ -1074,14 +1086,14 @@ bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
if (isa<ObjCIvarDecl>(ND))
return true;
}
-
+
return ND->getIdentifierNamespace() & IDNS;
}
-/// \brief Determines whether this given declaration will be found by
+/// Determines whether this given declaration will be found by
/// ordinary name lookup but is not a type name.
bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
- ND = cast<NamedDecl>(ND->getUnderlyingDecl());
+ ND = ND->getUnderlyingDecl();
if (isa<TypeDecl>(ND))
return false;
// Objective-C interfaces names are not filtered by this method because they
@@ -1099,51 +1111,51 @@ bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
if (isa<ObjCIvarDecl>(ND))
return true;
}
-
+
return ND->getIdentifierNamespace() & IDNS;
}
bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
if (!IsOrdinaryNonTypeName(ND))
return 0;
-
+
if (const ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
if (VD->getType()->isIntegralOrEnumerationType())
return true;
-
+
return false;
}
-/// \brief Determines whether this given declaration will be found by
+/// Determines whether this given declaration will be found by
/// ordinary name lookup.
bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
- ND = cast<NamedDecl>(ND->getUnderlyingDecl());
+ ND = ND->getUnderlyingDecl();
unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
if (SemaRef.getLangOpts().CPlusPlus)
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
-
- return (ND->getIdentifierNamespace() & IDNS) &&
- !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
+
+ return (ND->getIdentifierNamespace() & IDNS) &&
+ !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
!isa<ObjCPropertyDecl>(ND);
}
-/// \brief Determines whether the given declaration is suitable as the
+/// 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))
ND = ClassTemplate->getTemplatedDecl();
-
+
return SemaRef.isAcceptableNestedNameSpecifier(ND);
}
-/// \brief Determines whether the given declaration is an enumeration.
+/// Determines whether the given declaration is an enumeration.
bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
return isa<EnumDecl>(ND);
}
-/// \brief Determines whether the given declaration is a class or struct.
+/// 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))
@@ -1154,40 +1166,40 @@ bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
return RD->getTagKind() == TTK_Class ||
RD->getTagKind() == TTK_Struct ||
RD->getTagKind() == TTK_Interface;
-
+
return false;
}
-/// \brief Determines whether the given declaration is a union.
+/// 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))
ND = ClassTemplate->getTemplatedDecl();
-
+
if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
return RD->getTagKind() == TTK_Union;
-
+
return false;
}
-/// \brief Determines whether the given declaration is a namespace.
+/// Determines whether the given declaration is a namespace.
bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
return isa<NamespaceDecl>(ND);
}
-/// \brief Determines whether the given declaration is a namespace or
+/// Determines whether the given declaration is a namespace or
/// namespace alias.
bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
return isa<NamespaceDecl>(ND->getUnderlyingDecl());
}
-/// \brief Determines whether the given declaration is a type.
+/// Determines whether the given declaration is a type.
bool ResultBuilder::IsType(const NamedDecl *ND) const {
ND = ND->getUnderlyingDecl();
return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
}
-/// \brief Determines which members of a class should be visible via
+/// Determines which members of a class should be visible via
/// "." or "->". Only value declarations, nested name specifiers, and
/// using declarations thereof should show up.
bool ResultBuilder::IsMember(const NamedDecl *ND) const {
@@ -1199,31 +1211,31 @@ bool ResultBuilder::IsMember(const NamedDecl *ND) const {
static bool isObjCReceiverType(ASTContext &C, QualType T) {
T = C.getCanonicalType(T);
switch (T->getTypeClass()) {
- case Type::ObjCObject:
+ case Type::ObjCObject:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
return true;
-
+
case Type::Builtin:
switch (cast<BuiltinType>(T)->getKind()) {
case BuiltinType::ObjCId:
case BuiltinType::ObjCClass:
case BuiltinType::ObjCSel:
return true;
-
+
default:
break;
}
return false;
-
+
default:
break;
}
-
+
if (!C.getLangOpts().CPlusPlus)
return false;
- // FIXME: We could perform more analysis here to determine whether a
+ // FIXME: We could perform more analysis here to determine whether a
// particular class type has any conversions to Objective-C types. For now,
// just accept all class types.
return T->isDependentType() || T->isRecordType();
@@ -1233,7 +1245,7 @@ bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
QualType T = getDeclUsageType(SemaRef.Context, ND);
if (T.isNull())
return false;
-
+
T = SemaRef.Context.getBaseElementType(T);
return isObjCReceiverType(SemaRef.Context, T);
}
@@ -1241,11 +1253,11 @@ bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const {
if (IsObjCMessageReceiver(ND))
return true;
-
+
const VarDecl *Var = dyn_cast<VarDecl>(ND);
if (!Var)
return false;
-
+
return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
}
@@ -1253,14 +1265,14 @@ bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
(!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
return false;
-
+
QualType T = getDeclUsageType(SemaRef.Context, ND);
if (T.isNull())
return false;
-
+
T = SemaRef.Context.getBaseElementType(T);
return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
- T->isObjCIdType() ||
+ T->isObjCIdType() ||
(SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
}
@@ -1268,37 +1280,69 @@ bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
return false;
}
-/// \brief Determines whether the given declaration is an Objective-C
+/// Determines whether the given declaration is an Objective-C
/// instance variable.
bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
return isa<ObjCIvarDecl>(ND);
}
namespace {
- /// \brief Visible declaration consumer that adds a code-completion result
+ /// 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)
- : Results(Results), CurContext(CurContext) { }
+ CodeCompletionDeclConsumer(
+ ResultBuilder &Results, DeclContext *CurContext,
+ std::vector<FixItHint> FixIts = std::vector<FixItHint>())
+ : Results(Results), CurContext(CurContext), FixIts(std::move(FixIts)) {}
void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
bool InBaseClass) override {
bool Accessible = true;
- if (Ctx)
- Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
+ if (Ctx) {
+ DeclContext *AccessingCtx = Ctx;
+ // If ND comes from a base class, set the naming class back to the
+ // derived class if the search starts from the derived class (i.e.
+ // InBaseClass is true).
+ //
+ // Example:
+ // class B { protected: int X; }
+ // class D : public B { void f(); }
+ // void D::f() { this->^; }
+ // The completion after "this->" will have `InBaseClass` set to true and
+ // `Ctx` set to "B", when looking up in `B`. We need to set the actual
+ // accessing context (i.e. naming class) to "D" so that access can be
+ // calculated correctly.
+ if (InBaseClass && isa<CXXRecordDecl>(Ctx)) {
+ CXXRecordDecl *RC = nullptr;
+ // Get the enclosing record.
+ for (DeclContext *DC = CurContext; !DC->isFileContext();
+ DC = DC->getParent()) {
+ if ((RC = dyn_cast<CXXRecordDecl>(DC)))
+ break;
+ }
+ if (RC)
+ AccessingCtx = RC;
+ }
+ Accessible = Results.getSema().IsSimplyAccessible(ND, AccessingCtx);
+ }
ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
- false, Accessible);
+ false, Accessible, FixIts);
Results.AddResult(Result, CurContext, Hiding, InBaseClass);
}
+
+ void EnteredContext(DeclContext* Ctx) override {
+ Results.addVisitedContext(Ctx);
+ }
};
}
-/// \brief Add type specifiers for the current language as keyword results.
+/// Add type specifiers for the current language as keyword results.
static void AddTypeSpecifierResults(const LangOptions &LangOpts,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
@@ -1324,16 +1368,16 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Results.AddResult(Result("_Bool", CCP_Type));
Results.AddResult(Result("restrict", CCP_Type));
}
-
+
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
if (LangOpts.CPlusPlus) {
// C++-specific
- Results.AddResult(Result("bool", CCP_Type +
+ Results.AddResult(Result("bool", CCP_Type +
(LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Results.AddResult(Result("class", CCP_Type));
Results.AddResult(Result("wchar_t", CCP_Type));
-
+
// typename qualified-id
Builder.AddTypedTextChunk("typename");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -1341,12 +1385,12 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Builder.AddTextChunk("::");
Builder.AddPlaceholderChunk("name");
Results.AddResult(Result(Builder.TakeString()));
-
+
if (LangOpts.CPlusPlus11) {
Results.AddResult(Result("auto", CCP_Type));
Results.AddResult(Result("char16_t", CCP_Type));
Results.AddResult(Result("char32_t", CCP_Type));
-
+
Builder.AddTypedTextChunk("decltype");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression");
@@ -1356,13 +1400,13 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts,
} else
Results.AddResult(Result("__auto_type", CCP_Type));
- // GNU extensions
- if (LangOpts.GNUMode) {
+ // GNU keywords
+ if (LangOpts.GNUKeywords) {
// FIXME: Enable when we actually support decimal floating point.
// Results.AddResult(Result("_Decimal32"));
// Results.AddResult(Result("_Decimal64"));
// Results.AddResult(Result("_Decimal128"));
-
+
Builder.AddTypedTextChunk("typeof");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("expression");
@@ -1382,7 +1426,7 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts,
}
static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
- const LangOptions &LangOpts,
+ const LangOptions &LangOpts,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
// Note: we don't suggest either "auto" or "register", because both
@@ -1408,7 +1452,7 @@ static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
}
static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
- const LangOptions &LangOpts,
+ const LangOptions &LangOpts,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
switch (CCC) {
@@ -1419,7 +1463,7 @@ static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Results.AddResult(Result("friend"));
Results.AddResult(Result("mutable"));
Results.AddResult(Result("virtual"));
- }
+ }
LLVM_FALLTHROUGH;
case Sema::PCC_ObjCInterface:
@@ -1447,7 +1491,7 @@ static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
static void AddObjCVisibilityResults(const LangOptions &LangOpts,
ResultBuilder &Results,
- bool NeedAt);
+ bool NeedAt);
static void AddObjCImplementationResults(const LangOptions &LangOpts,
ResultBuilder &Results,
bool NeedAt);
@@ -1464,7 +1508,7 @@ static void AddTypedefResult(ResultBuilder &Results) {
Builder.AddPlaceholderChunk("type");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("name");
- Results.AddResult(CodeCompletionResult(Builder.TakeString()));
+ Results.AddResult(CodeCompletionResult(Builder.TakeString()));
}
static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
@@ -1481,15 +1525,15 @@ static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
case Sema::PCC_ParenthesizedExpression:
case Sema::PCC_LocalDeclarationSpecifiers:
return true;
-
+
case Sema::PCC_Expression:
case Sema::PCC_Condition:
return LangOpts.CPlusPlus;
-
+
case Sema::PCC_ObjCInterface:
case Sema::PCC_ObjCImplementation:
return false;
-
+
case Sema::PCC_ForInit:
return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
}
@@ -1507,12 +1551,12 @@ static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
return Policy;
}
-/// \brief Retrieve a printing policy suitable for code completion.
+/// Retrieve a printing policy suitable for code completion.
static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
return getCompletionPrintingPolicy(S.Context, S.PP);
}
-/// \brief Retrieve the string representation of the given type as a string
+/// Retrieve the string representation of the given type as a string
/// that has the appropriate lifetime for code completion.
///
/// This routine provides a fast path where we provide constant strings for
@@ -1525,7 +1569,7 @@ static const char *GetCompletionTypeString(QualType T,
// Built-in type names are constant strings.
if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
return BT->getNameAsCString(Policy);
-
+
// Anonymous tag types are constant strings.
if (const TagType *TagT = dyn_cast<TagType>(T))
if (TagDecl *Tag = TagT->getDecl())
@@ -1539,24 +1583,24 @@ static const char *GetCompletionTypeString(QualType T,
}
}
}
-
+
// Slow path: format the type as a string.
std::string Result;
T.getAsStringInternal(Result, Policy);
return Allocator.CopyString(Result);
}
-/// \brief Add a completion for "this", if we're in a member function.
+/// Add a completion for "this", if we're in a member function.
static void addThisCompletion(Sema &S, ResultBuilder &Results) {
QualType ThisTy = S.getCurrentThisType();
if (ThisTy.isNull())
return;
-
+
CodeCompletionAllocator &Allocator = Results.getAllocator();
CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
PrintingPolicy Policy = getCompletionPrintingPolicy(S);
- Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
- S.Context,
+ Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
+ S.Context,
Policy,
Allocator));
Builder.AddTypedTextChunk("this");
@@ -1578,14 +1622,14 @@ static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
Results.AddResult(CodeCompletionResult(Builder.TakeString()));
}
-/// \brief Add language constructs that show up for "ordinary" names.
+/// Add language constructs that show up for "ordinary" names.
static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Scope *S,
Sema &SemaRef,
ResultBuilder &Results) {
CodeCompletionAllocator &Allocator = Results.getAllocator();
CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
-
+
typedef CodeCompletionResult Result;
switch (CCC) {
case Sema::PCC_Namespace:
@@ -1601,7 +1645,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Results.AddResult(Result(Builder.TakeString()));
}
-
+
// namespace identifier = identifier ;
Builder.AddTypedTextChunk("namespace");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -1618,7 +1662,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddPlaceholderChunk("identifier");
Results.AddResult(Result(Builder.TakeString()));
- // asm(string-literal)
+ // asm(string-literal)
Builder.AddTypedTextChunk("asm");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("string-literal");
@@ -1633,10 +1677,10 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Results.AddResult(Result(Builder.TakeString()));
}
}
-
+
if (SemaRef.getLangOpts().ObjC1)
AddObjCTopLevelResults(Results, true);
-
+
AddTypedefResult(Results);
LLVM_FALLTHROUGH;
@@ -1649,7 +1693,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddTextChunk("::");
Builder.AddPlaceholderChunk("name");
Results.AddResult(Result(Builder.TakeString()));
-
+
// using typename qualifier::name (only in a dependent context)
if (SemaRef.CurContext->isDependentContext()) {
Builder.AddTypedTextChunk("using");
@@ -1710,17 +1754,17 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
break;
-
+
case Sema::PCC_ObjCImplementation:
AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
break;
-
+
case Sema::PCC_ObjCInstanceVariableList:
AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
break;
-
+
case Sema::PCC_RecoveryInFunction:
case Sema::PCC_Statement: {
AddTypedefResult(Results);
@@ -1744,7 +1788,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
}
if (SemaRef.getLangOpts().ObjC1)
AddObjCStatementResults(Results, true);
-
+
if (Results.includeCodePatterns()) {
// if (condition) { statements }
Builder.AddTypedTextChunk("if");
@@ -1773,7 +1817,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Results.AddResult(Result(Builder.TakeString()));
}
-
+
// Switch-specific statements.
if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
// case expression:
@@ -1835,7 +1879,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Results.AddResult(Result(Builder.TakeString()));
}
-
+
if (S->getContinueParent()) {
// continue ;
Builder.AddTypedTextChunk("continue");
@@ -1856,7 +1900,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
else if (ObjCMethodDecl *Method
= dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
isVoid = Method->getReturnType()->isVoidType();
- else if (SemaRef.getCurBlock() &&
+ else if (SemaRef.getCurBlock() &&
!SemaRef.getCurBlock()->ReturnType.isNull())
isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Builder.AddTypedTextChunk("return");
@@ -1870,7 +1914,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddTypedTextChunk("goto");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("label");
- Results.AddResult(Result(Builder.TakeString()));
+ Results.AddResult(Result(Builder.TakeString()));
// Using directives
Builder.AddTypedTextChunk("using");
@@ -1900,7 +1944,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddPlaceholderChunk("type");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddPlaceholderChunk("expression");
- Results.AddResult(Result(Builder.TakeString()));
+ Results.AddResult(Result(Builder.TakeString()));
// (__bridge_transfer <Objective-C type>)<expression>
Builder.AddTypedTextChunk("__bridge_transfer");
@@ -1908,7 +1952,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddPlaceholderChunk("Objective-C type");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddPlaceholderChunk("expression");
- Results.AddResult(Result(Builder.TakeString()));
+ Results.AddResult(Result(Builder.TakeString()));
// (__bridge_retained <CF type>)<expression>
Builder.AddTypedTextChunk("__bridge_retained");
@@ -1916,7 +1960,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddPlaceholderChunk("CF type");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddPlaceholderChunk("expression");
- Results.AddResult(Result(Builder.TakeString()));
+ Results.AddResult(Result(Builder.TakeString()));
}
// Fall through
LLVM_FALLTHROUGH;
@@ -1925,12 +1969,12 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
if (SemaRef.getLangOpts().CPlusPlus) {
// 'this', if we're in a non-static member function.
addThisCompletion(SemaRef, Results);
-
+
// true
Builder.AddResultTypeChunk("bool");
Builder.AddTypedTextChunk("true");
Results.AddResult(Result(Builder.TakeString()));
-
+
// false
Builder.AddResultTypeChunk("bool");
Builder.AddTypedTextChunk("false");
@@ -1945,9 +1989,9 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Builder.TakeString()));
+ Results.AddResult(Result(Builder.TakeString()));
}
-
+
// static_cast < type-id > ( expression )
Builder.AddTypedTextChunk("static_cast");
Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
@@ -1956,7 +2000,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Builder.TakeString()));
+ Results.AddResult(Result(Builder.TakeString()));
// reinterpret_cast < type-id > ( expression )
Builder.AddTypedTextChunk("reinterpret_cast");
@@ -1966,7 +2010,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Builder.TakeString()));
+ Results.AddResult(Result(Builder.TakeString()));
// const_cast < type-id > ( expression )
Builder.AddTypedTextChunk("const_cast");
@@ -1976,7 +2020,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Builder.TakeString()));
+ Results.AddResult(Result(Builder.TakeString()));
if (SemaRef.getLangOpts().RTTI) {
// typeid ( expression-or-type )
@@ -1985,9 +2029,9 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression-or-type");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Builder.TakeString()));
+ Results.AddResult(Result(Builder.TakeString()));
}
-
+
// new T ( ... )
Builder.AddTypedTextChunk("new");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -1995,7 +2039,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expressions");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Builder.TakeString()));
+ Results.AddResult(Result(Builder.TakeString()));
// new T [ ] ( ... )
Builder.AddTypedTextChunk("new");
@@ -2007,14 +2051,14 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expressions");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Builder.TakeString()));
+ Results.AddResult(Result(Builder.TakeString()));
// delete expression
Builder.AddResultTypeChunk("void");
Builder.AddTypedTextChunk("delete");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("expression");
- Results.AddResult(Result(Builder.TakeString()));
+ Results.AddResult(Result(Builder.TakeString()));
// delete [] expression
Builder.AddResultTypeChunk("void");
@@ -2034,7 +2078,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddPlaceholderChunk("expression");
Results.AddResult(Result(Builder.TakeString()));
}
-
+
// FIXME: Rethrow?
if (SemaRef.getLangOpts().CPlusPlus11) {
@@ -2079,7 +2123,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
SuperType = ID->getSuperClass()->getNameAsString();
if (Method->isInstanceMethod())
SuperType += " *";
-
+
Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
Builder.AddTypedTextChunk("super");
Results.AddResult(Result(Builder.TakeString()));
@@ -2111,7 +2155,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Results.AddResult(Result(Builder.TakeString()));
break;
}
-
+
case Sema::PCC_Type:
case Sema::PCC_LocalDeclarationSpecifiers:
break;
@@ -2124,7 +2168,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Results.AddResult(Result("operator"));
}
-/// \brief If the given declaration has an associated type, add it as a result
+/// If the given declaration has an associated type, add it as a result
/// type chunk.
static void AddResultTypeChunk(ASTContext &Context,
const PrintingPolicy &Policy,
@@ -2136,7 +2180,7 @@ static void AddResultTypeChunk(ASTContext &Context,
// Skip constructors and conversion functions, which have their return types
// built into their names.
- if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
+ if (isConstructor(ND) || isa<CXXConversionDecl>(ND))
return;
// Determine the type of the declaration (if it has a type).
@@ -2166,10 +2210,10 @@ static void AddResultTypeChunk(ASTContext &Context,
else
T = Property->getType();
}
-
+
if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
return;
-
+
Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Result.getAllocator()));
}
@@ -2188,7 +2232,7 @@ static void MaybeAddSentinel(Preprocessor &PP,
}
}
-static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
+static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
QualType &Type) {
std::string Result;
if (ObjCQuals & Decl::OBJC_TQ_In)
@@ -2223,7 +2267,7 @@ static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
return Result;
}
-/// \brief Tries to find the most appropriate type location for an Objective-C
+/// Tries to find the most appropriate type location for an Objective-C
/// block placeholder.
///
/// This function ignores things like typedefs and qualifiers in order to
@@ -2285,13 +2329,13 @@ static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
if (Param->getType()->isDependentType() ||
!Param->getType()->isBlockPointerType()) {
- // The argument for a dependent or non-block parameter is a placeholder
+ // The argument for a dependent or non-block parameter is a placeholder
// containing that parameter's type.
std::string Result;
-
+
if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Result = Param->getIdentifier()->getName();
-
+
QualType Type = Param->getType();
if (ObjCSubsts)
Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
@@ -2332,7 +2376,7 @@ static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
Result = Param->getIdentifier()->getName();
QualType Type = Param->getType().getUnqualifiedType();
-
+
if (ObjCMethodParam) {
Result = Type.getAsString(Policy);
std::string Quals =
@@ -2346,7 +2390,7 @@ static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
} else {
Type.getAsStringInternal(Result, Policy);
}
-
+
return Result;
}
@@ -2357,14 +2401,14 @@ static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
ObjCSubsts);
}
-/// \brief Returns a placeholder string that corresponds to an Objective-C block
+/// Returns a placeholder string that corresponds to an Objective-C block
/// declaration.
///
/// \param BlockDecl A declaration with an Objective-C block type.
///
/// \param Block The most relevant type location for that block type.
///
-/// \param SuppressBlockName Determines wether or not the name of the block
+/// \param SuppressBlockName Determines whether or not the name of the block
/// declaration is included in the resulting string.
static std::string
formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
@@ -2449,7 +2493,7 @@ static std::string GetDefaultValueString(const ParmVarDecl *Param,
return " " + DefValue;
}
-/// \brief Add function parameter chunks to the given code completion string.
+/// Add function parameter chunks to the given code completion string.
static void AddFunctionParameterChunks(Preprocessor &PP,
const PrintingPolicy &Policy,
const FunctionDecl *Function,
@@ -2457,10 +2501,10 @@ static void AddFunctionParameterChunks(Preprocessor &PP,
unsigned Start = 0,
bool InOptional = false) {
bool FirstParameter = true;
-
+
for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
const ParmVarDecl *Param = Function->getParamDecl(P);
-
+
if (Param->hasDefaultArg() && !InOptional) {
// When we see an optional default argument, put that argument and
// the remaining default arguments into a new, optional string.
@@ -2472,14 +2516,14 @@ static void AddFunctionParameterChunks(Preprocessor &PP,
Result.AddOptionalChunk(Opt.TakeString());
break;
}
-
+
if (FirstParameter)
FirstParameter = false;
else
Result.AddChunk(CodeCompletionString::CK_Comma);
-
+
InOptional = false;
-
+
// Format the placeholder string.
std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
if (Param->hasDefaultArg())
@@ -2492,8 +2536,8 @@ static void AddFunctionParameterChunks(Preprocessor &PP,
Result.AddPlaceholderChunk(
Result.getAllocator().CopyString(PlaceholderStr));
}
-
- if (const FunctionProtoType *Proto
+
+ if (const FunctionProtoType *Proto
= Function->getType()->getAs<FunctionProtoType>())
if (Proto->isVariadic()) {
if (Proto->getNumParams() == 0)
@@ -2503,7 +2547,7 @@ static void AddFunctionParameterChunks(Preprocessor &PP,
}
}
-/// \brief Add template parameter chunks to the given code completion string.
+/// Add template parameter chunks to the given code completion string.
static void AddTemplateParameterChunks(ASTContext &Context,
const PrintingPolicy &Policy,
const TemplateDecl *Template,
@@ -2521,7 +2565,7 @@ static void AddTemplateParameterChunks(ASTContext &Context,
TemplateParameterList::iterator PEnd = Params->end();
if (MaxParameters)
PEnd = Params->begin() + MaxParameters;
- for (TemplateParameterList::iterator P = Params->begin() + Start;
+ for (TemplateParameterList::iterator P = Params->begin() + Start;
P != PEnd; ++P) {
bool HasDefaultArg = false;
std::string PlaceholderStr;
@@ -2530,14 +2574,14 @@ static void AddTemplateParameterChunks(ASTContext &Context,
PlaceholderStr = "typename";
else
PlaceholderStr = "class";
-
+
if (TTP->getIdentifier()) {
PlaceholderStr += ' ';
PlaceholderStr += TTP->getIdentifier()->getName();
}
-
+
HasDefaultArg = TTP->hasDefaultArgument();
- } else if (NonTypeTemplateParmDecl *NTTP
+ } else if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(*P)) {
if (NTTP->getIdentifier())
PlaceholderStr = NTTP->getIdentifier()->getName();
@@ -2546,7 +2590,7 @@ static void AddTemplateParameterChunks(ASTContext &Context,
} else {
assert(isa<TemplateTemplateParmDecl>(*P));
TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
-
+
// Since putting the template argument list into the placeholder would
// be very, very long, we just use an abbreviation.
PlaceholderStr = "template<...> class";
@@ -2554,10 +2598,10 @@ static void AddTemplateParameterChunks(ASTContext &Context,
PlaceholderStr += ' ';
PlaceholderStr += TTP->getIdentifier()->getName();
}
-
+
HasDefaultArg = TTP->hasDefaultArgument();
}
-
+
if (HasDefaultArg && !InDefaultArg) {
// When we see an optional default argument, put that argument and
// the remaining default arguments into a new, optional string.
@@ -2570,31 +2614,31 @@ static void AddTemplateParameterChunks(ASTContext &Context,
Result.AddOptionalChunk(Opt.TakeString());
break;
}
-
+
InDefaultArg = false;
-
+
if (FirstParameter)
FirstParameter = false;
else
Result.AddChunk(CodeCompletionString::CK_Comma);
-
+
// Add the placeholder string.
Result.AddPlaceholderChunk(
Result.getAllocator().CopyString(PlaceholderStr));
- }
+ }
}
-/// \brief Add a qualifier to the given code-completion string, if the
+/// 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,
+static void
+AddQualifierToCompletionString(CodeCompletionBuilder &Result,
+ NestedNameSpecifier *Qualifier,
bool QualifierIsInformative,
ASTContext &Context,
const PrintingPolicy &Policy) {
if (!Qualifier)
return;
-
+
std::string PrintedNNS;
{
llvm::raw_string_ostream OS(PrintedNNS);
@@ -2606,7 +2650,7 @@ AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
}
-static void
+static void
AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
const FunctionDecl *Function) {
const FunctionProtoType *Proto
@@ -2615,7 +2659,7 @@ AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
return;
// FIXME: Add ref-qualifier!
-
+
// Handle single qualifiers without copying
if (Proto->getTypeQuals() == Qualifiers::Const) {
Result.AddInformativeChunk(" const");
@@ -2643,29 +2687,29 @@ AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
}
-/// \brief Add the name of the given declaration
+/// Add the name of the given declaration
static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
const NamedDecl *ND,
CodeCompletionBuilder &Result) {
DeclarationName Name = ND->getDeclName();
if (!Name)
return;
-
+
switch (Name.getNameKind()) {
case DeclarationName::CXXOperatorName: {
const char *OperatorName = nullptr;
switch (Name.getCXXOverloadedOperator()) {
- case OO_None:
+ case OO_None:
case OO_Conditional:
case NUM_OVERLOADED_OPERATORS:
- OperatorName = "operator";
+ 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)
#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;
@@ -2676,7 +2720,7 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Result.AddTypedTextChunk(OperatorName);
break;
}
-
+
case DeclarationName::Identifier:
case DeclarationName::CXXConversionFunctionName:
case DeclarationName::CXXDestructorName:
@@ -2684,14 +2728,14 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Result.AddTypedTextChunk(
Result.getAllocator().CopyString(ND->getNameAsString()));
break;
-
+
case DeclarationName::CXXDeductionGuideName:
case DeclarationName::CXXUsingDirective:
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
break;
-
+
case DeclarationName::CXXConstructorName: {
CXXRecordDecl *Record = nullptr;
QualType Ty = Name.getCXXNameType();
@@ -2705,7 +2749,7 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Result.getAllocator().CopyString(ND->getNameAsString()));
break;
}
-
+
Result.AddTypedTextChunk(
Result.getAllocator().CopyString(Record->getNameAsString()));
if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
@@ -2727,7 +2771,53 @@ CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
CCTUInfo, IncludeBriefComments);
}
-/// \brief If possible, create a new code completion string for the given
+CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro(
+ Preprocessor &PP, CodeCompletionAllocator &Allocator,
+ CodeCompletionTUInfo &CCTUInfo) {
+ assert(Kind == RK_Macro);
+ CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
+ const MacroInfo *MI = PP.getMacroInfo(Macro);
+ Result.AddTypedTextChunk(Result.getAllocator().CopyString(Macro->getName()));
+
+ if (!MI || !MI->isFunctionLike())
+ return Result.TakeString();
+
+ // Format a function-like macro with placeholders for the arguments.
+ Result.AddChunk(CodeCompletionString::CK_LeftParen);
+ MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
+
+ // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
+ if (MI->isC99Varargs()) {
+ --AEnd;
+
+ if (A == AEnd) {
+ Result.AddPlaceholderChunk("...");
+ }
+ }
+
+ for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
+ if (A != MI->param_begin())
+ Result.AddChunk(CodeCompletionString::CK_Comma);
+
+ if (MI->isVariadic() && (A + 1) == AEnd) {
+ SmallString<32> Arg = (*A)->getName();
+ if (MI->isC99Varargs())
+ Arg += ", ...";
+ else
+ Arg += "...";
+ Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
+ break;
+ }
+
+ // Non-variadic macros are simple.
+ Result.AddPlaceholderChunk(
+ Result.getAllocator().CopyString((*A)->getName()));
+ }
+ Result.AddChunk(CodeCompletionString::CK_RightParen);
+ return Result.TakeString();
+}
+
+/// If possible, create a new code completion string for the given
/// result.
///
/// \returns Either a new, heap-allocated code completion string describing
@@ -2740,104 +2830,42 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
CodeCompletionAllocator &Allocator,
CodeCompletionTUInfo &CCTUInfo,
bool IncludeBriefComments) {
+ if (Kind == RK_Macro)
+ return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo);
+
CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
-
+
PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
if (Kind == RK_Pattern) {
Pattern->Priority = Priority;
Pattern->Availability = Availability;
-
+
if (Declaration) {
Result.addParentContext(Declaration->getDeclContext());
Pattern->ParentName = Result.getParentName();
- // Provide code completion comment for self.GetterName where
- // GetterName is the getter method for a property with name
- // different from the property name (declared via a property
- // getter attribute.
- const NamedDecl *ND = Declaration;
- if (const ObjCMethodDecl *M = dyn_cast<ObjCMethodDecl>(ND))
- if (M->isPropertyAccessor())
- if (const ObjCPropertyDecl *PDecl = M->findPropertyDecl())
- if (PDecl->getGetterName() == M->getSelector() &&
- PDecl->getIdentifier() != M->getIdentifier()) {
- if (const RawComment *RC =
- Ctx.getRawCommentForAnyRedecl(M)) {
- Result.addBriefComment(RC->getBriefText(Ctx));
- Pattern->BriefComment = Result.getBriefComment();
- }
- else if (const RawComment *RC =
- Ctx.getRawCommentForAnyRedecl(PDecl)) {
- Result.addBriefComment(RC->getBriefText(Ctx));
- Pattern->BriefComment = Result.getBriefComment();
- }
- }
- }
-
- return Pattern;
- }
-
- if (Kind == RK_Keyword) {
- Result.AddTypedTextChunk(Keyword);
- return Result.TakeString();
- }
-
- if (Kind == RK_Macro) {
- const MacroInfo *MI = PP.getMacroInfo(Macro);
- Result.AddTypedTextChunk(
- Result.getAllocator().CopyString(Macro->getName()));
-
- if (!MI || !MI->isFunctionLike())
- return Result.TakeString();
-
- // Format a function-like macro with placeholders for the arguments.
- Result.AddChunk(CodeCompletionString::CK_LeftParen);
- MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
-
- // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
- if (MI->isC99Varargs()) {
- --AEnd;
-
- if (A == AEnd) {
- Result.AddPlaceholderChunk("...");
+ if (const RawComment *RC =
+ getPatternCompletionComment(Ctx, Declaration)) {
+ Result.addBriefComment(RC->getBriefText(Ctx));
+ Pattern->BriefComment = Result.getBriefComment();
}
}
-
- for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
- if (A != MI->param_begin())
- Result.AddChunk(CodeCompletionString::CK_Comma);
- if (MI->isVariadic() && (A+1) == AEnd) {
- SmallString<32> Arg = (*A)->getName();
- if (MI->isC99Varargs())
- Arg += ", ...";
- else
- Arg += "...";
- Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
- break;
- }
+ return Pattern;
+ }
- // Non-variadic macros are simple.
- Result.AddPlaceholderChunk(
- Result.getAllocator().CopyString((*A)->getName()));
- }
- Result.AddChunk(CodeCompletionString::CK_RightParen);
+ if (Kind == RK_Keyword) {
+ Result.AddTypedTextChunk(Keyword);
return Result.TakeString();
}
-
assert(Kind == RK_Declaration && "Missed a result kind?");
const NamedDecl *ND = Declaration;
Result.addParentContext(ND->getDeclContext());
if (IncludeBriefComments) {
// Add documentation comment, if it exists.
- if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(ND)) {
+ if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) {
Result.addBriefComment(RC->getBriefText(Ctx));
- }
- else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND))
- if (OMD->isPropertyAccessor())
- if (const ObjCPropertyDecl *PDecl = OMD->findPropertyDecl())
- if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
- Result.addBriefComment(RC->getBriefText(Ctx));
+ }
}
if (StartsNestedNameSpecifier) {
@@ -2851,9 +2879,9 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
-
+
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
- AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
+ AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Ctx, Policy);
AddTypedNameChunk(Ctx, Policy, ND, Result);
Result.AddChunk(CodeCompletionString::CK_LeftParen);
@@ -2862,9 +2890,9 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
AddFunctionTypeQualsToCompletionString(Result, Function);
return Result.TakeString();
}
-
+
if (const FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
- AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
+ AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Ctx, Policy);
FunctionDecl *Function = FunTmpl->getTemplatedDecl();
AddTypedNameChunk(Ctx, Policy, Function, Result);
@@ -2885,30 +2913,30 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
LastDeducibleArgument - 1);
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
HasDefaultArg = TTP->hasDefaultArgument();
- else if (NonTypeTemplateParmDecl *NTTP
+ else if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(Param))
HasDefaultArg = NTTP->hasDefaultArgument();
else {
assert(isa<TemplateTemplateParmDecl>(Param));
- HasDefaultArg
+ HasDefaultArg
= cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
}
-
+
if (!HasDefaultArg)
break;
}
}
-
+
if (LastDeducibleArgument) {
// Some of the function template arguments cannot be deduced from a
// function call, so we introduce an explicit template argument list
// containing all of the arguments up to the first deducible argument.
Result.AddChunk(CodeCompletionString::CK_LeftAngle);
- AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
+ AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
LastDeducibleArgument);
Result.AddChunk(CodeCompletionString::CK_RightAngle);
}
-
+
// Add the function parameters
Result.AddChunk(CodeCompletionString::CK_LeftParen);
AddFunctionParameterChunks(PP, Policy, Function, Result);
@@ -2916,9 +2944,9 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
AddFunctionTypeQualsToCompletionString(Result, Function);
return Result.TakeString();
}
-
+
if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
- AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
+ AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Ctx, Policy);
Result.AddTypedTextChunk(
Result.getAllocator().CopyString(Template->getNameAsString()));
@@ -2927,7 +2955,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
Result.AddChunk(CodeCompletionString::CK_RightAngle);
return Result.TakeString();
}
-
+
if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Selector Sel = Method->getSelector();
if (Sel.isUnarySelector()) {
@@ -2942,7 +2970,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
else {
Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
-
+
// If there is only one parameter, and we're past it, add an empty
// typed-text chunk since there is nothing to type.
if (Method->param_size() == 1)
@@ -2961,10 +2989,10 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
Keyword += ":";
if (Idx < StartParameter || AllParametersAreInformative)
Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
- else
+ else
Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
}
-
+
// If we're before the starting parameter, skip the placeholder.
if (Idx < StartParameter)
continue;
@@ -2990,10 +3018,10 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
if (DeclaringEntity || AllParametersAreInformative)
Arg += II->getName();
}
-
+
if (Method->isVariadic() && (P + 1) == PEnd)
Arg += ", ...";
-
+
if (DeclaringEntity)
Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
else if (AllParametersAreInformative)
@@ -3011,15 +3039,15 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
else
Result.AddPlaceholderChunk(", ...");
}
-
+
MaybeAddSentinel(PP, Method, Result);
}
-
+
return Result.TakeString();
}
if (Qualifier)
- AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
+ AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Ctx, Policy);
Result.AddTypedTextChunk(
@@ -3027,7 +3055,60 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
return Result.TakeString();
}
-/// \brief Add function overload parameter chunks to the given code completion
+const RawComment *clang::getCompletionComment(const ASTContext &Ctx,
+ const NamedDecl *ND) {
+ if (!ND)
+ return nullptr;
+ if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND))
+ return RC;
+
+ // Try to find comment from a property for ObjC methods.
+ const ObjCMethodDecl *M = dyn_cast<ObjCMethodDecl>(ND);
+ if (!M)
+ return nullptr;
+ const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
+ if (!PDecl)
+ return nullptr;
+
+ return Ctx.getRawCommentForAnyRedecl(PDecl);
+}
+
+const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx,
+ const NamedDecl *ND) {
+ const ObjCMethodDecl *M = dyn_cast_or_null<ObjCMethodDecl>(ND);
+ if (!M || !M->isPropertyAccessor())
+ return nullptr;
+
+ // Provide code completion comment for self.GetterName where
+ // GetterName is the getter method for a property with name
+ // different from the property name (declared via a property
+ // getter attribute.
+ const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
+ if (!PDecl)
+ return nullptr;
+ if (PDecl->getGetterName() == M->getSelector() &&
+ PDecl->getIdentifier() != M->getIdentifier()) {
+ if (auto *RC = Ctx.getRawCommentForAnyRedecl(M))
+ return RC;
+ if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
+ return RC;
+ }
+ return nullptr;
+}
+
+const RawComment *clang::getParameterComment(
+ const ASTContext &Ctx,
+ const CodeCompleteConsumer::OverloadCandidate &Result,
+ unsigned ArgIndex) {
+ auto FDecl = Result.getFunction();
+ if (!FDecl)
+ return nullptr;
+ if (ArgIndex < FDecl->getNumParams())
+ return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(ArgIndex));
+ return nullptr;
+}
+
+/// Add function overload parameter chunks to the given code completion
/// string.
static void AddOverloadParameterChunks(ASTContext &Context,
const PrintingPolicy &Policy,
@@ -3110,7 +3191,7 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(getFunctionType());
if (!FDecl && !Proto) {
- // Function without a prototype. Just give the return type and a
+ // Function without a prototype. Just give the return type and a
// highlighted ellipsis.
const FunctionType *FT = getFunctionType();
Result.AddResultTypeChunk(Result.getAllocator().CopyString(
@@ -3122,10 +3203,10 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
}
if (FDecl) {
- if (IncludeBriefComments && CurrentArg < FDecl->getNumParams())
- if (auto RC = S.getASTContext().getRawCommentForAnyRedecl(
- FDecl->getParamDecl(CurrentArg)))
+ if (IncludeBriefComments) {
+ if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg))
Result.addBriefComment(RC->getBriefText(S.getASTContext()));
+ }
AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Result.AddTextChunk(
Result.getAllocator().CopyString(FDecl->getNameAsString()));
@@ -3143,18 +3224,18 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
return Result.TakeString();
}
-unsigned clang::getMacroUsagePriority(StringRef MacroName,
+unsigned clang::getMacroUsagePriority(StringRef MacroName,
const LangOptions &LangOpts,
bool PreferredTypeIsPointer) {
unsigned Priority = CCP_Macro;
-
+
// Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
- if (MacroName.equals("nil") || MacroName.equals("NULL") ||
+ if (MacroName.equals("nil") || MacroName.equals("NULL") ||
MacroName.equals("Nil")) {
Priority = CCP_Constant;
if (PreferredTypeIsPointer)
Priority = Priority / CCF_SimilarTypeMatch;
- }
+ }
// Treat "YES", "NO", "true", and "false" as constants.
else if (MacroName.equals("YES") || MacroName.equals("NO") ||
MacroName.equals("true") || MacroName.equals("false"))
@@ -3162,27 +3243,27 @@ unsigned clang::getMacroUsagePriority(StringRef MacroName,
// Treat "bool" as a type.
else if (MacroName.equals("bool"))
Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
-
-
+
+
return Priority;
}
CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
if (!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:
+ 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::ObjCIvar: return CXCursor_ObjCIvarDecl;
case Decl::ObjCMethod:
return cast<ObjCMethodDecl>(D)->isInstanceMethod()
? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
@@ -3211,17 +3292,17 @@ CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
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:
+ 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;
}
@@ -3242,7 +3323,7 @@ CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
}
}
}
-
+
return CXCursor_UnexposedDecl;
}
@@ -3250,10 +3331,10 @@ static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
bool IncludeUndefined,
bool TargetTypeIsPointer = false) {
typedef CodeCompletionResult Result;
-
+
Results.EnterNewScope();
-
- for (Preprocessor::macro_iterator M = PP.macro_begin(),
+
+ for (Preprocessor::macro_iterator M = PP.macro_begin(),
MEnd = PP.macro_end();
M != MEnd; ++M) {
auto MD = PP.getMacroDefinition(M->first);
@@ -3268,17 +3349,17 @@ static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
TargetTypeIsPointer)));
}
}
-
+
Results.ExitScope();
-
+
}
-static void AddPrettyFunctionResults(const LangOptions &LangOpts,
+static void AddPrettyFunctionResults(const LangOptions &LangOpts,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
-
+
Results.EnterNewScope();
-
+
Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
Results.AddResult(Result("__FUNCTION__", CCP_Constant));
if (LangOpts.C99 || LangOpts.CPlusPlus11)
@@ -3295,24 +3376,24 @@ static void HandleCodeCompleteResults(Sema *S,
CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
}
-static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
+static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
Sema::ParserCompletionContext PCC) {
switch (PCC) {
case Sema::PCC_Namespace:
return CodeCompletionContext::CCC_TopLevel;
-
+
case Sema::PCC_Class:
return CodeCompletionContext::CCC_ClassStructUnion;
case Sema::PCC_ObjCInterface:
return CodeCompletionContext::CCC_ObjCInterface;
-
+
case Sema::PCC_ObjCImplementation:
return CodeCompletionContext::CCC_ObjCImplementation;
case Sema::PCC_ObjCInstanceVariableList:
return CodeCompletionContext::CCC_ObjCIvarList;
-
+
case Sema::PCC_Template:
case Sema::PCC_MemberTemplate:
if (S.CurContext->isFileContext())
@@ -3320,7 +3401,7 @@ static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
if (S.CurContext->isRecord())
return CodeCompletionContext::CCC_ClassStructUnion;
return CodeCompletionContext::CCC_Other;
-
+
case Sema::PCC_RecoveryInFunction:
return CodeCompletionContext::CCC_Recovery;
@@ -3334,7 +3415,7 @@ static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
case Sema::PCC_Expression:
case Sema::PCC_Condition:
return CodeCompletionContext::CCC_Expression;
-
+
case Sema::PCC_Statement:
return CodeCompletionContext::CCC_Statement;
@@ -3343,7 +3424,7 @@ static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
case Sema::PCC_ParenthesizedExpression:
return CodeCompletionContext::CCC_ParenthesizedExpression;
-
+
case Sema::PCC_LocalDeclarationSpecifiers:
return CodeCompletionContext::CCC_Type;
}
@@ -3351,27 +3432,27 @@ static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
llvm_unreachable("Invalid ParserCompletionContext!");
}
-/// \brief If we're in a C++ virtual member function, add completion results
-/// that invoke the functions we override, since it's common to invoke the
+/// If we're in a C++ virtual member function, add completion results
+/// that invoke the functions we override, since it's common to invoke the
/// overridden function as well as adding new functionality.
///
/// \param S The semantic analysis object for which we are generating results.
///
/// \param InContext This context in which the nested-name-specifier preceding
-/// the code-completion point
+/// the code-completion point
static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
ResultBuilder &Results) {
// Look through blocks.
DeclContext *CurContext = S.CurContext;
while (isa<BlockDecl>(CurContext))
CurContext = CurContext->getParent();
-
-
+
+
CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
if (!Method || !Method->isVirtual())
return;
-
- // We need to have names for all of the parameters, if we're going to
+
+ // We need to have names for all of the parameters, if we're going to
// generate a forwarding call.
for (auto P : Method->parameters())
if (!P->getDeclName())
@@ -3383,7 +3464,7 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
Results.getCodeCompletionTUInfo());
if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
continue;
-
+
// If we need a nested-name-specifier, add one now.
if (!InContext) {
NestedNameSpecifier *NNS
@@ -3397,8 +3478,8 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
}
} else if (!InContext->Equals(Overridden->getDeclContext()))
continue;
-
- Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
+
+ Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Overridden->getNameAsString()));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
bool FirstParam = true;
@@ -3421,14 +3502,14 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
}
}
-void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
+void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
ModuleIdPath Path) {
typedef CodeCompletionResult Result;
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Other);
Results.EnterNewScope();
-
+
CodeCompletionAllocator &Allocator = Results.getAllocator();
CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
typedef CodeCompletionResult Result;
@@ -3440,7 +3521,7 @@ void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
Builder.AddTypedTextChunk(
Builder.getAllocator().CopyString(Modules[I]->Name));
Results.AddResult(Result(Builder.TakeString(),
- CCP_Declaration,
+ CCP_Declaration,
CXCursor_ModuleImportDecl,
Modules[I]->isAvailable()
? CXAvailability_Available
@@ -3453,14 +3534,14 @@ void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
/*IsInclusionDirective=*/false);
// Enumerate submodules.
if (Mod) {
- for (Module::submodule_iterator Sub = Mod->submodule_begin(),
+ for (Module::submodule_iterator Sub = Mod->submodule_begin(),
SubEnd = Mod->submodule_end();
Sub != SubEnd; ++Sub) {
-
+
Builder.AddTypedTextChunk(
Builder.getAllocator().CopyString((*Sub)->Name));
Results.AddResult(Result(Builder.TakeString(),
- CCP_Declaration,
+ CCP_Declaration,
CXCursor_ModuleImportDecl,
(*Sub)->isAvailable()
? CXAvailability_Available
@@ -3468,18 +3549,18 @@ void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
}
}
}
- Results.ExitScope();
+ Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(),Results.size());
}
-void Sema::CodeCompleteOrdinaryName(Scope *S,
+void Sema::CodeCompleteOrdinaryName(Scope *S,
ParserCompletionContext CompletionContext) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
mapCodeCompletionContext(*this, CompletionContext));
Results.EnterNewScope();
-
+
// Determine how to filter results, e.g., so that the names of
// values (functions, enumerators, function templates, etc.) are
// only allowed where we can have an expression.
@@ -3505,11 +3586,11 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
Results.setFilter(&ResultBuilder::IsOrdinaryName);
else
Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
-
+
if (getLangOpts().CPlusPlus)
MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
break;
-
+
case PCC_RecoveryInFunction:
// Unfiltered
break;
@@ -3521,10 +3602,11 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
if (CurMethod->isInstance())
Results.setObjectTypeQualifiers(
Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
-
+
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
- CodeCompleter->includeGlobals());
+ CodeCompleter->includeGlobals(),
+ CodeCompleter->loadExternal());
AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Results.ExitScope();
@@ -3537,7 +3619,7 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
if (S->getFnParent())
AddPrettyFunctionResults(getLangOpts(), Results);
break;
-
+
case PCC_Namespace:
case PCC_Class:
case PCC_ObjCInterface:
@@ -3551,15 +3633,15 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
case PCC_LocalDeclarationSpecifiers:
break;
}
-
+
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results, false);
-
+
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(),Results.size());
}
-static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
+static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
ParsedType Receiver,
ArrayRef<IdentifierInfo *> SelIdents,
bool AtArgumentExpression,
@@ -3576,7 +3658,7 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
? CodeCompletionContext::CCC_PotentiallyQualifiedName
: CodeCompletionContext::CCC_Name);
Results.EnterNewScope();
-
+
// Type qualifiers can come after names.
Results.AddResult(Result("const"));
Results.AddResult(Result("volatile"));
@@ -3590,16 +3672,17 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
Results.AddResult("final");
if (AllowNonIdentifiers) {
- Results.AddResult(Result("operator"));
+ Results.AddResult(Result("operator"));
}
-
+
// Add nested-name-specifiers.
if (AllowNestedNameSpecifiers) {
Results.allowNestedNameSpecifiers();
Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
- CodeCompleter->includeGlobals());
+ CodeCompleter->includeGlobals(),
+ CodeCompleter->loadExternal());
Results.setFilter(nullptr);
}
}
@@ -3618,7 +3701,7 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
S &&
(S->getFlags() & Scope::DeclScope) != 0 &&
(S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
- Scope::FunctionPrototypeScope |
+ Scope::FunctionPrototypeScope |
Scope::AtCatchScope)) == 0) {
ParsedType T = DS.getRepAsType();
if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
@@ -3628,29 +3711,31 @@ 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,
+ HandleCodeCompleteResults(this, CodeCompleter,
Results.getCompletionContext(),
Results.data(), Results.size());
}
struct Sema::CodeCompleteExpressionData {
- CodeCompleteExpressionData(QualType PreferredType = QualType())
+ CodeCompleteExpressionData(QualType PreferredType = QualType())
: PreferredType(PreferredType), IntegralConstantExpression(false),
ObjCCollection(false) { }
-
+
QualType PreferredType;
bool IntegralConstantExpression;
bool ObjCCollection;
SmallVector<Decl *, 4> IgnoreDecls;
};
-/// \brief Perform code-completion in an expression context when we know what
+/// Perform code-completion in an expression context when we know what
/// type we're looking for.
-void Sema::CodeCompleteExpression(Scope *S,
+void Sema::CodeCompleteExpression(Scope *S,
const CodeCompleteExpressionData &Data) {
- ResultBuilder Results(*this, CodeCompleter->getAllocator(),
- CodeCompleter->getCodeCompletionTUInfo(),
- CodeCompletionContext::CCC_Expression);
+ ResultBuilder Results(
+ *this, CodeCompleter->getAllocator(),
+ CodeCompleter->getCodeCompletionTUInfo(),
+ CodeCompletionContext(CodeCompletionContext::CCC_Expression,
+ Data.PreferredType));
if (Data.ObjCCollection)
Results.setFilter(&ResultBuilder::IsObjCCollection);
else if (Data.IntegralConstantExpression)
@@ -3662,36 +3747,35 @@ void Sema::CodeCompleteExpression(Scope *S,
if (!Data.PreferredType.isNull())
Results.setPreferredType(Data.PreferredType.getNonReferenceType());
-
+
// Ignore any declarations that we were told that we don't care about.
for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
Results.Ignore(Data.IgnoreDecls[I]);
-
+
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
- CodeCompleter->includeGlobals());
-
+ CodeCompleter->includeGlobals(),
+ CodeCompleter->loadExternal());
+
Results.EnterNewScope();
AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Results.ExitScope();
-
+
bool PreferredTypeIsPointer = false;
if (!Data.PreferredType.isNull())
PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
- || Data.PreferredType->isMemberPointerType()
+ || 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);
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext(CodeCompletionContext::CCC_Expression,
- Data.PreferredType),
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
@@ -3701,29 +3785,29 @@ void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
}
-/// \brief The set of properties that have already been added, referenced by
+/// The set of properties that have already been added, referenced by
/// property name.
typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
-/// \brief Retrieve the container definition, if any?
+/// Retrieve the container definition, if any?
static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
if (Interface->hasDefinition())
return Interface->getDefinition();
-
+
return Interface;
}
-
+
if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
if (Protocol->hasDefinition())
return Protocol->getDefinition();
-
+
return Protocol;
}
return Container;
}
-/// \brief Adds a block invocation code completion result for the given block
+/// Adds a block invocation code completion result for the given block
/// declaration \p BD.
static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
CodeCompletionBuilder &Builder,
@@ -3770,7 +3854,7 @@ static void AddObjCProperties(
// Retrieve the definition.
Container = getContainerDef(Container);
-
+
// Add properties in this container.
const auto AddProperty = [&](const ObjCPropertyDecl *P) {
if (!AddedProperties.insert(P->getIdentifier()).second)
@@ -3889,7 +3973,7 @@ static void AddObjCProperties(
}
}
}
-
+
// Add properties in referenced protocols.
if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
for (auto *P : Protocol->protocols())
@@ -3929,17 +4013,22 @@ static void AddObjCProperties(
static void AddRecordMembersCompletionResults(Sema &SemaRef,
ResultBuilder &Results, Scope *S,
QualType BaseType,
- RecordDecl *RD) {
+ 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());
// Access to a C/C++ class, struct, or union.
Results.allowNestedNameSpecifiers();
- CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext);
+ std::vector<FixItHint> FixIts;
+ if (AccessOpFixIt)
+ FixIts.emplace_back(AccessOpFixIt.getValue());
+ CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext, std::move(FixIts));
SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
SemaRef.CodeCompleter->includeGlobals(),
- /*IncludeDependentBases=*/true);
+ /*IncludeDependentBases=*/true,
+ SemaRef.CodeCompleter->loadExternal());
if (SemaRef.getLangOpts().CPlusPlus) {
if (!Results.empty()) {
@@ -3962,106 +4051,138 @@ static void AddRecordMembersCompletionResults(Sema &SemaRef,
}
void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
+ Expr *OtherOpBase,
SourceLocation OpLoc, bool IsArrow,
bool IsBaseExprStatement) {
if (!Base || !CodeCompleter)
return;
-
+
ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
if (ConvertedBase.isInvalid())
return;
- Base = ConvertedBase.get();
-
- QualType BaseType = Base->getType();
+ QualType ConvertedBaseType = ConvertedBase.get()->getType();
+
+ enum CodeCompletionContext::Kind contextKind;
if (IsArrow) {
- if (const PointerType *Ptr = BaseType->getAs<PointerType>())
- BaseType = Ptr->getPointeeType();
- else if (BaseType->isObjCObjectPointerType())
- /*Do nothing*/ ;
- else
- return;
+ if (const PointerType *Ptr = ConvertedBaseType->getAs<PointerType>())
+ ConvertedBaseType = Ptr->getPointeeType();
}
-
- enum CodeCompletionContext::Kind contextKind;
-
+
if (IsArrow) {
contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
- }
- else {
- if (BaseType->isObjCObjectPointerType() ||
- BaseType->isObjCObjectOrInterfaceType()) {
+ } else {
+ if (ConvertedBaseType->isObjCObjectPointerType() ||
+ ConvertedBaseType->isObjCObjectOrInterfaceType()) {
contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
- }
- else {
+ } else {
contextKind = CodeCompletionContext::CCC_DotMemberAccess;
}
}
- CodeCompletionContext CCContext(contextKind, BaseType);
+ CodeCompletionContext CCContext(contextKind, ConvertedBaseType);
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
- CodeCompleter->getCodeCompletionTUInfo(),
- CCContext,
+ CodeCompleter->getCodeCompletionTUInfo(), CCContext,
&ResultBuilder::IsMember);
- Results.EnterNewScope();
- if (const RecordType *Record = BaseType->getAs<RecordType>()) {
- AddRecordMembersCompletionResults(*this, Results, S, BaseType,
- Record->getDecl());
- } else if (const auto *TST = BaseType->getAs<TemplateSpecializationType>()) {
- TemplateName TN = TST->getTemplateName();
- if (const auto *TD =
- dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
- CXXRecordDecl *RD = TD->getTemplatedDecl();
- AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD);
- }
- } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
- if (auto *RD = ICNT->getDecl())
- AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD);
- } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
- // Objective-C property reference.
- AddedPropertiesSet AddedProperties;
-
- if (const ObjCObjectPointerType *ObjCPtr =
- BaseType->getAsObjCInterfacePointerType()) {
- // Add property results based on our interface.
- assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
- AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
- /*AllowNullaryMethods=*/true, CurContext,
- AddedProperties, Results, IsBaseExprStatement);
- }
-
- // Add properties from the protocols in a qualified interface.
- for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
- AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
- CurContext, AddedProperties, Results,
- IsBaseExprStatement);
- } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
- (!IsArrow && BaseType->isObjCObjectType())) {
- // Objective-C instance variable access.
- ObjCInterfaceDecl *Class = nullptr;
- if (const ObjCObjectPointerType *ObjCPtr
- = BaseType->getAs<ObjCObjectPointerType>())
- Class = ObjCPtr->getInterfaceDecl();
- else
- Class = BaseType->getAs<ObjCObjectType>()->getInterface();
-
- // Add all ivars from this class and its superclasses.
- if (Class) {
- CodeCompletionDeclConsumer Consumer(Results, CurContext);
- Results.setFilter(&ResultBuilder::IsObjCIvar);
- LookupVisibleDecls(Class, LookupMemberName, Consumer,
- CodeCompleter->includeGlobals());
+
+ auto DoCompletion = [&](Expr *Base, bool IsArrow, Optional<FixItHint> AccessOpFixIt) -> bool {
+ if (!Base)
+ return false;
+
+ ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
+ if (ConvertedBase.isInvalid())
+ return false;
+ Base = ConvertedBase.get();
+
+ QualType BaseType = Base->getType();
+
+ if (IsArrow) {
+ if (const PointerType *Ptr = BaseType->getAs<PointerType>())
+ BaseType = Ptr->getPointeeType();
+ else if (BaseType->isObjCObjectPointerType())
+ /*Do nothing*/;
+ else
+ return false;
+ }
+
+ if (const RecordType *Record = BaseType->getAs<RecordType>()) {
+ AddRecordMembersCompletionResults(*this, Results, S, BaseType,
+ Record->getDecl(),
+ std::move(AccessOpFixIt));
+ } else if (const auto *TST =
+ BaseType->getAs<TemplateSpecializationType>()) {
+ TemplateName TN = TST->getTemplateName();
+ if (const auto *TD =
+ dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
+ CXXRecordDecl *RD = TD->getTemplatedDecl();
+ AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
+ std::move(AccessOpFixIt));
+ }
+ } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
+ if (auto *RD = ICNT->getDecl())
+ AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
+ std::move(AccessOpFixIt));
+ } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
+ // Objective-C property reference.
+ AddedPropertiesSet AddedProperties;
+
+ if (const ObjCObjectPointerType *ObjCPtr =
+ BaseType->getAsObjCInterfacePointerType()) {
+ // Add property results based on our interface.
+ assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
+ AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
+ /*AllowNullaryMethods=*/true, CurContext,
+ AddedProperties, Results, IsBaseExprStatement);
+ }
+
+ // Add properties from the protocols in a qualified interface.
+ for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
+ AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
+ CurContext, AddedProperties, Results,
+ IsBaseExprStatement);
+ } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
+ (!IsArrow && BaseType->isObjCObjectType())) {
+ // Objective-C instance variable access.
+ ObjCInterfaceDecl *Class = nullptr;
+ if (const ObjCObjectPointerType *ObjCPtr =
+ BaseType->getAs<ObjCObjectPointerType>())
+ Class = ObjCPtr->getInterfaceDecl();
+ else
+ Class = BaseType->getAs<ObjCObjectType>()->getInterface();
+
+ // Add all ivars from this class and its superclasses.
+ if (Class) {
+ CodeCompletionDeclConsumer Consumer(Results, CurContext);
+ Results.setFilter(&ResultBuilder::IsObjCIvar);
+ LookupVisibleDecls(
+ Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(),
+ /*IncludeDependentBases=*/false, CodeCompleter->loadExternal());
+ }
}
+
+ // FIXME: How do we cope with isa?
+ return true;
+ };
+
+ Results.EnterNewScope();
+
+ bool CompletionSucceded = DoCompletion(Base, IsArrow, None);
+ if (CodeCompleter->includeFixIts()) {
+ const CharSourceRange OpRange =
+ CharSourceRange::getTokenRange(OpLoc, OpLoc);
+ CompletionSucceded |= DoCompletion(
+ OtherOpBase, !IsArrow,
+ FixItHint::CreateReplacement(OpRange, IsArrow ? "." : "->"));
}
-
- // FIXME: How do we cope with isa?
-
+
Results.ExitScope();
+ if (!CompletionSucceded)
+ return;
+
// Hand off the results found for code completion.
- HandleCodeCompleteResults(this, CodeCompleter,
- Results.getCompletionContext(),
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
@@ -4100,23 +4221,23 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
Filter = &ResultBuilder::IsEnum;
ContextKind = CodeCompletionContext::CCC_EnumTag;
break;
-
+
case DeclSpec::TST_union:
Filter = &ResultBuilder::IsUnion;
ContextKind = CodeCompletionContext::CCC_UnionTag;
break;
-
+
case DeclSpec::TST_struct:
case DeclSpec::TST_class:
case DeclSpec::TST_interface:
Filter = &ResultBuilder::IsClassOrStruct;
ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
break;
-
+
default:
llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
}
-
+
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
CodeCompletionDeclConsumer Consumer(Results, CurContext);
@@ -4124,14 +4245,17 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
// First pass: look for tags.
Results.setFilter(Filter);
LookupVisibleDecls(S, LookupTagName, Consumer,
- CodeCompleter->includeGlobals());
+ CodeCompleter->includeGlobals(),
+ CodeCompleter->loadExternal());
if (CodeCompleter->includeGlobals()) {
// Second pass: look for nested name specifiers.
Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
- LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
+ LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
+ CodeCompleter->includeGlobals(),
+ CodeCompleter->loadExternal());
}
-
+
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(),Results.size());
}
@@ -4157,7 +4281,7 @@ void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Results.EnterNewScope();
AddTypeQualifierResults(DS, Results, LangOpts);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
+ HandleCodeCompleteResults(this, CodeCompleter,
Results.getCompletionContext(),
Results.data(), Results.size());
}
@@ -4192,7 +4316,7 @@ void Sema::CodeCompleteCase(Scope *S) {
if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
return;
- SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
+ SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer();
QualType type = Switch->getCond()->IgnoreImplicit()->getType();
if (!type->isEnumeralType()) {
CodeCompleteExpressionData Data(type);
@@ -4200,20 +4324,20 @@ void Sema::CodeCompleteCase(Scope *S) {
CodeCompleteExpression(S, Data);
return;
}
-
+
// Code-complete the cases of a switch statement over an enumeration type
- // by providing the list of
+ // by providing the list of
EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
if (EnumDecl *Def = Enum->getDefinition())
Enum = Def;
-
+
// Determine which enumerators we have already seen in the switch statement.
// FIXME: Ideally, we would also be able to look *past* the code-completion
// token, in case we are code-completing in the middle of the switch and not
// at the end. However, we aren't able to do so at the moment.
llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
NestedNameSpecifier *Qualifier = nullptr;
- for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
+ for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
SC = SC->getNextSwitchCase()) {
CaseStmt *Case = dyn_cast<CaseStmt>(SC);
if (!Case)
@@ -4221,16 +4345,16 @@ void Sema::CodeCompleteCase(Scope *S) {
Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
- if (EnumConstantDecl *Enumerator
+ if (EnumConstantDecl *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
+ // 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
- // values of each enumerator. However, value-based approach would not
- // work as well with C++ templates where enumerators declared within a
+ // values of each enumerator. However, value-based approach would not
+ // work as well with C++ templates where enumerators declared within a
// template are type- and value-dependent.
EnumeratorsSeen.insert(Enumerator);
-
+
// If this is a qualified-id, keep track of the nested-name-specifier
// so that we can reproduce it as part of code completion, e.g.,
//
@@ -4245,14 +4369,14 @@ void Sema::CodeCompleteCase(Scope *S) {
Qualifier = DRE->getQualifier();
}
}
-
+
if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
- // If there are no prior enumerators in C++, check whether we have to
+ // If there are no prior enumerators in C++, check whether we have to
// qualify the names of the enumerators that we suggest, because they
// may not be visible in this scope.
Qualifier = getRequiredQualification(Context, CurContext, Enum);
}
-
+
// Add any enumerators that have not yet been mentioned.
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
@@ -4261,23 +4385,17 @@ void Sema::CodeCompleteCase(Scope *S) {
for (auto *E : Enum->enumerators()) {
if (EnumeratorsSeen.count(E))
continue;
-
+
CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
Results.AddResult(R, CurContext, nullptr, false);
}
Results.ExitScope();
- //We need to make sure we're setting the right context,
- //so only say we include macros if the code completer says we do
- enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
if (CodeCompleter->includeMacros()) {
AddMacroResults(PP, Results, false);
- kind = CodeCompletionContext::CCC_OtherWithMacros;
}
-
- HandleCodeCompleteResults(this, CodeCompleter,
- kind,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
static bool anyNullArguments(ArrayRef<Expr *> Args) {
@@ -4316,7 +4434,7 @@ static void mergeCandidatesWithResults(Sema &SemaRef,
}
}
-/// \brief Get the type of the Nth parameter from a given set of overload
+/// Get the type of the Nth parameter from a given set of overload
/// candidates.
static QualType getParamType(Sema &SemaRef,
ArrayRef<ResultCandidate> Candidates,
@@ -4470,10 +4588,8 @@ void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc,
return;
// A complete type is needed to lookup for constructors.
- if (!isCompleteType(Loc, Type))
- return;
-
- CXXRecordDecl *RD = Type->getAsCXXRecordDecl();
+ CXXRecordDecl *RD =
+ isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
if (!RD) {
CodeCompleteExpression(S, Type);
return;
@@ -4511,7 +4627,7 @@ void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
CodeCompleteOrdinaryName(S, PCC_Expression);
return;
}
-
+
CodeCompleteExpression(S, VD->getType());
}
@@ -4537,13 +4653,14 @@ void Sema::CodeCompleteAfterIf(Scope *S) {
mapCodeCompletionContext(*this, PCC_Statement));
Results.setFilter(&ResultBuilder::IsOrdinaryName);
Results.EnterNewScope();
-
+
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
- CodeCompleter->includeGlobals());
-
+ CodeCompleter->includeGlobals(),
+ CodeCompleter->loadExternal());
+
AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
-
+
// "else" block
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
@@ -4580,13 +4697,13 @@ void Sema::CodeCompleteAfterIf(Scope *S) {
Results.AddResult(Builder.TakeString());
Results.ExitScope();
-
+
if (S->getFnParent())
AddPrettyFunctionResults(getLangOpts(), Results);
-
+
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results, false);
-
+
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(),Results.size());
}
@@ -4649,7 +4766,8 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
/*IncludeGlobalScope=*/true,
- /*IncludeDependentBases=*/true);
+ /*IncludeDependentBases=*/true,
+ CodeCompleter->loadExternal());
}
auto CC = Results.getCompletionContext();
@@ -4662,33 +4780,33 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
void Sema::CodeCompleteUsing(Scope *S) {
if (!CodeCompleter)
return;
-
+
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_PotentiallyQualifiedName,
&ResultBuilder::IsNestedNameSpecifier);
Results.EnterNewScope();
-
+
// If we aren't in class scope, we could see the "namespace" keyword.
if (!S->isClassScope())
Results.AddResult(CodeCompletionResult("namespace"));
-
- // After "using", we can see anything that would start a
+
+ // After "using", we can see anything that would start a
// nested-name-specifier.
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
- CodeCompleter->includeGlobals());
+ CodeCompleter->includeGlobals(),
+ CodeCompleter->loadExternal());
Results.ExitScope();
-
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_PotentiallyQualifiedName,
- Results.data(),Results.size());
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompleteUsingDirective(Scope *S) {
if (!CodeCompleter)
return;
-
+
// After "using namespace", we expect to see a namespace name or namespace
// alias.
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
@@ -4698,46 +4816,46 @@ void Sema::CodeCompleteUsingDirective(Scope *S) {
Results.EnterNewScope();
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
- CodeCompleter->includeGlobals());
+ CodeCompleter->includeGlobals(),
+ CodeCompleter->loadExternal());
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Namespace,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompleteNamespaceDecl(Scope *S) {
if (!CodeCompleter)
return;
-
+
DeclContext *Ctx = S->getEntity();
if (!S->getParent())
Ctx = Context.getTranslationUnitDecl();
-
+
bool SuppressedGlobalResults
= Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
-
+
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
SuppressedGlobalResults
? CodeCompletionContext::CCC_Namespace
: CodeCompletionContext::CCC_Other,
&ResultBuilder::IsNamespace);
-
+
if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
// We only want to see those namespaces that have already been defined
// within this scope, because its likely that the user is creating an
- // extended namespace declaration. Keep track of the most recent
+ // extended namespace declaration. Keep track of the most recent
// definition of each namespace.
std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
- for (DeclContext::specific_decl_iterator<NamespaceDecl>
+ for (DeclContext::specific_decl_iterator<NamespaceDecl>
NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
NS != NSEnd; ++NS)
OrigToLatest[NS->getOriginalNamespace()] = *NS;
-
- // Add the most recent definition (or extended definition) of each
+
+ // Add the most recent definition (or extended definition) of each
// namespace to the list of results.
Results.EnterNewScope();
- for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
+ for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
NS = OrigToLatest.begin(),
NSEnd = OrigToLatest.end();
NS != NSEnd; ++NS)
@@ -4747,8 +4865,8 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) {
CurContext, nullptr, false);
Results.ExitScope();
}
-
- HandleCodeCompleteResults(this, CodeCompleter,
+
+ HandleCodeCompleteResults(this, CodeCompleter,
Results.getCompletionContext(),
Results.data(),Results.size());
}
@@ -4756,7 +4874,7 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) {
void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
if (!CodeCompleter)
return;
-
+
// After "namespace", we expect to see a namespace or alias.
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
@@ -4764,8 +4882,9 @@ void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
&ResultBuilder::IsNamespaceOrAlias);
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
- CodeCompleter->includeGlobals());
- HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompleter->includeGlobals(),
+ CodeCompleter->loadExternal());
+ HandleCodeCompleteResults(this, CodeCompleter,
Results.getCompletionContext(),
Results.data(),Results.size());
}
@@ -4780,26 +4899,26 @@ void Sema::CodeCompleteOperatorName(Scope *S) {
CodeCompletionContext::CCC_Type,
&ResultBuilder::IsType);
Results.EnterNewScope();
-
+
// Add the names of overloadable operators.
#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
if (std::strcmp(Spelling, "?")) \
Results.AddResult(Result(Spelling));
#include "clang/Basic/OperatorKinds.def"
-
+
// Add any type names visible from the current scope
Results.allowNestedNameSpecifiers();
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
- CodeCompleter->includeGlobals());
-
+ CodeCompleter->includeGlobals(),
+ CodeCompleter->loadExternal());
+
// Add any type specifiers
AddTypeSpecifierResults(getLangOpts(), Results);
Results.ExitScope();
-
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Type,
- Results.data(),Results.size());
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompleteConstructorInitializer(
@@ -4813,12 +4932,12 @@ void Sema::CodeCompleteConstructorInitializer(
CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
if (!Constructor)
return;
-
+
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_PotentiallyQualifiedName);
Results.EnterNewScope();
-
+
// Fill in any already-initialized fields or base classes.
llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
@@ -4830,7 +4949,7 @@ void Sema::CodeCompleteConstructorInitializer(
InitializedFields.insert(cast<FieldDecl>(
Initializers[I]->getAnyMember()));
}
-
+
// Add completions for base classes.
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
@@ -4841,69 +4960,69 @@ void Sema::CodeCompleteConstructorInitializer(
if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
.second) {
SawLastInitializer
- = !Initializers.empty() &&
+ = !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(),
+ Results.AddResult(CodeCompletionResult(Builder.TakeString(),
SawLastInitializer? CCP_NextInitializer
: CCP_MemberDeclaration));
SawLastInitializer = false;
}
-
+
// Add completions for virtual base classes.
for (const auto &Base : ClassDecl->vbases()) {
if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
.second) {
SawLastInitializer
- = !Initializers.empty() &&
+ = !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(),
+ Results.AddResult(CodeCompletionResult(Builder.TakeString(),
SawLastInitializer? CCP_NextInitializer
: CCP_MemberDeclaration));
SawLastInitializer = false;
}
-
+
// Add completions for members.
for (auto *Field : ClassDecl->fields()) {
if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
.second) {
SawLastInitializer
- = !Initializers.empty() &&
+ = !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(),
+ Results.AddResult(CodeCompletionResult(Builder.TakeString(),
SawLastInitializer? CCP_NextInitializer
: CCP_MemberDeclaration,
CXCursor_MemberRef,
@@ -4912,12 +5031,12 @@ void Sema::CodeCompleteConstructorInitializer(
SawLastInitializer = false;
}
Results.ExitScope();
-
+
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
-/// \brief Determine whether this scope denotes a namespace.
+/// Determine whether this scope denotes a namespace.
static bool isNamespaceScope(Scope *S) {
DeclContext *DC = S->getEntity();
if (!DC)
@@ -4941,10 +5060,10 @@ void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
IncludedThis = true;
continue;
}
-
+
Known.insert(C.Id);
}
-
+
// Look for other capturable variables.
for (; S && !isNamespaceScope(S); S = S->getParent()) {
for (const auto *D : S->decls()) {
@@ -4953,7 +5072,7 @@ void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
!Var->hasLocalStorage() ||
Var->hasAttr<BlocksAttr>())
continue;
-
+
if (Known.insert(Var->getIdentifier()).second)
Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
CurContext, nullptr, false);
@@ -4963,9 +5082,9 @@ void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
// Add 'this', if it would be valid.
if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
addThisCompletion(*this, Results);
-
+
Results.ExitScope();
-
+
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
@@ -4980,7 +5099,7 @@ static void AddObjCImplementationResults(const LangOptions &LangOpts,
typedef CodeCompletionResult Result;
// Since we have an implementation, we can end it.
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
-
+
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
if (LangOpts.ObjC2) {
@@ -4989,30 +5108,30 @@ static void AddObjCImplementationResults(const LangOptions &LangOpts,
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("property");
Results.AddResult(Result(Builder.TakeString()));
-
+
// @synthesize
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("property");
Results.AddResult(Result(Builder.TakeString()));
- }
+ }
}
static void AddObjCInterfaceResults(const LangOptions &LangOpts,
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")));
-
+
if (LangOpts.ObjC2) {
// @property
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
-
+
// @required
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
-
+
// @optional
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
}
@@ -5022,35 +5141,35 @@ static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
typedef CodeCompletionResult Result;
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
-
+
// @class name ;
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("name");
Results.AddResult(Result(Builder.TakeString()));
-
+
if (Results.includeCodePatterns()) {
- // @interface name
- // FIXME: Could introduce the whole pattern, including superclasses and
+ // @interface name
+ // FIXME: Could introduce the whole pattern, including superclasses and
// such.
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.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("protocol");
Results.AddResult(Result(Builder.TakeString()));
-
+
// @implementation name
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.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -5080,9 +5199,8 @@ void Sema::CodeCompleteObjCAtDirective(Scope *S) {
else
AddObjCTopLevelResults(Results, false);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
@@ -5101,7 +5219,7 @@ static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
Builder.AddPlaceholderChunk("type-name");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
-
+
// @protocol ( protocol-name )
Builder.AddResultTypeChunk("Protocol *");
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
@@ -5154,7 +5272,7 @@ static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
typedef CodeCompletionResult Result;
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
-
+
if (Results.includeCodePatterns()) {
// @try { statements } @catch ( declaration ) { statements } @finally
// { statements }
@@ -5175,13 +5293,13 @@ static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Results.AddResult(Result(Builder.TakeString()));
}
-
+
// @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"));
@@ -5214,9 +5332,8 @@ void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Results.EnterNewScope();
AddObjCVisibilityResults(getLangOpts(), Results, false);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompleteObjCAtStatement(Scope *S) {
@@ -5227,9 +5344,8 @@ void Sema::CodeCompleteObjCAtStatement(Scope *S) {
AddObjCStatementResults(Results, false);
AddObjCExpressionResults(Results, false);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompleteObjCAtExpression(Scope *S) {
@@ -5239,25 +5355,24 @@ void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Results.EnterNewScope();
AddObjCExpressionResults(Results, false);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
-/// \brief Determine whether the addition of the given flag to an Objective-C
+/// Determine whether the addition of the given flag to an Objective-C
/// property's attributes will cause a conflict.
static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
// Check if we've already added this flag.
if (Attributes & NewFlag)
return true;
-
+
Attributes |= NewFlag;
-
+
// Check for collisions with "readonly".
if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
(Attributes & ObjCDeclSpec::DQ_PR_readwrite))
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 |
@@ -5273,16 +5388,16 @@ static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
return true;
-
+
return false;
}
-void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
+void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
if (!CodeCompleter)
return;
-
+
unsigned Attributes = ODS.getPropertyAttributes();
-
+
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Other);
@@ -5335,12 +5450,11 @@ void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Results.AddResult(CodeCompletionResult("null_resettable"));
}
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
-/// \brief Describes the kind of Objective-C method that we want to find
+/// Describes the kind of Objective-C method that we want to find
/// via code completion.
enum ObjCMethodKind {
MK_Any, ///< Any kind of method, provided it means other specified criteria.
@@ -5355,20 +5469,20 @@ static bool isAcceptableObjCSelector(Selector Sel,
unsigned NumSelIdents = SelIdents.size();
if (NumSelIdents > Sel.getNumArgs())
return false;
-
+
switch (WantKind) {
case MK_Any: break;
case MK_ZeroArgSelector: return Sel.isUnarySelector();
case MK_OneArgSelector: return Sel.getNumArgs() == 1;
}
-
+
if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
return false;
-
+
for (unsigned I = 0; I != NumSelIdents; ++I)
if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
return false;
-
+
return true;
}
@@ -5381,16 +5495,16 @@ static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
}
namespace {
- /// \brief A set of selectors, which is used to avoid introducing multiple
+ /// 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;
}
-/// \brief Add all of the Objective-C methods in the given Objective-C
+/// Add all of the Objective-C methods in the given Objective-C
/// container to the set of results.
///
-/// The container will be a class, protocol, category, or implementation of
-/// any of the above. This mether will recurse to include methods from
+/// The container will be a class, protocol, category, or implementation of
+/// any of the above. This mether will recurse to include methods from
/// the superclasses of classes along with their categories, protocols, and
/// implementations.
///
@@ -5422,7 +5536,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
// metaclass.
if (M->isInstanceMethod() == WantInstanceMethods ||
(IsRootClass && !WantInstanceMethods)) {
- // Check whether the selector identifiers we've been given are a
+ // Check whether the selector identifiers we've been given are a
// subset of the identifiers for this particular method.
if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
continue;
@@ -5438,23 +5552,23 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
Results.MaybeAddResult(R, CurContext);
}
}
-
+
// Visit the protocols of protocols.
if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
if (Protocol->hasDefinition()) {
const ObjCList<ObjCProtocolDecl> &Protocols
= Protocol->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
- E = Protocols.end();
+ E = Protocols.end();
I != E; ++I)
AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
Selectors, AllowSameLength, Results, false, IsRootClass);
}
}
-
+
if (!IFace || !IFace->hasDefinition())
return;
-
+
// Add methods in protocols.
for (auto *I : IFace->protocols())
AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
@@ -5467,7 +5581,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
InOriginalClass, IsRootClass);
// Add a categories protocol methods.
- const ObjCList<ObjCProtocolDecl> &Protocols
+ const ObjCList<ObjCProtocolDecl> &Protocols
= CatDecl->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
E = Protocols.end();
@@ -5481,7 +5595,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
Selectors, AllowSameLength, Results, InOriginalClass,
IsRootClass);
}
-
+
// Add methods in superclass.
// Avoid passing in IsRootClass since root classes won't have super classes.
if (IFace->getSuperClass())
@@ -5519,9 +5633,8 @@ void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
/*AllowSameLength=*/true, Results);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
@@ -5548,9 +5661,8 @@ void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Selectors, /*AllowSameLength=*/true, Results);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
@@ -5559,22 +5671,22 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Type);
Results.EnterNewScope();
-
+
// Add context-sensitive, Objective-C parameter-passing keywords.
bool AddedInOut = false;
- if ((DS.getObjCDeclQualifier() &
+ if ((DS.getObjCDeclQualifier() &
(ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
Results.AddResult("in");
Results.AddResult("inout");
AddedInOut = true;
}
- if ((DS.getObjCDeclQualifier() &
+ if ((DS.getObjCDeclQualifier() &
(ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
Results.AddResult("out");
if (!AddedInOut)
Results.AddResult("inout");
}
- if ((DS.getObjCDeclQualifier() &
+ if ((DS.getObjCDeclQualifier() &
(ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
ObjCDeclSpec::DQ_Oneway)) == 0) {
Results.AddResult("bycopy");
@@ -5586,8 +5698,8 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
Results.AddResult("nullable");
Results.AddResult("null_unspecified");
}
-
- // If we're completing the return type of an Objective-C method and the
+
+ // If we're completing the return type of an Objective-C method and the
// identifier IBAction refers to a macro, provide a completion item for
// an action, e.g.,
// IBAction)<#selector#>:(id)sender
@@ -5611,26 +5723,26 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
if (!IsParameter) {
Results.AddResult(CodeCompletionResult("instancetype"));
}
-
+
// Add various builtin type names and specifiers.
AddOrdinaryNameResults(PCC_Type, S, *this, Results);
Results.ExitScope();
-
+
// Add the various type names
Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
- CodeCompleter->includeGlobals());
-
+ CodeCompleter->includeGlobals(),
+ CodeCompleter->loadExternal());
+
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results, false);
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Type,
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
-/// \brief When we have an expression with type "id", we may assume
+/// When we have an expression with type "id", we may assume
/// that it has some more-specific class type based on knowledge of
/// common uses of Objective-C. This routine returns that class type,
/// or NULL if no better result could be determined.
@@ -5702,7 +5814,7 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
}
// Add a special completion for a message send to "super", which fills in the
-// most likely case of forwarding all of our arguments to the superclass
+// most likely case of forwarding all of our arguments to the superclass
// function.
///
/// \param S The semantic analysis object.
@@ -5715,7 +5827,7 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
///
/// \param Results The set of results to augment.
///
-/// \returns the Objective-C method declaration that would be invoked by
+/// \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,
@@ -5733,7 +5845,7 @@ static ObjCMethodDecl *AddSuperSendCompletion(
ObjCMethodDecl *SuperMethod = nullptr;
while ((Class = Class->getSuperClass()) && !SuperMethod) {
// Check in the class
- SuperMethod = Class->getMethod(CurMethod->getSelector(),
+ SuperMethod = Class->getMethod(CurMethod->getSelector(),
CurMethod->isInstanceMethod());
// Check in categories or class extensions.
@@ -5759,7 +5871,7 @@ static ObjCMethodDecl *AddSuperSendCompletion(
SuperP = SuperMethod->param_begin();
CurP != CurPEnd; ++CurP, ++SuperP) {
// Make sure the parameter types are compatible.
- if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
+ if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
(*SuperP)->getType()))
return nullptr;
@@ -5767,11 +5879,11 @@ static ObjCMethodDecl *AddSuperSendCompletion(
if (!(*CurP)->getIdentifier())
return nullptr;
}
-
+
// We have a superclass method. Now, form the send-to-super completion.
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
-
+
// Give this completion a return type.
AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
Results.getCompletionContext().getBaseType(),
@@ -5782,7 +5894,7 @@ static ObjCMethodDecl *AddSuperSendCompletion(
Builder.AddTypedTextChunk("super");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
}
-
+
Selector Sel = CurMethod->getSelector();
if (Sel.isUnarySelector()) {
if (NeedSuperKeyword)
@@ -5796,7 +5908,7 @@ static ObjCMethodDecl *AddSuperSendCompletion(
for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
if (I > SelIdents.size())
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
-
+
if (I < SelIdents.size())
Builder.AddInformativeChunk(
Builder.getAllocator().CopyString(
@@ -5812,16 +5924,16 @@ static ObjCMethodDecl *AddSuperSendCompletion(
Builder.getAllocator().CopyString(
Sel.getNameForSlot(I) + ":"));
Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
- (*CurP)->getIdentifier()->getName()));
+ (*CurP)->getIdentifier()->getName()));
}
}
}
-
+
Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
CCP_SuperCompletion));
return SuperMethod;
}
-
+
void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
typedef CodeCompletionResult Result;
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
@@ -5830,32 +5942,33 @@ void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
getLangOpts().CPlusPlus11
? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
: &ResultBuilder::IsObjCMessageReceiver);
-
+
CodeCompletionDeclConsumer Consumer(Results, CurContext);
Results.EnterNewScope();
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
- CodeCompleter->includeGlobals());
-
+ CodeCompleter->includeGlobals(),
+ CodeCompleter->loadExternal());
+
// If we are in an Objective-C method inside a class that has a superclass,
// add "super" as an option.
if (ObjCMethodDecl *Method = getCurMethodDecl())
if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
if (Iface->getSuperClass()) {
Results.AddResult(Result("super"));
-
+
AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
}
-
+
if (getLangOpts().CPlusPlus11)
addThisCompletion(*this, Results);
-
+
Results.ExitScope();
-
+
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results, false);
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
-
+
}
void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
@@ -5867,7 +5980,7 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
CDecl = CurMethod->getClassInterface();
if (!CDecl)
return;
-
+
// Find the superclass of this class.
CDecl = CDecl->getSuperClass();
if (!CDecl)
@@ -5887,7 +6000,7 @@ 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,
+ NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
LookupOrdinaryName);
if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
// "super" names an interface. Use it.
@@ -5916,24 +6029,24 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
ParsedType Receiver;
if (CDecl)
Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
- return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
+ return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
AtArgumentExpression,
/*IsSuper=*/true);
}
-/// \brief Given a set of code-completion results for the argument of a message
+/// Given a set of code-completion results for the argument of a message
/// send, determine the preferred type (if any) for that argument expression.
static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
unsigned NumSelIdents) {
- typedef CodeCompletionResult Result;
+ typedef CodeCompletionResult Result;
ASTContext &Context = Results.getSema().Context;
-
+
QualType PreferredType;
unsigned BestPriority = CCP_Unlikely * 2;
Result *ResultsData = Results.data();
for (unsigned I = 0, N = Results.size(); I != N; ++I) {
Result &R = ResultsData[I];
- if (R.Kind == Result::RK_Declaration &&
+ if (R.Kind == Result::RK_Declaration &&
isa<ObjCMethodDecl>(R.Declaration)) {
if (R.Priority <= BestPriority) {
const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
@@ -5955,7 +6068,7 @@ static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
return PreferredType;
}
-static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
+static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
ParsedType Receiver,
ArrayRef<IdentifierInfo *> SelIdents,
bool AtArgumentExpression,
@@ -5968,55 +6081,55 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
// corresponding declaration.
if (Receiver) {
QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
- if (!T.isNull())
+ if (!T.isNull())
if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
CDecl = Interface->getInterface();
}
-
+
// Add all of the factory methods in this Objective-C class, its protocols,
// superclasses, categories, implementation, etc.
Results.EnterNewScope();
-
- // If this is a send-to-super, try to add the special "super" send
+
+ // 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))
Results.Ignore(SuperMethod);
}
-
+
// If we're inside an Objective-C method definition, prefer its selector to
// others.
if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Results.setPreferredSelector(CurMethod->getSelector());
-
+
VisitedSelectorSet Selectors;
- if (CDecl)
+ if (CDecl)
AddObjCMethods(CDecl, false, MK_Any, SelIdents,
SemaRef.CurContext, Selectors, AtArgumentExpression,
- Results);
+ Results);
else {
// We're messaging "id" as a type; provide all class/factory methods.
-
+
// If we have an external source, load the entire class method
// pool from the AST file.
if (SemaRef.getExternalSource()) {
- for (uint32_t I = 0,
+ for (uint32_t I = 0,
N = SemaRef.getExternalSource()->GetNumExternalSelectors();
I != N; ++I) {
Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
continue;
-
+
SemaRef.ReadMethodPool(Sel);
}
}
-
+
for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
MEnd = SemaRef.MethodPool.end();
M != MEnd; ++M) {
for (ObjCMethodList *MethList = &M->second.second;
- MethList && MethList->getMethod();
+ MethList && MethList->getMethod();
MethList = MethList->getNext()) {
if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
continue;
@@ -6029,32 +6142,32 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
}
}
}
-
- Results.ExitScope();
+
+ Results.ExitScope();
}
void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
ArrayRef<IdentifierInfo *> SelIdents,
bool AtArgumentExpression,
bool IsSuper) {
-
+
QualType T = this->GetTypeFromParser(Receiver);
-
+
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
T, SelIdents));
-
+
AddClassMessageCompletions(*this, S, Receiver, SelIdents,
AtArgumentExpression, IsSuper, Results);
-
- // If we're actually at the argument expression (rather than prior to the
+
+ // 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
+ // 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,
+ QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
SelIdents.size());
if (PreferredType.isNull())
CodeCompleteOrdinaryName(S, PCC_Expression);
@@ -6063,7 +6176,7 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
return;
}
- HandleCodeCompleteResults(this, CodeCompleter,
+ HandleCodeCompleteResults(this, CodeCompleter,
Results.getCompletionContext(),
Results.data(), Results.size());
}
@@ -6073,9 +6186,9 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
bool AtArgumentExpression,
ObjCInterfaceDecl *Super) {
typedef CodeCompletionResult Result;
-
+
Expr *RecExpr = static_cast<Expr *>(Receiver);
-
+
// If necessary, apply function/array conversion to the receiver.
// C99 6.7.5.3p[7,8].
if (RecExpr) {
@@ -6084,18 +6197,18 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
return;
RecExpr = Conv.get();
}
- QualType ReceiverType = RecExpr? RecExpr->getType()
+ QualType ReceiverType = RecExpr? RecExpr->getType()
: Super? Context.getObjCObjectPointerType(
Context.getObjCInterfaceType(Super))
: Context.getObjCIdType();
-
+
// If we're messaging an expression with type "id" or "Class", check
// whether we know something special about the receiver that allows
// us to assume a more-specific receiver type.
if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
if (ReceiverType->isObjCClassType())
- return CodeCompleteObjCClassMessage(S,
+ return CodeCompleteObjCClassMessage(S,
ParsedType::make(Context.getObjCInterfaceType(IFace)),
SelIdents,
AtArgumentExpression, Super);
@@ -6116,36 +6229,36 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
ReceiverType, SelIdents));
-
+
Results.EnterNewScope();
- // If this is a send-to-super, try to add the special "super" send
+ // 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))
Results.Ignore(SuperMethod);
}
-
+
// If we're inside an Objective-C method definition, prefer its selector to
// others.
if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
Results.setPreferredSelector(CurMethod->getSelector());
-
+
// Keep track of the selectors we've already added.
VisitedSelectorSet Selectors;
-
+
// Handle messages to Class. This really isn't a message to an instance
// method, so we treat it the same way we would treat a message send to a
// class method.
- if (ReceiverType->isObjCClassType() ||
+ if (ReceiverType->isObjCClassType() ||
ReceiverType->isObjCQualifiedClassType()) {
if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
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()) {
@@ -6161,7 +6274,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
CurContext, Selectors, AtArgumentExpression,
Results);
-
+
// Search protocols for instance methods.
for (auto *I : IFacePtr->quals())
AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
@@ -6189,11 +6302,11 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
MEnd = MethodPool.end();
M != MEnd; ++M) {
for (ObjCMethodList *MethList = &M->second.first;
- MethList && MethList->getMethod();
+ MethList && MethList->getMethod();
MethList = MethList->getNext()) {
if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
continue;
-
+
if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
continue;
@@ -6206,15 +6319,15 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
}
}
Results.ExitScope();
-
-
- // If we're actually at the argument expression (rather than prior to the
+
+
+ // 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
+ // 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,
+ QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
SelIdents.size());
if (PreferredType.isNull())
CodeCompleteOrdinaryName(S, PCC_Expression);
@@ -6222,17 +6335,17 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
CodeCompleteExpression(S, PreferredType);
return;
}
-
- HandleCodeCompleteResults(this, CodeCompleter,
+
+ HandleCodeCompleteResults(this, CodeCompleter,
Results.getCompletionContext(),
Results.data(),Results.size());
}
-void Sema::CodeCompleteObjCForCollection(Scope *S,
+void Sema::CodeCompleteObjCForCollection(Scope *S,
DeclGroupPtrTy IterationVar) {
CodeCompleteExpressionData Data;
Data.ObjCCollection = true;
-
+
if (IterationVar.getAsOpaquePtr()) {
DeclGroupRef DG = IterationVar.get();
for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
@@ -6240,7 +6353,7 @@ void Sema::CodeCompleteObjCForCollection(Scope *S,
Data.IgnoreDecls.push_back(*I);
}
}
-
+
CodeCompleteExpression(S, Data);
}
@@ -6254,11 +6367,11 @@ void Sema::CodeCompleteObjCSelector(Scope *S,
Selector Sel = ExternalSource->GetExternalSelector(I);
if (Sel.isNull() || MethodPool.count(Sel))
continue;
-
+
ReadMethodPool(Sel);
}
}
-
+
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_SelectorName);
@@ -6266,7 +6379,7 @@ void Sema::CodeCompleteObjCSelector(Scope *S,
for (GlobalMethodPool::iterator M = MethodPool.begin(),
MEnd = MethodPool.end();
M != MEnd; ++M) {
-
+
Selector Sel = M->first;
if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
continue;
@@ -6279,7 +6392,7 @@ void Sema::CodeCompleteObjCSelector(Scope *S,
Results.AddResult(Builder.TakeString());
continue;
}
-
+
std::string Accumulator;
for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
if (I == SelIdents.size()) {
@@ -6289,7 +6402,7 @@ void Sema::CodeCompleteObjCSelector(Scope *S,
Accumulator.clear();
}
}
-
+
Accumulator += Sel.getNameForSlot(I);
Accumulator += ':';
}
@@ -6297,19 +6410,18 @@ void Sema::CodeCompleteObjCSelector(Scope *S,
Results.AddResult(Builder.TakeString());
}
Results.ExitScope();
-
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_SelectorName,
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
-/// \brief Add all of the protocol declarations that we find in the given
+/// Add all of the protocol declarations that we find in the given
/// (translation unit) context.
static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
bool OnlyForwardDeclarations,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
-
+
for (const auto *D : Ctx->decls()) {
// Record any protocols we find.
if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
@@ -6324,10 +6436,10 @@ void Sema::CodeCompleteObjCProtocolReferences(
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_ObjCProtocolName);
-
+
if (CodeCompleter->includeGlobals()) {
Results.EnterNewScope();
-
+
// Tell the result set to ignore all of the protocols we have
// already seen.
// FIXME: This doesn't work when caching code-completion results.
@@ -6342,40 +6454,38 @@ void Sema::CodeCompleteObjCProtocolReferences(
Results.ExitScope();
}
-
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_ObjCProtocolName,
- Results.data(),Results.size());
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_ObjCProtocolName);
-
+
if (CodeCompleter->includeGlobals()) {
Results.EnterNewScope();
-
+
// Add all protocols.
AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
Results);
Results.ExitScope();
}
-
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_ObjCProtocolName,
- Results.data(),Results.size());
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
-/// \brief Add all of the Objective-C interface declarations that we find in
+/// Add all of the Objective-C interface declarations that we find in
/// the given (translation unit) context.
static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
bool OnlyForwardDeclarations,
bool OnlyUnimplemented,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
-
+
for (const auto *D : Ctx->decls()) {
// Record any interfaces we find.
if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
@@ -6386,32 +6496,31 @@ static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
}
}
-void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
+void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
- CodeCompletionContext::CCC_Other);
+ CodeCompletionContext::CCC_ObjCInterfaceName);
Results.EnterNewScope();
-
+
if (CodeCompleter->includeGlobals()) {
// Add all classes.
AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
false, Results);
}
-
+
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_ObjCInterfaceName,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
- SourceLocation ClassNameLoc) {
+ SourceLocation ClassNameLoc) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_ObjCInterfaceName);
Results.EnterNewScope();
-
+
// Make sure that we ignore the class we're currently defining.
NamedDecl *CurClass
= LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
@@ -6423,18 +6532,17 @@ void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
false, Results);
}
-
+
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_ObjCInterfaceName,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
-void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
+void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
- CodeCompletionContext::CCC_Other);
+ CodeCompletionContext::CCC_ObjCImplementation);
Results.EnterNewScope();
if (CodeCompleter->includeGlobals()) {
@@ -6442,23 +6550,22 @@ void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
true, Results);
}
-
+
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_ObjCInterfaceName,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
-void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
+void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
IdentifierInfo *ClassName,
SourceLocation ClassNameLoc) {
typedef CodeCompletionResult Result;
-
+
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_ObjCCategoryName);
-
+
// Ignore any categories we find that have already been implemented by this
// interface.
llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
@@ -6472,24 +6579,23 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
// Add all of the categories we know about.
Results.EnterNewScope();
TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
- for (const auto *D : TU->decls())
+ 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.ExitScope();
-
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_ObjCCategoryName,
- Results.data(),Results.size());
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
-void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
+void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
IdentifierInfo *ClassName,
SourceLocation ClassNameLoc) {
typedef CodeCompletionResult Result;
-
+
// 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.
@@ -6498,12 +6604,12 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
if (!Class)
return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
-
+
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_ObjCCategoryName);
-
- // Add all of the categories that have have corresponding interface
+
+ // Add all of the categories that have have corresponding interface
// declarations in this class and any of its superclasses, except for
// already-implemented categories in the class itself.
llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
@@ -6516,15 +6622,14 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
CurContext, nullptr, false);
}
-
+
Class = Class->getSuperClass();
IgnoreImplemented = false;
}
Results.ExitScope();
-
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_ObjCCategoryName,
- Results.data(),Results.size());
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
@@ -6536,38 +6641,37 @@ void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
// Figure out where this @synthesize lives.
ObjCContainerDecl *Container
= dyn_cast_or_null<ObjCContainerDecl>(CurContext);
- if (!Container ||
- (!isa<ObjCImplementationDecl>(Container) &&
+ if (!Container ||
+ (!isa<ObjCImplementationDecl>(Container) &&
!isa<ObjCCategoryImplDecl>(Container)))
- return;
+ return;
// Ignore any properties that have already been implemented.
Container = getContainerDef(Container);
for (const auto *D : Container->decls())
if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Results.Ignore(PropertyImpl->getPropertyDecl());
-
+
// Add any properties that we find.
AddedPropertiesSet AddedProperties;
Results.EnterNewScope();
if (ObjCImplementationDecl *ClassImpl
= dyn_cast<ObjCImplementationDecl>(Container))
AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
- /*AllowNullaryMethods=*/false, CurContext,
+ /*AllowNullaryMethods=*/false, CurContext,
AddedProperties, Results);
else
AddObjCProperties(CCContext,
cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
- false, /*AllowNullaryMethods=*/false, CurContext,
+ false, /*AllowNullaryMethods=*/false, CurContext,
AddedProperties, Results);
Results.ExitScope();
-
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other,
- Results.data(),Results.size());
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
-void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
+void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
IdentifierInfo *PropertyName) {
typedef CodeCompletionResult Result;
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
@@ -6577,11 +6681,11 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
// Figure out where this @synthesize lives.
ObjCContainerDecl *Container
= dyn_cast_or_null<ObjCContainerDecl>(CurContext);
- if (!Container ||
- (!isa<ObjCImplementationDecl>(Container) &&
+ if (!Container ||
+ (!isa<ObjCImplementationDecl>(Container) &&
!isa<ObjCCategoryImplDecl>(Container)))
- return;
-
+ return;
+
// Figure out which interface we're looking into.
ObjCInterfaceDecl *Class = nullptr;
if (ObjCImplementationDecl *ClassImpl
@@ -6596,10 +6700,10 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
if (Class) {
if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
- PropertyType
+ PropertyType
= Property->getType().getNonReferenceType().getUnqualifiedType();
-
- // Give preference to ivars
+
+ // Give preference to ivars
Results.setPreferredType(PropertyType);
}
}
@@ -6613,32 +6717,32 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
std::string NameWithSuffix = PropertyName->getName().str();
NameWithSuffix += '_';
for(; Class; Class = Class->getSuperClass()) {
- for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
+ for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
Ivar = Ivar->getNextIvar()) {
Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
CurContext, nullptr, false);
- // Determine whether we've seen an ivar with a name similar to the
+ // Determine whether we've seen an ivar with a name similar to the
// property.
if ((PropertyName == Ivar->getIdentifier() ||
NameWithPrefix == Ivar->getName() ||
NameWithSuffix == Ivar->getName())) {
SawSimilarlyNamedIvar = true;
-
+
// 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
+ if (Results.size() &&
+ Results.data()[Results.size() - 1].Kind
== CodeCompletionResult::RK_Declaration &&
Results.data()[Results.size() - 1].Declaration == Ivar)
Results.data()[Results.size() - 1].Priority--;
}
}
}
-
+
if (!SawSimilarlyNamedIvar) {
// Create ivar result _propName, that the user can use to synthesize
- // an ivar of the appropriate type.
+ // an ivar of the appropriate type.
unsigned Priority = CCP_MemberDeclaration + 1;
typedef CodeCompletionResult Result;
CodeCompletionAllocator &Allocator = Results.getAllocator();
@@ -6649,15 +6753,14 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Policy, Allocator));
Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
- Results.AddResult(Result(Builder.TakeString(), Priority,
+ Results.AddResult(Result(Builder.TakeString(), Priority,
CXCursor_ObjCIvarDecl));
}
-
+
Results.ExitScope();
-
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other,
- Results.data(),Results.size());
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
// Mapping from selectors to the methods that implement that selector, along
@@ -6665,7 +6768,7 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
typedef llvm::DenseMap<
Selector, llvm::PointerIntPair<ObjCMethodDecl *, 1, bool> > KnownMethodsMap;
-/// \brief Find all of the methods that reside in the given container
+/// Find all of the methods that reside in the given container
/// (and its superclasses, protocols, etc.) that meet the given
/// criteria. Insert those methods into the map of known methods,
/// indexed by selector so they can be easily found.
@@ -6682,11 +6785,11 @@ static void FindImplementableMethods(ASTContext &Context,
IFace = IFace->getDefinition();
Container = IFace;
-
+
const ObjCList<ObjCProtocolDecl> &Protocols
= IFace->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
- E = Protocols.end();
+ E = Protocols.end();
I != E; ++I)
FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
KnownMethods, InOriginalClass);
@@ -6694,12 +6797,12 @@ static void FindImplementableMethods(ASTContext &Context,
// Add methods from any class extensions and categories.
for (auto *Cat : IFace->visible_categories()) {
FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
- KnownMethods, false);
+ KnownMethods, false);
}
// Visit the superclass.
if (IFace->getSuperClass())
- FindImplementableMethods(Context, IFace->getSuperClass(),
+ FindImplementableMethods(Context, IFace->getSuperClass(),
WantInstanceMethods, ReturnType,
KnownMethods, false);
}
@@ -6709,14 +6812,14 @@ static void FindImplementableMethods(ASTContext &Context,
const ObjCList<ObjCProtocolDecl> &Protocols
= Category->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
- E = Protocols.end();
+ E = Protocols.end();
I != E; ++I)
FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
KnownMethods, InOriginalClass);
-
+
// If this category is the original class, jump to the interface.
if (InOriginalClass && Category->getClassInterface())
- FindImplementableMethods(Context, Category->getClassInterface(),
+ FindImplementableMethods(Context, Category->getClassInterface(),
WantInstanceMethods, ReturnType, KnownMethods,
false);
}
@@ -6727,12 +6830,12 @@ static void FindImplementableMethods(ASTContext &Context,
return;
Protocol = Protocol->getDefinition();
Container = Protocol;
-
+
// Recurse into protocols.
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);
@@ -6753,7 +6856,7 @@ static void FindImplementableMethods(ASTContext &Context,
}
}
-/// \brief Add the parenthesized return or parameter type chunk to a code
+/// Add the parenthesized return or parameter type chunk to a code
/// completion string.
static void AddObjCPassingTypeChunk(QualType Type,
unsigned ObjCDeclQuals,
@@ -6769,20 +6872,20 @@ static void AddObjCPassingTypeChunk(QualType Type,
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-/// \brief Determine whether the given class is or inherits from a class by
+/// Determine whether the given class is or inherits from a class by
/// the given name.
-static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
+static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
StringRef Name) {
if (!Class)
return false;
-
+
if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
return true;
-
+
return InheritsFromClassNamed(Class->getSuperClass(), Name);
}
-
-/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
+
+/// Add code completions for Objective-C Key-Value Coding (KVC) and
/// Key-Value Observing (KVO).
static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
bool IsInstanceMethod,
@@ -6793,17 +6896,17 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
IdentifierInfo *PropName = Property->getIdentifier();
if (!PropName || PropName->getLength() == 0)
return;
-
+
PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
// Builder that will create each code completion.
typedef CodeCompletionResult Result;
CodeCompletionAllocator &Allocator = Results.getAllocator();
CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
-
+
// The selector table.
SelectorTable &Selectors = Context.Selectors;
-
+
// The property name, copied into the code completion allocation region
// on demand.
struct KeyHolder {
@@ -6817,22 +6920,22 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
operator const char *() {
if (CopiedKey)
return CopiedKey;
-
+
return CopiedKey = Allocator.CopyString(Key);
}
} Key(Allocator, PropName->getName());
-
+
// The uppercased name of the property name.
std::string UpperKey = PropName->getName();
if (!UpperKey.empty())
UpperKey[0] = toUppercase(UpperKey[0]);
-
+
bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
- Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
+ Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
Property->getType());
- bool ReturnTypeMatchesVoid
+ bool ReturnTypeMatchesVoid
= ReturnType.isNull() || ReturnType->isVoidType();
-
+
// Add the normal accessor -(type)key.
if (IsInstanceMethod &&
KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
@@ -6840,19 +6943,19 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
if (ReturnType.isNull())
AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
Context, Policy, Builder);
-
+
Builder.AddTypedTextChunk(Key);
- Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
+ Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
CXCursor_ObjCInstanceMethodDecl));
}
-
+
// If we have an integral or boolean property (or the user has provided
// an integral or boolean return type), add the accessor -(type)isKey.
if (IsInstanceMethod &&
- ((!ReturnType.isNull() &&
+ ((!ReturnType.isNull() &&
(ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
- (ReturnType.isNull() &&
- (Property->getType()->isIntegerType() ||
+ (ReturnType.isNull() &&
+ (Property->getType()->isIntegerType() ||
Property->getType()->isBooleanType())))) {
std::string SelectorName = (Twine("is") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
@@ -6863,16 +6966,16 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("BOOL");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(
Allocator.CopyString(SelectorId->getName()));
- Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
+ Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
CXCursor_ObjCInstanceMethodDecl));
}
}
-
+
// Add the normal mutator.
- if (IsInstanceMethod && ReturnTypeMatchesVoid &&
+ if (IsInstanceMethod && ReturnTypeMatchesVoid &&
!Property->getSetterMethodDecl()) {
std::string SelectorName = (Twine("set") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
@@ -6882,36 +6985,36 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(
Allocator.CopyString(SelectorId->getName()));
Builder.AddTypedTextChunk(":");
AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
Context, Policy, Builder);
Builder.AddTextChunk(Key);
- Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
+ Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
CXCursor_ObjCInstanceMethodDecl));
}
}
-
+
// Indexed and unordered accessors
unsigned IndexedGetterPriority = CCP_CodePattern;
unsigned IndexedSetterPriority = CCP_CodePattern;
unsigned UnorderedGetterPriority = CCP_CodePattern;
unsigned UnorderedSetterPriority = CCP_CodePattern;
- if (const ObjCObjectPointerType *ObjCPointer
+ if (const ObjCObjectPointerType *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.
if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
- IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
+ IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
if (!InheritsFromClassNamed(IFace, "NSArray"))
IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
}
if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
- UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
+ UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
if (!InheritsFromClassNamed(IFace, "NSSet"))
UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
}
@@ -6922,9 +7025,9 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
}
-
+
// Add -(NSUInteger)countOf<key>
- if (IsInstanceMethod &&
+ if (IsInstanceMethod &&
(ReturnType.isNull() || ReturnType->isIntegerType())) {
std::string SelectorName = (Twine("countOf") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
@@ -6935,16 +7038,16 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("NSUInteger");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(
Allocator.CopyString(SelectorId->getName()));
- Results.AddResult(Result(Builder.TakeString(),
- std::min(IndexedGetterPriority,
+ Results.AddResult(Result(Builder.TakeString(),
+ std::min(IndexedGetterPriority,
UnorderedGetterPriority),
CXCursor_ObjCInstanceMethodDecl));
}
}
-
+
// Indexed getters
// Add -(id)objectInKeyAtIndex:(NSUInteger)index
if (IsInstanceMethod &&
@@ -6958,20 +7061,20 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("id");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSUInteger");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("index");
- Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
-
+
// Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
if (IsInstanceMethod &&
- (ReturnType.isNull() ||
+ (ReturnType.isNull() ||
(ReturnType->isObjCObjectPointerType() &&
ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
@@ -6985,17 +7088,17 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("NSArray *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSIndexSet *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("indexes");
- Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
-
+
// Add -(void)getKey:(type **)buffer range:(NSRange)inRange
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName = (Twine("get") + UpperKey).str();
@@ -7003,14 +7106,14 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
&Context.Idents.get(SelectorName),
&Context.Idents.get("range")
};
-
+
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("object-type");
@@ -7023,13 +7126,13 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("NSRange");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("inRange");
- Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
-
+
// Mutable indexed accessors
-
+
// - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
@@ -7037,14 +7140,14 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
&Context.Idents.get("insertObject"),
&Context.Idents.get(SelectorName)
};
-
+
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk("insertObject:");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("object-type");
@@ -7057,11 +7160,11 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddPlaceholderChunk("NSUInteger");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("index");
- Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
-
+
// - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName = (Twine("insert") + UpperKey).str();
@@ -7069,14 +7172,14 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
&Context.Idents.get(SelectorName),
&Context.Idents.get("atIndexes")
};
-
+
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSArray *");
@@ -7088,55 +7191,55 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddPlaceholderChunk("NSIndexSet *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("indexes");
- Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
-
+
// -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName
= (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
- IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+ IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSUInteger");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("index");
- Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
-
+
// -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName
= (Twine("remove") + UpperKey + "AtIndexes").str();
- IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+ IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSIndexSet *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("indexes");
- Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
-
+
// - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName
@@ -7145,14 +7248,14 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
&Context.Idents.get(SelectorName),
&Context.Idents.get("withObject")
};
-
+
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("NSUInteger");
@@ -7164,28 +7267,28 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("id");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("object");
- Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
-
+
// - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
- std::string SelectorName1
+ 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)
};
-
+
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("NSIndexSet *");
@@ -7197,15 +7300,15 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("NSArray *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("array");
- Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
- }
-
+ }
+
// Unordered getters
// - (NSEnumerator *)enumeratorOfKey
- if (IsInstanceMethod &&
- (ReturnType.isNull() ||
+ if (IsInstanceMethod &&
+ (ReturnType.isNull() ||
(ReturnType->isObjCObjectPointerType() &&
ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
@@ -7219,15 +7322,15 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("NSEnumerator *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
- Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
// - (type *)memberOfKey:(type *)object
- if (IsInstanceMethod &&
+ if (IsInstanceMethod &&
(ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
std::string SelectorName = (Twine("memberOf") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
@@ -7238,24 +7341,24 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk(" *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
if (ReturnType.isNull()) {
Builder.AddPlaceholderChunk("object-type");
Builder.AddTextChunk(" *");
} else {
- Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
+ Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Policy,
Builder.getAllocator()));
}
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("object");
- Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
-
+
// Mutable unordered accessors
// - (void)addKeyObject:(type *)object
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
@@ -7268,17 +7371,17 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("object-type");
Builder.AddTextChunk(" *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("object");
- Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
- }
+ }
// - (void)addKey:(NSSet *)objects
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
@@ -7290,17 +7393,17 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSSet *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("objects");
- Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
- }
-
+ }
+
// - (void)removeKeyObject:(type *)object
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName
@@ -7312,18 +7415,18 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("object-type");
Builder.AddTextChunk(" *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("object");
- Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
- }
-
+ }
+
// - (void)removeKey:(NSSet *)objects
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName = (Twine("remove") + UpperKey).str();
@@ -7334,16 +7437,16 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSSet *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("objects");
- Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
- }
+ }
// - (void)intersectKey:(NSSet *)objects
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
@@ -7355,26 +7458,26 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSSet *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("objects");
- Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
+ Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
- }
-
+ }
+
// Key-Value Observing
// + (NSSet *)keyPathsForValuesAffectingKey
- if (!IsInstanceMethod &&
- (ReturnType.isNull() ||
+ if (!IsInstanceMethod &&
+ (ReturnType.isNull() ||
(ReturnType->isObjCObjectPointerType() &&
ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
->getName() == "NSSet"))) {
- std::string SelectorName
+ std::string SelectorName
= (Twine("keyPathsForValuesAffecting") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
@@ -7384,9 +7487,9 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("NSSet<NSString *> *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
- Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
+ Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
CXCursor_ObjCClassMethodDecl));
}
}
@@ -7394,9 +7497,9 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
// + (BOOL)automaticallyNotifiesObserversForKey
if (!IsInstanceMethod &&
(ReturnType.isNull() ||
- ReturnType->isIntegerType() ||
+ ReturnType->isIntegerType() ||
ReturnType->isBooleanType())) {
- std::string SelectorName
+ std::string SelectorName
= (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
@@ -7406,9 +7509,9 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTextChunk("BOOL");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-
+
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
- Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
+ Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
CXCursor_ObjCClassMethodDecl));
}
}
@@ -7422,7 +7525,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Decl *IDecl = nullptr;
if (CurContext->isObjCContainer()) {
ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
- IDecl = cast<Decl>(OCD);
+ IDecl = OCD;
}
// Determine where we should start searching for methods.
ObjCContainerDecl *SearchDecl = nullptr;
@@ -7431,7 +7534,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
SearchDecl = Impl->getClassInterface();
IsInImplementation = true;
- } else if (ObjCCategoryImplDecl *CatImpl
+ } else if (ObjCCategoryImplDecl *CatImpl
= dyn_cast<ObjCCategoryImplDecl>(D)) {
SearchDecl = CatImpl->getCategoryDecl();
IsInImplementation = true;
@@ -7445,17 +7548,17 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
}
if (!SearchDecl) {
- HandleCodeCompleteResults(this, CodeCompleter,
+ HandleCodeCompleteResults(this, CodeCompleter,
CodeCompletionContext::CCC_Other,
nullptr, 0);
return;
}
-
+
// Find all of the methods that we could declare/implement here.
KnownMethodsMap KnownMethods;
- FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
+ FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
ReturnType, KnownMethods);
-
+
// Add declarations or definitions for each of the known methods.
typedef CodeCompletionResult Result;
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
@@ -7463,7 +7566,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
CodeCompletionContext::CCC_Other);
Results.EnterNewScope();
PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
- for (KnownMethodsMap::iterator M = KnownMethods.begin(),
+ for (KnownMethodsMap::iterator M = KnownMethods.begin(),
MEnd = KnownMethods.end();
M != MEnd; ++M) {
ObjCMethodDecl *Method = M->second.getPointer();
@@ -7494,7 +7597,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
// Add parameters to the pattern.
unsigned I = 0;
- for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
+ for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
PEnd = Method->param_end();
P != PEnd; (void)++P, ++I) {
// Add the part of the selector name.
@@ -7520,16 +7623,16 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
(*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()) {
if (Method->param_size() > 0)
Builder.AddChunk(CodeCompletionString::CK_Comma);
Builder.AddTextChunk("...");
- }
+ }
if (IsInImplementation && Results.includeCodePatterns()) {
// We will be defining the method here, so add a compound statement.
@@ -7544,7 +7647,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Builder.AddChunk(CodeCompletionString::CK_SemiColon);
} else
Builder.AddPlaceholderChunk("statements");
-
+
Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
}
@@ -7552,28 +7655,28 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
unsigned Priority = CCP_CodePattern;
if (!M->second.getInt())
Priority += CCD_InBaseClass;
-
+
Results.AddResult(Result(Builder.TakeString(), Method, Priority));
}
- // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
+ // 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) {
SmallVector<ObjCContainerDecl *, 4> Containers;
Containers.push_back(SearchDecl);
-
+
VisitedSelectorSet KnownSelectors;
- for (KnownMethodsMap::iterator M = KnownMethods.begin(),
+ for (KnownMethodsMap::iterator M = KnownMethods.begin(),
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))
IFace = Category->getClassInterface();
-
+
if (IFace)
for (auto *Cat : IFace->visible_categories())
Containers.push_back(Cat);
@@ -7585,15 +7688,14 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
KnownSelectors, Results);
}
}
-
+
Results.ExitScope();
-
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other,
- Results.data(),Results.size());
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
-void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
+void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
bool IsInstanceMethod,
bool AtParameterName,
ParsedType ReturnTy,
@@ -7616,21 +7718,21 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Other);
-
+
if (ReturnTy)
Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
- Results.EnterNewScope();
+ Results.EnterNewScope();
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->getMethod();
MethList = MethList->getNext()) {
if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
continue;
-
+
if (AtParameterName) {
// Suggest parameter names we've seen before.
unsigned NumSelIdents = SelIdents.size();
@@ -7646,7 +7748,7 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
Results.AddResult(Builder.TakeString());
}
}
-
+
continue;
}
@@ -7658,7 +7760,7 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
Results.MaybeAddResult(R, CurContext);
}
}
-
+
Results.ExitScope();
if (!AtParameterName && !SelIdents.empty() &&
@@ -7677,9 +7779,8 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
}
}
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other,
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
@@ -7687,7 +7788,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_PreprocessorDirective);
Results.EnterNewScope();
-
+
// #if <condition>
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
@@ -7695,13 +7796,13 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("condition");
Results.AddResult(Builder.TakeString());
-
+
// #ifdef <macro>
Builder.AddTypedTextChunk("ifdef");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("macro");
Results.AddResult(Builder.TakeString());
-
+
// #ifndef <macro>
Builder.AddTypedTextChunk("ifndef");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -7723,7 +7824,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Builder.AddTypedTextChunk("endif");
Results.AddResult(Builder.TakeString());
}
-
+
// #include "header"
Builder.AddTypedTextChunk("include");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -7739,13 +7840,13 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Builder.AddPlaceholderChunk("header");
Builder.AddTextChunk(">");
Results.AddResult(Builder.TakeString());
-
+
// #define <macro>
Builder.AddTypedTextChunk("define");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("macro");
Results.AddResult(Builder.TakeString());
-
+
// #define <macro>(<args>)
Builder.AddTypedTextChunk("define");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -7754,7 +7855,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Builder.AddPlaceholderChunk("args");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Builder.TakeString());
-
+
// #undef <macro>
Builder.AddTypedTextChunk("undef");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -7766,7 +7867,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("number");
Results.AddResult(Builder.TakeString());
-
+
// #line <number> "filename"
Builder.AddTypedTextChunk("line");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -7776,7 +7877,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Builder.AddPlaceholderChunk("filename");
Builder.AddTextChunk("\"");
Results.AddResult(Builder.TakeString());
-
+
// #error <message>
Builder.AddTypedTextChunk("error");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -7797,7 +7898,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Builder.AddPlaceholderChunk("header");
Builder.AddTextChunk("\"");
Results.AddResult(Builder.TakeString());
-
+
// #import <header>
Builder.AddTypedTextChunk("import");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -7806,7 +7907,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Builder.AddTextChunk(">");
Results.AddResult(Builder.TakeString());
}
-
+
// #include_next "header"
Builder.AddTypedTextChunk("include_next");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -7814,7 +7915,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Builder.AddPlaceholderChunk("header");
Builder.AddTextChunk("\"");
Results.AddResult(Builder.TakeString());
-
+
// #include_next <header>
Builder.AddTypedTextChunk("include_next");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -7835,15 +7936,14 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
// FIXME: we don't support #assert or #unassert, so don't suggest them.
Results.ExitScope();
-
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_PreprocessorDirective,
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
CodeCompleteOrdinaryName(S,
- S->getFnParent()? Sema::PCC_RecoveryInFunction
+ S->getFnParent()? Sema::PCC_RecoveryInFunction
: Sema::PCC_Namespace);
}
@@ -7853,11 +7953,11 @@ void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
IsDefinition? CodeCompletionContext::CCC_MacroName
: CodeCompletionContext::CCC_MacroNameUse);
if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
- // Add just the names of macros, not their arguments.
+ // 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(),
+ for (Preprocessor::macro_iterator M = PP.macro_begin(),
MEnd = PP.macro_end();
M != MEnd; ++M) {
Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
@@ -7870,19 +7970,19 @@ void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
} else if (IsDefinition) {
// FIXME: Can we detect when the user just wrote an include guard above?
}
-
+
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
- Results.data(), Results.size());
+ Results.data(), Results.size());
}
void Sema::CodeCompletePreprocessorExpression() {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_PreprocessorExpression);
-
+
if (!CodeCompleter || CodeCompleter->includeMacros())
AddMacroResults(PP, Results, true);
-
+
// defined (<macro>)
Results.EnterNewScope();
CodeCompletionBuilder Builder(Results.getAllocator(),
@@ -7894,10 +7994,9 @@ void Sema::CodeCompletePreprocessorExpression() {
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Builder.TakeString());
Results.ExitScope();
-
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_PreprocessorExpression,
- Results.data(), Results.size());
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
@@ -7906,7 +8005,7 @@ void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
unsigned Argument) {
// FIXME: In the future, we could provide "overload" results, much like we
// do for function calls.
-
+
// Now just ignore this. There will be another code-completion callback
// for the expanded tokens.
}
@@ -7929,9 +8028,8 @@ void Sema::CodeCompleteAvailabilityPlatformName() {
Twine(Platform) + "ApplicationExtension")));
}
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other, Results.data(),
- Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
@@ -7940,16 +8038,17 @@ void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
ResultBuilder Builder(*this, Allocator, CCTUInfo,
CodeCompletionContext::CCC_Recovery);
if (!CodeCompleter || CodeCompleter->includeGlobals()) {
- CodeCompletionDeclConsumer Consumer(Builder,
+ CodeCompletionDeclConsumer Consumer(Builder,
Context.getTranslationUnitDecl());
- LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
- Consumer);
+ LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
+ Consumer,
+ !CodeCompleter || CodeCompleter->loadExternal());
}
-
+
if (!CodeCompleter || CodeCompleter->includeMacros())
AddMacroResults(PP, Builder, true);
-
+
Results.clear();
- Results.insert(Results.end(),
+ Results.insert(Results.end(),
Builder.data(), Builder.data() + Builder.size());
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp
index e6b640f878c2..1d5454ca778b 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp
@@ -9,15 +9,20 @@
//
// This file implements semantic analysis for C++ Coroutines.
//
+// This file contains references to sections of the Coroutines TS, which
+// can be found at http://wg21.link/coroutines.
+//
//===----------------------------------------------------------------------===//
#include "CoroutineStmtBuilder.h"
+#include "clang/AST/ASTLambda.h"
#include "clang/AST/Decl.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Overload.h"
+#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
using namespace clang;
@@ -55,20 +60,8 @@ static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD,
return QualType();
}
- LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_traits"),
- FuncLoc, Sema::LookupOrdinaryName);
- if (!S.LookupQualifiedName(Result, StdExp)) {
- S.Diag(KwLoc, diag::err_implied_coroutine_type_not_found)
- << "std::experimental::coroutine_traits";
- return QualType();
- }
-
- ClassTemplateDecl *CoroTraits = Result.getAsSingle<ClassTemplateDecl>();
+ ClassTemplateDecl *CoroTraits = S.lookupCoroutineTraits(KwLoc, FuncLoc);
if (!CoroTraits) {
- Result.suppressDiagnostics();
- // We found something weird. Complain about the first thing we found.
- NamedDecl *Found = *Result.begin();
- S.Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits);
return QualType();
}
@@ -194,13 +187,25 @@ static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType,
static bool isValidCoroutineContext(Sema &S, SourceLocation Loc,
StringRef Keyword) {
- // 'co_await' and 'co_yield' are not permitted in unevaluated operands.
+ // 'co_await' and 'co_yield' are not permitted in unevaluated operands,
+ // such as subexpressions of \c sizeof.
+ //
+ // [expr.await]p2, emphasis added: "An await-expression shall appear only in
+ // a *potentially evaluated* expression within the compound-statement of a
+ // function-body outside of a handler [...] A context within a function where
+ // an await-expression can appear is called a suspension context of the
+ // function." And per [expr.yield]p1: "A yield-expression shall appear only
+ // within a suspension context of a function."
if (S.isUnevaluatedContext()) {
S.Diag(Loc, diag::err_coroutine_unevaluated_context) << Keyword;
return false;
}
- // Any other usage must be within a function.
+ // Per [expr.await]p2, any other usage must be within a function.
+ // FIXME: This also covers [expr.await]p2: "An await-expression shall not
+ // appear in a default argument." But the diagnostic QoI here could be
+ // improved to inform the user that default arguments specifically are not
+ // allowed.
auto *FD = dyn_cast<FunctionDecl>(S.CurContext);
if (!FD) {
S.Diag(Loc, isa<ObjCMethodDecl>(S.CurContext)
@@ -231,22 +236,37 @@ static bool isValidCoroutineContext(Sema &S, SourceLocation Loc,
// Diagnose when a constructor, destructor, copy/move assignment operator,
// or the function 'main' are declared as a coroutine.
auto *MD = dyn_cast<CXXMethodDecl>(FD);
+ // [class.ctor]p6: "A constructor shall not be a coroutine."
if (MD && isa<CXXConstructorDecl>(MD))
return DiagInvalid(DiagCtor);
+ // [class.dtor]p17: "A destructor shall not be a coroutine."
else if (MD && isa<CXXDestructorDecl>(MD))
return DiagInvalid(DiagDtor);
+ // N4499 [special]p6: "A special member function shall not be a coroutine."
+ // Per C++ [special]p1, special member functions are the "default constructor,
+ // copy constructor and copy assignment operator, move constructor and move
+ // assignment operator, and destructor."
else if (MD && MD->isCopyAssignmentOperator())
return DiagInvalid(DiagCopyAssign);
else if (MD && MD->isMoveAssignmentOperator())
return DiagInvalid(DiagMoveAssign);
+ // [basic.start.main]p3: "The function main shall not be a coroutine."
else if (FD->isMain())
return DiagInvalid(DiagMain);
// Emit a diagnostics for each of the following conditions which is not met.
+ // [expr.const]p2: "An expression e is a core constant expression unless the
+ // evaluation of e [...] would evaluate one of the following expressions:
+ // [...] an await-expression [...] a yield-expression."
if (FD->isConstexpr())
DiagInvalid(DiagConstexpr);
+ // [dcl.spec.auto]p15: "A function declared with a return type that uses a
+ // placeholder type shall not be a coroutine."
if (FD->getReturnType()->isUndeducedType())
DiagInvalid(DiagAutoRet);
+ // [dcl.fct.def.coroutine]p1: "The parameter-declaration-clause of the
+ // coroutine shall not terminate with an ellipsis that is not part of a
+ // parameter-declaration."
if (FD->isVariadic())
DiagInvalid(DiagVarargs);
@@ -360,12 +380,21 @@ static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc,
if (Result.isInvalid())
return ExprError();
+ // We meant exactly what we asked for. No need for typo correction.
+ if (auto *TE = dyn_cast<TypoExpr>(Result.get())) {
+ S.clearDelayedTypo(TE);
+ S.Diag(Loc, diag::err_no_member)
+ << NameInfo.getName() << Base->getType()->getAsCXXRecordDecl()
+ << Base->getSourceRange();
+ return ExprError();
+ }
+
return S.ActOnCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr);
}
// See if return type is coroutine-handle and if so, invoke builtin coro-resume
// on its address. This is to enable experimental support for coroutine-handle
-// returning await_suspend that results in a guranteed tail call to the target
+// returning await_suspend that results in a guaranteed tail call to the target
// coroutine.
static Expr *maybeTailCall(Sema &S, QualType RetType, Expr *E,
SourceLocation Loc) {
@@ -494,9 +523,72 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) {
CheckVariableDeclarationType(VD);
if (VD->isInvalidDecl())
return nullptr;
- ActOnUninitializedDecl(VD);
+
+ auto *ScopeInfo = getCurFunction();
+ // Build a list of arguments, based on the coroutine functions arguments,
+ // that will be passed to the promise type's constructor.
+ llvm::SmallVector<Expr *, 4> CtorArgExprs;
+
+ // Add implicit object parameter.
+ if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ if (MD->isInstance() && !isLambdaCallOperator(MD)) {
+ ExprResult ThisExpr = ActOnCXXThis(Loc);
+ if (ThisExpr.isInvalid())
+ return nullptr;
+ ThisExpr = CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get());
+ if (ThisExpr.isInvalid())
+ return nullptr;
+ CtorArgExprs.push_back(ThisExpr.get());
+ }
+ }
+
+ auto &Moves = ScopeInfo->CoroutineParameterMoves;
+ for (auto *PD : FD->parameters()) {
+ if (PD->getType()->isDependentType())
+ continue;
+
+ auto RefExpr = ExprEmpty();
+ auto Move = Moves.find(PD);
+ assert(Move != Moves.end() &&
+ "Coroutine function parameter not inserted into move map");
+ // If a reference to the function parameter exists in the coroutine
+ // frame, use that reference.
+ auto *MoveDecl =
+ cast<VarDecl>(cast<DeclStmt>(Move->second)->getSingleDecl());
+ RefExpr =
+ BuildDeclRefExpr(MoveDecl, MoveDecl->getType().getNonReferenceType(),
+ ExprValueKind::VK_LValue, FD->getLocation());
+ if (RefExpr.isInvalid())
+ return nullptr;
+ CtorArgExprs.push_back(RefExpr.get());
+ }
+
+ // 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());
+ InitializedEntity Entity = InitializedEntity::InitializeVariable(VD);
+ InitializationKind Kind = InitializationKind::CreateForInit(
+ VD->getLocation(), /*DirectInit=*/true, PLE);
+ InitializationSequence InitSeq(*this, Entity, Kind, CtorArgExprs,
+ /*TopLevelOfInitList=*/false,
+ /*TreatUnavailableAsInvalid=*/false);
+
+ // Attempt to initialize the promise type with the arguments.
+ // If that fails, fall back to the promise type's default constructor.
+ if (InitSeq) {
+ ExprResult Result = InitSeq.Perform(*this, Entity, Kind, CtorArgExprs);
+ if (Result.isInvalid()) {
+ VD->setInvalidDecl();
+ } else if (Result.get()) {
+ VD->setInit(MaybeCreateExprWithCleanups(Result.get()));
+ VD->setInitStyle(VarDecl::CallInit);
+ CheckCompleteVariableDeclaration(VD);
+ }
+ } else
+ ActOnUninitializedDecl(VD);
+
FD->addDecl(VD);
- assert(!VD->isInvalidDecl());
return VD;
}
@@ -518,6 +610,9 @@ static FunctionScopeInfo *checkCoroutineContext(Sema &S, SourceLocation Loc,
if (ScopeInfo->CoroutinePromise)
return ScopeInfo;
+ if (!S.buildCoroutineParameterMoves(Loc))
+ return nullptr;
+
ScopeInfo->CoroutinePromise = S.buildCoroutinePromise(Loc);
if (!ScopeInfo->CoroutinePromise)
return nullptr;
@@ -654,9 +749,14 @@ ExprResult Sema::BuildResolvedCoawaitExpr(SourceLocation Loc, Expr *E,
if (E->getValueKind() == VK_RValue)
E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
+ // The location of the `co_await` token cannot be used when constructing
+ // the member call expressions since it's before the location of `Expr`, which
+ // is used as the start of the member call expression.
+ SourceLocation CallLoc = E->getExprLoc();
+
// Build the await_ready, await_suspend, await_resume calls.
ReadySuspendResumeResult RSS =
- buildCoawaitCalls(*this, Coroutine->CoroutinePromise, Loc, E);
+ buildCoawaitCalls(*this, Coroutine->CoroutinePromise, CallLoc, E);
if (RSS.IsInvalid)
return ExprError();
@@ -861,6 +961,11 @@ CoroutineStmtBuilder::CoroutineStmtBuilder(Sema &S, FunctionDecl &FD,
!Fn.CoroutinePromise ||
Fn.CoroutinePromise->getType()->isDependentType()) {
this->Body = Body;
+
+ for (auto KV : Fn.CoroutineParameterMoves)
+ this->ParamMovesVector.push_back(KV.second);
+ this->ParamMoves = this->ParamMovesVector;
+
if (!IsPromiseDependentType) {
PromiseRecordDecl = Fn.CoroutinePromise->getType()->getAsCXXRecordDecl();
assert(PromiseRecordDecl && "Type should have already been checked");
@@ -870,7 +975,7 @@ CoroutineStmtBuilder::CoroutineStmtBuilder(Sema &S, FunctionDecl &FD,
bool CoroutineStmtBuilder::buildStatements() {
assert(this->IsValid && "coroutine already invalid");
- this->IsValid = makeReturnObject() && makeParamMoves();
+ this->IsValid = makeReturnObject();
if (this->IsValid && !IsPromiseDependentType)
buildDependentStatements();
return this->IsValid;
@@ -886,12 +991,6 @@ bool CoroutineStmtBuilder::buildDependentStatements() {
return this->IsValid;
}
-bool CoroutineStmtBuilder::buildParameterMoves() {
- assert(this->IsValid && "coroutine already invalid");
- assert(this->ParamMoves.empty() && "param moves already built");
- return this->IsValid = makeParamMoves();
-}
-
bool CoroutineStmtBuilder::makePromiseStmt() {
// Form a declaration statement for the promise declaration, so that AST
// visitors can more easily find it.
@@ -990,7 +1089,12 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
const bool RequiresNoThrowAlloc = ReturnStmtOnAllocFailure != nullptr;
- // FIXME: Add support for stateful allocators.
+ // [dcl.fct.def.coroutine]/7
+ // Lookup allocation functions using a parameter list composed of the
+ // requested size of the coroutine state being allocated, followed by
+ // the coroutine function's arguments. If a matching allocation function
+ // exists, use it. Otherwise, use an allocation function that just takes
+ // the requested size.
FunctionDecl *OperatorNew = nullptr;
FunctionDecl *OperatorDelete = nullptr;
@@ -998,10 +1102,73 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
bool PassAlignment = false;
SmallVector<Expr *, 1> PlacementArgs;
- S.FindAllocationFunctions(Loc, SourceRange(),
- /*UseGlobal*/ false, PromiseType,
+ // [dcl.fct.def.coroutine]/7
+ // "The allocation function’s name is looked up in the scope of P.
+ // [...] If the lookup finds an allocation function in the scope of P,
+ // overload resolution is performed on a function call created by assembling
+ // an argument list. The first argument is the amount of space requested,
+ // and has type std::size_t. The lvalues p1 ... pn are the succeeding
+ // arguments."
+ //
+ // ...where "p1 ... pn" are defined earlier as:
+ //
+ // [dcl.fct.def.coroutine]/3
+ // "For a coroutine f that is a non-static member function, let P1 denote the
+ // type of the implicit object parameter (13.3.1) and P2 ... Pn be the types
+ // of the function parameters; otherwise let P1 ... Pn be the types of the
+ // function parameters. Let p1 ... pn be lvalues denoting those objects."
+ if (auto *MD = dyn_cast<CXXMethodDecl>(&FD)) {
+ if (MD->isInstance() && !isLambdaCallOperator(MD)) {
+ ExprResult ThisExpr = S.ActOnCXXThis(Loc);
+ if (ThisExpr.isInvalid())
+ return false;
+ ThisExpr = S.CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get());
+ if (ThisExpr.isInvalid())
+ return false;
+ PlacementArgs.push_back(ThisExpr.get());
+ }
+ }
+ for (auto *PD : FD.parameters()) {
+ if (PD->getType()->isDependentType())
+ continue;
+
+ // Build a reference to the parameter.
+ auto PDLoc = PD->getLocation();
+ ExprResult PDRefExpr =
+ S.BuildDeclRefExpr(PD, PD->getOriginalType().getNonReferenceType(),
+ ExprValueKind::VK_LValue, PDLoc);
+ if (PDRefExpr.isInvalid())
+ return false;
+
+ PlacementArgs.push_back(PDRefExpr.get());
+ }
+ S.FindAllocationFunctions(Loc, SourceRange(), /*NewScope*/ Sema::AFS_Class,
+ /*DeleteScope*/ Sema::AFS_Both, PromiseType,
/*isArray*/ false, PassAlignment, PlacementArgs,
- OperatorNew, UnusedResult);
+ OperatorNew, UnusedResult, /*Diagnose*/ false);
+
+ // [dcl.fct.def.coroutine]/7
+ // "If no matching function is found, overload resolution is performed again
+ // on a function call created by passing just the amount of space required as
+ // an argument of type std::size_t."
+ if (!OperatorNew && !PlacementArgs.empty()) {
+ PlacementArgs.clear();
+ S.FindAllocationFunctions(Loc, SourceRange(), /*NewScope*/ Sema::AFS_Class,
+ /*DeleteScope*/ Sema::AFS_Both, PromiseType,
+ /*isArray*/ false, PassAlignment, PlacementArgs,
+ OperatorNew, UnusedResult, /*Diagnose*/ false);
+ }
+
+ // [dcl.fct.def.coroutine]/7
+ // "The allocation function’s name is looked up in the scope of P. If this
+ // lookup fails, the allocation function’s name is looked up in the global
+ // scope."
+ if (!OperatorNew) {
+ S.FindAllocationFunctions(Loc, SourceRange(), /*NewScope*/ Sema::AFS_Global,
+ /*DeleteScope*/ Sema::AFS_Both, PromiseType,
+ /*isArray*/ false, PassAlignment, PlacementArgs,
+ OperatorNew, UnusedResult);
+ }
bool IsGlobalOverload =
OperatorNew && !isa<CXXRecordDecl>(OperatorNew->getDeclContext());
@@ -1014,17 +1181,18 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
return false;
PlacementArgs = {StdNoThrow};
OperatorNew = nullptr;
- S.FindAllocationFunctions(Loc, SourceRange(),
- /*UseGlobal*/ true, PromiseType,
+ S.FindAllocationFunctions(Loc, SourceRange(), /*NewScope*/ Sema::AFS_Both,
+ /*DeleteScope*/ Sema::AFS_Both, PromiseType,
/*isArray*/ false, PassAlignment, PlacementArgs,
OperatorNew, UnusedResult);
}
- assert(OperatorNew && "expected definition of operator new to be found");
+ if (!OperatorNew)
+ return false;
if (RequiresNoThrowAlloc) {
const auto *FT = OperatorNew->getType()->getAs<FunctionProtoType>();
- if (!FT->isNothrow(S.Context, /*ResultIfDependent*/ false)) {
+ if (!FT->isNothrow(/*ResultIfDependent*/ false)) {
S.Diag(OperatorNew->getLocation(),
diag::err_coroutine_promise_new_requires_nothrow)
<< OperatorNew;
@@ -1256,10 +1424,6 @@ bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() {
if (Res.isInvalid())
return false;
- if (GroType == FnRetType) {
- GroDecl->setNRVOVariable(true);
- }
-
S.AddInitializerToDecl(GroDecl, Res.get(),
/*DirectInit=*/false);
@@ -1283,6 +1447,8 @@ bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() {
noteMemberDeclaredHere(S, ReturnValue, Fn);
return false;
}
+ if (cast<clang::ReturnStmt>(ReturnStmt.get())->getNRVOCandidate() == GroDecl)
+ GroDecl->setNRVOVariable(true);
this->ReturnStmt = ReturnStmt.get();
return true;
@@ -1304,47 +1470,53 @@ static Expr *castForMoving(Sema &S, Expr *E, QualType T = QualType()) {
.get();
}
-
-/// \brief Build a variable declaration for move parameter.
+/// Build a variable declaration for move parameter.
static VarDecl *buildVarDecl(Sema &S, SourceLocation Loc, QualType Type,
IdentifierInfo *II) {
TypeSourceInfo *TInfo = S.Context.getTrivialTypeSourceInfo(Type, Loc);
- VarDecl *Decl =
- VarDecl::Create(S.Context, S.CurContext, Loc, Loc, II, Type, TInfo, SC_None);
+ VarDecl *Decl = VarDecl::Create(S.Context, S.CurContext, Loc, Loc, II, Type,
+ TInfo, SC_None);
Decl->setImplicit();
return Decl;
}
-bool CoroutineStmtBuilder::makeParamMoves() {
- for (auto *paramDecl : FD.parameters()) {
- auto Ty = paramDecl->getType();
- if (Ty->isDependentType())
+// Build statements that move coroutine function parameters to the coroutine
+// frame, and store them on the function scope info.
+bool Sema::buildCoroutineParameterMoves(SourceLocation Loc) {
+ assert(isa<FunctionDecl>(CurContext) && "not in a function scope");
+ auto *FD = cast<FunctionDecl>(CurContext);
+
+ auto *ScopeInfo = getCurFunction();
+ assert(ScopeInfo->CoroutineParameterMoves.empty() &&
+ "Should not build parameter moves twice");
+
+ for (auto *PD : FD->parameters()) {
+ if (PD->getType()->isDependentType())
continue;
- // No need to copy scalars, llvm will take care of them.
- if (Ty->getAsCXXRecordDecl()) {
- ExprResult ParamRef =
- S.BuildDeclRefExpr(paramDecl, paramDecl->getType(),
- ExprValueKind::VK_LValue, Loc); // FIXME: scope?
- if (ParamRef.isInvalid())
- return false;
+ ExprResult PDRefExpr =
+ BuildDeclRefExpr(PD, PD->getType().getNonReferenceType(),
+ ExprValueKind::VK_LValue, Loc); // FIXME: scope?
+ if (PDRefExpr.isInvalid())
+ return false;
- Expr *RCast = castForMoving(S, ParamRef.get());
+ Expr *CExpr = nullptr;
+ if (PD->getType()->getAsCXXRecordDecl() ||
+ PD->getType()->isRValueReferenceType())
+ CExpr = castForMoving(*this, PDRefExpr.get());
+ else
+ CExpr = PDRefExpr.get();
- auto D = buildVarDecl(S, Loc, Ty, paramDecl->getIdentifier());
- S.AddInitializerToDecl(D, RCast, /*DirectInit=*/true);
+ auto D = buildVarDecl(*this, Loc, PD->getType(), PD->getIdentifier());
+ AddInitializerToDecl(D, CExpr, /*DirectInit=*/true);
- // Convert decl to a statement.
- StmtResult Stmt = S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(D), Loc, Loc);
- if (Stmt.isInvalid())
- return false;
+ // Convert decl to a statement.
+ StmtResult Stmt = ActOnDeclStmt(ConvertDeclToDeclGroup(D), Loc, Loc);
+ if (Stmt.isInvalid())
+ return false;
- ParamMovesVector.push_back(Stmt.get());
- }
+ ScopeInfo->CoroutineParameterMoves.insert(std::make_pair(PD, Stmt.get()));
}
-
- // Convert to ArrayRef in CtorArgs structure that builder inherits from.
- ParamMoves = ParamMovesVector;
return true;
}
@@ -1354,3 +1526,27 @@ StmtResult Sema::BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs Args) {
return StmtError();
return Res;
}
+
+ClassTemplateDecl *Sema::lookupCoroutineTraits(SourceLocation KwLoc,
+ SourceLocation FuncLoc) {
+ if (!StdCoroutineTraitsCache) {
+ if (auto StdExp = lookupStdExperimentalNamespace()) {
+ LookupResult Result(*this,
+ &PP.getIdentifierTable().get("coroutine_traits"),
+ FuncLoc, LookupOrdinaryName);
+ if (!LookupQualifiedName(Result, StdExp)) {
+ Diag(KwLoc, diag::err_implied_coroutine_type_not_found)
+ << "std::experimental::coroutine_traits";
+ return nullptr;
+ }
+ if (!(StdCoroutineTraitsCache =
+ Result.getAsSingle<ClassTemplateDecl>())) {
+ Result.suppressDiagnostics();
+ NamedDecl *Found = *Result.begin();
+ Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits);
+ return nullptr;
+ }
+ }
+ }
+ return StdCoroutineTraitsCache;
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
index 0ceaf7c6d691..55542828f783 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
@@ -115,7 +115,7 @@ class TypeNameValidatorCCC : public CorrectionCandidateCallback {
} // end anonymous namespace
-/// \brief Determine whether the token kind starts a simple-type-specifier.
+/// Determine whether the token kind starts a simple-type-specifier.
bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const {
switch (Kind) {
// FIXME: Take into account the current language when deciding whether a
@@ -148,6 +148,9 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const {
case tok::kw_decltype:
return getLangOpts().CPlusPlus;
+ case tok::kw_char8_t:
+ return getLangOpts().Char8;
+
default:
break;
}
@@ -163,7 +166,7 @@ enum class UnqualifiedTypeNameLookupResult {
};
} // end anonymous namespace
-/// \brief Tries to perform unqualified lookup of the type decls in bases for
+/// Tries to perform unqualified lookup of the type decls in bases for
/// dependent class.
/// \return \a NotFound if no any decls is found, \a FoundNotType if found not a
/// type decl, \a FoundType if only type decls are found.
@@ -263,7 +266,7 @@ static ParsedType recoverFromTypeInKnownDependentBase(Sema &S,
return S.CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
}
-/// \brief If the identifier refers to a type name within this scope,
+/// If the identifier refers to a type name within this scope,
/// return the declaration of that type.
///
/// This routine performs ordinary name lookup of the identifier II
@@ -724,13 +727,7 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
if (isTemplateName(S, SS ? *SS : EmptySS, /*hasTemplateKeyword=*/false,
Name, nullptr, true, TemplateResult,
MemberOfUnknownSpecialization) == TNK_Type_template) {
- TemplateName TplName = TemplateResult.get();
- Diag(IILoc, diag::err_template_missing_args)
- << (int)getTemplateNameKindForDiagnostics(TplName) << TplName;
- if (TemplateDecl *TplDecl = TplName.getAsTemplateDecl()) {
- Diag(TplDecl->getLocation(), diag::note_template_decl_here)
- << TplDecl->getTemplateParameters()->getSourceRange();
- }
+ diagnoseMissingTemplateArguments(TemplateResult.get(), IILoc);
return;
}
}
@@ -763,7 +760,7 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
}
}
-/// \brief Determine whether the given result set contains either a type name
+/// Determine whether the given result set contains either a type name
/// or
static bool isResultTypeOrTemplate(LookupResult &R, const Token &NextToken) {
bool CheckTemplate = R.getSema().getLangOpts().CPlusPlus &&
@@ -1318,7 +1315,7 @@ void Sema::ActOnExitFunctionContext() {
assert(CurContext && "Popped translation unit!");
}
-/// \brief Determine whether we allow overloading of the function
+/// Determine whether we allow overloading of the function
/// PrevDecl with another declaration.
///
/// This routine determines whether overloading is possible, not
@@ -1504,7 +1501,7 @@ static void RemoveUsingDecls(LookupResult &R) {
F.done();
}
-/// \brief Check for this common pattern:
+/// Check for this common pattern:
/// @code
/// class S {
/// S(const S&); // DO NOT IMPLEMENT
@@ -1519,9 +1516,7 @@ static bool IsDisallowedCopyOrAssign(const CXXMethodDecl *D) {
if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D))
return CD->isCopyConstructor();
- if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
- return Method->isCopyAssignmentOperator();
- return false;
+ return D->isCopyAssignmentOperator();
}
// We need this to handle
@@ -1843,7 +1838,7 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
}
}
-/// \brief Look for an Objective-C class in the translation unit.
+/// Look for an Objective-C class in the translation unit.
///
/// \param Id The name of the Objective-C class we're looking for. If
/// typo-correction fixes this name, the Id will be updated
@@ -1913,7 +1908,7 @@ Scope *Sema::getNonFieldDeclScope(Scope *S) {
return S;
}
-/// \brief Looks up the declaration of "struct objc_super" and
+/// Looks up the declaration of "struct objc_super" and
/// saves it for later use in building builtin declaration of
/// objc_msgSendSuper and objc_msgSendSuper_stret. If no such
/// pre-existing declaration exists no action takes place.
@@ -2457,6 +2452,9 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
else if (const auto *SA = dyn_cast<SectionAttr>(Attr))
NewAttr = S.mergeSectionAttr(D, SA->getRange(), SA->getName(),
AttrSpellingListIndex);
+ else if (const auto *CSA = dyn_cast<CodeSegAttr>(Attr))
+ NewAttr = S.mergeCodeSegAttr(D, CSA->getRange(), CSA->getName(),
+ AttrSpellingListIndex);
else if (const auto *IA = dyn_cast<MSInheritanceAttr>(Attr))
NewAttr = S.mergeMSInheritanceAttr(D, IA->getRange(), IA->getBestCase(),
AttrSpellingListIndex,
@@ -2495,7 +2493,7 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
else if (const auto *UA = dyn_cast<UuidAttr>(Attr))
NewAttr = S.mergeUuidAttr(D, UA->getRange(), AttrSpellingListIndex,
UA->getGuid());
- else if (Attr->duplicatesAllowed() || !DeclHasAttr(D, Attr))
+ else if (Attr->shouldInheritEvenIfAlreadyPresent() || !DeclHasAttr(D, Attr))
NewAttr = cast<InheritableAttr>(Attr->clone(S.Context));
if (NewAttr) {
@@ -2675,6 +2673,15 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
}
}
+ // Redeclaration adds code-seg attribute.
+ const auto *NewCSA = New->getAttr<CodeSegAttr>();
+ if (NewCSA && !Old->hasAttr<CodeSegAttr>() &&
+ !NewCSA->isImplicit() && isa<CXXMethodDecl>(New)) {
+ Diag(New->getLocation(), diag::warn_mismatched_section)
+ << 0 /*codeseg*/;
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ }
+
if (!Old->hasAttrs())
return;
@@ -2875,7 +2882,7 @@ static bool haveIncompatibleLanguageLinkages(const T *Old, const T *New) {
template<typename T> static bool isExternC(T *D) { return D->isExternC(); }
static bool isExternC(VarTemplateDecl *) { return false; }
-/// \brief Check whether a redeclaration of an entity introduced by a
+/// Check whether a redeclaration of an entity introduced by a
/// using-declaration is valid, given that we know it's not an overload
/// (nor a hidden tag declaration).
template<typename ExpectedDecl>
@@ -2929,6 +2936,48 @@ static bool hasIdenticalPassObjectSizeAttrs(const FunctionDecl *A,
return std::equal(A->param_begin(), A->param_end(), B->param_begin(), AttrEq);
}
+/// If necessary, adjust the semantic declaration context for a qualified
+/// declaration to name the correct inline namespace within the qualifier.
+static void adjustDeclContextForDeclaratorDecl(DeclaratorDecl *NewD,
+ DeclaratorDecl *OldD) {
+ // The only case where we need to update the DeclContext is when
+ // redeclaration lookup for a qualified name finds a declaration
+ // in an inline namespace within the context named by the qualifier:
+ //
+ // inline namespace N { int f(); }
+ // int ::f(); // Sema DC needs adjusting from :: to N::.
+ //
+ // For unqualified declarations, the semantic context *can* change
+ // along the redeclaration chain (for local extern declarations,
+ // extern "C" declarations, and friend declarations in particular).
+ if (!NewD->getQualifier())
+ return;
+
+ // NewD is probably already in the right context.
+ auto *NamedDC = NewD->getDeclContext()->getRedeclContext();
+ auto *SemaDC = OldD->getDeclContext()->getRedeclContext();
+ if (NamedDC->Equals(SemaDC))
+ return;
+
+ assert((NamedDC->InEnclosingNamespaceSetOf(SemaDC) ||
+ NewD->isInvalidDecl() || OldD->isInvalidDecl()) &&
+ "unexpected context for redeclaration");
+
+ auto *LexDC = NewD->getLexicalDeclContext();
+ auto FixSemaDC = [=](NamedDecl *D) {
+ if (!D)
+ return;
+ D->setDeclContext(SemaDC);
+ D->setLexicalDeclContext(LexDC);
+ };
+
+ FixSemaDC(NewD);
+ if (auto *FD = dyn_cast<FunctionDecl>(NewD))
+ FixSemaDC(FD->getDescribedFunctionTemplate());
+ else if (auto *VD = dyn_cast<VarDecl>(NewD))
+ FixSemaDC(VD->getDescribedVarTemplate());
+}
+
/// MergeFunctionDecl - We just parsed a function 'New' from
/// declarator D which has the same name and scope as a previous
/// declaration 'Old'. Figure out how to resolve this situation,
@@ -2971,6 +3020,14 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
if (Old->isInvalidDecl())
return true;
+ // Disallow redeclaration of some builtins.
+ if (!getASTContext().canBuiltinBeRedeclared(Old)) {
+ Diag(New->getLocation(), diag::err_builtin_redeclare) << Old->getDeclName();
+ Diag(Old->getLocation(), diag::note_previous_builtin_declaration)
+ << Old << Old->getType();
+ return true;
+ }
+
diag::kind PrevDiag;
SourceLocation OldLocation;
std::tie(PrevDiag, OldLocation) =
@@ -3518,7 +3575,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
return true;
}
-/// \brief Completes the merge of two function declarations that are
+/// Completes the merge of two function declarations that are
/// known to be compatible.
///
/// This routine handles the merging of attributes and other
@@ -3581,6 +3638,8 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod,
ni = newMethod->param_begin(), ne = newMethod->param_end();
ni != ne && oi != oe; ++ni, ++oi)
mergeParamDeclAttributes(*ni, *oi, *this);
+
+ CheckObjCMethodOverride(newMethod, oldMethod);
}
static void diagnoseVarDeclTypeMismatch(Sema &S, VarDecl *New, VarDecl* Old) {
@@ -3953,6 +4012,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
New->setPreviousDecl(Old);
if (NewTemplate)
NewTemplate->setPreviousDecl(OldTemplate);
+ adjustDeclContextForDeclaratorDecl(New, Old);
// Inherit access appropriately.
New->setAccess(Old->getAccess());
@@ -4014,7 +4074,8 @@ void Sema::notePreviousDefinition(const NamedDecl *Old, SourceLocation New) {
}
// Redefinition coming from different files or couldn't do better above.
- Diag(Old->getLocation(), diag::note_previous_definition);
+ if (Old->getLocation().isValid())
+ Diag(Old->getLocation(), diag::note_previous_definition);
}
/// We've just determined that \p Old and \p New both appear to be definitions
@@ -4398,10 +4459,9 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
TypeSpecType == DeclSpec::TST_interface ||
TypeSpecType == DeclSpec::TST_union ||
TypeSpecType == DeclSpec::TST_enum) {
- for (AttributeList* attrs = DS.getAttributes().getList(); attrs;
- attrs = attrs->getNext())
- Diag(attrs->getLoc(), diag::warn_declspec_attribute_ignored)
- << attrs->getName() << GetDiagnosticTypeSpecifierID(TypeSpecType);
+ for (const ParsedAttr &AL : DS.getAttributes())
+ Diag(AL.getLoc(), diag::warn_declspec_attribute_ignored)
+ << AL.getName() << GetDiagnosticTypeSpecifierID(TypeSpecType);
}
}
@@ -4593,12 +4653,14 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
unsigned DiagID;
if (Record->isUnion()) {
// C++ [class.union]p6:
+ // C++17 [class.union.anon]p2:
// Anonymous unions declared in a named namespace or in the
// global namespace shall be declared static.
+ DeclContext *OwnerScope = Owner->getRedeclContext();
if (DS.getStorageClassSpec() != DeclSpec::SCS_static &&
- (isa<TranslationUnitDecl>(Owner) ||
- (isa<NamespaceDecl>(Owner) &&
- cast<NamespaceDecl>(Owner)->getDeclName()))) {
+ (OwnerScope->isTranslationUnit() ||
+ (OwnerScope->isNamespace() &&
+ !cast<NamespaceDecl>(OwnerScope)->isAnonymousNamespace()))) {
Diag(Record->getLocation(), diag::err_anonymous_union_not_static)
<< FixItHint::CreateInsertion(Record->getLocation(), "static ");
@@ -4889,7 +4951,7 @@ DeclarationNameInfo Sema::GetNameForDeclarator(Declarator &D) {
return GetNameFromUnqualifiedId(D.getName());
}
-/// \brief Retrieves the declaration name from a parsed unqualified-id.
+/// Retrieves the declaration name from a parsed unqualified-id.
DeclarationNameInfo
Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
DeclarationNameInfo NameInfo;
@@ -5176,7 +5238,7 @@ bool Sema::DiagnoseClassNameShadow(DeclContext *DC,
return false;
}
-/// \brief Diagnose a declaration whose declarator-id has the given
+/// Diagnose a declaration whose declarator-id has the given
/// nested-name-specifier.
///
/// \param SS The nested-name-specifier of the declarator-id.
@@ -5188,10 +5250,13 @@ bool Sema::DiagnoseClassNameShadow(DeclContext *DC,
///
/// \param Loc The location of the name of the entity being declared.
///
+/// \param IsTemplateId Whether the name is a (simple-)template-id, and thus
+/// we're declaring an explicit / partial specialization / instantiation.
+///
/// \returns true if we cannot safely recover from this error, false otherwise.
bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
DeclarationName Name,
- SourceLocation Loc) {
+ SourceLocation Loc, bool IsTemplateId) {
DeclContext *Cur = CurContext;
while (isa<LinkageSpecDecl>(Cur) || isa<CapturedDecl>(Cur))
Cur = Cur->getParent();
@@ -5218,8 +5283,9 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
}
// Check whether the qualifying scope encloses the scope of the original
- // declaration.
- if (!Cur->Encloses(DC)) {
+ // declaration. For a template-id, we perform the checks in
+ // CheckTemplateSpecializationScope.
+ if (!Cur->Encloses(DC) && !IsTemplateId) {
if (Cur->isRecord())
Diag(Loc, diag::err_member_qualification)
<< Name << SS.getRange();
@@ -5331,8 +5397,9 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
return nullptr;
}
if (!D.getDeclSpec().isFriendSpecified()) {
- if (diagnoseQualifiedDeclaration(D.getCXXScopeSpec(), DC,
- Name, D.getIdentifierLoc())) {
+ if (diagnoseQualifiedDeclaration(
+ D.getCXXScopeSpec(), DC, Name, D.getIdentifierLoc(),
+ D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId)) {
if (DC->isRecord())
return nullptr;
@@ -5609,7 +5676,7 @@ TryToFixInvalidVariablyModifiedTypeSourceInfo(TypeSourceInfo *TInfo,
return FixedTInfo;
}
-/// \brief Register the given locally-scoped extern "C" declaration so
+/// Register the given locally-scoped extern "C" declaration so
/// that it can be found later for redeclarations. We include any extern "C"
/// declaration that is not visible in the translation unit here, not just
/// function-scope declarations.
@@ -5630,7 +5697,7 @@ NamedDecl *Sema::findLocallyScopedExternCDecl(DeclarationName Name) {
return Result.empty() ? nullptr : *Result.begin();
}
-/// \brief Diagnose function specifiers on a declaration of an identifier that
+/// Diagnose function specifiers on a declaration of an identifier that
/// does not identify a function.
void Sema::DiagnoseFunctionSpecifiers(const DeclSpec &DS) {
// FIXME: We should probably indicate the identifier in question to avoid
@@ -5704,7 +5771,7 @@ Sema::CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *NewTD) {
TypeSourceInfo *TInfo = NewTD->getTypeSourceInfo();
QualType T = TInfo->getType();
if (T->isVariablyModifiedType()) {
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
if (S->getFnParent() == nullptr) {
bool SizeIsNegative;
@@ -5772,7 +5839,7 @@ Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD,
return NewTD;
}
-/// \brief Determines whether the given declaration is an out-of-scope
+/// Determines whether the given declaration is an out-of-scope
/// previous declaration.
///
/// This routine should be invoked when name lookup has found a
@@ -6148,29 +6215,21 @@ static bool shouldConsiderLinkage(const FunctionDecl *FD) {
llvm_unreachable("Unexpected context");
}
-static bool hasParsedAttr(Scope *S, const AttributeList *AttrList,
- AttributeList::Kind Kind) {
- for (const AttributeList *L = AttrList; L; L = L->getNext())
- if (L->getKind() == Kind)
- return true;
- return false;
-}
-
static bool hasParsedAttr(Scope *S, const Declarator &PD,
- AttributeList::Kind Kind) {
+ ParsedAttr::Kind Kind) {
// Check decl attributes on the DeclSpec.
- if (hasParsedAttr(S, PD.getDeclSpec().getAttributes().getList(), Kind))
+ if (PD.getDeclSpec().getAttributes().hasAttribute(Kind))
return true;
// Walk the declarator structure, checking decl attributes that were in a type
// position to the decl itself.
for (unsigned I = 0, E = PD.getNumTypeObjects(); I != E; ++I) {
- if (hasParsedAttr(S, PD.getTypeObject(I).getAttrs(), Kind))
+ if (PD.getTypeObject(I).getAttrs().hasAttribute(Kind))
return true;
}
// Finally, check attributes on the decl itself.
- return hasParsedAttr(S, PD.getAttributes(), Kind);
+ return PD.getAttributes().hasAttribute(Kind);
}
/// Adjust the \c DeclContext for a function or variable that might be a
@@ -6197,7 +6256,7 @@ bool Sema::adjustContextForLocalExternDecl(DeclContext *&DC) {
return true;
}
-/// \brief Returns true if given declaration has external C language linkage.
+/// Returns true if given declaration has external C language linkage.
static bool isDeclExternC(const Decl *D) {
if (const auto *FD = dyn_cast<FunctionDecl>(D))
return FD->isExternC();
@@ -6303,6 +6362,20 @@ NamedDecl *Sema::ActOnVariableDeclarator(
D.setInvalidType();
}
}
+
+ // OpenCL C++ 1.0 s2.9: the thread_local storage qualifier is not
+ // supported. OpenCL C does not support thread_local either, and
+ // also reject all other thread storage class specifiers.
+ DeclSpec::TSCS TSC = D.getDeclSpec().getThreadStorageClassSpec();
+ if (TSC != TSCS_unspecified) {
+ bool IsCXX = getLangOpts().OpenCLCPlusPlus;
+ Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
+ diag::err_opencl_unknown_type_specifier)
+ << IsCXX << getLangOpts().getOpenCLVersionTuple().getAsString()
+ << DeclSpec::getSpecifierName(TSC) << 1;
+ D.setInvalidType();
+ return nullptr;
+ }
}
DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec();
@@ -6311,8 +6384,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(
// dllimport globals without explicit storage class are treated as extern. We
// have to change the storage class this early to get the right DeclContext.
if (SC == SC_None && !DC->isRecord() &&
- hasParsedAttr(S, D, AttributeList::AT_DLLImport) &&
- !hasParsedAttr(S, D, AttributeList::AT_DLLExport))
+ hasParsedAttr(S, D, ParsedAttr::AT_DLLImport) &&
+ !hasParsedAttr(S, D, ParsedAttr::AT_DLLExport))
SC = SC_Extern;
DeclContext *OriginalDC = DC;
@@ -6842,9 +6915,9 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
if (D.isRedeclaration() && !Previous.empty()) {
- checkDLLAttributeRedeclaration(
- *this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewVD,
- IsMemberSpecialization, D.isFunctionDefinition());
+ NamedDecl *Prev = Previous.getRepresentativeDecl();
+ checkDLLAttributeRedeclaration(*this, Prev, NewVD, IsMemberSpecialization,
+ D.isFunctionDefinition());
}
if (NewTemplate) {
@@ -6887,7 +6960,7 @@ static ShadowedDeclKind computeShadowedDeclKind(const NamedDecl *ShadowedDecl,
/// variable \p VD, or an invalid source location otherwise.
static SourceLocation getCaptureLocation(const LambdaScopeInfo *LSI,
const VarDecl *VD) {
- for (const LambdaScopeInfo::Capture &Capture : LSI->Captures) {
+ for (const Capture &Capture : LSI->Captures) {
if (Capture.isVariableCapture() && Capture.getVariable() == VD)
return Capture.getLocation();
}
@@ -6904,7 +6977,7 @@ static bool shouldWarnIfShadowedDecl(const DiagnosticsEngine &Diags,
return !Diags.isIgnored(diag::warn_decl_shadow, R.getNameLoc());
}
-/// \brief Return the declaration shadowed by the given variable \p D, or null
+/// Return the declaration shadowed by the given variable \p D, or null
/// if it doesn't shadow any declaration or shadowing warnings are disabled.
NamedDecl *Sema::getShadowedDeclaration(const VarDecl *D,
const LookupResult &R) {
@@ -6921,14 +6994,14 @@ NamedDecl *Sema::getShadowedDeclaration(const VarDecl *D,
: nullptr;
}
-/// \brief Return the declaration shadowed by the given typedef \p D, or null
+/// Return the declaration shadowed by the given typedef \p D, or null
/// if it doesn't shadow any declaration or shadowing warnings are disabled.
NamedDecl *Sema::getShadowedDeclaration(const TypedefNameDecl *D,
const LookupResult &R) {
// Don't warn if typedef declaration is part of a class
if (D->getDeclContext()->isRecord())
return nullptr;
-
+
if (!shouldWarnIfShadowedDecl(Diags, R))
return nullptr;
@@ -6936,7 +7009,7 @@ NamedDecl *Sema::getShadowedDeclaration(const TypedefNameDecl *D,
return isa<TypedefNameDecl>(ShadowedDecl) ? ShadowedDecl : nullptr;
}
-/// \brief Diagnose variable or built-in function shadowing. Implements
+/// Diagnose variable or built-in function shadowing. Implements
/// -Wshadow.
///
/// This method is called whenever a VarDecl is added to a "useful"
@@ -7067,7 +7140,7 @@ void Sema::DiagnoseShadowingLambdaDecls(const LambdaScopeInfo *LSI) {
}
}
-/// \brief Check -Wshadow without the advantage of a previous lookup.
+/// Check -Wshadow without the advantage of a previous lookup.
void Sema::CheckShadow(Scope *S, VarDecl *D) {
if (Diags.isIgnored(diag::warn_decl_shadow, D->getLocation()))
return;
@@ -7225,8 +7298,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
if (NewVD->isInvalidDecl())
return;
- TypeSourceInfo *TInfo = NewVD->getTypeSourceInfo();
- QualType T = TInfo->getType();
+ QualType T = NewVD->getType();
// Defer checking an 'auto' type until its initializer is attached.
if (T->isUndeducedType())
@@ -7364,16 +7436,24 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
bool isVM = T->isVariablyModifiedType();
if (isVM || NewVD->hasAttr<CleanupAttr>() ||
NewVD->hasAttr<BlocksAttr>())
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
if ((isVM && NewVD->hasLinkage()) ||
(T->isVariableArrayType() && NewVD->hasGlobalStorage())) {
bool SizeIsNegative;
llvm::APSInt Oversized;
- TypeSourceInfo *FixedTInfo =
- TryToFixInvalidVariablyModifiedTypeSourceInfo(TInfo, Context,
- SizeIsNegative, Oversized);
- if (!FixedTInfo && T->isVariableArrayType()) {
+ TypeSourceInfo *FixedTInfo = TryToFixInvalidVariablyModifiedTypeSourceInfo(
+ NewVD->getTypeSourceInfo(), Context, SizeIsNegative, Oversized);
+ QualType FixedT;
+ if (FixedTInfo && T == NewVD->getTypeSourceInfo()->getType())
+ FixedT = FixedTInfo->getType();
+ else if (FixedTInfo) {
+ // Type and type-as-written are canonically different. We need to fix up
+ // both types separately.
+ FixedT = TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative,
+ Oversized);
+ }
+ if ((!FixedTInfo || FixedT.isNull()) && T->isVariableArrayType()) {
const VariableArrayType *VAT = Context.getAsVariableArrayType(T);
// FIXME: This won't give the correct result for
// int a[10][n];
@@ -7402,7 +7482,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
}
Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size);
- NewVD->setType(FixedTInfo->getType());
+ NewVD->setType(FixedT);
NewVD->setTypeSourceInfo(FixedTInfo);
}
@@ -7437,7 +7517,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
}
}
-/// \brief Perform semantic checking on a newly-created variable
+/// Perform semantic checking on a newly-created variable
/// declaration.
///
/// This routine performs all of the type-checking required for a
@@ -7508,8 +7588,8 @@ struct FindOverriddenMethod {
enum OverrideErrorKind { OEK_All, OEK_NonDeleted, OEK_Deleted };
} // end anonymous namespace
-/// \brief Report an error regarding overriding, along with any relevant
-/// overriden methods.
+/// Report an error regarding overriding, along with any relevant
+/// overridden methods.
///
/// \param DiagID the primary error to report.
/// \param MD the overriding method.
@@ -7624,7 +7704,7 @@ void Sema::MarkTypoCorrectedFunctionDefinition(const NamedDecl *F) {
TypoCorrectedFunctionDefinitions.insert(F);
}
-/// \brief Generate diagnostics for an invalid function redeclaration.
+/// Generate diagnostics for an invalid function redeclaration.
///
/// This routine handles generating the diagnostic messages for an invalid
/// function redeclaration, including finding possible similar declarations
@@ -8176,7 +8256,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
bool &AddToScope) {
QualType R = TInfo->getType();
- assert(R.getTypePtr()->isFunctionType());
+ assert(R->isFunctionType());
// TODO: consider using NameInfo for diagnostic.
DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
@@ -8655,6 +8735,15 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewFD->dropAttr<SectionAttr>();
}
+ // Apply an implicit CodeSegAttr from class declspec or
+ // apply an implicit SectionAttr from #pragma code_seg if active.
+ if (!NewFD->hasAttr<CodeSegAttr>()) {
+ if (Attr *SAttr = getImplicitCodeSegOrSectionAttrForFunction(NewFD,
+ D.isFunctionDefinition())) {
+ NewFD->addAttr(SAttr);
+ }
+ }
+
// Handle attributes.
ProcessDeclAttributes(S, NewFD, D);
@@ -8785,10 +8874,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (CurContext->isDependentContext() && CurContext->isRecord()
&& !isFriend) {
isDependentClassScopeExplicitSpecialization = true;
- Diag(NewFD->getLocation(), getLangOpts().MicrosoftExt ?
- diag::ext_function_specialization_in_class :
- diag::err_function_specialization_in_class)
- << NewFD->getDeclName();
} else if (!NewFD->isInvalidDecl() &&
CheckFunctionTemplateSpecialization(
NewFD, (HasExplicitTemplateArgs ? &TemplateArgs : nullptr),
@@ -8994,19 +9079,22 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewFD->setRangeEnd(D.getSourceRange().getEnd());
if (D.isRedeclaration() && !Previous.empty()) {
- checkDLLAttributeRedeclaration(
- *this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewFD,
- isMemberSpecialization || isFunctionTemplateSpecialization,
- D.isFunctionDefinition());
+ NamedDecl *Prev = Previous.getRepresentativeDecl();
+ checkDLLAttributeRedeclaration(*this, Prev, NewFD,
+ isMemberSpecialization ||
+ isFunctionTemplateSpecialization,
+ D.isFunctionDefinition());
}
if (getLangOpts().CUDA) {
IdentifierInfo *II = NewFD->getIdentifier();
- if (II && II->isStr("cudaConfigureCall") && !NewFD->isInvalidDecl() &&
+ if (II &&
+ II->isStr(getLangOpts().HIP ? "hipConfigureCall"
+ : "cudaConfigureCall") &&
+ !NewFD->isInvalidDecl() &&
NewFD->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
if (!R->getAs<FunctionType>()->getReturnType()->isScalarType())
Diag(NewFD->getLocation(), diag::err_config_scalar_return);
-
Context.setcudaConfigureCallDecl(NewFD);
}
@@ -9073,22 +9161,95 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
// Here we have an function template explicit specialization at class scope.
- // The actually specialization will be postponed to template instatiation
+ // The actual specialization will be postponed to template instatiation
// time via the ClassScopeFunctionSpecializationDecl node.
if (isDependentClassScopeExplicitSpecialization) {
ClassScopeFunctionSpecializationDecl *NewSpec =
ClassScopeFunctionSpecializationDecl::Create(
- Context, CurContext, SourceLocation(),
+ Context, CurContext, NewFD->getLocation(),
cast<CXXMethodDecl>(NewFD),
HasExplicitTemplateArgs, TemplateArgs);
CurContext->addDecl(NewSpec);
AddToScope = false;
}
+ // Diagnose availability attributes. Availability cannot be used on functions
+ // that are run during load/unload.
+ if (const auto *attr = NewFD->getAttr<AvailabilityAttr>()) {
+ if (NewFD->hasAttr<ConstructorAttr>()) {
+ Diag(attr->getLocation(), diag::warn_availability_on_static_initializer)
+ << 1;
+ NewFD->dropAttr<AvailabilityAttr>();
+ }
+ if (NewFD->hasAttr<DestructorAttr>()) {
+ Diag(attr->getLocation(), diag::warn_availability_on_static_initializer)
+ << 2;
+ NewFD->dropAttr<AvailabilityAttr>();
+ }
+ }
+
return NewFD;
}
-/// \brief Checks if the new declaration declared in dependent context must be
+/// Return a CodeSegAttr from a containing class. The Microsoft docs say
+/// when __declspec(code_seg) "is applied to a class, all member functions of
+/// the class and nested classes -- this includes compiler-generated special
+/// member functions -- are put in the specified segment."
+/// The actual behavior is a little more complicated. The Microsoft compiler
+/// won't check outer classes if there is an active value from #pragma code_seg.
+/// The CodeSeg is always applied from the direct parent but only from outer
+/// classes when the #pragma code_seg stack is empty. See:
+/// https://reviews.llvm.org/D22931, the Microsoft feedback page is no longer
+/// available since MS has removed the page.
+static Attr *getImplicitCodeSegAttrFromClass(Sema &S, const FunctionDecl *FD) {
+ const auto *Method = dyn_cast<CXXMethodDecl>(FD);
+ if (!Method)
+ return nullptr;
+ const CXXRecordDecl *Parent = Method->getParent();
+ if (const auto *SAttr = Parent->getAttr<CodeSegAttr>()) {
+ Attr *NewAttr = SAttr->clone(S.getASTContext());
+ NewAttr->setImplicit(true);
+ return NewAttr;
+ }
+
+ // The Microsoft compiler won't check outer classes for the CodeSeg
+ // when the #pragma code_seg stack is active.
+ if (S.CodeSegStack.CurrentValue)
+ return nullptr;
+
+ while ((Parent = dyn_cast<CXXRecordDecl>(Parent->getParent()))) {
+ if (const auto *SAttr = Parent->getAttr<CodeSegAttr>()) {
+ Attr *NewAttr = SAttr->clone(S.getASTContext());
+ NewAttr->setImplicit(true);
+ return NewAttr;
+ }
+ }
+ return nullptr;
+}
+
+/// Returns an implicit CodeSegAttr if a __declspec(code_seg) is found on a
+/// containing class. Otherwise it will return implicit SectionAttr if the
+/// function is a definition and there is an active value on CodeSegStack
+/// (from the current #pragma code-seg value).
+///
+/// \param FD Function being declared.
+/// \param IsDefinition Whether it is a definition or just a declarartion.
+/// \returns A CodeSegAttr or SectionAttr to apply to the function or
+/// nullptr if no attribute should be added.
+Attr *Sema::getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD,
+ bool IsDefinition) {
+ if (Attr *A = getImplicitCodeSegAttrFromClass(*this, FD))
+ return A;
+ if (!FD->hasAttr<SectionAttr>() && IsDefinition &&
+ CodeSegStack.CurrentValue) {
+ return SectionAttr::CreateImplicit(getASTContext(),
+ SectionAttr::Declspec_allocate,
+ CodeSegStack.CurrentValue->getString(),
+ CodeSegStack.CurrentPragmaLocation);
+ }
+ return nullptr;
+}
+/// Checks if the new declaration declared in dependent context must be
/// put in the same redeclaration chain as the specified declaration.
///
/// \param D Declaration that is checked.
@@ -9114,7 +9275,524 @@ bool Sema::shouldLinkDependentDeclWithPrevious(Decl *D, Decl *PrevDecl) {
D->getFriendObjectKind() != Decl::FOK_None);
}
-/// \brief Perform semantic checking of a new function declaration.
+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;
+}
+/// Check the target attribute of the function for MultiVersion
+/// validity.
+///
+/// Returns true if there was an error, false otherwise.
+static bool CheckMultiVersionValue(Sema &S, const FunctionDecl *FD) {
+ const auto *TA = FD->getAttr<TargetAttr>();
+ assert(TA && "MultiVersion Candidate requires a target attribute");
+ TargetAttr::ParsedTargetAttr ParseInfo = TA->parse();
+ const TargetInfo &TargetInfo = S.Context.getTargetInfo();
+ enum ErrType { Feature = 0, Architecture = 1 };
+
+ if (!ParseInfo.Architecture.empty() &&
+ !TargetInfo.validateCpuIs(ParseInfo.Architecture)) {
+ S.Diag(FD->getLocation(), diag::err_bad_multiversion_option)
+ << Architecture << ParseInfo.Architecture;
+ return true;
+ }
+
+ for (const auto &Feat : ParseInfo.Features) {
+ auto BareFeat = StringRef{Feat}.substr(1);
+ if (Feat[0] == '-') {
+ S.Diag(FD->getLocation(), diag::err_bad_multiversion_option)
+ << Feature << ("no-" + BareFeat).str();
+ return true;
+ }
+
+ if (!TargetInfo.validateCpuSupports(BareFeat) ||
+ !TargetInfo.isValidFeatureName(BareFeat)) {
+ S.Diag(FD->getLocation(), diag::err_bad_multiversion_option)
+ << Feature << BareFeat;
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD,
+ const FunctionDecl *NewFD,
+ bool CausesMV,
+ MultiVersioning::Type MVType) {
+ enum DoesntSupport {
+ FuncTemplates = 0,
+ VirtFuncs = 1,
+ DeducedReturn = 2,
+ Constructors = 3,
+ Destructors = 4,
+ DeletedFuncs = 5,
+ DefaultedFuncs = 6,
+ ConstexprFuncs = 7,
+ };
+ enum Different {
+ CallingConv = 0,
+ ReturnType = 1,
+ ConstexprSpec = 2,
+ InlineSpec = 3,
+ StorageClass = 4,
+ Linkage = 5
+ };
+
+ bool IsCPUSpecificCPUDispatchMVType =
+ MVType == MultiVersioning::CPUDispatch ||
+ MVType == MultiVersioning::CPUSpecific;
+
+ if (OldFD && !OldFD->getType()->getAs<FunctionProtoType>()) {
+ S.Diag(OldFD->getLocation(), diag::err_multiversion_noproto);
+ S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here);
+ return true;
+ }
+
+ if (!NewFD->getType()->getAs<FunctionProtoType>())
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_noproto);
+
+ if (!S.getASTContext().getTargetInfo().supportsMultiVersioning()) {
+ S.Diag(NewFD->getLocation(), diag::err_multiversion_not_supported);
+ if (OldFD)
+ S.Diag(OldFD->getLocation(), diag::note_previous_declaration);
+ return true;
+ }
+
+ // 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) {
+ 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)
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_no_other_attrs)
+ << IsCPUSpecificCPUDispatchMVType;
+
+ if (NewFD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate)
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support)
+ << IsCPUSpecificCPUDispatchMVType << FuncTemplates;
+
+ if (const auto *NewCXXFD = dyn_cast<CXXMethodDecl>(NewFD)) {
+ if (NewCXXFD->isVirtual())
+ return S.Diag(NewCXXFD->getLocation(),
+ diag::err_multiversion_doesnt_support)
+ << IsCPUSpecificCPUDispatchMVType << VirtFuncs;
+
+ if (const auto *NewCXXCtor = dyn_cast<CXXConstructorDecl>(NewFD))
+ return S.Diag(NewCXXCtor->getLocation(),
+ diag::err_multiversion_doesnt_support)
+ << IsCPUSpecificCPUDispatchMVType << Constructors;
+
+ if (const auto *NewCXXDtor = dyn_cast<CXXDestructorDecl>(NewFD))
+ return S.Diag(NewCXXDtor->getLocation(),
+ diag::err_multiversion_doesnt_support)
+ << IsCPUSpecificCPUDispatchMVType << Destructors;
+ }
+
+ if (NewFD->isDeleted())
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support)
+ << IsCPUSpecificCPUDispatchMVType << DeletedFuncs;
+
+ if (NewFD->isDefaulted())
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support)
+ << IsCPUSpecificCPUDispatchMVType << DefaultedFuncs;
+
+ if (NewFD->isConstexpr() && (MVType == MultiVersioning::CPUDispatch ||
+ MVType == MultiVersioning::CPUSpecific))
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support)
+ << IsCPUSpecificCPUDispatchMVType << ConstexprFuncs;
+
+ QualType NewQType = S.getASTContext().getCanonicalType(NewFD->getType());
+ const auto *NewType = cast<FunctionType>(NewQType);
+ QualType NewReturnType = NewType->getReturnType();
+
+ if (NewReturnType->isUndeducedType())
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support)
+ << IsCPUSpecificCPUDispatchMVType << DeducedReturn;
+
+ // Only allow transition to MultiVersion if it hasn't been used.
+ if (OldFD && CausesMV && OldFD->isUsed(false))
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_after_used);
+
+ // Ensure the return type is identical.
+ if (OldFD) {
+ QualType OldQType = S.getASTContext().getCanonicalType(OldFD->getType());
+ const auto *OldType = cast<FunctionType>(OldQType);
+ FunctionType::ExtInfo OldTypeInfo = OldType->getExtInfo();
+ FunctionType::ExtInfo NewTypeInfo = NewType->getExtInfo();
+
+ if (OldTypeInfo.getCC() != NewTypeInfo.getCC())
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
+ << CallingConv;
+
+ QualType OldReturnType = OldType->getReturnType();
+
+ if (OldReturnType != NewReturnType)
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
+ << ReturnType;
+
+ if (OldFD->isConstexpr() != NewFD->isConstexpr())
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
+ << ConstexprSpec;
+
+ if (OldFD->isInlineSpecified() != NewFD->isInlineSpecified())
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
+ << InlineSpec;
+
+ if (OldFD->getStorageClass() != NewFD->getStorageClass())
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
+ << StorageClass;
+
+ if (OldFD->isExternC() != NewFD->isExternC())
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
+ << Linkage;
+
+ if (S.CheckEquivalentExceptionSpec(
+ OldFD->getType()->getAs<FunctionProtoType>(), OldFD->getLocation(),
+ NewFD->getType()->getAs<FunctionProtoType>(), NewFD->getLocation()))
+ return true;
+ }
+ return false;
+}
+
+/// Check the validity of a multiversion function declaration that is the
+/// first of its kind. Also sets the multiversion'ness' of the function itself.
+///
+/// This sets NewFD->isInvalidDecl() to true if there was an error.
+///
+/// Returns true if there was an error, false otherwise.
+static bool CheckMultiVersionFirstFunction(Sema &S, FunctionDecl *FD,
+ MultiVersioning::Type MVType,
+ const TargetAttr *TA,
+ const CPUDispatchAttr *CPUDisp,
+ const CPUSpecificAttr *CPUSpec) {
+ assert(MVType != MultiVersioning::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())
+ return false;
+
+ if (MVType == MultiVersioning::Target && CheckMultiVersionValue(S, FD)) {
+ FD->setInvalidDecl();
+ return true;
+ }
+
+ if (CheckMultiVersionAdditionalRules(S, nullptr, FD, true, MVType)) {
+ FD->setInvalidDecl();
+ return true;
+ }
+
+ FD->setIsMultiVersion();
+ return false;
+}
+
+static bool CheckTargetCausesMultiVersioning(
+ Sema &S, FunctionDecl *OldFD, FunctionDecl *NewFD, const TargetAttr *NewTA,
+ bool &Redeclaration, NamedDecl *&OldDecl, bool &MergeTypeWithPrevious,
+ LookupResult &Previous) {
+ 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());
+
+ // 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())
+ return false;
+
+ // Otherwise, this decl causes MultiVersioning.
+ if (!S.getASTContext().getTargetInfo().supportsMultiVersioning()) {
+ S.Diag(NewFD->getLocation(), diag::err_multiversion_not_supported);
+ S.Diag(OldFD->getLocation(), diag::note_previous_declaration);
+ NewFD->setInvalidDecl();
+ return true;
+ }
+
+ if (CheckMultiVersionAdditionalRules(S, OldFD, NewFD, true,
+ MultiVersioning::Target)) {
+ NewFD->setInvalidDecl();
+ return true;
+ }
+
+ if (CheckMultiVersionValue(S, NewFD)) {
+ NewFD->setInvalidDecl();
+ return true;
+ }
+
+ if (CheckMultiVersionValue(S, OldFD)) {
+ S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here);
+ NewFD->setInvalidDecl();
+ return true;
+ }
+
+ TargetAttr::ParsedTargetAttr OldParsed =
+ OldTA->parse(std::less<std::string>());
+
+ if (OldParsed == NewParsed) {
+ S.Diag(NewFD->getLocation(), diag::err_multiversion_duplicate);
+ S.Diag(OldFD->getLocation(), diag::note_previous_declaration);
+ NewFD->setInvalidDecl();
+ return true;
+ }
+
+ for (const auto *FD : OldFD->redecls()) {
+ const auto *CurTA = FD->getAttr<TargetAttr>();
+ if (!CurTA || CurTA->isInherited()) {
+ S.Diag(FD->getLocation(), diag::err_multiversion_required_in_redecl)
+ << 0;
+ S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here);
+ NewFD->setInvalidDecl();
+ return true;
+ }
+ }
+
+ OldFD->setIsMultiVersion();
+ NewFD->setIsMultiVersion();
+ Redeclaration = false;
+ MergeTypeWithPrevious = false;
+ OldDecl = nullptr;
+ Previous.clear();
+ return false;
+}
+
+/// Check the validity of a new function declaration being added to an existing
+/// multiversioned declaration collection.
+static bool CheckMultiVersionAdditionalDecl(
+ Sema &S, FunctionDecl *OldFD, FunctionDecl *NewFD,
+ MultiVersioning::Type NewMVType, const TargetAttr *NewTA,
+ const CPUDispatchAttr *NewCPUDisp, const CPUSpecificAttr *NewCPUSpec,
+ bool &Redeclaration, NamedDecl *&OldDecl, bool &MergeTypeWithPrevious,
+ LookupResult &Previous) {
+
+ MultiVersioning::Type OldMVType = getMultiVersionType(OldFD);
+ // Disallow mixing of multiversioning types.
+ if ((OldMVType == MultiVersioning::Target &&
+ NewMVType != MultiVersioning::Target) ||
+ (NewMVType == MultiVersioning::Target &&
+ OldMVType != MultiVersioning::Target)) {
+ S.Diag(NewFD->getLocation(), diag::err_multiversion_types_mixed);
+ S.Diag(OldFD->getLocation(), diag::note_previous_declaration);
+ NewFD->setInvalidDecl();
+ return true;
+ }
+
+ TargetAttr::ParsedTargetAttr NewParsed;
+ if (NewTA) {
+ NewParsed = NewTA->parse();
+ llvm::sort(NewParsed.Features.begin(), NewParsed.Features.end());
+ }
+
+ bool UseMemberUsingDeclRules =
+ S.CurContext->isRecord() && !NewFD->getFriendObjectKind();
+
+ // Next, check ALL non-overloads to see if this is a redeclaration of a
+ // previous member of the MultiVersion set.
+ for (NamedDecl *ND : Previous) {
+ FunctionDecl *CurFD = ND->getAsFunction();
+ if (!CurFD)
+ continue;
+ if (S.IsOverload(NewFD, CurFD, UseMemberUsingDeclRules))
+ continue;
+
+ if (NewMVType == MultiVersioning::Target) {
+ const auto *CurTA = CurFD->getAttr<TargetAttr>();
+ if (CurTA->getFeaturesStr() == NewTA->getFeaturesStr()) {
+ NewFD->setIsMultiVersion();
+ Redeclaration = true;
+ OldDecl = ND;
+ return false;
+ }
+
+ TargetAttr::ParsedTargetAttr CurParsed =
+ CurTA->parse(std::less<std::string>());
+ if (CurParsed == NewParsed) {
+ S.Diag(NewFD->getLocation(), diag::err_multiversion_duplicate);
+ S.Diag(CurFD->getLocation(), diag::note_previous_declaration);
+ NewFD->setInvalidDecl();
+ return true;
+ }
+ } else {
+ const auto *CurCPUSpec = CurFD->getAttr<CPUSpecificAttr>();
+ const auto *CurCPUDisp = CurFD->getAttr<CPUDispatchAttr>();
+ // Handle CPUDispatch/CPUSpecific versions.
+ // Only 1 CPUDispatch function is allowed, this will make it go through
+ // the redeclaration errors.
+ if (NewMVType == MultiVersioning::CPUDispatch &&
+ CurFD->hasAttr<CPUDispatchAttr>()) {
+ if (CurCPUDisp->cpus_size() == NewCPUDisp->cpus_size() &&
+ std::equal(
+ CurCPUDisp->cpus_begin(), CurCPUDisp->cpus_end(),
+ NewCPUDisp->cpus_begin(),
+ [](const IdentifierInfo *Cur, const IdentifierInfo *New) {
+ return Cur->getName() == New->getName();
+ })) {
+ NewFD->setIsMultiVersion();
+ Redeclaration = true;
+ OldDecl = ND;
+ return false;
+ }
+
+ // If the declarations don't match, this is an error condition.
+ S.Diag(NewFD->getLocation(), diag::err_cpu_dispatch_mismatch);
+ S.Diag(CurFD->getLocation(), diag::note_previous_declaration);
+ NewFD->setInvalidDecl();
+ return true;
+ }
+ if (NewMVType == MultiVersioning::CPUSpecific && CurCPUSpec) {
+
+ if (CurCPUSpec->cpus_size() == NewCPUSpec->cpus_size() &&
+ std::equal(
+ CurCPUSpec->cpus_begin(), CurCPUSpec->cpus_end(),
+ NewCPUSpec->cpus_begin(),
+ [](const IdentifierInfo *Cur, const IdentifierInfo *New) {
+ return Cur->getName() == New->getName();
+ })) {
+ NewFD->setIsMultiVersion();
+ Redeclaration = true;
+ OldDecl = ND;
+ return false;
+ }
+
+ // Only 1 version of CPUSpecific is allowed for each CPU.
+ for (const IdentifierInfo *CurII : CurCPUSpec->cpus()) {
+ for (const IdentifierInfo *NewII : NewCPUSpec->cpus()) {
+ if (CurII == NewII) {
+ S.Diag(NewFD->getLocation(), diag::err_cpu_specific_multiple_defs)
+ << NewII;
+ S.Diag(CurFD->getLocation(), diag::note_previous_declaration);
+ NewFD->setInvalidDecl();
+ return true;
+ }
+ }
+ }
+ }
+ // If the two decls aren't the same MVType, there is no possible error
+ // condition.
+ }
+ }
+
+ // 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 &&
+ CheckMultiVersionValue(S, NewFD)) {
+ NewFD->setInvalidDecl();
+ return true;
+ }
+
+ if (CheckMultiVersionAdditionalRules(S, OldFD, NewFD, false, NewMVType)) {
+ NewFD->setInvalidDecl();
+ return true;
+ }
+
+ NewFD->setIsMultiVersion();
+ Redeclaration = false;
+ MergeTypeWithPrevious = false;
+ OldDecl = nullptr;
+ Previous.clear();
+ return false;
+}
+
+
+/// Check the validity of a mulitversion function declaration.
+/// Also sets the multiversion'ness' of the function itself.
+///
+/// This sets NewFD->isInvalidDecl() to true if there was an error.
+///
+/// Returns true if there was an error, false otherwise.
+static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD,
+ bool &Redeclaration, NamedDecl *&OldDecl,
+ bool &MergeTypeWithPrevious,
+ LookupResult &Previous) {
+ const auto *NewTA = NewFD->getAttr<TargetAttr>();
+ const auto *NewCPUDisp = NewFD->getAttr<CPUDispatchAttr>();
+ const auto *NewCPUSpec = NewFD->getAttr<CPUSpecificAttr>();
+
+ // Mixing Multiversioning types is prohibited.
+ if ((NewTA && NewCPUDisp) || (NewTA && NewCPUSpec) ||
+ (NewCPUDisp && NewCPUSpec)) {
+ S.Diag(NewFD->getLocation(), diag::err_multiversion_types_mixed);
+ NewFD->setInvalidDecl();
+ return true;
+ }
+
+ MultiVersioning::Type MVType = getMultiVersionType(NewFD);
+
+ // 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) {
+ S.Diag(NewFD->getLocation(), diag::err_multiversion_not_allowed_on_main);
+ NewFD->setInvalidDecl();
+ return true;
+ }
+ return false;
+ }
+
+ if (!OldDecl || !OldDecl->getAsFunction() ||
+ OldDecl->getDeclContext()->getRedeclContext() !=
+ 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)
+ return false;
+ return CheckMultiVersionFirstFunction(S, NewFD, MVType, NewTA, NewCPUDisp,
+ NewCPUSpec);
+ }
+
+ FunctionDecl *OldFD = OldDecl->getAsFunction();
+
+ if (!OldFD->isMultiVersion() && MVType == MultiVersioning::None)
+ return false;
+
+ if (OldFD->isMultiVersion() && MVType == MultiVersioning::None) {
+ S.Diag(NewFD->getLocation(), diag::err_multiversion_required_in_redecl)
+ << (getMultiVersionType(OldFD) != MultiVersioning::Target);
+ NewFD->setInvalidDecl();
+ return true;
+ }
+
+ // Handle the target potentially causes multiversioning case.
+ if (!OldFD->isMultiVersion() && MVType == MultiVersioning::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
+ // still compatible with previous declarations.
+ return CheckMultiVersionAdditionalDecl(
+ S, OldFD, NewFD, MVType, NewTA, NewCPUDisp, NewCPUSpec, Redeclaration,
+ OldDecl, MergeTypeWithPrevious, Previous);
+}
+
+/// Perform semantic checking of a new function declaration.
///
/// Performs semantic analysis of the new function declaration
/// NewFD. This routine performs all semantic checking that does not
@@ -9201,6 +9879,10 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
}
}
+ if (CheckMultiVersionFunction(*this, NewFD, Redeclaration, OldDecl,
+ MergeTypeWithPrevious, Previous))
+ return Redeclaration;
+
// C++11 [dcl.constexpr]p8:
// A constexpr specifier for a non-static member function that is not
// a constructor declares that member function to be const.
@@ -9250,15 +9932,16 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
Previous.clear();
Previous.addDecl(OldDecl);
- if (FunctionTemplateDecl *OldTemplateDecl
- = dyn_cast<FunctionTemplateDecl>(OldDecl)) {
- NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl());
+ 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");
- if (CXXMethodDecl *Method
- = dyn_cast<CXXMethodDecl>(NewTemplateDecl->getTemplatedDecl())) {
- Method->setAccess(OldTemplateDecl->getAccess());
+ if (NewFD->isCXXClassMember()) {
+ NewFD->setAccess(OldTemplateDecl->getAccess());
NewTemplateDecl->setAccess(OldTemplateDecl->getAccess());
}
@@ -9270,22 +9953,22 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
assert(OldTemplateDecl->isMemberSpecialization());
// Explicit specializations of a member template do not inherit deleted
// status from the parent member template that they are specializing.
- if (OldTemplateDecl->getTemplatedDecl()->isDeleted()) {
- FunctionDecl *const OldTemplatedDecl =
- OldTemplateDecl->getTemplatedDecl();
+ if (OldFD->isDeleted()) {
// FIXME: This assert will not hold in the presence of modules.
- assert(OldTemplatedDecl->getCanonicalDecl() == OldTemplatedDecl);
+ assert(OldFD->getCanonicalDecl() == OldFD);
// FIXME: We need an update record for this AST mutation.
- OldTemplatedDecl->setDeletedAsWritten(false);
+ OldFD->setDeletedAsWritten(false);
}
}
} else {
if (shouldLinkDependentDeclWithPrevious(NewFD, OldDecl)) {
+ auto *OldFD = cast<FunctionDecl>(OldDecl);
// This needs to happen first so that 'inline' propagates.
- NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
- if (isa<CXXMethodDecl>(NewFD))
- NewFD->setAccess(OldDecl->getAccess());
+ NewFD->setPreviousDeclaration(OldFD);
+ adjustDeclContextForDeclaratorDecl(NewFD, OldFD);
+ if (NewFD->isCXXClassMember())
+ NewFD->setAccess(OldFD->getAccess());
}
}
} else if (!getLangOpts().CPlusPlus && MayNeedOverloadableChecks &&
@@ -9440,7 +10123,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
else if (auto *MPT = T->getAs<MemberPointerType>())
T = MPT->getPointeeType();
if (auto *FPT = T->getAs<FunctionProtoType>())
- if (FPT->isNothrow(Context))
+ if (FPT->isNothrow())
return true;
return false;
};
@@ -9951,7 +10634,7 @@ namespace {
S.DiagRuntimeBehavior(DRE->getLocStart(), DRE,
S.PDiag(diag)
- << DRE->getNameInfo().getName()
+ << DRE->getDecl()
<< OrigDecl->getLocation()
<< DRE->getSourceRange());
}
@@ -10011,12 +10694,22 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
// C++11 [dcl.spec.auto]p3
if (!Init) {
assert(VDecl && "no init for init capture deduction?");
- Diag(VDecl->getLocation(), diag::err_auto_var_requires_init)
- << VDecl->getDeclName() << Type;
- return QualType();
+
+ // Except for class argument deduction, and then for an initializing
+ // declaration only, i.e. no static at class scope or extern.
+ if (!isa<DeducedTemplateSpecializationType>(Deduced) ||
+ VDecl->hasExternalStorage() ||
+ VDecl->isStaticDataMember()) {
+ Diag(VDecl->getLocation(), diag::err_auto_var_requires_init)
+ << VDecl->getDeclName() << Type;
+ return QualType();
+ }
}
- ArrayRef<Expr*> DeduceInits = Init;
+ ArrayRef<Expr*> DeduceInits;
+ if (Init)
+ DeduceInits = Init;
+
if (DirectInit) {
if (auto *PL = dyn_cast_or_null<ParenListExpr>(Init))
DeduceInits = PL->exprs();
@@ -10260,7 +10953,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
}
if (VDecl->hasLocalStorage())
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer)) {
VDecl->setInvalidDecl();
@@ -10360,11 +11053,12 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
// we do not warn to warn spuriously when 'x' and 'y' are on separate
// paths through the function. This should be revisited if
// -Wrepeated-use-of-weak is made flow-sensitive.
- if ((VDecl->getType().getObjCLifetime() == Qualifiers::OCL_Strong ||
- VDecl->getType().isNonWeakInMRRWithObjCWeak(Context)) &&
- !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak,
- Init->getLocStart()))
- getCurFunction()->markSafeWeakUse(Init);
+ if (FunctionScopeInfo *FSI = getCurFunction())
+ if ((VDecl->getType().getObjCLifetime() == Qualifiers::OCL_Strong ||
+ VDecl->getType().isNonWeakInMRRWithObjCWeak(Context)) &&
+ !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak,
+ Init->getLocStart()))
+ FSI->markSafeWeakUse(Init);
}
// The initialization is usually a full-expression.
@@ -10471,6 +11165,9 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
; // Nothing to check.
else if (Init->isIntegerConstantExpr(Context, &Loc))
; // Ok, it's an ICE!
+ else if (Init->getType()->isScopedEnumeralType() &&
+ Init->isCXX11ConstantExpr(Context))
+ ; // Ok, it is a scoped-enum constant expression.
else if (Init->isEvaluatable(Context)) {
// If we can constant fold the initializer through heroics, accept it,
// but report this as a use of an extension for -pedantic.
@@ -10521,7 +11218,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
} else if (VDecl->isFileVarDecl()) {
// In C, extern is typically used to avoid tentative definitions when
// declaring variables in headers, but adding an intializer makes it a
- // defintion. This is somewhat confusing, so GCC and Clang both warn on it.
+ // definition. This is somewhat confusing, so GCC and Clang both warn on it.
// In C++, extern is often used to give implictly static const variables
// external linkage, so don't warn in that case. If selectany is present,
// this might be header code intended for C and C++ inclusion, so apply the
@@ -10794,11 +11491,11 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
if (const RecordType *Record
= Context.getBaseElementType(Type)->getAs<RecordType>()) {
CXXRecordDecl *CXXRecord = cast<CXXRecordDecl>(Record->getDecl());
- // Mark the function for further checking even if the looser rules of
- // C++11 do not require such checks, so that we can diagnose
- // incompatibilities with C++98.
+ // Mark the function (if we're in one) for further checking even if the
+ // looser rules of C++11 do not require such checks, so that we can
+ // diagnose incompatibilities with C++98.
if (!CXXRecord->isPOD())
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
}
}
@@ -10898,8 +11595,8 @@ Sema::ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc,
D.takeAttributes(Attrs, AttrEnd);
ParsedAttributes EmptyAttrs(Attrs.getPool().getFactory());
- D.AddTypeInfo(DeclaratorChunk::getReference(0, IdentLoc, /*lvalue*/false),
- EmptyAttrs, IdentLoc);
+ D.AddTypeInfo(DeclaratorChunk::getReference(0, IdentLoc, /*lvalue*/ false),
+ IdentLoc);
Decl *Var = ActOnDeclarator(S, D);
cast<VarDecl>(Var)->setCXXForRangeDecl(true);
FinalizeDeclaration(Var);
@@ -10934,11 +11631,15 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
case Qualifiers::OCL_Weak:
case Qualifiers::OCL_Strong:
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
break;
}
}
+ if (var->hasLocalStorage() &&
+ var->getType().isDestructedType() == QualType::DK_nontrivial_c_struct)
+ setFunctionHasBranchProtectedScope();
+
// Warn about externally-visible variables being defined without a
// prior declaration. We only want to do this for global
// declarations, but we also specifically need to avoid doing it for
@@ -11142,7 +11843,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
Context.addModuleInitializer(ModuleScopes.back().Module, var);
}
-/// \brief Determines if a variable's alignment is dependent.
+/// Determines if a variable's alignment is dependent.
static bool hasDependentAlignment(VarDecl *VD) {
if (VD->getType()->isDependentType())
return true;
@@ -11229,58 +11930,8 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) {
// 7.5). We must also apply the same checks to all __shared__
// variables whether they are local or not. CUDA also allows
// constant initializers for __constant__ and __device__ variables.
- if (getLangOpts().CUDA) {
- const Expr *Init = VD->getInit();
- if (Init && VD->hasGlobalStorage()) {
- if (VD->hasAttr<CUDADeviceAttr>() || VD->hasAttr<CUDAConstantAttr>() ||
- VD->hasAttr<CUDASharedAttr>()) {
- assert(!VD->isStaticLocal() || VD->hasAttr<CUDASharedAttr>());
- bool AllowedInit = false;
- if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(Init))
- AllowedInit =
- isEmptyCudaConstructor(VD->getLocation(), CE->getConstructor());
- // We'll allow constant initializers even if it's a non-empty
- // constructor according to CUDA rules. This deviates from NVCC,
- // but allows us to handle things like constexpr constructors.
- if (!AllowedInit &&
- (VD->hasAttr<CUDADeviceAttr>() || VD->hasAttr<CUDAConstantAttr>()))
- AllowedInit = VD->getInit()->isConstantInitializer(
- Context, VD->getType()->isReferenceType());
-
- // Also make sure that destructor, if there is one, is empty.
- if (AllowedInit)
- if (CXXRecordDecl *RD = VD->getType()->getAsCXXRecordDecl())
- AllowedInit =
- isEmptyCudaDestructor(VD->getLocation(), RD->getDestructor());
-
- if (!AllowedInit) {
- Diag(VD->getLocation(), VD->hasAttr<CUDASharedAttr>()
- ? diag::err_shared_var_init
- : diag::err_dynamic_var_init)
- << Init->getSourceRange();
- VD->setInvalidDecl();
- }
- } else {
- // This is a host-side global variable. Check that the initializer is
- // callable from the host side.
- const FunctionDecl *InitFn = nullptr;
- if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(Init)) {
- InitFn = CE->getConstructor();
- } else if (const CallExpr *CE = dyn_cast<CallExpr>(Init)) {
- InitFn = CE->getDirectCallee();
- }
- if (InitFn) {
- CUDAFunctionTarget InitFnTarget = IdentifyCUDATarget(InitFn);
- if (InitFnTarget != CFT_Host && InitFnTarget != CFT_HostDevice) {
- Diag(VD->getLocation(), diag::err_ref_bad_target_global_initializer)
- << InitFnTarget << InitFn;
- Diag(InitFn->getLocation(), diag::note_previous_decl) << InitFn;
- VD->setInvalidDecl();
- }
- }
- }
- }
- }
+ if (getLangOpts().CUDA)
+ checkAllowedCUDAInitializer(VD);
// Grab the dllimport or dllexport attribute off of the VarDecl.
const InheritableAttr *DLLAttr = getDLLAttr(VD);
@@ -11659,7 +12310,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
return New;
}
-/// \brief Synthesizes a variable for a parameter arising from a
+/// Synthesizes a variable for a parameter arising from a
/// typedef.
ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC,
SourceLocation Loc,
@@ -11896,9 +12547,45 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
const FunctionDecl *EffectiveDefinition,
SkipBodyInfo *SkipBody) {
const FunctionDecl *Definition = EffectiveDefinition;
+ if (!Definition && !FD->isDefined(Definition) && !FD->isCXXClassMember()) {
+ // If this is a friend function defined in a class template, it does not
+ // have a body until it is used, nevertheless it is a definition, see
+ // [temp.inst]p2:
+ //
+ // ... for the purpose of determining whether an instantiated redeclaration
+ // is valid according to [basic.def.odr] and [class.mem], a declaration that
+ // corresponds to a definition in the template is considered to be a
+ // definition.
+ //
+ // The following code must produce redefinition error:
+ //
+ // template<typename T> struct C20 { friend void func_20() {} };
+ // C20<int> c20i;
+ // void func_20() {}
+ //
+ for (auto I : FD->redecls()) {
+ if (I != FD && !I->isInvalidDecl() &&
+ I->getFriendObjectKind() != Decl::FOK_None) {
+ if (FunctionDecl *Original = I->getInstantiatedFromMemberFunction()) {
+ if (FunctionDecl *OrigFD = FD->getInstantiatedFromMemberFunction()) {
+ // A merged copy of the same function, instantiated as a member of
+ // the same class, is OK.
+ if (declaresSameEntity(OrigFD, Original) &&
+ declaresSameEntity(cast<Decl>(I->getLexicalDeclContext()),
+ cast<Decl>(FD->getLexicalDeclContext())))
+ continue;
+ }
+
+ if (Original->isThisDeclarationADefinition()) {
+ Definition = I;
+ break;
+ }
+ }
+ }
+ }
+ }
if (!Definition)
- if (!FD->isDefined(Definition))
- return;
+ return;
if (canRedefineFunction(Definition, getLangOpts()))
return;
@@ -11983,8 +12670,13 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator,
Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
SkipBodyInfo *SkipBody) {
- if (!D)
+ if (!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();
return D;
+ }
+
FunctionDecl *FD = nullptr;
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
@@ -12121,7 +12813,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
return D;
}
-/// \brief Given the set of return statements within a function body,
+/// Given the set of return statements within a function body,
/// compute the variables that are subject to the named return value
/// optimization.
///
@@ -12174,9 +12866,15 @@ bool Sema::canSkipFunctionBody(Decl *D) {
// rest of the file.
// We cannot skip the body of a function with an undeduced return type,
// because any callers of that function need to know the type.
- if (const FunctionDecl *FD = D->getAsFunction())
- if (FD->isConstexpr() || FD->getReturnType()->isUndeducedType())
+ if (const FunctionDecl *FD = D->getAsFunction()) {
+ if (FD->isConstexpr())
return false;
+ // We can't simply call Type::isUndeducedType here, because inside template
+ // auto can be deduced to a dependent type, which is not considered
+ // "undeduced".
+ if (FD->getReturnType()->getContainedDeducedType())
+ return false;
+ }
return Consumer.shouldSkipFunctionBody(D);
}
@@ -12272,8 +12970,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
// Try to apply the named return value optimization. We have to check
// if we can do this here because lambdas keep return statements around
// to deduce an implicit return type.
- if (getLangOpts().CPlusPlus && FD->getReturnType()->isRecordType() &&
- !FD->isDependentContext())
+ if (FD->getReturnType()->isRecordType() &&
+ (!getLangOpts().CPlusPlus || !FD->isDependentContext()))
computeNRVO(Body, getCurFunction());
}
@@ -12316,6 +13014,13 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
}
}
+ // Warn on CPUDispatch with an actual 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::warn_dispatch_body_ignored);
+
if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
const CXXMethodDecl *KeyFunction;
if (MD->isOutOfLine() && (MD = MD->getCanonicalDecl()) &&
@@ -12393,6 +13098,9 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
getCurFunction()->ObjCWarnForNoInitDelegation = false;
}
} else {
+ // Parsing the function declaration failed in some way. Pop the fake scope
+ // we pushed on.
+ PopFunctionScopeInfo(ActivePolicy, dcl);
return nullptr;
}
@@ -12498,7 +13206,7 @@ void Sema::ActOnFinishDelayedAttribute(Scope *S, Decl *D,
// Always attach attributes to the underlying decl.
if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
D = TD->getTemplatedDecl();
- ProcessDeclAttributeList(S, D, Attrs.getList());
+ ProcessDeclAttributeList(S, D, Attrs);
if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(D))
if (Method->isStatic())
@@ -12600,18 +13308,16 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
/*ConstQualifierLoc=*/NoLoc,
/*VolatileQualifierLoc=*/NoLoc,
/*RestrictQualifierLoc=*/NoLoc,
- /*MutableLoc=*/NoLoc,
- EST_None,
+ /*MutableLoc=*/NoLoc, EST_None,
/*ESpecRange=*/SourceRange(),
/*Exceptions=*/nullptr,
/*ExceptionRanges=*/nullptr,
/*NumExceptions=*/0,
/*NoexceptExpr=*/nullptr,
/*ExceptionSpecTokens=*/nullptr,
- /*DeclsInPrototype=*/None,
- Loc, Loc, D),
- DS.getAttributes(),
- SourceLocation());
+ /*DeclsInPrototype=*/None, Loc,
+ Loc, D),
+ std::move(DS.getAttributes()), SourceLocation());
D.SetIdentifier(&II, Loc);
// Insert this function into the enclosing block scope.
@@ -12623,7 +13329,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
return FD;
}
-/// \brief Adds any function attributes that we know a priori based on
+/// Adds any function attributes that we know a priori based on
/// the declaration of this function.
///
/// These attributes can apply both to implicitly-declared builtins
@@ -12673,11 +13379,11 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
Context.BuiltinInfo.isConstWithoutErrno(BuiltinID))
FD->addAttr(ConstAttr::CreateImplicit(Context, FD->getLocation()));
- // We make "fma" on GNU or Windows const because we know it does not set
+ // We make "fma" on some platforms const because we know it does not set
// errno in those environments even though it could set errno based on the
// C standard.
const llvm::Triple &Trip = Context.getTargetInfo().getTriple();
- if ((Trip.isGNUEnvironment() || Trip.isOSMSVCRT()) &&
+ if ((Trip.isGNUEnvironment() || Trip.isAndroid() || Trip.isOSMSVCRT()) &&
!FD->hasAttr<ConstAttr>()) {
switch (BuiltinID) {
case Builtin::BI__builtin_fma:
@@ -12753,7 +13459,7 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
// We already have a __builtin___CFStringMakeConstantString,
// but builds that use -fno-constant-cfstrings don't go through that.
if (!FD->hasAttr<FormatArgAttr>())
- FD->addAttr(FormatArgAttr::CreateImplicit(Context, 1,
+ FD->addAttr(FormatArgAttr::CreateImplicit(Context, ParamIdx(1, FD),
FD->getLocation()));
}
}
@@ -12815,7 +13521,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
return NewTD;
}
-/// \brief Check that this is a valid underlying type for an enum declaration.
+/// Check that this is a valid underlying type for an enum declaration.
bool Sema::CheckEnumUnderlyingType(TypeSourceInfo *TI) {
SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc();
QualType T = TI->getType();
@@ -12833,11 +13539,9 @@ bool Sema::CheckEnumUnderlyingType(TypeSourceInfo *TI) {
/// Check whether this is a valid redeclaration of a previous enumeration.
/// \return true if the redeclaration was invalid.
-bool Sema::CheckEnumRedeclaration(
- SourceLocation EnumLoc, bool IsScoped, QualType EnumUnderlyingTy,
- bool EnumUnderlyingIsImplicit, const EnumDecl *Prev) {
- bool IsFixed = !EnumUnderlyingTy.isNull();
-
+bool Sema::CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped,
+ QualType EnumUnderlyingTy, bool IsFixed,
+ const EnumDecl *Prev) {
if (IsScoped != Prev->isScoped()) {
Diag(EnumLoc, diag::err_enum_redeclare_scoped_mismatch)
<< Prev->isScoped();
@@ -12857,10 +13561,6 @@ bool Sema::CheckEnumRedeclaration(
<< Prev->getIntegerTypeRange();
return true;
}
- } else if (IsFixed && !Prev->isFixed() && EnumUnderlyingIsImplicit) {
- ;
- } else if (!IsFixed && Prev->isFixed() && !Prev->getIntegerTypeSourceInfo()) {
- ;
} else if (IsFixed != Prev->isFixed()) {
Diag(EnumLoc, diag::err_enum_redeclare_fixed_mismatch)
<< Prev->isFixed();
@@ -12871,7 +13571,7 @@ bool Sema::CheckEnumRedeclaration(
return false;
}
-/// \brief Get diagnostic %select index for tag kind for
+/// Get diagnostic %select index for tag kind for
/// redeclaration diagnostic message.
/// WARNING: Indexes apply to particular diagnostics only!
///
@@ -12885,7 +13585,7 @@ static unsigned getRedeclDiagFromTagKind(TagTypeKind Tag) {
}
}
-/// \brief Determine if tag kind is a class-key compatible with
+/// Determine if tag kind is a class-key compatible with
/// class for redeclaration (class, struct, or __interface).
///
/// \returns true iff the tag kind is compatible.
@@ -12919,7 +13619,7 @@ Sema::NonTagKind Sema::getNonTagTypeDeclKind(const Decl *PrevDecl,
llvm_unreachable("invalid TTK");
}
-/// \brief Determine whether a tag with a given kind is acceptable
+/// Determine whether a tag with a given kind is acceptable
/// as a redeclaration of the given tag declaration.
///
/// \returns true if the new tag kind is acceptable, false otherwise.
@@ -13055,8 +13755,8 @@ static FixItHint createFriendTagNNSFixIt(Sema &SemaRef, NamedDecl *ND, Scope *S,
return FixItHint::CreateInsertion(NameLoc, Insertion);
}
-/// \brief Determine whether a tag originally declared in context \p OldDC can
-/// be redeclared with an unqualfied name in \p NewDC (assuming name lookup
+/// Determine whether a tag originally declared in context \p OldDC can
+/// be redeclared with an unqualified name in \p NewDC (assuming name lookup
/// found a declaration in \p OldDC as a previous decl, perhaps through a
/// using-declaration).
static bool isAcceptableTagRedeclContext(Sema &S, DeclContext *OldDC,
@@ -13076,7 +13776,7 @@ static bool isAcceptableTagRedeclContext(Sema &S, DeclContext *OldDC,
return false;
}
-/// \brief This is invoked when we see 'struct foo' or 'struct {'. In the
+/// This is invoked when we see 'struct foo' or 'struct {'. In the
/// former case, Name will be non-null. In the later case, Name will be null.
/// TagSpec indicates what kind of tag this is. TUK indicates whether this is a
/// reference/declaration/definition of a tag.
@@ -13089,13 +13789,12 @@ static bool isAcceptableTagRedeclContext(Sema &S, DeclContext *OldDC,
Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
SourceLocation KWLoc, CXXScopeSpec &SS,
IdentifierInfo *Name, SourceLocation NameLoc,
- AttributeList *Attr, AccessSpecifier AS,
+ const ParsedAttributesView &Attrs, AccessSpecifier AS,
SourceLocation ModulePrivateLoc,
MultiTemplateParamsArg TemplateParameterLists,
bool &OwnedDecl, bool &IsDependent,
SourceLocation ScopedEnumKWLoc,
- bool ScopedEnumUsesClassTag,
- TypeResult UnderlyingType,
+ bool ScopedEnumUsesClassTag, TypeResult UnderlyingType,
bool IsTypeSpecifier, bool IsTemplateParamOrArg,
SkipBodyInfo *SkipBody) {
// If this is not a definition, it must have a name.
@@ -13134,14 +13833,11 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
return nullptr;
OwnedDecl = false;
- DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc,
- SS, Name, NameLoc, Attr,
- TemplateParams, AS,
- ModulePrivateLoc,
- /*FriendLoc*/SourceLocation(),
- TemplateParameterLists.size()-1,
- TemplateParameterLists.data(),
- SkipBody);
+ DeclResult Result = CheckClassTemplate(
+ S, TagSpec, TUK, KWLoc, SS, Name, NameLoc, Attrs, TemplateParams,
+ AS, ModulePrivateLoc,
+ /*FriendLoc*/ SourceLocation(), TemplateParameterLists.size() - 1,
+ TemplateParameterLists.data(), SkipBody);
return Result.get();
} else {
// The "template<>" header is extraneous.
@@ -13156,14 +13852,14 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// this early, because it's needed to detect if this is an incompatible
// redeclaration.
llvm::PointerUnion<const Type*, TypeSourceInfo*> EnumUnderlying;
- bool EnumUnderlyingIsImplicit = false;
+ bool IsFixed = !UnderlyingType.isUnset() || ScopedEnum;
if (Kind == TTK_Enum) {
- if (UnderlyingType.isInvalid() || (!UnderlyingType.get() && ScopedEnum))
+ if (UnderlyingType.isInvalid() || (!UnderlyingType.get() && ScopedEnum)) {
// No underlying type explicitly specified, or we failed to parse the
// type, default to int.
EnumUnderlying = Context.IntTy.getTypePtr();
- else if (UnderlyingType.get()) {
+ } else if (UnderlyingType.get()) {
// C++0x 7.2p2: The type-specifier-seq of an enum-base shall name an
// integral type; any cv-qualification is ignored.
TypeSourceInfo *TI = nullptr;
@@ -13179,11 +13875,12 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
EnumUnderlying = Context.IntTy.getTypePtr();
} else if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- if (getLangOpts().MSVCCompat || TUK == TUK_Definition) {
- // Microsoft enums are always of int type.
+ // For MSVC ABI compatibility, unfixed enums must use an underlying type
+ // of 'int'. However, if this is an unfixed forward declaration, don't set
+ // the underlying type unless the user enables -fms-compatibility. This
+ // makes unfixed forward declared enums incomplete and is more conforming.
+ if (TUK == TUK_Definition || getLangOpts().MSVCCompat)
EnumUnderlying = Context.IntTy.getTypePtr();
- EnumUnderlyingIsImplicit = true;
- }
}
}
@@ -13209,8 +13906,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
if (Kind == TTK_Enum) {
New = EnumDecl::Create(Context, SearchDC, KWLoc, Loc, Name, nullptr,
- ScopedEnum, ScopedEnumUsesClassTag,
- !EnumUnderlying.isNull());
+ ScopedEnum, ScopedEnumUsesClassTag, IsFixed);
// If this is an undefined enum, bail.
if (TUK != TUK_Definition && !Invalid)
return nullptr;
@@ -13589,7 +14285,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// in which case we want the caller to bail out.
if (CheckEnumRedeclaration(NameLoc.isValid() ? NameLoc : KWLoc,
ScopedEnum, EnumUnderlyingTy,
- EnumUnderlyingIsImplicit, PrevEnum))
+ IsFixed, PrevEnum))
return TUK == TUK_Declaration ? PrevTagDecl : nullptr;
}
@@ -13607,7 +14303,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// If this is a use, just return the declaration we found, unless
// we have attributes.
if (TUK == TUK_Reference || TUK == TUK_Friend) {
- if (Attr) {
+ if (!Attrs.empty()) {
// FIXME: Diagnose these attributes. For now, we create a new
// declaration to hold them.
} else if (TUK == TUK_Reference &&
@@ -13799,13 +14495,12 @@ CreateNewDecl:
// PrevDecl.
TagDecl *New;
- bool IsForwardReference = false;
if (Kind == TTK_Enum) {
// FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.:
// enum X { A, B, C } D; D should chain to X.
New = EnumDecl::Create(Context, SearchDC, KWLoc, Loc, Name,
cast_or_null<EnumDecl>(PrevDecl), ScopedEnum,
- ScopedEnumUsesClassTag, !EnumUnderlying.isNull());
+ ScopedEnumUsesClassTag, IsFixed);
if (isStdAlignValT && (!StdAlignValT || getStdAlignValT()->isImplicit()))
StdAlignValT = cast<EnumDecl>(New);
@@ -13813,8 +14508,7 @@ CreateNewDecl:
// If this is an undefined enum, warn.
if (TUK != TUK_Definition && !Invalid) {
TagDecl *Def;
- if (!EnumUnderlyingIsImplicit &&
- (getLangOpts().CPlusPlus11 || getLangOpts().ObjC2) &&
+ if (IsFixed && (getLangOpts().CPlusPlus11 || getLangOpts().ObjC2) &&
cast<EnumDecl>(New)->isFixed()) {
// C++0x: 7.2p2: opaque-enum-declaration.
// Conflicts are diagnosed above. Do nothing.
@@ -13830,12 +14524,6 @@ CreateNewDecl:
else if (getLangOpts().CPlusPlus)
DiagID = diag::err_forward_ref_enum;
Diag(Loc, DiagID);
-
- // If this is a forward-declared reference to an enumeration, make a
- // note of it; we won't actually be introducing the declaration into
- // the declaration context.
- if (TUK == TUK_Reference)
- IsForwardReference = true;
}
}
@@ -13846,6 +14534,7 @@ CreateNewDecl:
else
ED->setIntegerType(QualType(EnumUnderlying.get<const Type*>(), 0));
ED->setPromotionType(ED->getIntegerType());
+ assert(ED->isComplete() && "enum with type should be complete");
}
} else {
// struct/union/class
@@ -13884,13 +14573,10 @@ CreateNewDecl:
if (SS.isNotEmpty()) {
if (SS.isSet()) {
// If this is either a declaration or a definition, check the
- // nested-name-specifier against the current context. We don't do this
- // for explicit specializations, because they have similar checking
- // (with more specific diagnostics) in the call to
- // CheckMemberSpecialization, below.
- if (!isMemberSpecialization &&
- (TUK == TUK_Definition || TUK == TUK_Declaration) &&
- diagnoseQualifiedDeclaration(SS, DC, OrigName, Loc))
+ // nested-name-specifier against the current context.
+ if ((TUK == TUK_Definition || TUK == TUK_Declaration) &&
+ diagnoseQualifiedDeclaration(SS, DC, OrigName, Loc,
+ isMemberSpecialization))
Invalid = true;
New->setQualifierInfo(SS.getWithLocInContext(Context));
@@ -13977,8 +14663,7 @@ CreateNewDecl:
if (TUK == TUK_Definition)
New->startDefinition();
- if (Attr)
- ProcessDeclAttributeList(S, New, Attr);
+ ProcessDeclAttributeList(S, New, Attrs);
AddPragmaAttributes(S, New);
// If this has an identifier, add it to the scope stack.
@@ -13995,9 +14680,7 @@ CreateNewDecl:
PushOnScopeChains(New, EnclosingScope, /* AddToContext = */ false);
} else if (Name) {
S = getNonFieldDeclScope(S);
- PushOnScopeChains(New, S, !IsForwardReference);
- if (IsForwardReference)
- SearchDC->makeDeclVisibleInContext(New);
+ PushOnScopeChains(New, S, true);
} else {
CurContext->addDecl(New);
}
@@ -14381,7 +15064,7 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
return NewFD;
}
-/// \brief Build a new FieldDecl and check its well-formedness.
+/// Build a new FieldDecl and check its well-formedness.
///
/// This routine builds a new FieldDecl given the fields name, type,
/// record, etc. \p PrevDecl should refer to any previous declaration
@@ -14432,6 +15115,13 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
InvalidDecl = true;
}
+ // Anonymous bit-fields cannot be cv-qualified (CWG 2229).
+ if (!InvalidDecl && getLangOpts().CPlusPlus && !II && BitWidth &&
+ T.hasQualifiers()) {
+ InvalidDecl = true;
+ Diag(Loc, diag::err_anon_bitfield_qualifiers);
+ }
+
// C99 6.7.2.1p8: A member of a structure or union may have any type other
// than a variably modified type.
if (!InvalidDecl && T->isVariablyModifiedType()) {
@@ -14764,7 +15454,7 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc,
Decl *ivarDecl = AllIvarDecls[AllIvarDecls.size()-1];
ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(ivarDecl);
- if (!Ivar->isBitField() || Ivar->getBitWidthValue(Context) == 0)
+ if (!Ivar->isBitField() || Ivar->isZeroLengthBitField(Context))
return;
ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CurContext);
if (!ID) {
@@ -14792,7 +15482,8 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc,
void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
ArrayRef<Decl *> Fields, SourceLocation LBrac,
- SourceLocation RBrac, AttributeList *Attr) {
+ SourceLocation RBrac,
+ const ParsedAttributesView &Attrs) {
assert(EnclosingDecl && "missing record or interface decl");
// If this is an Objective-C @implementation or category and we have
@@ -14975,8 +15666,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
QualType T = Context.getObjCObjectPointerType(FD->getType());
FD->setType(T);
} else if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() &&
- Record && !ObjCFieldLifetimeErrReported &&
- (!getLangOpts().CPlusPlus || Record->isUnion())) {
+ Record && !ObjCFieldLifetimeErrReported && Record->isUnion()) {
// It's an error in ARC or Weak if a field has lifetime.
// We don't want to report this in a system header, though,
// so we just make the field unavailable.
@@ -15012,6 +15702,27 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
Record->setHasObjectMember(true);
}
}
+
+ if (Record && !getLangOpts().CPlusPlus && !FD->hasAttr<UnavailableAttr>()) {
+ QualType FT = FD->getType();
+ if (FT.isNonTrivialToPrimitiveDefaultInitialize())
+ Record->setNonTrivialToPrimitiveDefaultInitialize(true);
+ QualType::PrimitiveCopyKind PCK = FT.isNonTrivialToPrimitiveCopy();
+ if (PCK != QualType::PCK_Trivial && PCK != QualType::PCK_VolatileTrivial)
+ Record->setNonTrivialToPrimitiveCopy(true);
+ if (FT.isDestructedType()) {
+ Record->setNonTrivialToPrimitiveDestroy(true);
+ Record->setParamDestroyedInCallee(true);
+ }
+
+ if (const auto *RT = FT->getAs<RecordType>()) {
+ if (RT->getDecl()->getArgPassingRestrictions() ==
+ RecordDecl::APK_CanNeverPassInRegs)
+ Record->setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs);
+ } else if (FT.getQualifiers().getObjCLifetime() == Qualifiers::OCL_Weak)
+ Record->setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs);
+ }
+
if (Record && FD->getType().isVolatileQualified())
Record->setHasVolatileMember(true);
// Keep track of the number of named members.
@@ -15039,10 +15750,10 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
CXXRecord->getDestructor());
}
- if (!CXXRecord->isInvalidDecl()) {
- // Add any implicitly-declared members to this class.
- AddImplicitlyDeclaredMembersToClass(CXXRecord);
+ // Add any implicitly-declared members to this class.
+ AddImplicitlyDeclaredMembersToClass(CXXRecord);
+ if (!CXXRecord->isInvalidDecl()) {
// If we have virtual base classes, we may end up finding multiple
// final overriders for a given virtual function. Check for this
// problem now.
@@ -15057,7 +15768,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
SOEnd = M->second.end();
SO != SOEnd; ++SO) {
assert(SO->second.size() > 0 &&
- "Virtual function without overridding functions?");
+ "Virtual function without overriding functions?");
if (SO->second.size() == 1)
continue;
@@ -15089,6 +15800,9 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
if (!Completed)
Record->completeDefinition();
+ // Handle attributes before checking the layout.
+ ProcessDeclAttributeList(S, Record, Attrs);
+
// We may have deferred checking for a deleted destructor. Check now.
if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record)) {
auto *Dtor = CXXRecord->getDestructor();
@@ -15131,7 +15845,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
(NonBitFields == 0 || ZeroSize) && I != E; ++I) {
IsEmpty = false;
if (I->isUnnamedBitfield()) {
- if (I->getBitWidthValue(Context) > 0)
+ if (!I->isZeroLengthBitField(Context))
ZeroSize = false;
} else {
++NonBitFields;
@@ -15219,12 +15933,9 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
CDecl->setIvarRBraceLoc(RBrac);
}
}
-
- if (Attr)
- ProcessDeclAttributeList(S, Record, Attr);
}
-/// \brief Determine whether the given integral value is representable within
+/// Determine whether the given integral value is representable within
/// the given type T.
static bool isRepresentableIntegerValue(ASTContext &Context,
llvm::APSInt &Value,
@@ -15241,7 +15952,7 @@ static bool isRepresentableIntegerValue(ASTContext &Context,
return Value.getMinSignedBits() <= BitWidth;
}
-// \brief Given an integral type, return the next larger integral type
+// Given an integral type, return the next larger integral type
// (or a NULL type of no such type exists).
static QualType getNextLargerIntegralType(ASTContext &Context, QualType T) {
// FIXME: Int128/UInt128 support, which also needs to be introduced into
@@ -15304,7 +16015,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
&EnumVal).get())) {
// C99 6.7.2.2p2: Make sure we have an integer constant expression.
} else {
- if (Enum->isFixed()) {
+ if (Enum->isComplete()) {
EltTy = Enum->getIntegerType();
// In Obj-C and Microsoft mode, require the enumeration value to be
@@ -15468,7 +16179,7 @@ Sema::SkipBodyInfo Sema::shouldSkipAnonEnumBody(Scope *S, IdentifierInfo *II,
Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
SourceLocation IdLoc, IdentifierInfo *Id,
- AttributeList *Attr,
+ const ParsedAttributesView &Attrs,
SourceLocation EqualLoc, Expr *Val) {
EnumDecl *TheEnumDecl = cast<EnumDecl>(theEnumDecl);
EnumConstantDecl *LastEnumConst =
@@ -15519,7 +16230,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
}
// Process attributes.
- if (Attr) ProcessDeclAttributeList(S, New, Attr);
+ ProcessDeclAttributeList(S, New, Attrs);
AddPragmaAttributes(S, New);
// Register this decl in the current scope stack.
@@ -15571,39 +16282,10 @@ static bool ValidDuplicateEnum(EnumConstantDecl *ECD, EnumDecl *Enum) {
return false;
}
-namespace {
-struct DupKey {
- int64_t val;
- bool isTombstoneOrEmptyKey;
- DupKey(int64_t val, bool isTombstoneOrEmptyKey)
- : val(val), isTombstoneOrEmptyKey(isTombstoneOrEmptyKey) {}
-};
-
-static DupKey GetDupKey(const llvm::APSInt& Val) {
- return DupKey(Val.isSigned() ? Val.getSExtValue() : Val.getZExtValue(),
- false);
-}
-
-struct DenseMapInfoDupKey {
- static DupKey getEmptyKey() { return DupKey(0, true); }
- static DupKey getTombstoneKey() { return DupKey(1, true); }
- static unsigned getHashValue(const DupKey Key) {
- return (unsigned)(Key.val * 37);
- }
- static bool isEqual(const DupKey& LHS, const DupKey& RHS) {
- return LHS.isTombstoneOrEmptyKey == RHS.isTombstoneOrEmptyKey &&
- LHS.val == RHS.val;
- }
-};
-} // end anonymous namespace
-
// Emits a warning when an element is implicitly set a value that
// a previous element has already been set to.
static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements,
- EnumDecl *Enum,
- QualType EnumType) {
- if (S.Diags.isIgnored(diag::warn_duplicate_enum_values, Enum->getLocation()))
- return;
+ EnumDecl *Enum, QualType EnumType) {
// Avoid anonymous enums
if (!Enum->getIdentifier())
return;
@@ -15612,20 +16294,28 @@ static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements,
if (Enum->getNumPositiveBits() > 63 || Enum->getNumNegativeBits() > 64)
return;
+ if (S.Diags.isIgnored(diag::warn_duplicate_enum_values, Enum->getLocation()))
+ return;
+
typedef SmallVector<EnumConstantDecl *, 3> ECDVector;
- typedef SmallVector<ECDVector *, 3> DuplicatesVector;
+ typedef SmallVector<std::unique_ptr<ECDVector>, 3> DuplicatesVector;
typedef llvm::PointerUnion<EnumConstantDecl*, ECDVector*> DeclOrVector;
- typedef llvm::DenseMap<DupKey, DeclOrVector, DenseMapInfoDupKey>
- ValueToVectorMap;
+ typedef llvm::DenseMap<int64_t, DeclOrVector> ValueToVectorMap;
+
+ // Use int64_t as a key to avoid needing special handling for DenseMap keys.
+ auto EnumConstantToKey = [](const EnumConstantDecl *D) {
+ llvm::APSInt Val = D->getInitVal();
+ return Val.isSigned() ? Val.getSExtValue() : Val.getZExtValue();
+ };
DuplicatesVector DupVector;
ValueToVectorMap EnumMap;
// Populate the EnumMap with all values represented by enum constants without
- // an initialier.
- for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
- EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(Elements[i]);
+ // an initializer.
+ for (auto *Element : Elements) {
+ EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(Element);
// Null EnumConstantDecl means a previous diagnostic has been emitted for
// this constant. Skip this enum since it may be ill-formed.
@@ -15633,45 +16323,45 @@ static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements,
return;
}
+ // Constants with initalizers are handled in the next loop.
if (ECD->getInitExpr())
continue;
- DupKey Key = GetDupKey(ECD->getInitVal());
- DeclOrVector &Entry = EnumMap[Key];
-
- // First time encountering this value.
- if (Entry.isNull())
- Entry = ECD;
+ // Duplicate values are handled in the next loop.
+ EnumMap.insert({EnumConstantToKey(ECD), ECD});
}
+ if (EnumMap.size() == 0)
+ return;
+
// Create vectors for any values that has duplicates.
- for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
- EnumConstantDecl *ECD = cast<EnumConstantDecl>(Elements[i]);
+ for (auto *Element : Elements) {
+ // The last loop returned if any constant was null.
+ EnumConstantDecl *ECD = cast<EnumConstantDecl>(Element);
if (!ValidDuplicateEnum(ECD, Enum))
continue;
- DupKey Key = GetDupKey(ECD->getInitVal());
-
- DeclOrVector& Entry = EnumMap[Key];
- if (Entry.isNull())
+ auto Iter = EnumMap.find(EnumConstantToKey(ECD));
+ if (Iter == EnumMap.end())
continue;
+ DeclOrVector& Entry = Iter->second;
if (EnumConstantDecl *D = Entry.dyn_cast<EnumConstantDecl*>()) {
// Ensure constants are different.
if (D == ECD)
continue;
// Create new vector and push values onto it.
- ECDVector *Vec = new ECDVector();
+ auto Vec = llvm::make_unique<ECDVector>();
Vec->push_back(D);
Vec->push_back(ECD);
// Update entry to point to the duplicates vector.
- Entry = Vec;
+ Entry = Vec.get();
// Store the vector somewhere we can consult later for quick emission of
// diagnostics.
- DupVector.push_back(Vec);
+ DupVector.emplace_back(std::move(Vec));
continue;
}
@@ -15684,26 +16374,21 @@ static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements,
}
// Emit diagnostics.
- for (DuplicatesVector::iterator DupVectorIter = DupVector.begin(),
- DupVectorEnd = DupVector.end();
- DupVectorIter != DupVectorEnd; ++DupVectorIter) {
- ECDVector *Vec = *DupVectorIter;
+ for (const auto &Vec : DupVector) {
assert(Vec->size() > 1 && "ECDVector should have at least 2 elements.");
// Emit warning for one enum constant.
- ECDVector::iterator I = Vec->begin();
- S.Diag((*I)->getLocation(), diag::warn_duplicate_enum_values)
- << (*I)->getName() << (*I)->getInitVal().toString(10)
- << (*I)->getSourceRange();
- ++I;
+ auto *FirstECD = Vec->front();
+ S.Diag(FirstECD->getLocation(), diag::warn_duplicate_enum_values)
+ << FirstECD << FirstECD->getInitVal().toString(10)
+ << FirstECD->getSourceRange();
// Emit one note for each of the remaining enum constants with
// the same value.
- for (ECDVector::iterator E = Vec->end(); I != E; ++I)
- S.Diag((*I)->getLocation(), diag::note_duplicate_element)
- << (*I)->getName() << (*I)->getInitVal().toString(10)
- << (*I)->getSourceRange();
- delete Vec;
+ for (auto *ECD : llvm::make_range(Vec->begin() + 1, Vec->end()))
+ S.Diag(ECD->getLocation(), diag::note_duplicate_element)
+ << ECD << ECD->getInitVal().toString(10)
+ << ECD->getSourceRange();
}
}
@@ -15737,14 +16422,12 @@ bool Sema::IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val,
}
void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
- Decl *EnumDeclX,
- ArrayRef<Decl *> Elements,
- Scope *S, AttributeList *Attr) {
+ Decl *EnumDeclX, ArrayRef<Decl *> Elements, Scope *S,
+ const ParsedAttributesView &Attrs) {
EnumDecl *Enum = cast<EnumDecl>(EnumDeclX);
QualType EnumType = Context.getTypeDeclType(Enum);
- if (Attr)
- ProcessDeclAttributeList(S, Enum, Attr);
+ ProcessDeclAttributeList(S, Enum, Attrs);
if (Enum->isDependentType()) {
for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
@@ -15815,7 +16498,9 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
if (LangOpts.ShortEnums)
Packed = true;
- if (Enum->isFixed()) {
+ // If the enum already has a type because it is fixed or dictated by the
+ // target, promote that type instead of analyzing the enumerators.
+ if (Enum->isComplete()) {
BestType = Enum->getIntegerType();
if (BestType->isPromotableIntegerType())
BestPromotionType = Context.getPromotedIntegerType(BestType);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
index 21fe46ad9dd1..320eabd5ec2f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
@@ -31,6 +31,7 @@
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
@@ -58,7 +59,7 @@ static bool isFunctionOrMethod(const Decl *D) {
return (D->getFunctionType() != nullptr) || isa<ObjCMethodDecl>(D);
}
-/// \brief Return true if the given decl has function type (function or
+/// Return true if the given decl has function type (function or
/// function-typed variable) or an Objective-C method or a block.
static bool isFunctionOrMethodOrBlock(const Decl *D) {
return isFunctionOrMethod(D) || isa<BlockDecl>(D);
@@ -87,7 +88,7 @@ static bool hasFunctionProto(const Decl *D) {
static unsigned getFunctionOrMethodNumParams(const Decl *D) {
if (const FunctionType *FnTy = D->getFunctionType())
return cast<FunctionProtoType>(FnTy)->getNumParams();
- if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
+ if (const auto *BD = dyn_cast<BlockDecl>(D))
return BD->getNumParams();
return cast<ObjCMethodDecl>(D)->param_size();
}
@@ -95,7 +96,7 @@ static unsigned getFunctionOrMethodNumParams(const Decl *D) {
static QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx) {
if (const FunctionType *FnTy = D->getFunctionType())
return cast<FunctionProtoType>(FnTy)->getParamType(Idx);
- if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
+ if (const auto *BD = dyn_cast<BlockDecl>(D))
return BD->getParamDecl(Idx)->getType();
return cast<ObjCMethodDecl>(D)->parameters()[Idx]->getType();
@@ -113,7 +114,7 @@ static SourceRange getFunctionOrMethodParamRange(const Decl *D, unsigned Idx) {
static QualType getFunctionOrMethodResultType(const Decl *D) {
if (const FunctionType *FnTy = D->getFunctionType())
- return cast<FunctionType>(FnTy)->getReturnType();
+ return FnTy->getReturnType();
return cast<ObjCMethodDecl>(D)->getReturnType();
}
@@ -126,24 +127,21 @@ static SourceRange getFunctionOrMethodResultSourceRange(const Decl *D) {
}
static bool isFunctionOrMethodVariadic(const Decl *D) {
- if (const FunctionType *FnTy = D->getFunctionType()) {
- const FunctionProtoType *proto = cast<FunctionProtoType>(FnTy);
- return proto->isVariadic();
- }
- if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
+ if (const FunctionType *FnTy = D->getFunctionType())
+ return cast<FunctionProtoType>(FnTy)->isVariadic();
+ if (const auto *BD = dyn_cast<BlockDecl>(D))
return BD->isVariadic();
-
return cast<ObjCMethodDecl>(D)->isVariadic();
}
static bool isInstanceMethod(const Decl *D) {
- if (const CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(D))
+ if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(D))
return MethodDecl->isInstance();
return false;
}
static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
- const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
+ const auto *PT = T->getAs<ObjCObjectPointerType>();
if (!PT)
return false;
@@ -159,11 +157,11 @@ static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
}
static inline bool isCFStringType(QualType T, ASTContext &Ctx) {
- const PointerType *PT = T->getAs<PointerType>();
+ const auto *PT = T->getAs<PointerType>();
if (!PT)
return false;
- const RecordType *RT = PT->getPointeeType()->getAs<RecordType>();
+ const auto *RT = PT->getPointeeType()->getAs<RecordType>();
if (!RT)
return false;
@@ -174,89 +172,86 @@ static inline bool isCFStringType(QualType T, ASTContext &Ctx) {
return RD->getIdentifier() == &Ctx.Idents.get("__CFString");
}
-static unsigned getNumAttributeArgs(const AttributeList &Attr) {
+static unsigned getNumAttributeArgs(const ParsedAttr &AL) {
// FIXME: Include the type in the argument list.
- return Attr.getNumArgs() + Attr.hasParsedType();
+ return AL.getNumArgs() + AL.hasParsedType();
}
template <typename Compare>
-static bool checkAttributeNumArgsImpl(Sema &S, const AttributeList &Attr,
+static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL,
unsigned Num, unsigned Diag,
Compare Comp) {
- if (Comp(getNumAttributeArgs(Attr), Num)) {
- S.Diag(Attr.getLoc(), Diag) << Attr.getName() << Num;
+ if (Comp(getNumAttributeArgs(AL), Num)) {
+ S.Diag(AL.getLoc(), Diag) << AL.getName() << Num;
return false;
}
return true;
}
-/// \brief Check if the attribute has exactly as many args as Num. May
+/// Check if the attribute has exactly as many args as Num. May
/// output an error.
-static bool checkAttributeNumArgs(Sema &S, const AttributeList &Attr,
- unsigned Num) {
- return checkAttributeNumArgsImpl(S, Attr, Num,
+static bool checkAttributeNumArgs(Sema &S, const ParsedAttr &AL, unsigned Num) {
+ return checkAttributeNumArgsImpl(S, AL, Num,
diag::err_attribute_wrong_number_arguments,
std::not_equal_to<unsigned>());
}
-/// \brief Check if the attribute has at least as many args as Num. May
+/// Check if the attribute has at least as many args as Num. May
/// output an error.
-static bool checkAttributeAtLeastNumArgs(Sema &S, const AttributeList &Attr,
+static bool checkAttributeAtLeastNumArgs(Sema &S, const ParsedAttr &AL,
unsigned Num) {
- return checkAttributeNumArgsImpl(S, Attr, Num,
+ return checkAttributeNumArgsImpl(S, AL, Num,
diag::err_attribute_too_few_arguments,
std::less<unsigned>());
}
-/// \brief Check if the attribute has at most as many args as Num. May
+/// Check if the attribute has at most as many args as Num. May
/// output an error.
-static bool checkAttributeAtMostNumArgs(Sema &S, const AttributeList &Attr,
- unsigned Num) {
- return checkAttributeNumArgsImpl(S, Attr, Num,
+static bool checkAttributeAtMostNumArgs(Sema &S, const ParsedAttr &AL,
+ unsigned Num) {
+ return checkAttributeNumArgsImpl(S, AL, Num,
diag::err_attribute_too_many_arguments,
std::greater<unsigned>());
}
-/// \brief A helper function to provide Attribute Location for the Attr types
-/// AND the AttributeList.
+/// A helper function to provide Attribute Location for the Attr types
+/// AND the ParsedAttr.
template <typename AttrInfo>
-static typename std::enable_if<std::is_base_of<clang::Attr, AttrInfo>::value,
+static typename std::enable_if<std::is_base_of<Attr, AttrInfo>::value,
SourceLocation>::type
-getAttrLoc(const AttrInfo &Attr) {
- return Attr.getLocation();
-}
-static SourceLocation getAttrLoc(const clang::AttributeList &Attr) {
- return Attr.getLoc();
+getAttrLoc(const AttrInfo &AL) {
+ return AL.getLocation();
}
+static SourceLocation getAttrLoc(const ParsedAttr &AL) { return AL.getLoc(); }
-/// \brief A helper function to provide Attribute Name for the Attr types
-/// AND the AttributeList.
+/// 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<clang::Attr, AttrInfo>::value,
+static typename std::enable_if<std::is_base_of<Attr, AttrInfo>::value,
const AttrInfo *>::type
-getAttrName(const AttrInfo &Attr) {
- return &Attr;
+getAttrName(const AttrInfo &AL) {
+ return &AL;
}
-static const IdentifierInfo *getAttrName(const clang::AttributeList &Attr) {
- return Attr.getName();
+static const IdentifierInfo *getAttrName(const ParsedAttr &AL) {
+ return AL.getName();
}
-/// \brief If Expr is a valid integer constant, get the value of the integer
+/// If Expr is a valid integer constant, get the value of the integer
/// expression and return success or failure. May output an error.
-template<typename AttrInfo>
-static bool checkUInt32Argument(Sema &S, const AttrInfo& Attr, const Expr *Expr,
+template <typename AttrInfo>
+static bool checkUInt32Argument(Sema &S, const AttrInfo &AI, const Expr *Expr,
uint32_t &Val, unsigned Idx = UINT_MAX) {
llvm::APSInt I(32);
if (Expr->isTypeDependent() || Expr->isValueDependent() ||
!Expr->isIntegerConstantExpr(I, S.Context)) {
if (Idx != UINT_MAX)
- S.Diag(getAttrLoc(Attr), diag::err_attribute_argument_n_type)
- << getAttrName(Attr) << Idx << AANT_ArgumentIntegerConstant
+ S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type)
+ << getAttrName(AI) << Idx << AANT_ArgumentIntegerConstant
<< Expr->getSourceRange();
else
- S.Diag(getAttrLoc(Attr), diag::err_attribute_argument_type)
- << getAttrName(Attr) << AANT_ArgumentIntegerConstant
+ S.Diag(getAttrLoc(AI), diag::err_attribute_argument_type)
+ << getAttrName(AI) << AANT_ArgumentIntegerConstant
<< Expr->getSourceRange();
return false;
}
@@ -271,14 +266,14 @@ static bool checkUInt32Argument(Sema &S, const AttrInfo& Attr, const Expr *Expr,
return true;
}
-/// \brief Wrapper around checkUInt32Argument, with an extra check to be sure
+/// Wrapper around checkUInt32Argument, with an extra check to be sure
/// that the result will fit into a regular (signed) int. All args have the same
/// purpose as they do in checkUInt32Argument.
-template<typename AttrInfo>
-static bool checkPositiveIntArgument(Sema &S, const AttrInfo& Attr, const Expr *Expr,
+template <typename AttrInfo>
+static bool checkPositiveIntArgument(Sema &S, const AttrInfo &AI, const Expr *Expr,
int &Val, unsigned Idx = UINT_MAX) {
uint32_t UVal;
- if (!checkUInt32Argument(S, Attr, Expr, UVal, Idx))
+ if (!checkUInt32Argument(S, AI, Expr, UVal, Idx))
return false;
if (UVal > (uint32_t)std::numeric_limits<int>::max()) {
@@ -293,12 +288,12 @@ static bool checkPositiveIntArgument(Sema &S, const AttrInfo& Attr, const Expr *
return true;
}
-/// \brief Diagnose mutually exclusive attributes when present on a given
+/// 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) {
- if (AttrTy *A = D->getAttr<AttrTy>()) {
+ if (const auto *A = D->getAttr<AttrTy>()) {
S.Diag(Range.getBegin(), diag::err_attributes_are_not_compatible) << Ident
<< A;
S.Diag(A->getLocation(), diag::note_conflicting_attribute);
@@ -307,14 +302,14 @@ static bool checkAttrMutualExclusion(Sema &S, Decl *D, SourceRange Range,
return false;
}
-/// \brief Check if IdxExpr is a valid parameter index for a function or
+/// Check if IdxExpr is a valid parameter index for a function or
/// instance method D. May output an error.
///
/// \returns true if IdxExpr is a valid index.
template <typename AttrInfo>
static bool checkFunctionOrMethodParameterIndex(
- Sema &S, const Decl *D, const AttrInfo &Attr, unsigned AttrArgNum,
- const Expr *IdxExpr, uint64_t &Idx, bool AllowImplicitThis = false) {
+ Sema &S, const Decl *D, const AttrInfo &AI, unsigned AttrArgNum,
+ const Expr *IdxExpr, ParamIdx &Idx, bool CanIndexImplicitThis = false) {
assert(isFunctionOrMethodOrBlock(D));
// In C++ the implicit 'this' function parameter also counts.
@@ -328,44 +323,43 @@ static bool checkFunctionOrMethodParameterIndex(
llvm::APSInt IdxInt;
if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
!IdxExpr->isIntegerConstantExpr(IdxInt, S.Context)) {
- S.Diag(getAttrLoc(Attr), diag::err_attribute_argument_n_type)
- << getAttrName(Attr) << AttrArgNum << AANT_ArgumentIntegerConstant
+ S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type)
+ << getAttrName(AI) << AttrArgNum << AANT_ArgumentIntegerConstant
<< IdxExpr->getSourceRange();
return false;
}
- Idx = IdxInt.getLimitedValue();
- if (Idx < 1 || (!IV && Idx > NumParams)) {
- S.Diag(getAttrLoc(Attr), diag::err_attribute_argument_out_of_bounds)
- << getAttrName(Attr) << AttrArgNum << IdxExpr->getSourceRange();
+ 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();
return false;
}
- Idx--; // Convert to zero-based.
- if (HasImplicitThisParam && !AllowImplicitThis) {
- if (Idx == 0) {
- S.Diag(getAttrLoc(Attr),
+ if (HasImplicitThisParam && !CanIndexImplicitThis) {
+ if (IdxSource == 1) {
+ S.Diag(getAttrLoc(AI),
diag::err_attribute_invalid_implicit_this_argument)
- << getAttrName(Attr) << IdxExpr->getSourceRange();
+ << getAttrName(AI) << IdxExpr->getSourceRange();
return false;
}
- --Idx;
}
+ Idx = ParamIdx(IdxSource, D);
return true;
}
-/// \brief Check if the argument \p ArgNum of \p Attr is a ASCII string literal.
+/// Check if the argument \p ArgNum of \p Attr is a ASCII string literal.
/// If not emit an error and return false. If the argument is an identifier it
/// will emit an error with a fixit hint and treat it as if it was a string
/// literal.
-bool Sema::checkStringLiteralArgumentAttr(const AttributeList &Attr,
- unsigned ArgNum, StringRef &Str,
+bool Sema::checkStringLiteralArgumentAttr(const ParsedAttr &AL, unsigned ArgNum,
+ StringRef &Str,
SourceLocation *ArgLocation) {
// Look for identifiers. If we have one emit a hint to fix it to a literal.
- if (Attr.isArgIdent(ArgNum)) {
- IdentifierLoc *Loc = Attr.getArgAsIdent(ArgNum);
+ if (AL.isArgIdent(ArgNum)) {
+ IdentifierLoc *Loc = AL.getArgAsIdent(ArgNum);
Diag(Loc->Loc, diag::err_attribute_argument_type)
- << Attr.getName() << AANT_ArgumentString
+ << AL.getName() << AANT_ArgumentString
<< FixItHint::CreateInsertion(Loc->Loc, "\"")
<< FixItHint::CreateInsertion(getLocForEndOfToken(Loc->Loc), "\"");
Str = Loc->Ident->getName();
@@ -375,14 +369,14 @@ bool Sema::checkStringLiteralArgumentAttr(const AttributeList &Attr,
}
// Now check for an actual string literal.
- Expr *ArgExpr = Attr.getArgAsExpr(ArgNum);
- StringLiteral *Literal = dyn_cast<StringLiteral>(ArgExpr->IgnoreParenCasts());
+ Expr *ArgExpr = AL.getArgAsExpr(ArgNum);
+ const auto *Literal = dyn_cast<StringLiteral>(ArgExpr->IgnoreParenCasts());
if (ArgLocation)
*ArgLocation = ArgExpr->getLocStart();
if (!Literal || !Literal->isAscii()) {
Diag(ArgExpr->getLocStart(), diag::err_attribute_argument_type)
- << Attr.getName() << AANT_ArgumentString;
+ << AL.getName() << AANT_ArgumentString;
return false;
}
@@ -390,35 +384,34 @@ bool Sema::checkStringLiteralArgumentAttr(const AttributeList &Attr,
return true;
}
-/// \brief Applies the given attribute to the Decl without performing any
+/// Applies the given attribute to the Decl without performing any
/// additional semantic checking.
template <typename AttrType>
-static void handleSimpleAttribute(Sema &S, Decl *D,
- const AttributeList &Attr) {
- D->addAttr(::new (S.Context) AttrType(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+static void handleSimpleAttribute(Sema &S, Decl *D, const ParsedAttr &AL) {
+ D->addAttr(::new (S.Context) AttrType(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
template <typename AttrType>
static void handleSimpleAttributeWithExclusions(Sema &S, Decl *D,
- const AttributeList &Attr) {
- handleSimpleAttribute<AttrType>(S, D, Attr);
+ const ParsedAttr &AL) {
+ handleSimpleAttribute<AttrType>(S, D, AL);
}
-/// \brief Applies the given attribute to the Decl so long as the Decl doesn't
+/// Applies the given attribute to the Decl so long as the Decl doesn't
/// already have one of the given incompatible attributes.
template <typename AttrType, typename IncompatibleAttrType,
typename... IncompatibleAttrTypes>
static void handleSimpleAttributeWithExclusions(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (checkAttrMutualExclusion<IncompatibleAttrType>(S, D, Attr.getRange(),
- Attr.getName()))
+ const ParsedAttr &AL) {
+ if (checkAttrMutualExclusion<IncompatibleAttrType>(S, D, AL.getRange(),
+ AL.getName()))
return;
handleSimpleAttributeWithExclusions<AttrType, IncompatibleAttrTypes...>(S, D,
- Attr);
+ AL);
}
-/// \brief Check if the passed-in expression is of type int or bool.
+/// Check if the passed-in expression is of type int or bool.
static bool isIntOrBool(Expr *Exp) {
QualType QT = Exp->getType();
return QT->isBooleanType() || QT->isIntegerType();
@@ -441,17 +434,17 @@ static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) {
return true;
}
-/// \brief Check if passed in Decl is a pointer type.
+/// Check if passed in Decl is a pointer type.
/// Note that this function may produce an error message.
/// \return true if the Decl is a pointer type; false otherwise
static bool threadSafetyCheckIsPointer(Sema &S, const Decl *D,
- const AttributeList &Attr) {
- const ValueDecl *vd = cast<ValueDecl>(D);
- QualType QT = vd->getType();
+ const ParsedAttr &AL) {
+ const auto *VD = cast<ValueDecl>(D);
+ QualType QT = VD->getType();
if (QT->isAnyPointerType())
return true;
- if (const RecordType *RT = QT->getAs<RecordType>()) {
+ if (const auto *RT = QT->getAs<RecordType>()) {
// If it's an incomplete type, it could be a smart pointer; skip it.
// (We don't want to force template instantiation if we can avoid it,
// since that would alter the order in which templates are instantiated.)
@@ -462,19 +455,19 @@ static bool threadSafetyCheckIsPointer(Sema &S, const Decl *D,
return true;
}
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_pointer)
- << Attr.getName() << QT;
+ S.Diag(AL.getLoc(), diag::warn_thread_attribute_decl_not_pointer)
+ << AL.getName() << QT;
return false;
}
-/// \brief Checks that the passed in QualType either is of RecordType or points
+/// Checks that the passed in QualType either is of RecordType or points
/// to RecordType. Returns the relevant RecordType, null if it does not exit.
static const RecordType *getRecordType(QualType QT) {
- if (const RecordType *RT = QT->getAs<RecordType>())
+ if (const auto *RT = QT->getAs<RecordType>())
return RT;
// Now check if we point to record type.
- if (const PointerType *PT = QT->getAs<PointerType>())
+ if (const auto *PT = QT->getAs<PointerType>())
return PT->getPointeeType()->getAs<RecordType>();
return nullptr;
@@ -501,7 +494,7 @@ static bool checkRecordTypeForCapability(Sema &S, QualType Ty) {
return true;
// Else check if any base classes have a capability.
- if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
+ 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>();
@@ -559,18 +552,18 @@ static bool isCapabilityExpr(Sema &S, const Expr *Ex) {
return typeHasCapability(S, Ex->getType());
}
-/// \brief Checks that all attribute arguments, starting from Sidx, resolve to
+/// Checks that all attribute arguments, starting from Sidx, resolve to
/// a capability object.
/// \param Sidx The attribute argument index to start checking with.
/// \param ParamIdxOk Whether an argument can be indexing into a function
/// parameter list.
static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D,
- const AttributeList &Attr,
+ const ParsedAttr &AL,
SmallVectorImpl<Expr *> &Args,
int Sidx = 0,
bool ParamIdxOk = false) {
- for (unsigned Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) {
- Expr *ArgExp = Attr.getArgAsExpr(Idx);
+ for (unsigned Idx = Sidx; Idx < AL.getNumArgs(); ++Idx) {
+ Expr *ArgExp = AL.getArgAsExpr(Idx);
if (ArgExp->isTypeDependent()) {
// FIXME -- need to check this again on template instantiation
@@ -578,7 +571,7 @@ static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D,
continue;
}
- if (StringLiteral *StrLit = dyn_cast<StringLiteral>(ArgExp)) {
+ if (const auto *StrLit = dyn_cast<StringLiteral>(ArgExp)) {
if (StrLit->getLength() == 0 ||
(StrLit->isAscii() && StrLit->getString() == StringRef("*"))) {
// Pass empty strings to the analyzer without warnings.
@@ -589,8 +582,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(Attr.getLoc(), diag::warn_thread_attribute_ignored) <<
- Attr.getName();
+ S.Diag(AL.getLoc(), diag::warn_thread_attribute_ignored) << AL.getName();
Args.push_back(ArgExp);
continue;
}
@@ -599,9 +591,9 @@ static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D,
// A pointer to member expression of the form &MyClass::mu is treated
// specially -- we need to look at the type of the member.
- if (UnaryOperator *UOp = dyn_cast<UnaryOperator>(ArgExp))
+ if (const auto *UOp = dyn_cast<UnaryOperator>(ArgExp))
if (UOp->getOpcode() == UO_AddrOf)
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(UOp->getSubExpr()))
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(UOp->getSubExpr()))
if (DRE->getDecl()->isCXXInstanceMember())
ArgTy = DRE->getDecl()->getType();
@@ -610,16 +602,16 @@ static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D,
// Now check if we index into a record type function param.
if(!RT && ParamIdxOk) {
- FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
- IntegerLiteral *IL = dyn_cast<IntegerLiteral>(ArgExp);
+ const auto *FD = dyn_cast<FunctionDecl>(D);
+ const auto *IL = dyn_cast<IntegerLiteral>(ArgExp);
if(FD && IL) {
unsigned int NumParams = FD->getNumParams();
llvm::APInt ArgValue = IL->getValue();
uint64_t ParamIdxFromOne = ArgValue.getZExtValue();
uint64_t ParamIdxFromZero = ParamIdxFromOne - 1;
- if(!ArgValue.isStrictlyPositive() || ParamIdxFromOne > NumParams) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_range)
- << Attr.getName() << Idx + 1 << NumParams;
+ if (!ArgValue.isStrictlyPositive() || ParamIdxFromOne > NumParams) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_range)
+ << AL.getName() << Idx + 1 << NumParams;
continue;
}
ArgTy = FD->getParamDecl(ParamIdxFromZero)->getType();
@@ -631,8 +623,8 @@ static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D,
// capability may be on the type, and the expression is a capability
// boolean logic expression. Eg) requires_capability(A || B && !C)
if (!typeHasCapability(S, ArgTy) && !isCapabilityExpr(S, ArgExp))
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_argument_not_lockable)
- << Attr.getName() << ArgTy;
+ S.Diag(AL.getLoc(), diag::warn_thread_attribute_argument_not_lockable)
+ << AL.getName() << ArgTy;
Args.push_back(ArgExp);
}
@@ -642,22 +634,20 @@ static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D,
// Attribute Implementations
//===----------------------------------------------------------------------===//
-static void handlePtGuardedVarAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!threadSafetyCheckIsPointer(S, D, Attr))
+static void handlePtGuardedVarAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!threadSafetyCheckIsPointer(S, D, AL))
return;
D->addAttr(::new (S.Context)
- PtGuardedVarAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ PtGuardedVarAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static bool checkGuardedByAttrCommon(Sema &S, Decl *D,
- const AttributeList &Attr,
- Expr* &Arg) {
- SmallVector<Expr*, 1> Args;
+static bool checkGuardedByAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
+ Expr *&Arg) {
+ SmallVector<Expr *, 1> Args;
// check that all arguments are lockable objects
- checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
+ checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
unsigned Size = Args.size();
if (Size != 1)
return false;
@@ -667,273 +657,239 @@ static bool checkGuardedByAttrCommon(Sema &S, Decl *D,
return true;
}
-static void handleGuardedByAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleGuardedByAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
Expr *Arg = nullptr;
- if (!checkGuardedByAttrCommon(S, D, Attr, Arg))
+ if (!checkGuardedByAttrCommon(S, D, AL, Arg))
return;
- D->addAttr(::new (S.Context) GuardedByAttr(Attr.getRange(), S.Context, Arg,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) GuardedByAttr(
+ AL.getRange(), S.Context, Arg, AL.getAttributeSpellingListIndex()));
}
-static void handlePtGuardedByAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handlePtGuardedByAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
Expr *Arg = nullptr;
- if (!checkGuardedByAttrCommon(S, D, Attr, Arg))
+ if (!checkGuardedByAttrCommon(S, D, AL, Arg))
return;
- if (!threadSafetyCheckIsPointer(S, D, Attr))
+ if (!threadSafetyCheckIsPointer(S, D, AL))
return;
- D->addAttr(::new (S.Context) PtGuardedByAttr(Attr.getRange(),
- S.Context, Arg,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) PtGuardedByAttr(
+ AL.getRange(), S.Context, Arg, AL.getAttributeSpellingListIndex()));
}
-static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D,
- const AttributeList &Attr,
+static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
SmallVectorImpl<Expr *> &Args) {
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+ if (!checkAttributeAtLeastNumArgs(S, AL, 1))
return false;
// Check that this attribute only applies to lockable types.
QualType QT = cast<ValueDecl>(D)->getType();
if (!QT->isDependentType() && !typeHasCapability(S, QT)) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_lockable)
- << Attr.getName();
+ S.Diag(AL.getLoc(), diag::warn_thread_attribute_decl_not_lockable)
+ << AL.getName();
return false;
}
// Check that all arguments are lockable objects.
- checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
+ checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
if (Args.empty())
return false;
return true;
}
-static void handleAcquiredAfterAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- SmallVector<Expr*, 1> Args;
- if (!checkAcquireOrderAttrCommon(S, D, Attr, Args))
+static void handleAcquiredAfterAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ SmallVector<Expr *, 1> Args;
+ if (!checkAcquireOrderAttrCommon(S, D, AL, Args))
return;
Expr **StartArg = &Args[0];
- D->addAttr(::new (S.Context)
- AcquiredAfterAttr(Attr.getRange(), S.Context,
- StartArg, Args.size(),
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) AcquiredAfterAttr(
+ AL.getRange(), S.Context, StartArg, Args.size(),
+ AL.getAttributeSpellingListIndex()));
}
-static void handleAcquiredBeforeAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- SmallVector<Expr*, 1> Args;
- if (!checkAcquireOrderAttrCommon(S, D, Attr, Args))
+static void handleAcquiredBeforeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ SmallVector<Expr *, 1> Args;
+ if (!checkAcquireOrderAttrCommon(S, D, AL, Args))
return;
Expr **StartArg = &Args[0];
- D->addAttr(::new (S.Context)
- AcquiredBeforeAttr(Attr.getRange(), S.Context,
- StartArg, Args.size(),
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) AcquiredBeforeAttr(
+ AL.getRange(), S.Context, StartArg, Args.size(),
+ AL.getAttributeSpellingListIndex()));
}
-static bool checkLockFunAttrCommon(Sema &S, Decl *D,
- const AttributeList &Attr,
+static bool checkLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
SmallVectorImpl<Expr *> &Args) {
// zero or more arguments ok
// check that all arguments are lockable objects
- checkAttrArgsAreCapabilityObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true);
+ checkAttrArgsAreCapabilityObjs(S, D, AL, Args, 0, /*ParamIdxOk=*/true);
return true;
}
-static void handleAssertSharedLockAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- SmallVector<Expr*, 1> Args;
- if (!checkLockFunAttrCommon(S, D, Attr, Args))
+static void handleAssertSharedLockAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ SmallVector<Expr *, 1> Args;
+ if (!checkLockFunAttrCommon(S, D, AL, Args))
return;
unsigned Size = Args.size();
Expr **StartArg = Size == 0 ? nullptr : &Args[0];
D->addAttr(::new (S.Context)
- AssertSharedLockAttr(Attr.getRange(), S.Context, StartArg, Size,
- Attr.getAttributeSpellingListIndex()));
+ AssertSharedLockAttr(AL.getRange(), S.Context, StartArg, Size,
+ AL.getAttributeSpellingListIndex()));
}
static void handleAssertExclusiveLockAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- SmallVector<Expr*, 1> Args;
- if (!checkLockFunAttrCommon(S, D, Attr, Args))
+ const ParsedAttr &AL) {
+ SmallVector<Expr *, 1> Args;
+ if (!checkLockFunAttrCommon(S, D, AL, Args))
return;
unsigned Size = Args.size();
Expr **StartArg = Size == 0 ? nullptr : &Args[0];
- D->addAttr(::new (S.Context)
- AssertExclusiveLockAttr(Attr.getRange(), S.Context,
- StartArg, Size,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) AssertExclusiveLockAttr(
+ AL.getRange(), S.Context, StartArg, Size,
+ AL.getAttributeSpellingListIndex()));
}
-/// \brief Checks to be sure that the given parameter number is in bounds, and is
-/// an integral type. Will emit appropriate diagnostics if this returns
+/// Checks to be sure that the given parameter number is in bounds, and
+/// is an integral type. Will emit appropriate diagnostics if this returns
/// false.
///
-/// FuncParamNo is expected to be from the user, so is base-1. AttrArgNo is used
-/// to actually retrieve the argument, so it's base-0.
+/// AttrArgNo is used to actually retrieve the argument, so it's base-0.
template <typename AttrInfo>
static bool checkParamIsIntegerType(Sema &S, const FunctionDecl *FD,
- const AttrInfo &Attr, Expr *AttrArg,
- unsigned FuncParamNo, unsigned AttrArgNo,
- bool AllowDependentType = false) {
- uint64_t Idx;
- if (!checkFunctionOrMethodParameterIndex(S, FD, Attr, FuncParamNo, AttrArg,
+ const AttrInfo &AI, unsigned AttrArgNo) {
+ assert(AI.isArgExpr(AttrArgNo) && "Expected expression argument");
+ Expr *AttrArg = AI.getArgAsExpr(AttrArgNo);
+ ParamIdx Idx;
+ if (!checkFunctionOrMethodParameterIndex(S, FD, AI, AttrArgNo + 1, AttrArg,
Idx))
return false;
- const ParmVarDecl *Param = FD->getParamDecl(Idx);
- if (AllowDependentType && Param->getType()->isDependentType())
- return true;
+ const ParmVarDecl *Param = FD->getParamDecl(Idx.getASTIndex());
if (!Param->getType()->isIntegerType() && !Param->getType()->isCharType()) {
SourceLocation SrcLoc = AttrArg->getLocStart();
S.Diag(SrcLoc, diag::err_attribute_integers_only)
- << getAttrName(Attr) << Param->getSourceRange();
+ << getAttrName(AI) << Param->getSourceRange();
return false;
}
return true;
}
-/// \brief Checks to be sure that the given parameter number is in bounds, and is
-/// an integral type. Will emit appropriate diagnostics if this returns false.
-///
-/// FuncParamNo is expected to be from the user, so is base-1. AttrArgNo is used
-/// to actually retrieve the argument, so it's base-0.
-static bool checkParamIsIntegerType(Sema &S, const FunctionDecl *FD,
- const AttributeList &Attr,
- unsigned FuncParamNo, unsigned AttrArgNo,
- bool AllowDependentType = false) {
- assert(Attr.isArgExpr(AttrArgNo) && "Expected expression argument");
- return checkParamIsIntegerType(S, FD, Attr, Attr.getArgAsExpr(AttrArgNo),
- FuncParamNo, AttrArgNo, AllowDependentType);
-}
-
-static void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1) ||
- !checkAttributeAtMostNumArgs(S, Attr, 2))
+static void handleAllocSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!checkAttributeAtLeastNumArgs(S, AL, 1) ||
+ !checkAttributeAtMostNumArgs(S, AL, 2))
return;
const auto *FD = cast<FunctionDecl>(D);
if (!FD->getReturnType()->isPointerType()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_return_pointers_only)
- << Attr.getName();
+ S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only)
+ << AL.getName();
return;
}
- const Expr *SizeExpr = Attr.getArgAsExpr(0);
- int SizeArgNo;
+ const Expr *SizeExpr = AL.getArgAsExpr(0);
+ int SizeArgNoVal;
// Parameter indices are 1-indexed, hence Index=1
- if (!checkPositiveIntArgument(S, Attr, SizeExpr, SizeArgNo, /*Index=*/1))
+ if (!checkPositiveIntArgument(S, AL, SizeExpr, SizeArgNoVal, /*Index=*/1))
return;
-
- if (!checkParamIsIntegerType(S, FD, Attr, SizeArgNo, /*AttrArgNo=*/0))
+ if (!checkParamIsIntegerType(S, FD, AL, /*AttrArgNo=*/0))
return;
+ ParamIdx SizeArgNo(SizeArgNoVal, D);
- // Args are 1-indexed, so 0 implies that the arg was not present
- int NumberArgNo = 0;
- if (Attr.getNumArgs() == 2) {
- const Expr *NumberExpr = Attr.getArgAsExpr(1);
+ ParamIdx NumberArgNo;
+ if (AL.getNumArgs() == 2) {
+ const Expr *NumberExpr = AL.getArgAsExpr(1);
+ int Val;
// Parameter indices are 1-based, hence Index=2
- if (!checkPositiveIntArgument(S, Attr, NumberExpr, NumberArgNo,
- /*Index=*/2))
+ if (!checkPositiveIntArgument(S, AL, NumberExpr, Val, /*Index=*/2))
return;
-
- if (!checkParamIsIntegerType(S, FD, Attr, NumberArgNo, /*AttrArgNo=*/1))
+ if (!checkParamIsIntegerType(S, FD, AL, /*AttrArgNo=*/1))
return;
+ NumberArgNo = ParamIdx(Val, D);
}
- D->addAttr(::new (S.Context) AllocSizeAttr(
- Attr.getRange(), S.Context, SizeArgNo, NumberArgNo,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context)
+ AllocSizeAttr(AL.getRange(), S.Context, SizeArgNo, NumberArgNo,
+ AL.getAttributeSpellingListIndex()));
}
-static bool checkTryLockFunAttrCommon(Sema &S, Decl *D,
- const AttributeList &Attr,
+static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
SmallVectorImpl<Expr *> &Args) {
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+ if (!checkAttributeAtLeastNumArgs(S, AL, 1))
return false;
- if (!isIntOrBool(Attr.getArgAsExpr(0))) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
- << Attr.getName() << 1 << AANT_ArgumentIntOrBool;
+ if (!isIntOrBool(AL.getArgAsExpr(0))) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
+ << AL.getName() << 1 << AANT_ArgumentIntOrBool;
return false;
}
// check that all arguments are lockable objects
- checkAttrArgsAreCapabilityObjs(S, D, Attr, Args, 1);
+ checkAttrArgsAreCapabilityObjs(S, D, AL, Args, 1);
return true;
}
static void handleSharedTrylockFunctionAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+ const ParsedAttr &AL) {
SmallVector<Expr*, 2> Args;
- if (!checkTryLockFunAttrCommon(S, D, Attr, Args))
+ if (!checkTryLockFunAttrCommon(S, D, AL, Args))
return;
- D->addAttr(::new (S.Context)
- SharedTrylockFunctionAttr(Attr.getRange(), S.Context,
- Attr.getArgAsExpr(0),
- Args.data(), Args.size(),
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) SharedTrylockFunctionAttr(
+ AL.getRange(), S.Context, AL.getArgAsExpr(0), Args.data(), Args.size(),
+ AL.getAttributeSpellingListIndex()));
}
static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+ const ParsedAttr &AL) {
SmallVector<Expr*, 2> Args;
- if (!checkTryLockFunAttrCommon(S, D, Attr, Args))
+ if (!checkTryLockFunAttrCommon(S, D, AL, Args))
return;
D->addAttr(::new (S.Context) ExclusiveTrylockFunctionAttr(
- Attr.getRange(), S.Context, Attr.getArgAsExpr(0), Args.data(),
- Args.size(), Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getArgAsExpr(0), Args.data(),
+ Args.size(), AL.getAttributeSpellingListIndex()));
}
-static void handleLockReturnedAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleLockReturnedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// check that the argument is lockable object
SmallVector<Expr*, 1> Args;
- checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
+ checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
unsigned Size = Args.size();
if (Size == 0)
return;
D->addAttr(::new (S.Context)
- LockReturnedAttr(Attr.getRange(), S.Context, Args[0],
- Attr.getAttributeSpellingListIndex()));
+ LockReturnedAttr(AL.getRange(), S.Context, Args[0],
+ AL.getAttributeSpellingListIndex()));
}
-static void handleLocksExcludedAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+static void handleLocksExcludedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!checkAttributeAtLeastNumArgs(S, AL, 1))
return;
// check that all arguments are lockable objects
SmallVector<Expr*, 1> Args;
- checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
+ checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
unsigned Size = Args.size();
if (Size == 0)
return;
Expr **StartArg = &Args[0];
D->addAttr(::new (S.Context)
- LocksExcludedAttr(Attr.getRange(), S.Context, StartArg, Size,
- Attr.getAttributeSpellingListIndex()));
+ LocksExcludedAttr(AL.getRange(), S.Context, StartArg, Size,
+ AL.getAttributeSpellingListIndex()));
}
-static bool checkFunctionConditionAttr(Sema &S, Decl *D,
- const AttributeList &Attr,
+static bool checkFunctionConditionAttr(Sema &S, Decl *D, const ParsedAttr &AL,
Expr *&Cond, StringRef &Msg) {
- Cond = Attr.getArgAsExpr(0);
+ Cond = AL.getArgAsExpr(0);
if (!Cond->isTypeDependent()) {
ExprResult Converted = S.PerformContextuallyConvertToBool(Cond);
if (Converted.isInvalid())
@@ -941,7 +897,7 @@ static bool checkFunctionConditionAttr(Sema &S, Decl *D,
Cond = Converted.get();
}
- if (!S.checkStringLiteralArgumentAttr(Attr, 1, Msg))
+ if (!S.checkStringLiteralArgumentAttr(AL, 1, Msg))
return false;
if (Msg.empty())
@@ -951,8 +907,8 @@ static bool checkFunctionConditionAttr(Sema &S, Decl *D,
if (isa<FunctionDecl>(D) && !Cond->isValueDependent() &&
!Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(D),
Diags)) {
- S.Diag(Attr.getLoc(), diag::err_attr_cond_never_constant_expr)
- << Attr.getName();
+ S.Diag(AL.getLoc(), diag::err_attr_cond_never_constant_expr)
+ << AL.getName();
for (const PartialDiagnosticAt &PDiag : Diags)
S.Diag(PDiag.first, PDiag.second);
return false;
@@ -960,15 +916,15 @@ static bool checkFunctionConditionAttr(Sema &S, Decl *D,
return true;
}
-static void handleEnableIfAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- S.Diag(Attr.getLoc(), diag::ext_clang_enable_if);
+static void handleEnableIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ S.Diag(AL.getLoc(), diag::ext_clang_enable_if);
Expr *Cond;
StringRef Msg;
- if (checkFunctionConditionAttr(S, D, Attr, Cond, Msg))
+ if (checkFunctionConditionAttr(S, D, AL, Cond, Msg))
D->addAttr(::new (S.Context)
- EnableIfAttr(Attr.getRange(), S.Context, Cond, Msg,
- Attr.getAttributeSpellingListIndex()));
+ EnableIfAttr(AL.getRange(), S.Context, Cond, Msg,
+ AL.getAttributeSpellingListIndex()));
}
namespace {
@@ -1017,21 +973,21 @@ public:
};
}
-static void handleDiagnoseIfAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- S.Diag(Attr.getLoc(), diag::ext_clang_diagnose_if);
+static void handleDiagnoseIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ S.Diag(AL.getLoc(), diag::ext_clang_diagnose_if);
Expr *Cond;
StringRef Msg;
- if (!checkFunctionConditionAttr(S, D, Attr, Cond, Msg))
+ if (!checkFunctionConditionAttr(S, D, AL, Cond, Msg))
return;
StringRef DiagTypeStr;
- if (!S.checkStringLiteralArgumentAttr(Attr, 2, DiagTypeStr))
+ if (!S.checkStringLiteralArgumentAttr(AL, 2, DiagTypeStr))
return;
DiagnoseIfAttr::DiagnosticType DiagType;
if (!DiagnoseIfAttr::ConvertStrToDiagnosticType(DiagTypeStr, DiagType)) {
- S.Diag(Attr.getArgAsExpr(2)->getLocStart(),
+ S.Diag(AL.getArgAsExpr(2)->getLocStart(),
diag::err_diagnose_if_invalid_diagnostic_type);
return;
}
@@ -1040,21 +996,20 @@ static void handleDiagnoseIfAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (const auto *FD = dyn_cast<FunctionDecl>(D))
ArgDependent = ArgumentDependenceChecker(FD).referencesArgs(Cond);
D->addAttr(::new (S.Context) DiagnoseIfAttr(
- Attr.getRange(), S.Context, Cond, Msg, DiagType, ArgDependent, cast<NamedDecl>(D),
- Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, Cond, Msg, DiagType, ArgDependent,
+ cast<NamedDecl>(D), AL.getAttributeSpellingListIndex()));
}
-static void handlePassObjectSizeAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+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)
- << Attr.getName();
+ << AL.getName();
return;
}
- Expr *E = Attr.getArgAsExpr(0);
+ Expr *E = AL.getArgAsExpr(0);
uint32_t Type;
- if (!checkUInt32Argument(S, Attr, E, Type, /*Idx=*/1))
+ if (!checkUInt32Argument(S, AL, E, Type, /*Idx=*/1))
return;
// pass_object_size's argument is passed in as the second argument of
@@ -1062,7 +1017,7 @@ static void handlePassObjectSizeAttr(Sema &S, Decl *D,
// argument; namely, it must be in the range [0, 3].
if (Type > 3) {
S.Diag(E->getLocStart(), diag::err_attribute_argument_outof_range)
- << Attr.getName() << 0 << 3 << E->getSourceRange();
+ << AL.getName() << 0 << 3 << E->getSourceRange();
return;
}
@@ -1072,45 +1027,44 @@ static void handlePassObjectSizeAttr(Sema &S, Decl *D,
// definition, so we defer the constness check until later.
if (!cast<ParmVarDecl>(D)->getType()->isPointerType()) {
S.Diag(D->getLocStart(), diag::err_attribute_pointers_only)
- << Attr.getName() << 1;
+ << AL.getName() << 1;
return;
}
- D->addAttr(::new (S.Context)
- PassObjectSizeAttr(Attr.getRange(), S.Context, (int)Type,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) PassObjectSizeAttr(
+ AL.getRange(), S.Context, (int)Type, AL.getAttributeSpellingListIndex()));
}
-static void handleConsumableAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleConsumableAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
ConsumableAttr::ConsumedState DefaultState;
- if (Attr.isArgIdent(0)) {
- IdentifierLoc *IL = Attr.getArgAsIdent(0);
+ if (AL.isArgIdent(0)) {
+ IdentifierLoc *IL = AL.getArgAsIdent(0);
if (!ConsumableAttr::ConvertStrToConsumedState(IL->Ident->getName(),
DefaultState)) {
S.Diag(IL->Loc, diag::warn_attribute_type_not_supported)
- << Attr.getName() << IL->Ident;
+ << AL.getName() << IL->Ident;
return;
}
} else {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
- << Attr.getName() << AANT_ArgumentIdentifier;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
+ << AL.getName() << AANT_ArgumentIdentifier;
return;
}
D->addAttr(::new (S.Context)
- ConsumableAttr(Attr.getRange(), S.Context, DefaultState,
- Attr.getAttributeSpellingListIndex()));
+ ConsumableAttr(AL.getRange(), S.Context, DefaultState,
+ AL.getAttributeSpellingListIndex()));
}
static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD,
- const AttributeList &Attr) {
+ const ParsedAttr &AL) {
ASTContext &CurrContext = S.getASTContext();
QualType ThisType = MD->getThisType(CurrContext)->getPointeeType();
if (const CXXRecordDecl *RD = ThisType->getAsCXXRecordDecl()) {
if (!RD->hasAttr<ConsumableAttr>()) {
- S.Diag(Attr.getLoc(), diag::warn_attr_on_unconsumable_class) <<
+ S.Diag(AL.getLoc(), diag::warn_attr_on_unconsumable_class) <<
RD->getNameAsString();
return false;
@@ -1120,33 +1074,32 @@ static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD,
return true;
}
-static void handleCallableWhenAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+static void handleCallableWhenAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!checkAttributeAtLeastNumArgs(S, AL, 1))
return;
- if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
+ if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL))
return;
SmallVector<CallableWhenAttr::ConsumedState, 3> States;
- for (unsigned ArgIndex = 0; ArgIndex < Attr.getNumArgs(); ++ArgIndex) {
+ for (unsigned ArgIndex = 0; ArgIndex < AL.getNumArgs(); ++ArgIndex) {
CallableWhenAttr::ConsumedState CallableState;
StringRef StateString;
SourceLocation Loc;
- if (Attr.isArgIdent(ArgIndex)) {
- IdentifierLoc *Ident = Attr.getArgAsIdent(ArgIndex);
+ if (AL.isArgIdent(ArgIndex)) {
+ IdentifierLoc *Ident = AL.getArgAsIdent(ArgIndex);
StateString = Ident->Ident->getName();
Loc = Ident->Loc;
} else {
- if (!S.checkStringLiteralArgumentAttr(Attr, ArgIndex, StateString, &Loc))
+ if (!S.checkStringLiteralArgumentAttr(AL, ArgIndex, StateString, &Loc))
return;
}
if (!CallableWhenAttr::ConvertStrToConsumedState(StateString,
CallableState)) {
S.Diag(Loc, diag::warn_attribute_type_not_supported)
- << Attr.getName() << StateString;
+ << AL.getName() << StateString;
return;
}
@@ -1154,27 +1107,26 @@ static void handleCallableWhenAttr(Sema &S, Decl *D,
}
D->addAttr(::new (S.Context)
- CallableWhenAttr(Attr.getRange(), S.Context, States.data(),
- States.size(), Attr.getAttributeSpellingListIndex()));
+ CallableWhenAttr(AL.getRange(), S.Context, States.data(),
+ States.size(), AL.getAttributeSpellingListIndex()));
}
-static void handleParamTypestateAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleParamTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
ParamTypestateAttr::ConsumedState ParamState;
- if (Attr.isArgIdent(0)) {
- IdentifierLoc *Ident = Attr.getArgAsIdent(0);
+ if (AL.isArgIdent(0)) {
+ IdentifierLoc *Ident = AL.getArgAsIdent(0);
StringRef StateString = Ident->Ident->getName();
if (!ParamTypestateAttr::ConvertStrToConsumedState(StateString,
ParamState)) {
S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported)
- << Attr.getName() << StateString;
+ << AL.getName() << StateString;
return;
}
} else {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) <<
- Attr.getName() << AANT_ArgumentIdentifier;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type) <<
+ AL.getName() << AANT_ArgumentIdentifier;
return;
}
@@ -1185,31 +1137,30 @@ static void handleParamTypestateAttr(Sema &S, Decl *D,
//const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl();
//
//if (!RD || !RD->hasAttr<ConsumableAttr>()) {
- // S.Diag(Attr.getLoc(), diag::warn_return_state_for_unconsumable_type) <<
+ // S.Diag(AL.getLoc(), diag::warn_return_state_for_unconsumable_type) <<
// ReturnType.getAsString();
// return;
//}
D->addAttr(::new (S.Context)
- ParamTypestateAttr(Attr.getRange(), S.Context, ParamState,
- Attr.getAttributeSpellingListIndex()));
+ ParamTypestateAttr(AL.getRange(), S.Context, ParamState,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleReturnTypestateAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleReturnTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
ReturnTypestateAttr::ConsumedState ReturnState;
- if (Attr.isArgIdent(0)) {
- IdentifierLoc *IL = Attr.getArgAsIdent(0);
+ if (AL.isArgIdent(0)) {
+ IdentifierLoc *IL = AL.getArgAsIdent(0);
if (!ReturnTypestateAttr::ConvertStrToConsumedState(IL->Ident->getName(),
ReturnState)) {
S.Diag(IL->Loc, diag::warn_attribute_type_not_supported)
- << Attr.getName() << IL->Ident;
+ << AL.getName() << IL->Ident;
return;
}
} else {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) <<
- Attr.getName() << AANT_ArgumentIdentifier;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type) <<
+ AL.getName() << AANT_ArgumentIdentifier;
return;
}
@@ -1237,72 +1188,70 @@ static void handleReturnTypestateAttr(Sema &S, Decl *D,
// ReturnType.getAsString();
// return;
//}
-
+
D->addAttr(::new (S.Context)
- ReturnTypestateAttr(Attr.getRange(), S.Context, ReturnState,
- Attr.getAttributeSpellingListIndex()));
+ ReturnTypestateAttr(AL.getRange(), S.Context, ReturnState,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleSetTypestateAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
+static void handleSetTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL))
return;
SetTypestateAttr::ConsumedState NewState;
- if (Attr.isArgIdent(0)) {
- IdentifierLoc *Ident = Attr.getArgAsIdent(0);
+ if (AL.isArgIdent(0)) {
+ 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)
- << Attr.getName() << Param;
+ << AL.getName() << Param;
return;
}
} else {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) <<
- Attr.getName() << AANT_ArgumentIdentifier;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type) <<
+ AL.getName() << AANT_ArgumentIdentifier;
return;
}
D->addAttr(::new (S.Context)
- SetTypestateAttr(Attr.getRange(), S.Context, NewState,
- Attr.getAttributeSpellingListIndex()));
+ SetTypestateAttr(AL.getRange(), S.Context, NewState,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleTestTypestateAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
+static void handleTestTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL))
return;
TestTypestateAttr::ConsumedState TestState;
- if (Attr.isArgIdent(0)) {
- IdentifierLoc *Ident = Attr.getArgAsIdent(0);
+ if (AL.isArgIdent(0)) {
+ 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)
- << Attr.getName() << Param;
+ << AL.getName() << Param;
return;
}
} else {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) <<
- Attr.getName() << AANT_ArgumentIdentifier;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type) <<
+ AL.getName() << AANT_ArgumentIdentifier;
return;
}
D->addAttr(::new (S.Context)
- TestTypestateAttr(Attr.getRange(), S.Context, TestState,
- Attr.getAttributeSpellingListIndex()));
+ TestTypestateAttr(AL.getRange(), S.Context, TestState,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D,
- const AttributeList &Attr) {
+static void handleExtVectorTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Remember this typedef decl, we will need it later for diagnostics.
S.ExtVectorDecls.push_back(cast<TypedefNameDecl>(D));
}
-static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (TagDecl *TD = dyn_cast<TagDecl>(D))
- TD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
+static void handlePackedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (auto *TD = dyn_cast<TagDecl>(D))
+ TD->addAttr(::new (S.Context) PackedAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
+ else if (auto *FD = dyn_cast<FieldDecl>(D)) {
bool BitfieldByteAligned = (!FD->getType()->isDependentType() &&
!FD->getType()->isIncompleteType() &&
FD->isBitField() &&
@@ -1311,81 +1260,80 @@ static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (S.getASTContext().getTargetInfo().getTriple().isPS4()) {
if (BitfieldByteAligned)
// The PS4 target needs to maintain ABI backwards compatibility.
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type)
- << Attr.getName() << FD->getType();
+ S.Diag(AL.getLoc(), diag::warn_attribute_ignored_for_field_of_type)
+ << AL.getName() << FD->getType();
else
FD->addAttr(::new (S.Context) PackedAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
} else {
// Report warning about changed offset in the newer compiler versions.
if (BitfieldByteAligned)
- S.Diag(Attr.getLoc(), diag::warn_attribute_packed_for_bitfield);
+ S.Diag(AL.getLoc(), diag::warn_attribute_packed_for_bitfield);
FD->addAttr(::new (S.Context) PackedAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
}
} else
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL.getName();
}
-static bool checkIBOutletCommon(Sema &S, Decl *D, const AttributeList &Attr) {
+static bool checkIBOutletCommon(Sema &S, Decl *D, const ParsedAttr &AL) {
// The IBOutlet/IBOutletCollection attributes only apply to instance
// variables or properties of Objective-C classes. The outlet must also
// have an object reference type.
- if (const ObjCIvarDecl *VD = dyn_cast<ObjCIvarDecl>(D)) {
+ if (const auto *VD = dyn_cast<ObjCIvarDecl>(D)) {
if (!VD->getType()->getAs<ObjCObjectPointerType>()) {
- S.Diag(Attr.getLoc(), diag::warn_iboutlet_object_type)
- << Attr.getName() << VD->getType() << 0;
+ S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type)
+ << AL.getName() << VD->getType() << 0;
return false;
}
}
- else if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) {
+ else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
if (!PD->getType()->getAs<ObjCObjectPointerType>()) {
- S.Diag(Attr.getLoc(), diag::warn_iboutlet_object_type)
- << Attr.getName() << PD->getType() << 1;
+ S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type)
+ << AL.getName() << PD->getType() << 1;
return false;
}
}
else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_iboutlet) << Attr.getName();
+ S.Diag(AL.getLoc(), diag::warn_attribute_iboutlet) << AL.getName();
return false;
}
return true;
}
-static void handleIBOutlet(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkIBOutletCommon(S, D, Attr))
+static void handleIBOutlet(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!checkIBOutletCommon(S, D, AL))
return;
D->addAttr(::new (S.Context)
- IBOutletAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ IBOutletAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleIBOutletCollection(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleIBOutletCollection(Sema &S, Decl *D, const ParsedAttr &AL) {
// The iboutletcollection attribute can have zero or one arguments.
- if (Attr.getNumArgs() > 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 1;
+ if (AL.getNumArgs() > 1) {
+ S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << AL.getName() << 1;
return;
}
- if (!checkIBOutletCommon(S, D, Attr))
+ if (!checkIBOutletCommon(S, D, AL))
return;
ParsedType PT;
- if (Attr.hasParsedType())
- PT = Attr.getTypeArg();
+ if (AL.hasParsedType())
+ PT = AL.getTypeArg();
else {
- PT = S.getTypeName(S.Context.Idents.get("NSObject"), Attr.getLoc(),
+ PT = S.getTypeName(S.Context.Idents.get("NSObject"), AL.getLoc(),
S.getScopeForContext(D->getDeclContext()->getParent()));
if (!PT) {
- S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << "NSObject";
+ S.Diag(AL.getLoc(), diag::err_iboutletcollection_type) << "NSObject";
return;
}
}
@@ -1393,22 +1341,22 @@ static void handleIBOutletCollection(Sema &S, Decl *D,
TypeSourceInfo *QTLoc = nullptr;
QualType QT = S.GetTypeFromParser(PT, &QTLoc);
if (!QTLoc)
- QTLoc = S.Context.getTrivialTypeSourceInfo(QT, Attr.getLoc());
+ QTLoc = S.Context.getTrivialTypeSourceInfo(QT, AL.getLoc());
// Diagnose use of non-object type in iboutletcollection attribute.
// FIXME. Gnu attribute extension ignores use of builtin types in
// attributes. So, __attribute__((iboutletcollection(char))) will be
// treated as __attribute__((iboutletcollection())).
if (!QT->isObjCIdType() && !QT->isObjCObjectType()) {
- S.Diag(Attr.getLoc(),
+ S.Diag(AL.getLoc(),
QT->isBuiltinType() ? diag::err_iboutletcollection_builtintype
: diag::err_iboutletcollection_type) << QT;
return;
}
D->addAttr(::new (S.Context)
- IBOutletCollectionAttr(Attr.getRange(), S.Context, QTLoc,
- Attr.getAttributeSpellingListIndex()));
+ IBOutletCollectionAttr(AL.getRange(), S.Context, QTLoc,
+ AL.getAttributeSpellingListIndex()));
}
bool Sema::isValidPointerAttrType(QualType T, bool RefOkay) {
@@ -1435,35 +1383,36 @@ bool Sema::isValidPointerAttrType(QualType T, bool RefOkay) {
return T->isAnyPointerType() || T->isBlockPointerType();
}
-static bool attrNonNullArgCheck(Sema &S, QualType T, const AttributeList &Attr,
+static bool attrNonNullArgCheck(Sema &S, QualType T, const ParsedAttr &AL,
SourceRange AttrParmRange,
SourceRange TypeRange,
bool isReturnValue = false) {
if (!S.isValidPointerAttrType(T)) {
if (isReturnValue)
- S.Diag(Attr.getLoc(), diag::warn_attribute_return_pointers_only)
- << Attr.getName() << AttrParmRange << TypeRange;
+ S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only)
+ << AL.getName() << AttrParmRange << TypeRange;
else
- S.Diag(Attr.getLoc(), diag::warn_attribute_pointers_only)
- << Attr.getName() << AttrParmRange << TypeRange << 0;
+ S.Diag(AL.getLoc(), diag::warn_attribute_pointers_only)
+ << AL.getName() << AttrParmRange << TypeRange << 0;
return false;
}
return true;
}
-static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- SmallVector<unsigned, 8> NonNullArgs;
- for (unsigned I = 0; I < Attr.getNumArgs(); ++I) {
- Expr *Ex = Attr.getArgAsExpr(I);
- uint64_t Idx;
- if (!checkFunctionOrMethodParameterIndex(S, D, Attr, I + 1, Ex, Idx))
+static void handleNonNullAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ SmallVector<ParamIdx, 8> NonNullArgs;
+ for (unsigned I = 0; I < AL.getNumArgs(); ++I) {
+ Expr *Ex = AL.getArgAsExpr(I);
+ ParamIdx Idx;
+ if (!checkFunctionOrMethodParameterIndex(S, D, AL, I + 1, Ex, Idx))
return;
// Is the function argument a pointer type?
- if (Idx < getFunctionOrMethodNumParams(D) &&
- !attrNonNullArgCheck(S, getFunctionOrMethodParamType(D, Idx), Attr,
- Ex->getSourceRange(),
- getFunctionOrMethodParamRange(D, Idx)))
+ if (Idx.getASTIndex() < getFunctionOrMethodNumParams(D) &&
+ !attrNonNullArgCheck(
+ S, getFunctionOrMethodParamType(D, Idx.getASTIndex()), AL,
+ Ex->getSourceRange(),
+ getFunctionOrMethodParamRange(D, Idx.getASTIndex())))
continue;
NonNullArgs.push_back(Idx);
@@ -1473,7 +1422,7 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// arguments have a nonnull attribute; warn if there aren't any. Skip this
// check if the attribute came from a macro expansion or a template
// instantiation.
- if (NonNullArgs.empty() && Attr.getLoc().isFileID() &&
+ if (NonNullArgs.empty() && AL.getLoc().isFileID() &&
!S.inTemplateInstantiation()) {
bool AnyPointers = isFunctionOrMethodVariadic(D);
for (unsigned I = 0, E = getFunctionOrMethodNumParams(D);
@@ -1484,80 +1433,77 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
if (!AnyPointers)
- S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_no_pointers);
+ S.Diag(AL.getLoc(), diag::warn_attribute_nonnull_no_pointers);
}
- unsigned *Start = NonNullArgs.data();
+ ParamIdx *Start = NonNullArgs.data();
unsigned Size = NonNullArgs.size();
llvm::array_pod_sort(Start, Start + Size);
D->addAttr(::new (S.Context)
- NonNullAttr(Attr.getRange(), S.Context, Start, Size,
- Attr.getAttributeSpellingListIndex()));
+ NonNullAttr(AL.getRange(), S.Context, Start, Size,
+ AL.getAttributeSpellingListIndex()));
}
static void handleNonNullAttrParameter(Sema &S, ParmVarDecl *D,
- const AttributeList &Attr) {
- if (Attr.getNumArgs() > 0) {
+ const ParsedAttr &AL) {
+ if (AL.getNumArgs() > 0) {
if (D->getFunctionType()) {
- handleNonNullAttr(S, D, Attr);
+ handleNonNullAttr(S, D, AL);
} else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_parm_no_args)
+ S.Diag(AL.getLoc(), diag::warn_attribute_nonnull_parm_no_args)
<< D->getSourceRange();
}
return;
}
// Is the argument a pointer type?
- if (!attrNonNullArgCheck(S, D->getType(), Attr, SourceRange(),
+ if (!attrNonNullArgCheck(S, D->getType(), AL, SourceRange(),
D->getSourceRange()))
return;
D->addAttr(::new (S.Context)
- NonNullAttr(Attr.getRange(), S.Context, nullptr, 0,
- Attr.getAttributeSpellingListIndex()));
+ NonNullAttr(AL.getRange(), S.Context, nullptr, 0,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleReturnsNonNullAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleReturnsNonNullAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
QualType ResultType = getFunctionOrMethodResultType(D);
SourceRange SR = getFunctionOrMethodResultSourceRange(D);
- if (!attrNonNullArgCheck(S, ResultType, Attr, SourceRange(), SR,
+ if (!attrNonNullArgCheck(S, ResultType, AL, SourceRange(), SR,
/* isReturnValue */ true))
return;
D->addAttr(::new (S.Context)
- ReturnsNonNullAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ ReturnsNonNullAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleNoEscapeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleNoEscapeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (D->isInvalidDecl())
return;
// noescape only applies to pointer types.
QualType T = cast<ParmVarDecl>(D)->getType();
if (!S.isValidPointerAttrType(T, /* RefOkay */ true)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_pointers_only)
- << Attr.getName() << Attr.getRange() << 0;
+ S.Diag(AL.getLoc(), diag::warn_attribute_pointers_only)
+ << AL.getName() << AL.getRange() << 0;
return;
}
D->addAttr(::new (S.Context) NoEscapeAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
}
-static void handleAssumeAlignedAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- Expr *E = Attr.getArgAsExpr(0),
- *OE = Attr.getNumArgs() > 1 ? Attr.getArgAsExpr(1) : nullptr;
- S.AddAssumeAlignedAttr(Attr.getRange(), D, E, OE,
- Attr.getAttributeSpellingListIndex());
+static void handleAssumeAlignedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ Expr *E = AL.getArgAsExpr(0),
+ *OE = AL.getNumArgs() > 1 ? AL.getArgAsExpr(1) : nullptr;
+ S.AddAssumeAlignedAttr(AL.getRange(), D, E, OE,
+ AL.getAttributeSpellingListIndex());
}
-static void handleAllocAlignAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- S.AddAllocAlignAttr(Attr.getRange(), D, Attr.getArgAsExpr(0),
- Attr.getAttributeSpellingListIndex());
+static void handleAllocAlignAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ S.AddAllocAlignAttr(AL.getRange(), D, AL.getArgAsExpr(0),
+ AL.getAttributeSpellingListIndex());
}
void Sema::AddAssumeAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
@@ -1615,7 +1561,7 @@ void Sema::AddAllocAlignAttr(SourceRange AttrRange, Decl *D, Expr *ParamExpr,
unsigned SpellingListIndex) {
QualType ResultType = getFunctionOrMethodResultType(D);
- AllocAlignAttr TmpAttr(AttrRange, Context, 0, SpellingListIndex);
+ AllocAlignAttr TmpAttr(AttrRange, Context, ParamIdx(), SpellingListIndex);
SourceLocation AttrLoc = AttrRange.getBegin();
if (!ResultType->isDependentType() &&
@@ -1625,28 +1571,22 @@ void Sema::AddAllocAlignAttr(SourceRange AttrRange, Decl *D, Expr *ParamExpr,
return;
}
- uint64_t IndexVal;
+ ParamIdx Idx;
const auto *FuncDecl = cast<FunctionDecl>(D);
if (!checkFunctionOrMethodParameterIndex(*this, FuncDecl, TmpAttr,
- /*AttrArgNo=*/1, ParamExpr,
- IndexVal))
+ /*AttrArgNo=*/1, ParamExpr, Idx))
return;
- QualType Ty = getFunctionOrMethodParamType(D, IndexVal);
+ QualType Ty = getFunctionOrMethodParamType(D, Idx.getASTIndex());
if (!Ty->isDependentType() && !Ty->isIntegralType(Context)) {
Diag(ParamExpr->getLocStart(), diag::err_attribute_integers_only)
- << &TmpAttr << FuncDecl->getParamDecl(IndexVal)->getSourceRange();
+ << &TmpAttr
+ << FuncDecl->getParamDecl(Idx.getASTIndex())->getSourceRange();
return;
}
- // We cannot use the Idx returned from checkFunctionOrMethodParameterIndex
- // because that has corrected for the implicit this parameter, and is zero-
- // based. The attribute expects what the user wrote explicitly.
- llvm::APSInt Val;
- ParamExpr->EvaluateAsInt(Val, Context);
-
- D->addAttr(::new (Context) AllocAlignAttr(
- AttrRange, Context, Val.getZExtValue(), SpellingListIndex));
+ D->addAttr(::new (Context)
+ AllocAlignAttr(AttrRange, Context, Idx, SpellingListIndex));
}
/// Normalize the attribute, __foo__ becomes foo.
@@ -1660,7 +1600,7 @@ static bool normalizeName(StringRef &AttrName) {
return false;
}
-static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
+static void handleOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// This attribute must be applied to a function declaration. The first
// argument to the attribute must be an identifier, the name of the resource,
// for example: malloc. The following arguments must be argument indexes, the
@@ -1706,15 +1646,15 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
Module = &S.PP.getIdentifierTable().get(ModuleName);
}
- SmallVector<unsigned, 8> OwnershipArgs;
+ SmallVector<ParamIdx, 8> OwnershipArgs;
for (unsigned i = 1; i < AL.getNumArgs(); ++i) {
Expr *Ex = AL.getArgAsExpr(i);
- uint64_t Idx;
+ ParamIdx Idx;
if (!checkFunctionOrMethodParameterIndex(S, D, AL, i, Ex, Idx))
return;
// Is the function argument a pointer type?
- QualType T = getFunctionOrMethodParamType(D, Idx);
+ QualType T = getFunctionOrMethodParamType(D, Idx.getASTIndex());
int Err = -1; // No error
switch (K) {
case OwnershipAttr::Takes:
@@ -1745,14 +1685,13 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
} else if (K == OwnershipAttr::Returns &&
I->getOwnKind() == OwnershipAttr::Returns) {
// A returns attribute conflicts with any other returns attribute using
- // a different index. Note, diagnostic reporting is 1-based, but stored
- // argument indexes are 0-based.
+ // a different index.
if (std::find(I->args_begin(), I->args_end(), Idx) == I->args_end()) {
S.Diag(I->getLocation(), diag::err_ownership_returns_index_mismatch)
- << *(I->args_begin()) + 1;
+ << I->args_begin()->getSourceIndex();
if (I->args_size())
S.Diag(AL.getLoc(), diag::note_ownership_returns_index_mismatch)
- << (unsigned)Idx + 1 << Ex->getSourceRange();
+ << Idx.getSourceIndex() << Ex->getSourceRange();
return;
}
}
@@ -1760,25 +1699,22 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
OwnershipArgs.push_back(Idx);
}
- unsigned* start = OwnershipArgs.data();
- unsigned size = OwnershipArgs.size();
- llvm::array_pod_sort(start, start + size);
-
+ ParamIdx *Start = OwnershipArgs.data();
+ unsigned Size = OwnershipArgs.size();
+ llvm::array_pod_sort(Start, Start + Size);
D->addAttr(::new (S.Context)
- OwnershipAttr(AL.getLoc(), S.Context, Module, start, size,
- AL.getAttributeSpellingListIndex()));
+ OwnershipAttr(AL.getLoc(), S.Context, Module, Start, Size,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleWeakRefAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Check the attribute arguments.
- if (Attr.getNumArgs() > 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 1;
+ if (AL.getNumArgs() > 1) {
+ S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << AL.getName() << 1;
return;
}
- NamedDecl *nd = cast<NamedDecl>(D);
-
// gcc rejects
// class c {
// static int a __attribute__((weakref ("v2")));
@@ -1791,8 +1727,8 @@ static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// we reject them
const DeclContext *Ctx = D->getDeclContext()->getRedeclContext();
if (!Ctx->isFileContext()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_global_context)
- << nd;
+ S.Diag(AL.getLoc(), diag::err_attribute_weakref_not_global_context)
+ << cast<NamedDecl>(D);
return;
}
@@ -1822,88 +1758,71 @@ static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// of transforming it into an AliasAttr. The WeakRefAttr never uses the
// StringRef parameter it was given anyway.
StringRef Str;
- if (Attr.getNumArgs() && S.checkStringLiteralArgumentAttr(Attr, 0, Str))
+ if (AL.getNumArgs() && S.checkStringLiteralArgumentAttr(AL, 0, Str))
// GCC will accept anything as the argument of weakref. Should we
// check for an existing decl?
- D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, Str,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) AliasAttr(AL.getRange(), S.Context, Str,
+ AL.getAttributeSpellingListIndex()));
D->addAttr(::new (S.Context)
- WeakRefAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ WeakRefAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleIFuncAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleIFuncAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
StringRef Str;
- if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str))
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
return;
// Aliases should be on declarations, not definitions.
const auto *FD = cast<FunctionDecl>(D);
if (FD->isThisDeclarationADefinition()) {
- S.Diag(Attr.getLoc(), diag::err_alias_is_definition) << FD << 1;
+ S.Diag(AL.getLoc(), diag::err_alias_is_definition) << FD << 1;
return;
}
- D->addAttr(::new (S.Context) IFuncAttr(Attr.getRange(), S.Context, Str,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) IFuncAttr(AL.getRange(), S.Context, Str,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
StringRef Str;
- if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str))
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
return;
if (S.Context.getTargetInfo().getTriple().isOSDarwin()) {
- S.Diag(Attr.getLoc(), diag::err_alias_not_supported_on_darwin);
+ S.Diag(AL.getLoc(), diag::err_alias_not_supported_on_darwin);
return;
}
if (S.Context.getTargetInfo().getTriple().isNVPTX()) {
- S.Diag(Attr.getLoc(), diag::err_alias_not_supported_on_nvptx);
+ S.Diag(AL.getLoc(), diag::err_alias_not_supported_on_nvptx);
}
// Aliases should be on declarations, not definitions.
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->isThisDeclarationADefinition()) {
- S.Diag(Attr.getLoc(), diag::err_alias_is_definition) << FD << 0;
+ S.Diag(AL.getLoc(), diag::err_alias_is_definition) << FD << 0;
return;
}
} else {
const auto *VD = cast<VarDecl>(D);
if (VD->isThisDeclarationADefinition() && VD->isExternallyVisible()) {
- S.Diag(Attr.getLoc(), diag::err_alias_is_definition) << VD << 0;
+ S.Diag(AL.getLoc(), diag::err_alias_is_definition) << VD << 0;
return;
}
}
// FIXME: check if target symbol exists in current file
- D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, Str,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (checkAttrMutualExclusion<HotAttr>(S, D, Attr.getRange(), Attr.getName()))
- return;
-
- D->addAttr(::new (S.Context) ColdAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (checkAttrMutualExclusion<ColdAttr>(S, D, Attr.getRange(), Attr.getName()))
- return;
-
- D->addAttr(::new (S.Context) HotAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) AliasAttr(AL.getRange(), S.Context, Str,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleTLSModelAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleTLSModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
StringRef Model;
SourceLocation LiteralLoc;
// Check that it is a string.
- if (!S.checkStringLiteralArgumentAttr(Attr, 0, Model, &LiteralLoc))
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, Model, &LiteralLoc))
return;
// Check that the value.
@@ -1914,60 +1833,101 @@ static void handleTLSModelAttr(Sema &S, Decl *D,
}
D->addAttr(::new (S.Context)
- TLSModelAttr(Attr.getRange(), S.Context, Model,
- Attr.getAttributeSpellingListIndex()));
+ TLSModelAttr(AL.getRange(), S.Context, Model,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleRestrictAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleRestrictAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
QualType ResultType = getFunctionOrMethodResultType(D);
if (ResultType->isAnyPointerType() || ResultType->isBlockPointerType()) {
D->addAttr(::new (S.Context) RestrictAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
return;
}
- S.Diag(Attr.getLoc(), diag::warn_attribute_return_pointers_only)
- << Attr.getName() << getFunctionOrMethodResultSourceRange(D);
+ S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only)
+ << AL.getName() << getFunctionOrMethodResultSourceRange(D);
}
-static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleCPUSpecificAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ FunctionDecl *FD = cast<FunctionDecl>(D);
+ if (!checkAttributeAtLeastNumArgs(S, AL, 1))
+ return;
+
+ SmallVector<IdentifierInfo *, 8> CPUs;
+ 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;
+ return;
+ }
+
+ IdentifierLoc *CPUArg = AL.getArgAsIdent(ArgNo);
+ StringRef CPUName = CPUArg->Ident->getName().trim();
+
+ if (!S.Context.getTargetInfo().validateCPUSpecificCPUDispatch(CPUName)) {
+ S.Diag(CPUArg->Loc, diag::err_invalid_cpu_specific_dispatch_value)
+ << CPUName << (AL.getKind() == ParsedAttr::AT_CPUDispatch);
+ return;
+ }
+
+ const TargetInfo &Target = S.Context.getTargetInfo();
+ if (llvm::any_of(CPUs, [CPUName, &Target](const IdentifierInfo *Cur) {
+ return Target.CPUSpecificManglingCharacter(CPUName) ==
+ Target.CPUSpecificManglingCharacter(Cur->getName());
+ })) {
+ S.Diag(AL.getLoc(), diag::warn_multiversion_duplicate_entries);
+ return;
+ }
+ CPUs.push_back(CPUArg->Ident);
+ }
+
+ FD->setIsMultiVersion(true);
+ if (AL.getKind() == ParsedAttr::AT_CPUSpecific)
+ D->addAttr(::new (S.Context) CPUSpecificAttr(
+ AL.getRange(), S.Context, CPUs.data(), CPUs.size(),
+ AL.getAttributeSpellingListIndex()));
+ else
+ D->addAttr(::new (S.Context) CPUDispatchAttr(
+ AL.getRange(), S.Context, CPUs.data(), CPUs.size(),
+ AL.getAttributeSpellingListIndex()));
+}
+
+static void handleCommonAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (S.LangOpts.CPlusPlus) {
- S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang)
- << Attr.getName() << AttributeLangSupport::Cpp;
+ S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang)
+ << AL.getName() << AttributeLangSupport::Cpp;
return;
}
- if (CommonAttr *CA = S.mergeCommonAttr(D, Attr.getRange(), Attr.getName(),
- Attr.getAttributeSpellingListIndex()))
+ if (CommonAttr *CA = S.mergeCommonAttr(D, AL.getRange(), AL.getName(),
+ AL.getAttributeSpellingListIndex()))
D->addAttr(CA);
}
-static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (checkAttrMutualExclusion<DisableTailCallsAttr>(S, D, Attr.getRange(),
- Attr.getName()))
+static void handleNakedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (checkAttrMutualExclusion<DisableTailCallsAttr>(S, D, AL.getRange(),
+ AL.getName()))
return;
- if (Attr.isDeclspecAttribute()) {
+ if (AL.isDeclspecAttribute()) {
const auto &Triple = S.getASTContext().getTargetInfo().getTriple();
const auto &Arch = Triple.getArch();
if (Arch != llvm::Triple::x86 &&
(Arch != llvm::Triple::arm && Arch != llvm::Triple::thumb)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_on_arch)
- << Attr.getName() << Triple.getArchName();
+ S.Diag(AL.getLoc(), diag::err_attribute_not_supported_on_arch)
+ << AL.getName() << Triple.getArchName();
return;
}
}
- D->addAttr(::new (S.Context) NakedAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) NakedAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &Attrs) {
+static void handleNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) {
if (hasDeclarator(D)) return;
- if (S.CheckNoReturnAttr(Attrs))
- return;
-
if (!isa<ObjCMethodDecl>(D)) {
S.Diag(Attrs.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attrs.getName() << ExpectedFunctionOrMethod;
@@ -1978,16 +1938,14 @@ static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &Attrs) {
Attrs.getRange(), S.Context, Attrs.getAttributeSpellingListIndex()));
}
-static void handleNoCallerSavedRegsAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (S.CheckNoCallerSavedRegsAttr(Attr))
- return;
-
- D->addAttr(::new (S.Context) AnyX86NoCallerSavedRegistersAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+static void handleNoCfCheckAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) {
+ if (!S.getLangOpts().CFProtectionBranch)
+ S.Diag(Attrs.getLoc(), diag::warn_nocf_check_attribute_ignored);
+ else
+ handleSimpleAttribute<AnyX86NoCfCheckAttr>(S, D, Attrs);
}
-bool Sema::CheckNoReturnAttr(const AttributeList &Attrs) {
+bool Sema::CheckAttrNoArgs(const ParsedAttr &Attrs) {
if (!checkAttributeNumArgs(*this, Attrs, 0)) {
Attrs.setInvalid();
return true;
@@ -1996,221 +1954,167 @@ bool Sema::CheckNoReturnAttr(const AttributeList &Attrs) {
return false;
}
-bool Sema::CheckNoCallerSavedRegsAttr(const AttributeList &Attr) {
+bool Sema::CheckAttrTarget(const ParsedAttr &AL) {
// Check whether the attribute is valid on the current target.
- if (!Attr.existsInTarget(Context.getTargetInfo())) {
- Diag(Attr.getLoc(), diag::warn_unknown_attribute_ignored) << Attr.getName();
- Attr.setInvalid();
- return true;
- }
-
- if (!checkAttributeNumArgs(*this, Attr, 0)) {
- Attr.setInvalid();
+ if (!AL.existsInTarget(Context.getTargetInfo())) {
+ Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) << AL.getName();
+ AL.setInvalid();
return true;
}
return false;
}
-static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
-
+static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+
// The checking path for 'noreturn' and 'analyzer_noreturn' are different
// because 'analyzer_noreturn' does not impact the type.
if (!isFunctionOrMethodOrBlock(D)) {
ValueDecl *VD = dyn_cast<ValueDecl>(D);
if (!VD || (!VD->getType()->isBlockPointerType() &&
!VD->getType()->isFunctionPointerType())) {
- S.Diag(Attr.getLoc(),
- Attr.isCXX11Attribute() ? diag::err_attribute_wrong_decl_type
+ S.Diag(AL.getLoc(),
+ AL.isCXX11Attribute() ? diag::err_attribute_wrong_decl_type
: diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionMethodOrBlock;
+ << AL.getName() << ExpectedFunctionMethodOrBlock;
return;
}
}
D->addAttr(::new (S.Context)
- AnalyzerNoReturnAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ AnalyzerNoReturnAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
// PS3 PPU-specific.
-static void handleVecReturnAttr(Sema &S, Decl *D, const AttributeList &Attr) {
-/*
- Returning a Vector Class in Registers
-
- According to the PPU ABI specifications, a class with a single member of
- vector type is returned in memory when used as the return value of a function.
- This results in inefficient code when implementing vector classes. To return
- the value in a single vector register, add the vecreturn attribute to the
- class definition. This attribute is also applicable to struct types.
-
- Example:
-
- struct Vector
- {
- __vector float xyzw;
- } __attribute__((vecreturn));
-
- Vector Add(Vector lhs, Vector rhs)
- {
- Vector result;
- result.xyzw = vec_add(lhs.xyzw, rhs.xyzw);
- return result; // This will be returned in a register
- }
-*/
+static void handleVecReturnAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ /*
+ Returning a Vector Class in Registers
+
+ According to the PPU ABI specifications, a class with a single member of
+ vector type is returned in memory when used as the return value of a
+ function.
+ This results in inefficient code when implementing vector classes. To return
+ the value in a single vector register, add the vecreturn attribute to the
+ class definition. This attribute is also applicable to struct types.
+
+ Example:
+
+ struct Vector
+ {
+ __vector float xyzw;
+ } __attribute__((vecreturn));
+
+ Vector Add(Vector lhs, Vector rhs)
+ {
+ Vector result;
+ result.xyzw = vec_add(lhs.xyzw, rhs.xyzw);
+ return result; // This will be returned in a register
+ }
+ */
if (VecReturnAttr *A = D->getAttr<VecReturnAttr>()) {
- S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << A;
+ S.Diag(AL.getLoc(), diag::err_repeat_attribute) << A;
return;
}
- RecordDecl *record = cast<RecordDecl>(D);
+ const auto *R = cast<RecordDecl>(D);
int count = 0;
- if (!isa<CXXRecordDecl>(record)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
+ if (!isa<CXXRecordDecl>(R)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
return;
}
- if (!cast<CXXRecordDecl>(record)->isPOD()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_pod_record);
+ if (!cast<CXXRecordDecl>(R)->isPOD()) {
+ S.Diag(AL.getLoc(), diag::err_attribute_vecreturn_only_pod_record);
return;
}
- for (const auto *I : record->fields()) {
+ for (const auto *I : R->fields()) {
if ((count == 1) || !I->getType()->isVectorType()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
+ S.Diag(AL.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
return;
}
count++;
}
- D->addAttr(::new (S.Context)
- VecReturnAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) VecReturnAttr(
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
}
static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D,
- const AttributeList &Attr) {
+ const ParsedAttr &AL) {
if (isa<ParmVarDecl>(D)) {
// [[carries_dependency]] can only be applied to a parameter if it is a
// parameter of a function declaration or lambda.
if (!(Scope->getFlags() & clang::Scope::FunctionDeclarationScope)) {
- S.Diag(Attr.getLoc(),
+ S.Diag(AL.getLoc(),
diag::err_carries_dependency_param_not_function_decl);
return;
}
}
D->addAttr(::new (S.Context) CarriesDependencyAttr(
- Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleNotTailCalledAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (checkAttrMutualExclusion<AlwaysInlineAttr>(S, D, Attr.getRange(),
- Attr.getName()))
- return;
-
- D->addAttr(::new (S.Context) NotTailCalledAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleDisableTailCallsAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (checkAttrMutualExclusion<NakedAttr>(S, D, Attr.getRange(),
- Attr.getName()))
- return;
-
- D->addAttr(::new (S.Context) DisableTailCallsAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
- if (VD->hasLocalStorage()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
- return;
- }
- } else if (!isFunctionOrMethod(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedVariableOrFunction;
- return;
- }
-
- D->addAttr(::new (S.Context)
- UsedAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- bool IsCXX17Attr = Attr.isCXX11Attribute() && !Attr.getScopeName();
-
- if (IsCXX17Attr && isa<VarDecl>(D)) {
- // The C++17 spelling of this attribute cannot be applied to a static data
- // member per [dcl.attr.unused]p2.
- if (cast<VarDecl>(D)->isStaticDataMember()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedForMaybeUnused;
- return;
- }
- }
+static void handleUnusedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ bool IsCXX17Attr = AL.isCXX11Attribute() && !AL.getScopeName();
// 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(Attr.getLoc(), diag::ext_cxx17_attr) << Attr.getName();
+ S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL.getName();
D->addAttr(::new (S.Context) UnusedAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
}
-static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleConstructorAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
uint32_t priority = ConstructorAttr::DefaultPriority;
- if (Attr.getNumArgs() &&
- !checkUInt32Argument(S, Attr, Attr.getArgAsExpr(0), priority))
+ if (AL.getNumArgs() &&
+ !checkUInt32Argument(S, AL, AL.getArgAsExpr(0), priority))
return;
D->addAttr(::new (S.Context)
- ConstructorAttr(Attr.getRange(), S.Context, priority,
- Attr.getAttributeSpellingListIndex()));
+ ConstructorAttr(AL.getRange(), S.Context, priority,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleDestructorAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
uint32_t priority = DestructorAttr::DefaultPriority;
- if (Attr.getNumArgs() &&
- !checkUInt32Argument(S, Attr, Attr.getArgAsExpr(0), priority))
+ if (AL.getNumArgs() &&
+ !checkUInt32Argument(S, AL, AL.getArgAsExpr(0), priority))
return;
D->addAttr(::new (S.Context)
- DestructorAttr(Attr.getRange(), S.Context, priority,
- Attr.getAttributeSpellingListIndex()));
+ DestructorAttr(AL.getRange(), S.Context, priority,
+ AL.getAttributeSpellingListIndex()));
}
template <typename AttrTy>
-static void handleAttrWithMessage(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleAttrWithMessage(Sema &S, Decl *D, const ParsedAttr &AL) {
// Handle the case where the attribute has a text message.
StringRef Str;
- if (Attr.getNumArgs() == 1 && !S.checkStringLiteralArgumentAttr(Attr, 0, Str))
+ if (AL.getNumArgs() == 1 && !S.checkStringLiteralArgumentAttr(AL, 0, Str))
return;
- D->addAttr(::new (S.Context) AttrTy(Attr.getRange(), S.Context, Str,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) AttrTy(AL.getRange(), S.Context, Str,
+ AL.getAttributeSpellingListIndex()));
}
static void handleObjCSuppresProtocolAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+ const ParsedAttr &AL) {
if (!cast<ObjCProtocolDecl>(D)->isThisDeclarationADefinition()) {
- S.Diag(Attr.getLoc(), diag::err_objc_attr_protocol_requires_definition)
- << Attr.getName() << Attr.getRange();
+ S.Diag(AL.getLoc(), diag::err_objc_attr_protocol_requires_definition)
+ << AL.getName() << AL.getRange();
return;
}
D->addAttr(::new (S.Context)
- ObjCExplicitProtocolImplAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ ObjCExplicitProtocolImplAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
static bool checkAvailabilityAttr(Sema &S, SourceRange Range,
@@ -2252,7 +2156,7 @@ static bool checkAvailabilityAttr(Sema &S, SourceRange Range,
return false;
}
-/// \brief Check whether the two versions match.
+/// Check whether the two versions match.
///
/// If either version tuple is empty, then they are assumed to match. If
/// \p BeforeIsOkay is true, then \p X can be less than or equal to \p Y.
@@ -2302,7 +2206,7 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range,
if (D->hasAttrs()) {
AttrVec &Attrs = D->getAttrs();
for (unsigned i = 0, e = Attrs.size(); i != e;) {
- const AvailabilityAttr *OldAA = dyn_cast<AvailabilityAttr>(Attrs[i]);
+ const auto *OldAA = dyn_cast<AvailabilityAttr>(Attrs[i]);
if (!OldAA) {
++i;
continue;
@@ -2434,37 +2338,34 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range,
return nullptr;
}
-static void handleAvailabilityAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!checkAttributeNumArgs(S, Attr, 1))
+static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!checkAttributeNumArgs(S, AL, 1))
return;
- IdentifierLoc *Platform = Attr.getArgAsIdent(0);
- unsigned Index = Attr.getAttributeSpellingListIndex();
+ IdentifierLoc *Platform = AL.getArgAsIdent(0);
+ unsigned Index = AL.getAttributeSpellingListIndex();
IdentifierInfo *II = Platform->Ident;
if (AvailabilityAttr::getPrettyPlatformName(II->getName()).empty())
S.Diag(Platform->Loc, diag::warn_availability_unknown_platform)
<< Platform->Ident;
- NamedDecl *ND = dyn_cast<NamedDecl>(D);
+ auto *ND = dyn_cast<NamedDecl>(D);
if (!ND) // We warned about this already, so just return.
return;
- AvailabilityChange Introduced = Attr.getAvailabilityIntroduced();
- AvailabilityChange Deprecated = Attr.getAvailabilityDeprecated();
- AvailabilityChange Obsoleted = Attr.getAvailabilityObsoleted();
- bool IsUnavailable = Attr.getUnavailableLoc().isValid();
- bool IsStrict = Attr.getStrictLoc().isValid();
+ AvailabilityChange Introduced = AL.getAvailabilityIntroduced();
+ AvailabilityChange Deprecated = AL.getAvailabilityDeprecated();
+ AvailabilityChange Obsoleted = AL.getAvailabilityObsoleted();
+ bool IsUnavailable = AL.getUnavailableLoc().isValid();
+ bool IsStrict = AL.getStrictLoc().isValid();
StringRef Str;
- if (const StringLiteral *SE =
- dyn_cast_or_null<StringLiteral>(Attr.getMessageExpr()))
+ if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getMessageExpr()))
Str = SE->getString();
StringRef Replacement;
- if (const StringLiteral *SE =
- dyn_cast_or_null<StringLiteral>(Attr.getReplacementExpr()))
+ if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getReplacementExpr()))
Replacement = SE->getString();
- AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, Attr.getRange(), II,
+ AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, AL.getRange(), II,
false/*Implicit*/,
Introduced.Version,
Deprecated.Version,
@@ -2509,7 +2410,7 @@ static void handleAvailabilityAttr(Sema &S, Decl *D,
auto NewObsoleted = adjustWatchOSVersion(Obsoleted.Version);
AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND,
- Attr.getRange(),
+ AL.getRange(),
NewII,
true/*Implicit*/,
NewIntroduced,
@@ -2534,7 +2435,7 @@ static void handleAvailabilityAttr(Sema &S, Decl *D,
if (NewII) {
AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND,
- Attr.getRange(),
+ AL.getRange(),
NewII,
true/*Implicit*/,
Introduced.Version,
@@ -2552,23 +2453,23 @@ static void handleAvailabilityAttr(Sema &S, Decl *D,
}
static void handleExternalSourceSymbolAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+ const ParsedAttr &AL) {
+ if (!checkAttributeAtLeastNumArgs(S, AL, 1))
return;
- assert(checkAttributeAtMostNumArgs(S, Attr, 3) &&
+ assert(checkAttributeAtMostNumArgs(S, AL, 3) &&
"Invalid number of arguments in an external_source_symbol attribute");
StringRef Language;
- if (const auto *SE = dyn_cast_or_null<StringLiteral>(Attr.getArgAsExpr(0)))
+ if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getArgAsExpr(0)))
Language = SE->getString();
StringRef DefinedIn;
- if (const auto *SE = dyn_cast_or_null<StringLiteral>(Attr.getArgAsExpr(1)))
+ if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getArgAsExpr(1)))
DefinedIn = SE->getString();
- bool IsGeneratedDeclaration = Attr.getArgAsIdent(2) != nullptr;
+ bool IsGeneratedDeclaration = AL.getArgAsIdent(2) != nullptr;
D->addAttr(::new (S.Context) ExternalSourceSymbolAttr(
- Attr.getRange(), S.Context, Language, DefinedIn, IsGeneratedDeclaration,
- Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, Language, DefinedIn, IsGeneratedDeclaration,
+ AL.getAttributeSpellingListIndex()));
}
template <class T>
@@ -2601,12 +2502,12 @@ TypeVisibilityAttr *Sema::mergeTypeVisibilityAttr(Decl *D, SourceRange Range,
AttrSpellingListIndex);
}
-static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr,
+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(Attr.getRange().getBegin(), diag::warn_attribute_ignored)
- << Attr.getName();
+ S.Diag(AL.getRange().getBegin(), diag::warn_attribute_ignored)
+ << AL.getName();
return;
}
@@ -2615,21 +2516,21 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr,
!(isa<TagDecl>(D) ||
isa<ObjCInterfaceDecl>(D) ||
isa<NamespaceDecl>(D))) {
- S.Diag(Attr.getRange().getBegin(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedTypeOrNamespace;
+ S.Diag(AL.getRange().getBegin(), diag::err_attribute_wrong_decl_type)
+ << AL.getName() << ExpectedTypeOrNamespace;
return;
}
// Check that the argument is a string literal.
StringRef TypeStr;
SourceLocation LiteralLoc;
- if (!S.checkStringLiteralArgumentAttr(Attr, 0, TypeStr, &LiteralLoc))
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, TypeStr, &LiteralLoc))
return;
VisibilityAttr::VisibilityType type;
if (!VisibilityAttr::ConvertStrToVisibilityType(TypeStr, type)) {
S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported)
- << Attr.getName() << TypeStr;
+ << AL.getName() << TypeStr;
return;
}
@@ -2637,62 +2538,60 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr,
// (like Darwin) that don't support it.
if (type == VisibilityAttr::Protected &&
!S.Context.getTargetInfo().hasProtectedVisibility()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_protected_visibility);
+ S.Diag(AL.getLoc(), diag::warn_attribute_protected_visibility);
type = VisibilityAttr::Default;
}
- unsigned Index = Attr.getAttributeSpellingListIndex();
- clang::Attr *newAttr;
+ unsigned Index = AL.getAttributeSpellingListIndex();
+ Attr *newAttr;
if (isTypeVisibility) {
- newAttr = S.mergeTypeVisibilityAttr(D, Attr.getRange(),
+ newAttr = S.mergeTypeVisibilityAttr(D, AL.getRange(),
(TypeVisibilityAttr::VisibilityType) type,
Index);
} else {
- newAttr = S.mergeVisibilityAttr(D, Attr.getRange(), type, Index);
+ newAttr = S.mergeVisibilityAttr(D, AL.getRange(), type, Index);
}
if (newAttr)
D->addAttr(newAttr);
}
-static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl,
- const AttributeList &Attr) {
- ObjCMethodDecl *method = cast<ObjCMethodDecl>(decl);
- if (!Attr.isArgIdent(0)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
- << Attr.getName() << 1 << AANT_ArgumentIdentifier;
+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;
return;
}
- IdentifierLoc *IL = Attr.getArgAsIdent(0);
+ 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) << Attr.getName()
- << IL->Ident;
+ S.Diag(IL->Loc, diag::warn_attribute_type_not_supported)
+ << AL.getName() << IL->Ident;
return;
}
if (F == ObjCMethodFamilyAttr::OMF_init &&
- !method->getReturnType()->isObjCObjectPointerType()) {
- S.Diag(method->getLocation(), diag::err_init_method_bad_return_type)
- << method->getReturnType();
+ !M->getReturnType()->isObjCObjectPointerType()) {
+ S.Diag(M->getLocation(), diag::err_init_method_bad_return_type)
+ << M->getReturnType();
// Ignore the attribute.
return;
}
- method->addAttr(new (S.Context) ObjCMethodFamilyAttr(Attr.getRange(),
- S.Context, F,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(new (S.Context) ObjCMethodFamilyAttr(
+ AL.getRange(), S.Context, F, AL.getAttributeSpellingListIndex()));
}
-static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) {
- if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
+static void handleObjCNSObject(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
QualType T = TD->getUnderlyingType();
if (!T->isCARCBridgableType()) {
S.Diag(TD->getLocation(), diag::err_nsobject_attribute);
return;
}
}
- else if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) {
+ else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
QualType T = PD->getType();
if (!T->isCARCBridgableType()) {
S.Diag(PD->getLocation(), diag::err_nsobject_attribute);
@@ -2709,12 +2608,12 @@ static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) {
S.Diag(D->getLocation(), diag::warn_nsobject_attribute);
}
D->addAttr(::new (S.Context)
- ObjCNSObjectAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ ObjCNSObjectAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleObjCIndependentClass(Sema &S, Decl *D, const AttributeList &Attr) {
- if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
+static void handleObjCIndependentClass(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
QualType T = TD->getUnderlyingType();
if (!T->isObjCObjectPointerType()) {
S.Diag(TD->getLocation(), diag::warn_ptr_independentclass_attribute);
@@ -2725,45 +2624,45 @@ static void handleObjCIndependentClass(Sema &S, Decl *D, const AttributeList &At
return;
}
D->addAttr(::new (S.Context)
- ObjCIndependentClassAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ ObjCIndependentClassAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!Attr.isArgIdent(0)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
- << Attr.getName() << 1 << AANT_ArgumentIdentifier;
+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;
return;
}
- IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident;
+ IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
BlocksAttr::BlockType type;
if (!BlocksAttr::ConvertStrToBlockType(II->getName(), type)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
- << Attr.getName() << II;
+ S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
+ << AL.getName() << II;
return;
}
D->addAttr(::new (S.Context)
- BlocksAttr(Attr.getRange(), S.Context, type,
- Attr.getAttributeSpellingListIndex()));
+ BlocksAttr(AL.getRange(), S.Context, type,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleSentinelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
unsigned sentinel = (unsigned)SentinelAttr::DefaultSentinel;
- if (Attr.getNumArgs() > 0) {
- Expr *E = Attr.getArgAsExpr(0);
+ if (AL.getNumArgs() > 0) {
+ Expr *E = AL.getArgAsExpr(0);
llvm::APSInt Idx(32);
if (E->isTypeDependent() || E->isValueDependent() ||
!E->isIntegerConstantExpr(Idx, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
- << Attr.getName() << 1 << AANT_ArgumentIntegerConstant
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
+ << AL.getName() << 1 << AANT_ArgumentIntegerConstant
<< E->getSourceRange();
return;
}
if (Idx.isSigned() && Idx.isNegative()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_less_than_zero)
+ S.Diag(AL.getLoc(), diag::err_attribute_sentinel_less_than_zero)
<< E->getSourceRange();
return;
}
@@ -2772,13 +2671,13 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
unsigned nullPos = (unsigned)SentinelAttr::DefaultNullPos;
- if (Attr.getNumArgs() > 1) {
- Expr *E = Attr.getArgAsExpr(1);
+ if (AL.getNumArgs() > 1) {
+ Expr *E = AL.getArgAsExpr(1);
llvm::APSInt Idx(32);
if (E->isTypeDependent() || E->isValueDependent() ||
!E->isIntegerConstantExpr(Idx, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
- << Attr.getName() << 2 << AANT_ArgumentIntegerConstant
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
+ << AL.getName() << 2 << AANT_ArgumentIntegerConstant
<< E->getSourceRange();
return;
}
@@ -2787,34 +2686,34 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if ((Idx.isSigned() && Idx.isNegative()) || nullPos > 1) {
// FIXME: This error message could be improved, it would be nice
// to say what the bounds actually are.
- S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_not_zero_or_one)
+ S.Diag(AL.getLoc(), diag::err_attribute_sentinel_not_zero_or_one)
<< E->getSourceRange();
return;
}
}
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
const FunctionType *FT = FD->getType()->castAs<FunctionType>();
if (isa<FunctionNoProtoType>(FT)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_named_arguments);
+ S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_named_arguments);
return;
}
if (!cast<FunctionProtoType>(FT)->isVariadic()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
+ S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
return;
}
- } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
if (!MD->isVariadic()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
+ S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
return;
}
- } else if (BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
+ } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
if (!BD->isVariadic()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1;
+ S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1;
return;
}
- } else if (const VarDecl *V = dyn_cast<VarDecl>(D)) {
+ } else if (const auto *V = dyn_cast<VarDecl>(D)) {
QualType Ty = V->getType();
if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) {
const FunctionType *FT = Ty->isFunctionPointerType()
@@ -2822,84 +2721,83 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) {
: Ty->getAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>();
if (!cast<FunctionProtoType>(FT)->isVariadic()) {
int m = Ty->isFunctionPointerType() ? 0 : 1;
- S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m;
+ S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m;
return;
}
} else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionMethodOrBlock;
+ S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << AL.getName() << ExpectedFunctionMethodOrBlock;
return;
}
} else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionMethodOrBlock;
+ S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << AL.getName() << ExpectedFunctionMethodOrBlock;
return;
}
D->addAttr(::new (S.Context)
- SentinelAttr(Attr.getRange(), S.Context, sentinel, nullPos,
- Attr.getAttributeSpellingListIndex()));
+ SentinelAttr(AL.getRange(), S.Context, sentinel, nullPos,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleWarnUnusedResult(Sema &S, Decl *D, const ParsedAttr &AL) {
if (D->getFunctionType() &&
D->getFunctionType()->getReturnType()->isVoidType()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method)
- << Attr.getName() << 0;
+ S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method)
+ << AL.getName() << 0;
return;
}
- if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
+ if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
if (MD->getReturnType()->isVoidType()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method)
- << Attr.getName() << 1;
+ S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method)
+ << AL.getName() << 1;
return;
}
// 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 && Attr.isCXX11Attribute() &&
- !Attr.getScopeName())
- S.Diag(Attr.getLoc(), diag::ext_cxx17_attr) << Attr.getName();
+ if (!S.getLangOpts().CPlusPlus17 && AL.isCXX11Attribute() &&
+ !AL.getScopeName())
+ S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL.getName();
D->addAttr(::new (S.Context)
- WarnUnusedResultAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ WarnUnusedResultAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleWeakImportAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// weak_import only applies to variable & function declarations.
bool isDef = false;
if (!D->canBeWeakImported(isDef)) {
if (isDef)
- S.Diag(Attr.getLoc(), diag::warn_attribute_invalid_on_definition)
+ S.Diag(AL.getLoc(), diag::warn_attribute_invalid_on_definition)
<< "weak_import";
else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D) ||
(S.Context.getTargetInfo().getTriple().isOSDarwin() &&
(isa<ObjCInterfaceDecl>(D) || isa<EnumDecl>(D)))) {
// Nothing to warn about here.
} else
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedVariableOrFunction;
+ S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << AL.getName() << ExpectedVariableOrFunction;
return;
}
D->addAttr(::new (S.Context)
- WeakImportAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ WeakImportAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
// Handles reqd_work_group_size and work_group_size_hint.
template <typename WorkGroupAttr>
-static void handleWorkGroupSize(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
uint32_t WGSize[3];
for (unsigned i = 0; i < 3; ++i) {
- const Expr *E = Attr.getArgAsExpr(i);
- if (!checkUInt32Argument(S, Attr, E, WGSize[i], i))
+ const Expr *E = AL.getArgAsExpr(i);
+ if (!checkUInt32Argument(S, AL, E, WGSize[i], i))
return;
if (WGSize[i] == 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_is_zero)
- << Attr.getName() << E->getSourceRange();
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_is_zero)
+ << AL.getName() << E->getSourceRange();
return;
}
}
@@ -2908,73 +2806,81 @@ static void handleWorkGroupSize(Sema &S, Decl *D,
if (Existing && !(Existing->getXDim() == WGSize[0] &&
Existing->getYDim() == WGSize[1] &&
Existing->getZDim() == WGSize[2]))
- S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr.getName();
+ S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL.getName();
- D->addAttr(::new (S.Context) WorkGroupAttr(Attr.getRange(), S.Context,
+ D->addAttr(::new (S.Context) WorkGroupAttr(AL.getRange(), S.Context,
WGSize[0], WGSize[1], WGSize[2],
- Attr.getAttributeSpellingListIndex()));
+ AL.getAttributeSpellingListIndex()));
}
// Handles intel_reqd_sub_group_size.
-static void handleSubGroupSize(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleSubGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
uint32_t SGSize;
- const Expr *E = Attr.getArgAsExpr(0);
- if (!checkUInt32Argument(S, Attr, E, SGSize))
+ const Expr *E = AL.getArgAsExpr(0);
+ if (!checkUInt32Argument(S, AL, E, SGSize))
return;
if (SGSize == 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_is_zero)
- << Attr.getName() << E->getSourceRange();
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_is_zero)
+ << AL.getName() << E->getSourceRange();
return;
}
OpenCLIntelReqdSubGroupSizeAttr *Existing =
D->getAttr<OpenCLIntelReqdSubGroupSizeAttr>();
if (Existing && Existing->getSubGroupSize() != SGSize)
- S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr.getName();
+ S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL.getName();
D->addAttr(::new (S.Context) OpenCLIntelReqdSubGroupSizeAttr(
- Attr.getRange(), S.Context, SGSize,
- Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, SGSize,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!Attr.hasParsedType()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 1;
+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;
return;
}
TypeSourceInfo *ParmTSI = nullptr;
- QualType ParmType = S.GetTypeFromParser(Attr.getTypeArg(), &ParmTSI);
+ QualType ParmType = S.GetTypeFromParser(AL.getTypeArg(), &ParmTSI);
assert(ParmTSI && "no type source info for attribute argument");
if (!ParmType->isExtVectorType() && !ParmType->isFloatingType() &&
(ParmType->isBooleanType() ||
!ParmType->isIntegralType(S.getASTContext()))) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_vec_type_hint)
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_vec_type_hint)
<< ParmType;
return;
}
if (VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>()) {
if (!S.Context.hasSameType(A->getTypeHint(), ParmType)) {
- S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr.getName();
+ S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL.getName();
return;
}
}
- D->addAttr(::new (S.Context) VecTypeHintAttr(Attr.getLoc(), S.Context,
+ D->addAttr(::new (S.Context) VecTypeHintAttr(AL.getLoc(), S.Context,
ParmTSI,
- Attr.getAttributeSpellingListIndex()));
+ AL.getAttributeSpellingListIndex()));
}
SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range,
StringRef Name,
unsigned AttrSpellingListIndex) {
+ // Explicit or partial specializations do not inherit
+ // the section attribute from the primary template.
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ if (AttrSpellingListIndex == SectionAttr::Declspec_allocate &&
+ FD->isFunctionTemplateSpecialization())
+ return nullptr;
+ }
if (SectionAttr *ExistingAttr = D->getAttr<SectionAttr>()) {
if (ExistingAttr->getName() == Name)
return nullptr;
- Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section);
+ Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section)
+ << 1 /*section*/;
Diag(Range.getBegin(), diag::note_previous_attribute);
return nullptr;
}
@@ -2985,18 +2891,19 @@ SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range,
bool Sema::checkSectionName(SourceLocation LiteralLoc, StringRef SecName) {
std::string Error = Context.getTargetInfo().isValidSectionSpecifier(SecName);
if (!Error.empty()) {
- Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) << Error;
+ Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) << Error
+ << 1 /*'section'*/;
return false;
}
return true;
}
-static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Make sure that there is a string literal as the sections's single
// argument.
StringRef Str;
SourceLocation LiteralLoc;
- if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &LiteralLoc))
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc))
return;
if (!S.checkSectionName(LiteralLoc, Str))
@@ -3010,12 +2917,65 @@ static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- unsigned Index = Attr.getAttributeSpellingListIndex();
- SectionAttr *NewAttr = S.mergeSectionAttr(D, Attr.getRange(), Str, Index);
+ unsigned Index = AL.getAttributeSpellingListIndex();
+ SectionAttr *NewAttr = S.mergeSectionAttr(D, AL.getRange(), Str, Index);
if (NewAttr)
D->addAttr(NewAttr);
}
+static bool checkCodeSegName(Sema&S, SourceLocation LiteralLoc, StringRef CodeSegName) {
+ std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(CodeSegName);
+ if (!Error.empty()) {
+ S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) << Error
+ << 0 /*'code-seg'*/;
+ return false;
+ }
+ return true;
+}
+
+CodeSegAttr *Sema::mergeCodeSegAttr(Decl *D, SourceRange Range,
+ StringRef Name,
+ unsigned AttrSpellingListIndex) {
+ // Explicit or partial specializations do not inherit
+ // the code_seg attribute from the primary template.
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FD->isFunctionTemplateSpecialization())
+ return nullptr;
+ }
+ if (const auto *ExistingAttr = D->getAttr<CodeSegAttr>()) {
+ if (ExistingAttr->getName() == Name)
+ return nullptr;
+ Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section)
+ << 0 /*codeseg*/;
+ Diag(Range.getBegin(), diag::note_previous_attribute);
+ return nullptr;
+ }
+ return ::new (Context) CodeSegAttr(Range, Context, Name,
+ AttrSpellingListIndex);
+}
+
+static void handleCodeSegAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ StringRef Str;
+ SourceLocation LiteralLoc;
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc))
+ return;
+ if (!checkCodeSegName(S, LiteralLoc, Str))
+ return;
+ if (const auto *ExistingAttr = D->getAttr<CodeSegAttr>()) {
+ if (!ExistingAttr->isImplicit()) {
+ S.Diag(AL.getLoc(),
+ ExistingAttr->getName() == Str
+ ? diag::warn_duplicate_codeseg_attribute
+ : diag::err_conflicting_codeseg_attribute);
+ return;
+ }
+ D->dropAttr<CodeSegAttr>();
+ }
+ if (CodeSegAttr *CSA = S.mergeCodeSegAttr(D, AL.getRange(), Str,
+ AL.getAttributeSpellingListIndex()))
+ D->addAttr(CSA);
+}
+
// Check for things we'd like to warn about. Multiversioning issues are
// handled later in the process, once we know how many exist.
bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
@@ -3044,30 +3004,50 @@ bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
<< Unsupported << None << CurFeature;
}
- return true;
+ return false;
}
-static void handleTargetAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleTargetAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
StringRef Str;
SourceLocation LiteralLoc;
- if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &LiteralLoc) ||
- !S.checkTargetAttr(LiteralLoc, Str))
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc) ||
+ S.checkTargetAttr(LiteralLoc, Str))
return;
- unsigned Index = Attr.getAttributeSpellingListIndex();
+
+ unsigned Index = AL.getAttributeSpellingListIndex();
TargetAttr *NewAttr =
- ::new (S.Context) TargetAttr(Attr.getRange(), S.Context, Str, Index);
+ ::new (S.Context) TargetAttr(AL.getRange(), S.Context, Str, Index);
D->addAttr(NewAttr);
}
-static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- Expr *E = Attr.getArgAsExpr(0);
+static void handleMinVectorWidthAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ Expr *E = AL.getArgAsExpr(0);
+ uint32_t VecWidth;
+ if (!checkUInt32Argument(S, AL, E, VecWidth)) {
+ AL.setInvalid();
+ return;
+ }
+
+ MinVectorWidthAttr *Existing = D->getAttr<MinVectorWidthAttr>();
+ if (Existing && Existing->getVectorWidth() != VecWidth) {
+ S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL.getName();
+ return;
+ }
+
+ D->addAttr(::new (S.Context)
+ MinVectorWidthAttr(AL.getRange(), S.Context, VecWidth,
+ AL.getAttributeSpellingListIndex()));
+}
+
+static void handleCleanupAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ Expr *E = AL.getArgAsExpr(0);
SourceLocation Loc = E->getExprLoc();
FunctionDecl *FD = nullptr;
DeclarationNameInfo NI;
// gcc only allows for simple identifiers. Since we support more than gcc, we
// will warn the user.
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+ if (auto *DRE = dyn_cast<DeclRefExpr>(E)) {
if (DRE->hasQualifier())
S.Diag(Loc, diag::warn_cleanup_ext);
FD = dyn_cast<FunctionDecl>(DRE->getDecl());
@@ -3077,7 +3057,7 @@ static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) {
<< NI.getName();
return;
}
- } else if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
+ } else if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
if (ULE->hasExplicitTemplateArgs())
S.Diag(Loc, diag::warn_cleanup_ext);
FD = S.ResolveSingleFunctionTemplateSpecialization(ULE, true);
@@ -3112,49 +3092,49 @@ static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
D->addAttr(::new (S.Context)
- CleanupAttr(Attr.getRange(), S.Context, FD,
- Attr.getAttributeSpellingListIndex()));
+ CleanupAttr(AL.getRange(), S.Context, FD,
+ AL.getAttributeSpellingListIndex()));
}
static void handleEnumExtensibilityAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!Attr.isArgIdent(0)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
- << Attr.getName() << 0 << AANT_ArgumentIdentifier;
+ const ParsedAttr &AL) {
+ if (!AL.isArgIdent(0)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
+ << AL.getName() << 0 << AANT_ArgumentIdentifier;
return;
}
EnumExtensibilityAttr::Kind ExtensibilityKind;
- IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident;
+ IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
if (!EnumExtensibilityAttr::ConvertStrToKind(II->getName(),
ExtensibilityKind)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
- << Attr.getName() << II;
+ S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
+ << AL.getName() << II;
return;
}
D->addAttr(::new (S.Context) EnumExtensibilityAttr(
- Attr.getRange(), S.Context, ExtensibilityKind,
- Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, ExtensibilityKind,
+ AL.getAttributeSpellingListIndex()));
}
/// Handle __attribute__((format_arg((idx)))) attribute based on
/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
-static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- Expr *IdxExpr = Attr.getArgAsExpr(0);
- uint64_t Idx;
- if (!checkFunctionOrMethodParameterIndex(S, D, Attr, 1, IdxExpr, Idx))
+static void handleFormatArgAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ Expr *IdxExpr = AL.getArgAsExpr(0);
+ ParamIdx Idx;
+ if (!checkFunctionOrMethodParameterIndex(S, D, AL, 1, IdxExpr, Idx))
return;
// Make sure the format string is really a string.
- QualType Ty = getFunctionOrMethodParamType(D, Idx);
+ QualType Ty = getFunctionOrMethodParamType(D, Idx.getASTIndex());
bool NotNSStringTy = !isNSStringType(Ty, S.Context);
if (NotNSStringTy &&
!isCFStringType(Ty, S.Context) &&
(!Ty->isPointerType() ||
!Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
- S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
+ S.Diag(AL.getLoc(), diag::err_format_attribute_not)
<< "a string type" << IdxExpr->getSourceRange()
<< getFunctionOrMethodParamRange(D, 0);
return;
@@ -3164,21 +3144,14 @@ static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) {
!isCFStringType(Ty, S.Context) &&
(!Ty->isPointerType() ||
!Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
- S.Diag(Attr.getLoc(), diag::err_format_attribute_result_not)
+ S.Diag(AL.getLoc(), diag::err_format_attribute_result_not)
<< (NotNSStringTy ? "string type" : "NSString")
<< IdxExpr->getSourceRange() << getFunctionOrMethodParamRange(D, 0);
return;
}
- // We cannot use the Idx returned from checkFunctionOrMethodParameterIndex
- // because that has corrected for the implicit this parameter, and is zero-
- // based. The attribute expects what the user wrote explicitly.
- llvm::APSInt Val;
- IdxExpr->EvaluateAsInt(Val, S.Context);
-
- D->addAttr(::new (S.Context)
- FormatArgAttr(Attr.getRange(), S.Context, Val.getZExtValue(),
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) FormatArgAttr(
+ AL.getRange(), S.Context, Idx, AL.getAttributeSpellingListIndex()));
}
enum FormatAttrKind {
@@ -3213,43 +3186,42 @@ static FormatAttrKind getFormatAttrKind(StringRef Format) {
/// Handle __attribute__((init_priority(priority))) attributes based on
/// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html
-static void handleInitPriorityAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleInitPriorityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!S.getLangOpts().CPlusPlus) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL.getName();
return;
}
if (S.getCurFunctionOrMethodDecl()) {
- S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr);
- Attr.setInvalid();
+ S.Diag(AL.getLoc(), diag::err_init_priority_object_attr);
+ AL.setInvalid();
return;
}
QualType T = cast<VarDecl>(D)->getType();
if (S.Context.getAsArrayType(T))
T = S.Context.getBaseElementType(T);
if (!T->getAs<RecordType>()) {
- S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr);
- Attr.setInvalid();
+ S.Diag(AL.getLoc(), diag::err_init_priority_object_attr);
+ AL.setInvalid();
return;
}
- Expr *E = Attr.getArgAsExpr(0);
+ Expr *E = AL.getArgAsExpr(0);
uint32_t prioritynum;
- if (!checkUInt32Argument(S, Attr, E, prioritynum)) {
- Attr.setInvalid();
+ if (!checkUInt32Argument(S, AL, E, prioritynum)) {
+ AL.setInvalid();
return;
}
if (prioritynum < 101 || prioritynum > 65535) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_outof_range)
- << E->getSourceRange() << Attr.getName() << 101 << 65535;
- Attr.setInvalid();
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_outof_range)
+ << E->getSourceRange() << AL.getName() << 101 << 65535;
+ AL.setInvalid();
return;
}
D->addAttr(::new (S.Context)
- InitPriorityAttr(Attr.getRange(), S.Context, prioritynum,
- Attr.getAttributeSpellingListIndex()));
+ InitPriorityAttr(AL.getRange(), S.Context, prioritynum,
+ AL.getAttributeSpellingListIndex()));
}
FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range,
@@ -3275,10 +3247,10 @@ FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range,
/// Handle __attribute__((format(type,idx,firstarg))) attributes based on
/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
-static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!Attr.isArgIdent(0)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
- << Attr.getName() << 1 << AANT_ArgumentIdentifier;
+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;
return;
}
@@ -3287,7 +3259,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
bool HasImplicitThisParam = isInstanceMethod(D);
unsigned NumArgs = getFunctionOrMethodNumParams(D) + HasImplicitThisParam;
- IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident;
+ IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
StringRef Format = II->getName();
if (normalizeName(Format)) {
@@ -3302,20 +3274,20 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
if (Kind == InvalidFormat) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
- << Attr.getName() << II->getName();
+ S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
+ << AL.getName() << II->getName();
return;
}
// checks for the 2nd argument
- Expr *IdxExpr = Attr.getArgAsExpr(1);
+ Expr *IdxExpr = AL.getArgAsExpr(1);
uint32_t Idx;
- if (!checkUInt32Argument(S, Attr, IdxExpr, Idx, 2))
+ if (!checkUInt32Argument(S, AL, IdxExpr, Idx, 2))
return;
if (Idx < 1 || Idx > NumArgs) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << Attr.getName() << 2 << IdxExpr->getSourceRange();
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
+ << AL.getName() << 2 << IdxExpr->getSourceRange();
return;
}
@@ -3324,7 +3296,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (HasImplicitThisParam) {
if (ArgIdx == 0) {
- S.Diag(Attr.getLoc(),
+ S.Diag(AL.getLoc(),
diag::err_format_attribute_implicit_this_format_string)
<< IdxExpr->getSourceRange();
return;
@@ -3337,7 +3309,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (Kind == CFStringFormat) {
if (!isCFStringType(Ty, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
+ S.Diag(AL.getLoc(), diag::err_format_attribute_not)
<< "a CFString" << IdxExpr->getSourceRange()
<< getFunctionOrMethodParamRange(D, ArgIdx);
return;
@@ -3346,23 +3318,23 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// FIXME: do we need to check if the type is NSString*? What are the
// semantics?
if (!isNSStringType(Ty, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
+ S.Diag(AL.getLoc(), diag::err_format_attribute_not)
<< "an NSString" << IdxExpr->getSourceRange()
<< getFunctionOrMethodParamRange(D, ArgIdx);
return;
}
} else if (!Ty->isPointerType() ||
!Ty->getAs<PointerType>()->getPointeeType()->isCharType()) {
- S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
+ S.Diag(AL.getLoc(), diag::err_format_attribute_not)
<< "a string type" << IdxExpr->getSourceRange()
<< getFunctionOrMethodParamRange(D, ArgIdx);
return;
}
// check the 3rd argument
- Expr *FirstArgExpr = Attr.getArgAsExpr(2);
+ Expr *FirstArgExpr = AL.getArgAsExpr(2);
uint32_t FirstArg;
- if (!checkUInt32Argument(S, Attr, FirstArgExpr, FirstArg, 3))
+ if (!checkUInt32Argument(S, AL, FirstArgExpr, FirstArg, 3))
return;
// check if the function is variadic if the 3rd argument non-zero
@@ -3379,43 +3351,42 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// variable the input is just the current time + the format string.
if (Kind == StrftimeFormat) {
if (FirstArg != 0) {
- S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter)
+ S.Diag(AL.getLoc(), diag::err_format_strftime_third_parameter)
<< FirstArgExpr->getSourceRange();
return;
}
// if 0 it disables parameter checking (to use with e.g. va_list)
} else if (FirstArg != 0 && FirstArg != NumArgs) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << Attr.getName() << 3 << FirstArgExpr->getSourceRange();
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
+ << AL.getName() << 3 << FirstArgExpr->getSourceRange();
return;
}
- FormatAttr *NewAttr = S.mergeFormatAttr(D, Attr.getRange(), II,
+ FormatAttr *NewAttr = S.mergeFormatAttr(D, AL.getRange(), II,
Idx, FirstArg,
- Attr.getAttributeSpellingListIndex());
+ AL.getAttributeSpellingListIndex());
if (NewAttr)
D->addAttr(NewAttr);
}
-static void handleTransparentUnionAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleTransparentUnionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Try to find the underlying union declaration.
RecordDecl *RD = nullptr;
- TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
+ const auto *TD = dyn_cast<TypedefNameDecl>(D);
if (TD && TD->getUnderlyingType()->isUnionType())
RD = TD->getUnderlyingType()->getAsUnionType()->getDecl();
else
RD = dyn_cast<RecordDecl>(D);
if (!RD || !RD->isUnion()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedUnion;
+ S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << AL.getName() << ExpectedUnion;
return;
}
if (!RD->isCompleteDefinition()) {
if (!RD->isBeingDefined())
- S.Diag(Attr.getLoc(),
+ S.Diag(AL.getLoc(),
diag::warn_transparent_union_attribute_not_definition);
return;
}
@@ -3423,7 +3394,7 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D,
RecordDecl::field_iterator Field = RD->field_begin(),
FieldEnd = RD->field_end();
if (Field == FieldEnd) {
- S.Diag(Attr.getLoc(), diag::warn_transparent_union_attribute_zero_fields);
+ S.Diag(AL.getLoc(), diag::warn_transparent_union_attribute_zero_fields);
return;
}
@@ -3467,15 +3438,15 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D,
}
RD->addAttr(::new (S.Context)
- TransparentUnionAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ TransparentUnionAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleAnnotateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Make sure that there is a string literal as the annotation's single
// argument.
StringRef Str;
- if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str))
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
return;
// Don't duplicate annotations that are already set.
@@ -3485,14 +3456,13 @@ static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
D->addAttr(::new (S.Context)
- AnnotateAttr(Attr.getRange(), S.Context, Str,
- Attr.getAttributeSpellingListIndex()));
+ AnnotateAttr(AL.getRange(), S.Context, Str,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleAlignValueAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- S.AddAlignValueAttr(Attr.getRange(), D, Attr.getArgAsExpr(0),
- Attr.getAttributeSpellingListIndex());
+static void handleAlignValueAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ S.AddAlignValueAttr(AL.getRange(), D, AL.getArgAsExpr(0),
+ AL.getAttributeSpellingListIndex());
}
void Sema::AddAlignValueAttr(SourceRange AttrRange, Decl *D, Expr *E,
@@ -3501,9 +3471,9 @@ void Sema::AddAlignValueAttr(SourceRange AttrRange, Decl *D, Expr *E,
SourceLocation AttrLoc = AttrRange.getBegin();
QualType T;
- if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
+ if (const auto *TD = dyn_cast<TypedefNameDecl>(D))
T = TD->getUnderlyingType();
- else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
+ else if (const auto *VD = dyn_cast<ValueDecl>(D))
T = VD->getType();
else
llvm_unreachable("Unknown decl type for align_value");
@@ -3540,42 +3510,32 @@ void Sema::AddAlignValueAttr(SourceRange AttrRange, Decl *D, Expr *E,
D->addAttr(::new (Context) AlignValueAttr(TmpAttr));
}
-static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleAlignedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// check the attribute arguments.
- if (Attr.getNumArgs() > 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 1;
+ if (AL.getNumArgs() > 1) {
+ S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << AL.getName() << 1;
return;
}
- if (Attr.getNumArgs() == 0) {
- D->addAttr(::new (S.Context) AlignedAttr(Attr.getRange(), S.Context,
- true, nullptr, Attr.getAttributeSpellingListIndex()));
+ if (AL.getNumArgs() == 0) {
+ D->addAttr(::new (S.Context) AlignedAttr(AL.getRange(), S.Context,
+ true, nullptr, AL.getAttributeSpellingListIndex()));
return;
}
- Expr *E = Attr.getArgAsExpr(0);
- if (Attr.isPackExpansion() && !E->containsUnexpandedParameterPack()) {
- S.Diag(Attr.getEllipsisLoc(),
+ Expr *E = AL.getArgAsExpr(0);
+ if (AL.isPackExpansion() && !E->containsUnexpandedParameterPack()) {
+ S.Diag(AL.getEllipsisLoc(),
diag::err_pack_expansion_without_parameter_packs);
return;
}
- if (!Attr.isPackExpansion() && S.DiagnoseUnexpandedParameterPack(E))
+ if (!AL.isPackExpansion() && S.DiagnoseUnexpandedParameterPack(E))
return;
- if (E->isValueDependent()) {
- if (const auto *TND = dyn_cast<TypedefNameDecl>(D)) {
- if (!TND->getUnderlyingType()->isDependentType()) {
- S.Diag(Attr.getLoc(), diag::err_alignment_dependent_typedef_name)
- << E->getSourceRange();
- return;
- }
- }
- }
-
- S.AddAlignedAttr(Attr.getRange(), D, E, Attr.getAttributeSpellingListIndex(),
- Attr.isPackExpansion());
+ S.AddAlignedAttr(AL.getRange(), D, E, AL.getAttributeSpellingListIndex(),
+ AL.isPackExpansion());
}
void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
@@ -3599,12 +3559,12 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
int DiagKind = -1;
if (isa<ParmVarDecl>(D)) {
DiagKind = 0;
- } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
if (VD->getStorageClass() == SC_Register)
DiagKind = 1;
if (VD->isExceptionVariable())
DiagKind = 2;
- } else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
+ } else if (const auto *FD = dyn_cast<FieldDecl>(D)) {
if (FD->isBitField())
DiagKind = 3;
} else if (!isa<TagDecl>(D)) {
@@ -3620,7 +3580,18 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
}
}
- if (E->isTypeDependent() || E->isValueDependent()) {
+ if (E->isValueDependent()) {
+ // We can't support a dependent alignment on a non-dependent type,
+ // because we have no way to model that a type is "alignment-dependent"
+ // but not dependent in any other way.
+ if (const auto *TND = dyn_cast<TypedefNameDecl>(D)) {
+ if (!TND->getUnderlyingType()->isDependentType()) {
+ Diag(AttrLoc, diag::err_alignment_dependent_typedef_name)
+ << E->getSourceRange();
+ return;
+ }
+ }
+
// Save dependent expressions in the AST to be instantiated.
AlignedAttr *AA = ::new (Context) AlignedAttr(TmpAttr);
AA->setPackExpansion(IsPackExpansion);
@@ -3628,7 +3599,7 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
return;
}
- // FIXME: Cache the number on the Attr object?
+ // FIXME: Cache the number on the AL object?
llvm::APSInt Alignment;
ExprResult ICE
= VerifyIntegerConstantExpression(E, &Alignment,
@@ -3666,7 +3637,7 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
unsigned MaxTLSAlign =
Context.toCharUnitsFromBits(Context.getTargetInfo().getMaxTLSAlign())
.getQuantity();
- auto *VD = dyn_cast<VarDecl>(D);
+ const auto *VD = dyn_cast<VarDecl>(D);
if (MaxTLSAlign && AlignVal > MaxTLSAlign && VD &&
VD->getTLSKind() != VarDecl::TLS_None) {
Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum)
@@ -3683,7 +3654,7 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *TS,
unsigned SpellingListIndex, bool IsPackExpansion) {
- // FIXME: Cache the number on the Attr object if non-dependent?
+ // FIXME: Cache the number on the AL object if non-dependent?
// FIXME: Perform checking of type validity
AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, false, TS,
SpellingListIndex);
@@ -3695,11 +3666,11 @@ void Sema::CheckAlignasUnderalignment(Decl *D) {
assert(D->hasAttrs() && "no attributes on decl");
QualType UnderlyingTy, DiagTy;
- if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
+ if (const auto *VD = dyn_cast<ValueDecl>(D)) {
UnderlyingTy = DiagTy = VD->getType();
} else {
UnderlyingTy = DiagTy = Context.getTagDeclType(cast<TagDecl>(D));
- if (EnumDecl *ED = dyn_cast<EnumDecl>(D))
+ if (const auto *ED = dyn_cast<EnumDecl>(D))
UnderlyingTy = ED->getIntegerType();
}
if (DiagTy->isDependentType() || DiagTy->isIncompleteType())
@@ -3819,18 +3790,18 @@ static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth,
/// Despite what would be logical, the mode attribute is a decl attribute, not a
/// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be
/// HImode, not an intermediate pointer.
-static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+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 (!Attr.isArgIdent(0)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName()
+ if (!AL.isArgIdent(0)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type) << AL.getName()
<< AANT_ArgumentIdentifier;
return;
}
- IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident;
+ IdentifierInfo *Name = AL.getArgAsIdent(0)->Ident;
- S.AddModeAttr(Attr.getRange(), D, Name, Attr.getAttributeSpellingListIndex());
+ S.AddModeAttr(AL.getRange(), D, Name, AL.getAttributeSpellingListIndex());
}
void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name,
@@ -3876,9 +3847,9 @@ void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name,
}
QualType OldTy;
- if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
+ if (const auto *TD = dyn_cast<TypedefNameDecl>(D))
OldTy = TD->getUnderlyingType();
- else if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
+ else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
// Something like 'typedef enum { X } __attribute__((mode(XX))) T;'.
// Try to get type from enum declaration, default to int.
OldTy = ED->getIntegerType();
@@ -3896,7 +3867,7 @@ void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name,
// Base type can also be a vector type (see PR17453).
// Distinguish between base type and base element type.
QualType OldElemTy = OldTy;
- if (const VectorType *VT = OldTy->getAs<VectorType>())
+ if (const auto *VT = OldTy->getAs<VectorType>())
OldElemTy = VT->getElementType();
// GCC allows 'mode' attribute on enumeration types (even incomplete), except
@@ -3945,7 +3916,7 @@ void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name,
if (VectorSize.getBoolValue()) {
NewTy = Context.getVectorType(NewTy, VectorSize.getZExtValue(),
VectorType::GenericVector);
- } else if (const VectorType *OldVT = OldTy->getAs<VectorType>()) {
+ } else if (const auto *OldVT = OldTy->getAs<VectorType>()) {
// Complex machine mode does not support base vector types.
if (ComplexMode) {
Diag(AttrLoc, diag::err_complex_mode_vector_type);
@@ -3964,9 +3935,9 @@ void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name,
}
// Install the new type.
- if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
+ if (auto *TD = dyn_cast<TypedefNameDecl>(D))
TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy);
- else if (EnumDecl *ED = dyn_cast<EnumDecl>(D))
+ else if (auto *ED = dyn_cast<EnumDecl>(D))
ED->setIntegerType(NewTy);
else
cast<ValueDecl>(D)->setType(NewTy);
@@ -3975,10 +3946,10 @@ void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name,
ModeAttr(AttrRange, Context, Name, SpellingListIndex));
}
-static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleNoDebugAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
D->addAttr(::new (S.Context)
- NoDebugAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ NoDebugAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
AlwaysInlineAttr *Sema::mergeAlwaysInlineAttr(Decl *D, SourceRange Range,
@@ -4010,7 +3981,7 @@ InternalLinkageAttr *
Sema::mergeInternalLinkageAttr(Decl *D, SourceRange Range,
IdentifierInfo *Ident,
unsigned AttrSpellingListIndex) {
- if (auto VD = dyn_cast<VarDecl>(D)) {
+ 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) {
@@ -4067,71 +4038,70 @@ OptimizeNoneAttr *Sema::mergeOptimizeNoneAttr(Decl *D, SourceRange Range,
AttrSpellingListIndex);
}
-static void handleAlwaysInlineAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (checkAttrMutualExclusion<NotTailCalledAttr>(S, D, Attr.getRange(),
- Attr.getName()))
+static void handleAlwaysInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (checkAttrMutualExclusion<NotTailCalledAttr>(S, D, AL.getRange(),
+ AL.getName()))
return;
if (AlwaysInlineAttr *Inline = S.mergeAlwaysInlineAttr(
- D, Attr.getRange(), Attr.getName(),
- Attr.getAttributeSpellingListIndex()))
+ D, AL.getRange(), AL.getName(),
+ AL.getAttributeSpellingListIndex()))
D->addAttr(Inline);
}
-static void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleMinSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (MinSizeAttr *MinSize = S.mergeMinSizeAttr(
- D, Attr.getRange(), Attr.getAttributeSpellingListIndex()))
+ D, AL.getRange(), AL.getAttributeSpellingListIndex()))
D->addAttr(MinSize);
}
-static void handleOptimizeNoneAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleOptimizeNoneAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (OptimizeNoneAttr *Optnone = S.mergeOptimizeNoneAttr(
- D, Attr.getRange(), Attr.getAttributeSpellingListIndex()))
+ D, AL.getRange(), AL.getAttributeSpellingListIndex()))
D->addAttr(Optnone);
}
-static void handleConstantAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (checkAttrMutualExclusion<CUDASharedAttr>(S, D, Attr.getRange(),
- Attr.getName()))
+static void handleConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (checkAttrMutualExclusion<CUDASharedAttr>(S, D, AL.getRange(),
+ AL.getName()))
return;
- auto *VD = cast<VarDecl>(D);
+ const auto *VD = cast<VarDecl>(D);
if (!VD->hasGlobalStorage()) {
- S.Diag(Attr.getLoc(), diag::err_cuda_nonglobal_constant);
+ S.Diag(AL.getLoc(), diag::err_cuda_nonglobal_constant);
return;
}
D->addAttr(::new (S.Context) CUDAConstantAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
}
-static void handleSharedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, Attr.getRange(),
- Attr.getName()))
+static void handleSharedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, AL.getRange(),
+ AL.getName()))
return;
- auto *VD = cast<VarDecl>(D);
+ const auto *VD = cast<VarDecl>(D);
// extern __shared__ is only allowed on arrays with no length (e.g.
// "int x[]").
- if (VD->hasExternalStorage() && !isa<IncompleteArrayType>(VD->getType())) {
- S.Diag(Attr.getLoc(), diag::err_cuda_extern_shared) << VD;
+ if (!S.getLangOpts().CUDARelocatableDeviceCode && VD->hasExternalStorage() &&
+ !isa<IncompleteArrayType>(VD->getType())) {
+ S.Diag(AL.getLoc(), diag::err_cuda_extern_shared) << VD;
return;
}
if (S.getLangOpts().CUDA && VD->hasLocalStorage() &&
- S.CUDADiagIfHostCode(Attr.getLoc(), diag::err_cuda_host_shared)
+ S.CUDADiagIfHostCode(AL.getLoc(), diag::err_cuda_host_shared)
<< S.CurrentCUDATarget())
return;
D->addAttr(::new (S.Context) CUDASharedAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
}
-static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (checkAttrMutualExclusion<CUDADeviceAttr>(S, D, Attr.getRange(),
- Attr.getName()) ||
- checkAttrMutualExclusion<CUDAHostAttr>(S, D, Attr.getRange(),
- Attr.getName())) {
+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())) {
return;
}
- FunctionDecl *FD = cast<FunctionDecl>(D);
+ const auto *FD = cast<FunctionDecl>(D);
if (!FD->getReturnType()->isVoidType()) {
SourceRange RTRange = FD->getReturnTypeSourceRange();
S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
@@ -4153,88 +4123,88 @@ static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
S.Diag(FD->getLocStart(), diag::warn_kern_is_inline) << FD;
D->addAttr(::new (S.Context)
- CUDAGlobalAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ CUDAGlobalAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- FunctionDecl *Fn = cast<FunctionDecl>(D);
+static void handleGNUInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ const auto *Fn = cast<FunctionDecl>(D);
if (!Fn->isInlineSpecified()) {
- S.Diag(Attr.getLoc(), diag::warn_gnu_inline_attribute_requires_inline);
+ S.Diag(AL.getLoc(), diag::warn_gnu_inline_attribute_requires_inline);
return;
}
D->addAttr(::new (S.Context)
- GNUInlineAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ GNUInlineAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (hasDeclarator(D)) return;
- // Diagnostic is emitted elsewhere: here we store the (valid) Attr
+ // Diagnostic is emitted elsewhere: here we store the (valid) AL
// in the Decl node for syntactic reasoning, e.g., pretty-printing.
CallingConv CC;
- if (S.CheckCallingConvAttr(Attr, CC, /*FD*/nullptr))
+ if (S.CheckCallingConvAttr(AL, CC, /*FD*/nullptr))
return;
if (!isa<ObjCMethodDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionOrMethod;
+ S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << AL.getName() << ExpectedFunctionOrMethod;
return;
}
- switch (Attr.getKind()) {
- case AttributeList::AT_FastCall:
+ switch (AL.getKind()) {
+ case ParsedAttr::AT_FastCall:
D->addAttr(::new (S.Context)
- FastCallAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ FastCallAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_StdCall:
+ case ParsedAttr::AT_StdCall:
D->addAttr(::new (S.Context)
- StdCallAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ StdCallAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_ThisCall:
+ case ParsedAttr::AT_ThisCall:
D->addAttr(::new (S.Context)
- ThisCallAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ ThisCallAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_CDecl:
+ case ParsedAttr::AT_CDecl:
D->addAttr(::new (S.Context)
- CDeclAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ CDeclAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_Pascal:
+ case ParsedAttr::AT_Pascal:
D->addAttr(::new (S.Context)
- PascalAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ PascalAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_SwiftCall:
+ case ParsedAttr::AT_SwiftCall:
D->addAttr(::new (S.Context)
- SwiftCallAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ SwiftCallAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_VectorCall:
+ case ParsedAttr::AT_VectorCall:
D->addAttr(::new (S.Context)
- VectorCallAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ VectorCallAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_MSABI:
+ case ParsedAttr::AT_MSABI:
D->addAttr(::new (S.Context)
- MSABIAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ MSABIAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_SysVABI:
+ case ParsedAttr::AT_SysVABI:
D->addAttr(::new (S.Context)
- SysVABIAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ SysVABIAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_RegCall:
+ case ParsedAttr::AT_RegCall:
D->addAttr(::new (S.Context) RegCallAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_Pcs: {
+ case ParsedAttr::AT_Pcs: {
PcsAttr::PCSType PCS;
switch (CC) {
case CC_AAPCS:
@@ -4248,37 +4218,37 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
D->addAttr(::new (S.Context)
- PcsAttr(Attr.getRange(), S.Context, PCS,
- Attr.getAttributeSpellingListIndex()));
+ PcsAttr(AL.getRange(), S.Context, PCS,
+ AL.getAttributeSpellingListIndex()));
return;
}
- case AttributeList::AT_IntelOclBicc:
+ case ParsedAttr::AT_IntelOclBicc:
D->addAttr(::new (S.Context)
- IntelOclBiccAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ IntelOclBiccAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_PreserveMost:
+ case ParsedAttr::AT_PreserveMost:
D->addAttr(::new (S.Context) PreserveMostAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_PreserveAll:
+ case ParsedAttr::AT_PreserveAll:
D->addAttr(::new (S.Context) PreserveAllAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
return;
default:
llvm_unreachable("unexpected attribute kind");
}
}
-static void handleSuppressAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+static void handleSuppressAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!checkAttributeAtLeastNumArgs(S, AL, 1))
return;
std::vector<StringRef> DiagnosticIdentifiers;
- for (unsigned I = 0, E = Attr.getNumArgs(); I != E; ++I) {
+ for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
StringRef RuleName;
- if (!S.checkStringLiteralArgumentAttr(Attr, I, RuleName, nullptr))
+ if (!S.checkStringLiteralArgumentAttr(AL, I, RuleName, nullptr))
return;
// FIXME: Warn if the rule name is unknown. This is tricky because only
@@ -4286,11 +4256,11 @@ static void handleSuppressAttr(Sema &S, Decl *D, const AttributeList &Attr) {
DiagnosticIdentifiers.push_back(RuleName);
}
D->addAttr(::new (S.Context) SuppressAttr(
- Attr.getRange(), S.Context, DiagnosticIdentifiers.data(),
- DiagnosticIdentifiers.size(), Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, DiagnosticIdentifiers.data(),
+ DiagnosticIdentifiers.size(), AL.getAttributeSpellingListIndex()));
}
-bool Sema::CheckCallingConvAttr(const AttributeList &Attrs, CallingConv &CC,
+bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
const FunctionDecl *FD) {
if (Attrs.isInvalid())
return true;
@@ -4300,7 +4270,7 @@ bool Sema::CheckCallingConvAttr(const AttributeList &Attrs, CallingConv &CC,
return false;
}
- unsigned ReqArgs = Attrs.getKind() == AttributeList::AT_Pcs ? 1 : 0;
+ unsigned ReqArgs = Attrs.getKind() == ParsedAttr::AT_Pcs ? 1 : 0;
if (!checkAttributeNumArgs(*this, Attrs, ReqArgs)) {
Attrs.setInvalid();
return true;
@@ -4308,23 +4278,39 @@ bool Sema::CheckCallingConvAttr(const AttributeList &Attrs, CallingConv &CC,
// TODO: diagnose uses of these conventions on the wrong target.
switch (Attrs.getKind()) {
- case AttributeList::AT_CDecl: CC = CC_C; break;
- case AttributeList::AT_FastCall: CC = CC_X86FastCall; break;
- case AttributeList::AT_StdCall: CC = CC_X86StdCall; break;
- case AttributeList::AT_ThisCall: CC = CC_X86ThisCall; break;
- case AttributeList::AT_Pascal: CC = CC_X86Pascal; break;
- case AttributeList::AT_SwiftCall: CC = CC_Swift; break;
- case AttributeList::AT_VectorCall: CC = CC_X86VectorCall; break;
- case AttributeList::AT_RegCall: CC = CC_X86RegCall; break;
- case AttributeList::AT_MSABI:
+ case ParsedAttr::AT_CDecl:
+ CC = CC_C;
+ break;
+ case ParsedAttr::AT_FastCall:
+ CC = CC_X86FastCall;
+ break;
+ case ParsedAttr::AT_StdCall:
+ CC = CC_X86StdCall;
+ break;
+ case ParsedAttr::AT_ThisCall:
+ CC = CC_X86ThisCall;
+ break;
+ case ParsedAttr::AT_Pascal:
+ CC = CC_X86Pascal;
+ break;
+ case ParsedAttr::AT_SwiftCall:
+ CC = CC_Swift;
+ break;
+ case ParsedAttr::AT_VectorCall:
+ CC = CC_X86VectorCall;
+ break;
+ case ParsedAttr::AT_RegCall:
+ CC = CC_X86RegCall;
+ break;
+ case ParsedAttr::AT_MSABI:
CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C :
CC_Win64;
break;
- case AttributeList::AT_SysVABI:
+ case ParsedAttr::AT_SysVABI:
CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_X86_64SysV :
CC_C;
break;
- case AttributeList::AT_Pcs: {
+ case ParsedAttr::AT_Pcs: {
StringRef StrRef;
if (!checkStringLiteralArgumentAttr(Attrs, 0, StrRef)) {
Attrs.setInvalid();
@@ -4342,9 +4328,15 @@ bool Sema::CheckCallingConvAttr(const AttributeList &Attrs, CallingConv &CC,
Diag(Attrs.getLoc(), diag::err_invalid_pcs);
return true;
}
- case AttributeList::AT_IntelOclBicc: CC = CC_IntelOclBicc; break;
- case AttributeList::AT_PreserveMost: CC = CC_PreserveMost; break;
- case AttributeList::AT_PreserveAll: CC = CC_PreserveAll; break;
+ case ParsedAttr::AT_IntelOclBicc:
+ CC = CC_IntelOclBicc;
+ break;
+ case ParsedAttr::AT_PreserveMost:
+ CC = CC_PreserveMost;
+ break;
+ case ParsedAttr::AT_PreserveAll:
+ CC = CC_PreserveAll;
+ break;
default: llvm_unreachable("unexpected attribute kind");
}
@@ -4369,39 +4361,39 @@ bool Sema::CheckCallingConvAttr(const AttributeList &Attrs, CallingConv &CC,
}
/// Pointer-like types in the default address space.
-static bool isValidSwiftContextType(QualType type) {
- if (!type->hasPointerRepresentation())
- return type->isDependentType();
- return type->getPointeeType().getAddressSpace() == LangAS::Default;
+static bool isValidSwiftContextType(QualType Ty) {
+ if (!Ty->hasPointerRepresentation())
+ return Ty->isDependentType();
+ return Ty->getPointeeType().getAddressSpace() == LangAS::Default;
}
/// Pointers and references in the default address space.
-static bool isValidSwiftIndirectResultType(QualType type) {
- if (auto ptrType = type->getAs<PointerType>()) {
- type = ptrType->getPointeeType();
- } else if (auto refType = type->getAs<ReferenceType>()) {
- type = refType->getPointeeType();
+static bool isValidSwiftIndirectResultType(QualType Ty) {
+ if (const auto *PtrType = Ty->getAs<PointerType>()) {
+ Ty = PtrType->getPointeeType();
+ } else if (const auto *RefType = Ty->getAs<ReferenceType>()) {
+ Ty = RefType->getPointeeType();
} else {
- return type->isDependentType();
+ return Ty->isDependentType();
}
- return type.getAddressSpace() == LangAS::Default;
+ return Ty.getAddressSpace() == LangAS::Default;
}
/// Pointers and references to pointers in the default address space.
-static bool isValidSwiftErrorResultType(QualType type) {
- if (auto ptrType = type->getAs<PointerType>()) {
- type = ptrType->getPointeeType();
- } else if (auto refType = type->getAs<ReferenceType>()) {
- type = refType->getPointeeType();
+static bool isValidSwiftErrorResultType(QualType Ty) {
+ if (const auto *PtrType = Ty->getAs<PointerType>()) {
+ Ty = PtrType->getPointeeType();
+ } else if (const auto *RefType = Ty->getAs<ReferenceType>()) {
+ Ty = RefType->getPointeeType();
} else {
- return type->isDependentType();
+ return Ty->isDependentType();
}
- if (!type.getQualifiers().empty())
+ if (!Ty.getQualifiers().empty())
return false;
- return isValidSwiftContextType(type);
+ return isValidSwiftContextType(Ty);
}
-static void handleParameterABIAttr(Sema &S, Decl *D, const AttributeList &Attrs,
+static void handleParameterABIAttr(Sema &S, Decl *D, const ParsedAttr &Attrs,
ParameterABI Abi) {
S.AddParameterABIAttr(Attrs.getRange(), D, Abi,
Attrs.getAttributeSpellingListIndex());
@@ -4460,34 +4452,34 @@ void Sema::AddParameterABIAttr(SourceRange range, Decl *D, ParameterABI abi,
/// Checks a regparm attribute, returning true if it is ill-formed and
/// otherwise setting numParams to the appropriate value.
-bool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) {
- if (Attr.isInvalid())
+bool Sema::CheckRegparmAttr(const ParsedAttr &AL, unsigned &numParams) {
+ if (AL.isInvalid())
return true;
- if (!checkAttributeNumArgs(*this, Attr, 1)) {
- Attr.setInvalid();
+ if (!checkAttributeNumArgs(*this, AL, 1)) {
+ AL.setInvalid();
return true;
}
uint32_t NP;
- Expr *NumParamsExpr = Attr.getArgAsExpr(0);
- if (!checkUInt32Argument(*this, Attr, NumParamsExpr, NP)) {
- Attr.setInvalid();
+ Expr *NumParamsExpr = AL.getArgAsExpr(0);
+ if (!checkUInt32Argument(*this, AL, NumParamsExpr, NP)) {
+ AL.setInvalid();
return true;
}
if (Context.getTargetInfo().getRegParmMax() == 0) {
- Diag(Attr.getLoc(), diag::err_attribute_regparm_wrong_platform)
+ Diag(AL.getLoc(), diag::err_attribute_regparm_wrong_platform)
<< NumParamsExpr->getSourceRange();
- Attr.setInvalid();
+ AL.setInvalid();
return true;
}
numParams = NP;
if (numParams > Context.getTargetInfo().getRegParmMax()) {
- Diag(Attr.getLoc(), diag::err_attribute_regparm_invalid_number)
+ Diag(AL.getLoc(), diag::err_attribute_regparm_invalid_number)
<< Context.getTargetInfo().getRegParmMax() << NumParamsExpr->getSourceRange();
- Attr.setInvalid();
+ AL.setInvalid();
return true;
}
@@ -4499,7 +4491,7 @@ bool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) {
// non-nullptr Expr result on success. Otherwise, it returns nullptr
// and may output an error.
static Expr *makeLaunchBoundsArgExpr(Sema &S, Expr *E,
- const CUDALaunchBoundsAttr &Attr,
+ const CUDALaunchBoundsAttr &AL,
const unsigned Idx) {
if (S.DiagnoseUnexpandedParameterPack(E))
return nullptr;
@@ -4512,7 +4504,7 @@ static Expr *makeLaunchBoundsArgExpr(Sema &S, Expr *E,
llvm::APSInt I(64);
if (!E->isIntegerConstantExpr(I, S.Context)) {
S.Diag(E->getExprLoc(), diag::err_attribute_argument_n_type)
- << &Attr << Idx << AANT_ArgumentIntegerConstant << E->getSourceRange();
+ << &AL << Idx << AANT_ArgumentIntegerConstant << E->getSourceRange();
return nullptr;
}
// Make sure we can fit it in 32 bits.
@@ -4523,7 +4515,7 @@ static Expr *makeLaunchBoundsArgExpr(Sema &S, Expr *E,
}
if (I < 0)
S.Diag(E->getExprLoc(), diag::warn_attribute_argument_n_negative)
- << &Attr << Idx << E->getSourceRange();
+ << &AL << Idx << E->getSourceRange();
// We may need to perform implicit conversion of the argument.
InitializedEntity Entity = InitializedEntity::InitializeParameter(
@@ -4553,253 +4545,232 @@ void Sema::AddLaunchBoundsAttr(SourceRange AttrRange, Decl *D, Expr *MaxThreads,
AttrRange, Context, MaxThreads, MinBlocks, SpellingListIndex));
}
-static void handleLaunchBoundsAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1) ||
- !checkAttributeAtMostNumArgs(S, Attr, 2))
+static void handleLaunchBoundsAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!checkAttributeAtLeastNumArgs(S, AL, 1) ||
+ !checkAttributeAtMostNumArgs(S, AL, 2))
return;
- S.AddLaunchBoundsAttr(Attr.getRange(), D, Attr.getArgAsExpr(0),
- Attr.getNumArgs() > 1 ? Attr.getArgAsExpr(1) : nullptr,
- Attr.getAttributeSpellingListIndex());
+ S.AddLaunchBoundsAttr(AL.getRange(), D, AL.getArgAsExpr(0),
+ AL.getNumArgs() > 1 ? AL.getArgAsExpr(1) : nullptr,
+ AL.getAttributeSpellingListIndex());
}
static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!Attr.isArgIdent(0)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
- << Attr.getName() << /* arg num = */ 1 << AANT_ArgumentIdentifier;
- return;
- }
-
- if (!checkAttributeNumArgs(S, Attr, 3))
- return;
-
- IdentifierInfo *ArgumentKind = Attr.getArgAsIdent(0)->Ident;
-
- if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionOrMethod;
+ const ParsedAttr &AL) {
+ if (!AL.isArgIdent(0)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
+ << AL.getName() << /* arg num = */ 1 << AANT_ArgumentIdentifier;
return;
}
- uint64_t ArgumentIdx;
- if (!checkFunctionOrMethodParameterIndex(S, D, Attr, 2, Attr.getArgAsExpr(1),
+ ParamIdx ArgumentIdx;
+ if (!checkFunctionOrMethodParameterIndex(S, D, AL, 2, AL.getArgAsExpr(1),
ArgumentIdx))
return;
- uint64_t TypeTagIdx;
- if (!checkFunctionOrMethodParameterIndex(S, D, Attr, 3, Attr.getArgAsExpr(2),
+ ParamIdx TypeTagIdx;
+ if (!checkFunctionOrMethodParameterIndex(S, D, AL, 3, AL.getArgAsExpr(2),
TypeTagIdx))
return;
- bool IsPointer = (Attr.getName()->getName() == "pointer_with_type_tag");
+ bool IsPointer = AL.getName()->getName() == "pointer_with_type_tag";
if (IsPointer) {
// Ensure that buffer has a pointer type.
- QualType BufferTy = getFunctionOrMethodParamType(D, ArgumentIdx);
- if (!BufferTy->isPointerType()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only)
- << Attr.getName() << 0;
- }
+ unsigned ArgumentIdxAST = ArgumentIdx.getASTIndex();
+ if (ArgumentIdxAST >= getFunctionOrMethodNumParams(D) ||
+ !getFunctionOrMethodParamType(D, ArgumentIdxAST)->isPointerType())
+ S.Diag(AL.getLoc(), diag::err_attribute_pointers_only)
+ << AL.getName() << 0;
}
- D->addAttr(::new (S.Context)
- ArgumentWithTypeTagAttr(Attr.getRange(), S.Context, ArgumentKind,
- ArgumentIdx, TypeTagIdx, IsPointer,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) ArgumentWithTypeTagAttr(
+ AL.getRange(), S.Context, AL.getArgAsIdent(0)->Ident, ArgumentIdx,
+ TypeTagIdx, IsPointer, AL.getAttributeSpellingListIndex()));
}
static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!Attr.isArgIdent(0)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
- << Attr.getName() << 1 << AANT_ArgumentIdentifier;
+ const ParsedAttr &AL) {
+ if (!AL.isArgIdent(0)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
+ << AL.getName() << 1 << AANT_ArgumentIdentifier;
return;
}
- if (!checkAttributeNumArgs(S, Attr, 1))
+ if (!checkAttributeNumArgs(S, AL, 1))
return;
if (!isa<VarDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedVariable;
+ S.Diag(AL.getLoc(), diag::err_attribute_wrong_decl_type)
+ << AL.getName() << ExpectedVariable;
return;
}
- IdentifierInfo *PointerKind = Attr.getArgAsIdent(0)->Ident;
+ IdentifierInfo *PointerKind = AL.getArgAsIdent(0)->Ident;
TypeSourceInfo *MatchingCTypeLoc = nullptr;
- S.GetTypeFromParser(Attr.getMatchingCType(), &MatchingCTypeLoc);
+ S.GetTypeFromParser(AL.getMatchingCType(), &MatchingCTypeLoc);
assert(MatchingCTypeLoc && "no type source info for attribute argument");
D->addAttr(::new (S.Context)
- TypeTagForDatatypeAttr(Attr.getRange(), S.Context, PointerKind,
+ TypeTagForDatatypeAttr(AL.getRange(), S.Context, PointerKind,
MatchingCTypeLoc,
- Attr.getLayoutCompatible(),
- Attr.getMustBeNull(),
- Attr.getAttributeSpellingListIndex()));
+ AL.getLayoutCompatible(),
+ AL.getMustBeNull(),
+ AL.getAttributeSpellingListIndex()));
}
-static void handleXRayLogArgsAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- uint64_t ArgCount;
+static void handleXRayLogArgsAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ ParamIdx ArgCount;
- if (!checkFunctionOrMethodParameterIndex(S, D, Attr, 1, Attr.getArgAsExpr(0),
+ if (!checkFunctionOrMethodParameterIndex(S, D, AL, 1, AL.getArgAsExpr(0),
ArgCount,
- true /* AllowImplicitThis*/))
+ true /* CanIndexImplicitThis */))
return;
- // ArgCount isn't a parameter index [0;n), it's a count [1;n] - hence + 1.
- D->addAttr(::new (S.Context)
- XRayLogArgsAttr(Attr.getRange(), S.Context, ++ArgCount,
- Attr.getAttributeSpellingListIndex()));
+ // ArgCount isn't a parameter index [0;n), it's a count [1;n]
+ D->addAttr(::new (S.Context) XRayLogArgsAttr(
+ AL.getRange(), S.Context, ArgCount.getSourceIndex(),
+ AL.getAttributeSpellingListIndex()));
}
//===----------------------------------------------------------------------===//
// Checker-specific attribute handlers.
//===----------------------------------------------------------------------===//
-static bool isValidSubjectOfNSReturnsRetainedAttribute(QualType type) {
- return type->isDependentType() ||
- type->isObjCRetainableType();
+static bool isValidSubjectOfNSReturnsRetainedAttribute(QualType QT) {
+ return QT->isDependentType() || QT->isObjCRetainableType();
}
-static bool isValidSubjectOfNSAttribute(Sema &S, QualType type) {
- return type->isDependentType() ||
- type->isObjCObjectPointerType() ||
- S.Context.isObjCNSObjectType(type);
+static bool isValidSubjectOfNSAttribute(Sema &S, QualType QT) {
+ return QT->isDependentType() || QT->isObjCObjectPointerType() ||
+ S.Context.isObjCNSObjectType(QT);
}
-static bool isValidSubjectOfCFAttribute(Sema &S, QualType type) {
- return type->isDependentType() ||
- type->isPointerType() ||
- isValidSubjectOfNSAttribute(S, type);
+static bool isValidSubjectOfCFAttribute(Sema &S, QualType QT) {
+ return QT->isDependentType() || QT->isPointerType() ||
+ isValidSubjectOfNSAttribute(S, QT);
}
-static void handleNSConsumedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- S.AddNSConsumedAttr(Attr.getRange(), D, Attr.getAttributeSpellingListIndex(),
- Attr.getKind() == AttributeList::AT_NSConsumed,
+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);
}
-void Sema::AddNSConsumedAttr(SourceRange attrRange, Decl *D,
- unsigned spellingIndex, bool isNSConsumed,
- bool isTemplateInstantiation) {
- ParmVarDecl *param = cast<ParmVarDecl>(D);
- bool typeOK;
+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());
- }
+ if (IsNSConsumed)
+ TypeOK = isValidSubjectOfNSAttribute(*this, Param->getType());
+ else
+ TypeOK = isValidSubjectOfCFAttribute(*this, Param->getType());
- if (!typeOK) {
+ 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);
+ 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);
return;
}
- if (isNSConsumed)
- param->addAttr(::new (Context)
- NSConsumedAttr(attrRange, Context, spellingIndex));
+ if (IsNSConsumed)
+ D->addAttr(::new (Context)
+ NSConsumedAttr(AttrRange, Context, SpellingIndex));
else
- param->addAttr(::new (Context)
- CFConsumedAttr(attrRange, Context, spellingIndex));
+ D->addAttr(::new (Context)
+ CFConsumedAttr(AttrRange, Context, SpellingIndex));
}
-bool Sema::checkNSReturnsRetainedReturnType(SourceLocation loc,
- QualType type) {
- if (isValidSubjectOfNSReturnsRetainedAttribute(type))
+bool Sema::checkNSReturnsRetainedReturnType(SourceLocation Loc, QualType QT) {
+ if (isValidSubjectOfNSReturnsRetainedAttribute(QT))
return false;
- Diag(loc, diag::warn_ns_attribute_wrong_return_type)
- << "'ns_returns_retained'" << 0 << 0;
+ Diag(Loc, diag::warn_ns_attribute_wrong_return_type)
+ << "'ns_returns_retained'" << 0 << 0;
return true;
}
static void handleNSReturnsRetainedAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- QualType returnType;
+ const ParsedAttr &AL) {
+ QualType ReturnType;
- if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
- returnType = MD->getReturnType();
+ if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
+ ReturnType = MD->getReturnType();
else if (S.getLangOpts().ObjCAutoRefCount && hasDeclarator(D) &&
- (Attr.getKind() == AttributeList::AT_NSReturnsRetained))
+ (AL.getKind() == ParsedAttr::AT_NSReturnsRetained))
return; // ignore: was handled as a type attribute
- else if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D))
- returnType = PD->getType();
- else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- returnType = FD->getReturnType();
- else if (auto *Param = dyn_cast<ParmVarDecl>(D)) {
- returnType = Param->getType()->getPointeeType();
- if (returnType.isNull()) {
+ else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D))
+ ReturnType = PD->getType();
+ else if (const auto *FD = dyn_cast<FunctionDecl>(D))
+ ReturnType = FD->getReturnType();
+ else if (const auto *Param = dyn_cast<ParmVarDecl>(D)) {
+ ReturnType = Param->getType()->getPointeeType();
+ if (ReturnType.isNull()) {
S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type)
- << Attr.getName() << /*pointer-to-CF*/2
- << Attr.getRange();
+ << AL.getName() << /*pointer-to-CF*/2
+ << AL.getRange();
return;
}
- } else if (Attr.isUsedAsTypeAttr()) {
+ } else if (AL.isUsedAsTypeAttr()) {
return;
} else {
AttributeDeclKind ExpectedDeclKind;
- switch (Attr.getKind()) {
+ switch (AL.getKind()) {
default: llvm_unreachable("invalid ownership attribute");
- case AttributeList::AT_NSReturnsRetained:
- case AttributeList::AT_NSReturnsAutoreleased:
- case AttributeList::AT_NSReturnsNotRetained:
+ case ParsedAttr::AT_NSReturnsRetained:
+ case ParsedAttr::AT_NSReturnsAutoreleased:
+ case ParsedAttr::AT_NSReturnsNotRetained:
ExpectedDeclKind = ExpectedFunctionOrMethod;
break;
- case AttributeList::AT_CFReturnsRetained:
- case AttributeList::AT_CFReturnsNotRetained:
+ case ParsedAttr::AT_CFReturnsRetained:
+ case ParsedAttr::AT_CFReturnsNotRetained:
ExpectedDeclKind = ExpectedFunctionMethodOrParameter;
break;
}
S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type)
- << Attr.getRange() << Attr.getName() << ExpectedDeclKind;
+ << AL.getRange() << AL.getName() << ExpectedDeclKind;
return;
}
- bool typeOK;
- bool cf;
- switch (Attr.getKind()) {
+ bool TypeOK;
+ bool Cf;
+ switch (AL.getKind()) {
default: llvm_unreachable("invalid ownership attribute");
- case AttributeList::AT_NSReturnsRetained:
- typeOK = isValidSubjectOfNSReturnsRetainedAttribute(returnType);
- cf = false;
+ case ParsedAttr::AT_NSReturnsRetained:
+ TypeOK = isValidSubjectOfNSReturnsRetainedAttribute(ReturnType);
+ Cf = false;
break;
-
- case AttributeList::AT_NSReturnsAutoreleased:
- case AttributeList::AT_NSReturnsNotRetained:
- typeOK = isValidSubjectOfNSAttribute(S, returnType);
- cf = false;
+
+ case ParsedAttr::AT_NSReturnsAutoreleased:
+ case ParsedAttr::AT_NSReturnsNotRetained:
+ TypeOK = isValidSubjectOfNSAttribute(S, ReturnType);
+ Cf = false;
break;
- case AttributeList::AT_CFReturnsRetained:
- case AttributeList::AT_CFReturnsNotRetained:
- typeOK = isValidSubjectOfCFAttribute(S, returnType);
- cf = true;
+ case ParsedAttr::AT_CFReturnsRetained:
+ case ParsedAttr::AT_CFReturnsNotRetained:
+ TypeOK = isValidSubjectOfCFAttribute(S, ReturnType);
+ Cf = true;
break;
}
- if (!typeOK) {
- if (Attr.isUsedAsTypeAttr())
+ if (!TypeOK) {
+ if (AL.isUsedAsTypeAttr())
return;
if (isa<ParmVarDecl>(D)) {
S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type)
- << Attr.getName() << /*pointer-to-CF*/2
- << Attr.getRange();
+ << AL.getName() << /*pointer-to-CF*/2
+ << AL.getRange();
} else {
// Needs to be kept in sync with warn_ns_attribute_wrong_return_type.
enum : unsigned {
@@ -4812,40 +4783,40 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D,
else if (isa<ObjCPropertyDecl>(D))
SubjectKind = Property;
S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type)
- << Attr.getName() << SubjectKind << cf
- << Attr.getRange();
+ << AL.getName() << SubjectKind << Cf
+ << AL.getRange();
}
return;
}
- switch (Attr.getKind()) {
+ switch (AL.getKind()) {
default:
llvm_unreachable("invalid ownership attribute");
- case AttributeList::AT_NSReturnsAutoreleased:
+ case ParsedAttr::AT_NSReturnsAutoreleased:
D->addAttr(::new (S.Context) NSReturnsAutoreleasedAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_CFReturnsNotRetained:
+ case ParsedAttr::AT_CFReturnsNotRetained:
D->addAttr(::new (S.Context) CFReturnsNotRetainedAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_NSReturnsNotRetained:
+ case ParsedAttr::AT_NSReturnsNotRetained:
D->addAttr(::new (S.Context) NSReturnsNotRetainedAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_CFReturnsRetained:
+ case ParsedAttr::AT_CFReturnsRetained:
D->addAttr(::new (S.Context) CFReturnsRetainedAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
return;
- case AttributeList::AT_NSReturnsRetained:
+ case ParsedAttr::AT_NSReturnsRetained:
D->addAttr(::new (S.Context) NSReturnsRetainedAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
return;
};
}
static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,
- const AttributeList &Attrs) {
+ const ParsedAttr &Attrs) {
const int EP_ObjCMethod = 1;
const int EP_ObjCProperty = 2;
@@ -4873,116 +4844,91 @@ static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,
}
static void handleObjCRequiresSuperAttr(Sema &S, Decl *D,
- const AttributeList &Attrs) {
- ObjCMethodDecl *method = cast<ObjCMethodDecl>(D);
-
- DeclContext *DC = method->getDeclContext();
- if (const ObjCProtocolDecl *PDecl = dyn_cast_or_null<ObjCProtocolDecl>(DC)) {
+ const ParsedAttr &Attrs) {
+ const auto *Method = cast<ObjCMethodDecl>(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;
+ << Attrs.getName() << 0;
S.Diag(PDecl->getLocation(), diag::note_protocol_decl);
return;
}
- if (method->getMethodFamily() == OMF_dealloc) {
+ if (Method->getMethodFamily() == OMF_dealloc) {
S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol)
- << Attrs.getName() << 1;
+ << Attrs.getName() << 1;
return;
}
-
- method->addAttr(::new (S.Context)
- ObjCRequiresSuperAttr(Attrs.getRange(), S.Context,
- Attrs.getAttributeSpellingListIndex()));
-}
-
-static void handleCFAuditedTransferAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (checkAttrMutualExclusion<CFUnknownTransferAttr>(S, D, Attr.getRange(),
- Attr.getName()))
- return;
- D->addAttr(::new (S.Context)
- CFAuditedTransferAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleCFUnknownTransferAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (checkAttrMutualExclusion<CFAuditedTransferAttr>(S, D, Attr.getRange(),
- Attr.getName()))
- return;
-
- D->addAttr(::new (S.Context)
- CFUnknownTransferAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) ObjCRequiresSuperAttr(
+ Attrs.getRange(), S.Context, Attrs.getAttributeSpellingListIndex()));
}
-static void handleObjCBridgeAttr(Sema &S, Scope *Sc, Decl *D,
- const AttributeList &Attr) {
- IdentifierLoc * Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : nullptr;
+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) << Attr.getName() << 0;
+ S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << AL.getName() << 0;
return;
}
// Typedefs only allow objc_bridge(id) and have some additional checking.
- if (auto TD = dyn_cast<TypedefNameDecl>(D)) {
+ if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
if (!Parm->Ident->isStr("id")) {
- S.Diag(Attr.getLoc(), diag::err_objc_attr_typedef_not_id)
- << Attr.getName();
+ S.Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_id)
+ << AL.getName();
return;
}
// Only allow 'cv void *'.
QualType T = TD->getUnderlyingType();
if (!T->isVoidPointerType()) {
- S.Diag(Attr.getLoc(), diag::err_objc_attr_typedef_not_void_pointer);
+ S.Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_void_pointer);
return;
}
}
D->addAttr(::new (S.Context)
- ObjCBridgeAttr(Attr.getRange(), S.Context, Parm->Ident,
- Attr.getAttributeSpellingListIndex()));
+ ObjCBridgeAttr(AL.getRange(), S.Context, Parm->Ident,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleObjCBridgeMutableAttr(Sema &S, Scope *Sc, Decl *D,
- const AttributeList &Attr) {
- IdentifierLoc * Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : nullptr;
+static void handleObjCBridgeMutableAttr(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) << Attr.getName() << 0;
+ S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << AL.getName() << 0;
return;
}
D->addAttr(::new (S.Context)
- ObjCBridgeMutableAttr(Attr.getRange(), S.Context, Parm->Ident,
- Attr.getAttributeSpellingListIndex()));
+ ObjCBridgeMutableAttr(AL.getRange(), S.Context, Parm->Ident,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleObjCBridgeRelatedAttr(Sema &S, Scope *Sc, Decl *D,
- const AttributeList &Attr) {
+static void handleObjCBridgeRelatedAttr(Sema &S, Decl *D,
+ const ParsedAttr &AL) {
IdentifierInfo *RelatedClass =
- Attr.isArgIdent(0) ? Attr.getArgAsIdent(0)->Ident : nullptr;
+ AL.isArgIdent(0) ? AL.getArgAsIdent(0)->Ident : nullptr;
if (!RelatedClass) {
- S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << Attr.getName() << 0;
+ S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << AL.getName() << 0;
return;
}
IdentifierInfo *ClassMethod =
- Attr.getArgAsIdent(1) ? Attr.getArgAsIdent(1)->Ident : nullptr;
+ AL.getArgAsIdent(1) ? AL.getArgAsIdent(1)->Ident : nullptr;
IdentifierInfo *InstanceMethod =
- Attr.getArgAsIdent(2) ? Attr.getArgAsIdent(2)->Ident : nullptr;
+ AL.getArgAsIdent(2) ? AL.getArgAsIdent(2)->Ident : nullptr;
D->addAttr(::new (S.Context)
- ObjCBridgeRelatedAttr(Attr.getRange(), S.Context, RelatedClass,
+ ObjCBridgeRelatedAttr(AL.getRange(), S.Context, RelatedClass,
ClassMethod, InstanceMethod,
- Attr.getAttributeSpellingListIndex()));
+ AL.getAttributeSpellingListIndex()));
}
static void handleObjCDesignatedInitializer(Sema &S, Decl *D,
- const AttributeList &Attr) {
+ const ParsedAttr &AL) {
ObjCInterfaceDecl *IFace;
- if (ObjCCategoryDecl *CatDecl =
- dyn_cast<ObjCCategoryDecl>(D->getDeclContext()))
+ if (auto *CatDecl = dyn_cast<ObjCCategoryDecl>(D->getDeclContext()))
IFace = CatDecl->getClassInterface();
else
IFace = cast<ObjCInterfaceDecl>(D->getDeclContext());
@@ -4992,29 +4938,28 @@ static void handleObjCDesignatedInitializer(Sema &S, Decl *D,
IFace->setHasDesignatedInitializers();
D->addAttr(::new (S.Context)
- ObjCDesignatedInitializerAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ ObjCDesignatedInitializerAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleObjCRuntimeName(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleObjCRuntimeName(Sema &S, Decl *D, const ParsedAttr &AL) {
StringRef MetaDataName;
- if (!S.checkStringLiteralArgumentAttr(Attr, 0, MetaDataName))
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, MetaDataName))
return;
D->addAttr(::new (S.Context)
- ObjCRuntimeNameAttr(Attr.getRange(), S.Context,
+ ObjCRuntimeNameAttr(AL.getRange(), S.Context,
MetaDataName,
- Attr.getAttributeSpellingListIndex()));
+ AL.getAttributeSpellingListIndex()));
}
// When a user wants to use objc_boxable with a union or struct
// but they don't have access to the declaration (legacy/third-party code)
// then they can 'enable' this feature with a typedef:
// typedef struct __attribute((objc_boxable)) legacy_struct legacy_struct;
-static void handleObjCBoxable(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleObjCBoxable(Sema &S, Decl *D, const ParsedAttr &AL) {
bool notify = false;
- RecordDecl *RD = dyn_cast<RecordDecl>(D);
+ auto *RD = dyn_cast<RecordDecl>(D);
if (RD && RD->getDefinition()) {
RD = RD->getDefinition();
notify = true;
@@ -5022,8 +4967,8 @@ static void handleObjCBoxable(Sema &S, Decl *D, const AttributeList &Attr) {
if (RD) {
ObjCBoxableAttr *BoxableAttr = ::new (S.Context)
- ObjCBoxableAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex());
+ ObjCBoxableAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex());
RD->addAttr(BoxableAttr);
if (notify) {
// we need to notify ASTReader/ASTWriter about
@@ -5034,36 +4979,35 @@ static void handleObjCBoxable(Sema &S, Decl *D, const AttributeList &Attr) {
}
}
-static void handleObjCOwnershipAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleObjCOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (hasDeclarator(D)) return;
S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
- << Attr.getRange() << Attr.getName() << ExpectedVariable;
+ << AL.getRange() << AL.getName() << ExpectedVariable;
}
static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- ValueDecl *vd = cast<ValueDecl>(D);
- QualType type = vd->getType();
+ const ParsedAttr &AL) {
+ const auto *VD = cast<ValueDecl>(D);
+ QualType QT = VD->getType();
- if (!type->isDependentType() &&
- !type->isObjCLifetimeType()) {
- S.Diag(Attr.getLoc(), diag::err_objc_precise_lifetime_bad_type)
- << type;
+ if (!QT->isDependentType() &&
+ !QT->isObjCLifetimeType()) {
+ S.Diag(AL.getLoc(), diag::err_objc_precise_lifetime_bad_type)
+ << QT;
return;
}
- Qualifiers::ObjCLifetime lifetime = type.getObjCLifetime();
+ Qualifiers::ObjCLifetime Lifetime = QT.getObjCLifetime();
// If we have no lifetime yet, check the lifetime we're presumably
// going to infer.
- if (lifetime == Qualifiers::OCL_None && !type->isDependentType())
- lifetime = type->getObjCARCImplicitLifetime();
+ if (Lifetime == Qualifiers::OCL_None && !QT->isDependentType())
+ Lifetime = QT->getObjCARCImplicitLifetime();
- switch (lifetime) {
+ switch (Lifetime) {
case Qualifiers::OCL_None:
- assert(type->isDependentType() &&
+ assert(QT->isDependentType() &&
"didn't infer lifetime for non-dependent type?");
break;
@@ -5073,14 +5017,14 @@ static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D,
case Qualifiers::OCL_ExplicitNone:
case Qualifiers::OCL_Autoreleasing:
- S.Diag(Attr.getLoc(), diag::warn_objc_precise_lifetime_meaningless)
- << (lifetime == Qualifiers::OCL_Autoreleasing);
+ S.Diag(AL.getLoc(), diag::warn_objc_precise_lifetime_meaningless)
+ << (Lifetime == Qualifiers::OCL_Autoreleasing);
break;
}
D->addAttr(::new (S.Context)
- ObjCPreciseLifetimeAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ ObjCPreciseLifetimeAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
//===----------------------------------------------------------------------===//
@@ -5100,16 +5044,16 @@ UuidAttr *Sema::mergeUuidAttr(Decl *D, SourceRange Range,
return ::new (Context) UuidAttr(Range, Context, Uuid, AttrSpellingListIndex);
}
-static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleUuidAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!S.LangOpts.CPlusPlus) {
- S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang)
- << Attr.getName() << AttributeLangSupport::C;
+ S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang)
+ << AL.getName() << AttributeLangSupport::C;
return;
}
StringRef StrRef;
SourceLocation LiteralLoc;
- if (!S.checkStringLiteralArgumentAttr(Attr, 0, StrRef, &LiteralLoc))
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, StrRef, &LiteralLoc))
return;
// GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or
@@ -5141,162 +5085,158 @@ static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// separating attributes nor of the [ and the ] are in the AST.
// Cf "SourceLocations of attribute list delimiters - [[ ... , ... ]] etc"
// on cfe-dev.
- if (Attr.isMicrosoftAttribute()) // Check for [uuid(...)] spelling.
- S.Diag(Attr.getLoc(), diag::warn_atl_uuid_deprecated);
+ if (AL.isMicrosoftAttribute()) // Check for [uuid(...)] spelling.
+ S.Diag(AL.getLoc(), diag::warn_atl_uuid_deprecated);
- UuidAttr *UA = S.mergeUuidAttr(D, Attr.getRange(),
- Attr.getAttributeSpellingListIndex(), StrRef);
+ UuidAttr *UA = S.mergeUuidAttr(D, AL.getRange(),
+ AL.getAttributeSpellingListIndex(), StrRef);
if (UA)
D->addAttr(UA);
}
-static void handleMSInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleMSInheritanceAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!S.LangOpts.CPlusPlus) {
- S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang)
- << Attr.getName() << AttributeLangSupport::C;
+ S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang)
+ << AL.getName() << AttributeLangSupport::C;
return;
}
MSInheritanceAttr *IA = S.mergeMSInheritanceAttr(
- D, Attr.getRange(), /*BestCase=*/true,
- Attr.getAttributeSpellingListIndex(),
- (MSInheritanceAttr::Spelling)Attr.getSemanticSpelling());
+ D, AL.getRange(), /*BestCase=*/true,
+ AL.getAttributeSpellingListIndex(),
+ (MSInheritanceAttr::Spelling)AL.getSemanticSpelling());
if (IA) {
D->addAttr(IA);
S.Consumer.AssignInheritanceModel(cast<CXXRecordDecl>(D));
}
}
-static void handleDeclspecThreadAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- VarDecl *VD = cast<VarDecl>(D);
+static void handleDeclspecThreadAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ const auto *VD = cast<VarDecl>(D);
if (!S.Context.getTargetInfo().isTLSSupported()) {
- S.Diag(Attr.getLoc(), diag::err_thread_unsupported);
+ S.Diag(AL.getLoc(), diag::err_thread_unsupported);
return;
}
if (VD->getTSCSpec() != TSCS_unspecified) {
- S.Diag(Attr.getLoc(), diag::err_declspec_thread_on_thread_variable);
+ S.Diag(AL.getLoc(), diag::err_declspec_thread_on_thread_variable);
return;
}
if (VD->hasLocalStorage()) {
- S.Diag(Attr.getLoc(), diag::err_thread_non_global) << "__declspec(thread)";
+ S.Diag(AL.getLoc(), diag::err_thread_non_global) << "__declspec(thread)";
return;
}
- VD->addAttr(::new (S.Context) ThreadAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) ThreadAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleAbiTagAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleAbiTagAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
SmallVector<StringRef, 4> Tags;
- for (unsigned I = 0, E = Attr.getNumArgs(); I != E; ++I) {
+ for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
StringRef Tag;
- if (!S.checkStringLiteralArgumentAttr(Attr, I, Tag))
+ if (!S.checkStringLiteralArgumentAttr(AL, I, Tag))
return;
Tags.push_back(Tag);
}
if (const auto *NS = dyn_cast<NamespaceDecl>(D)) {
if (!NS->isInline()) {
- S.Diag(Attr.getLoc(), diag::warn_attr_abi_tag_namespace) << 0;
+ S.Diag(AL.getLoc(), diag::warn_attr_abi_tag_namespace) << 0;
return;
}
if (NS->isAnonymousNamespace()) {
- S.Diag(Attr.getLoc(), diag::warn_attr_abi_tag_namespace) << 1;
+ S.Diag(AL.getLoc(), diag::warn_attr_abi_tag_namespace) << 1;
return;
}
- if (Attr.getNumArgs() == 0)
+ if (AL.getNumArgs() == 0)
Tags.push_back(NS->getName());
- } else if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+ } else if (!checkAttributeAtLeastNumArgs(S, AL, 1))
return;
// Store tags sorted and without duplicates.
- std::sort(Tags.begin(), Tags.end());
+ llvm::sort(Tags.begin(), Tags.end());
Tags.erase(std::unique(Tags.begin(), Tags.end()), Tags.end());
D->addAttr(::new (S.Context)
- AbiTagAttr(Attr.getRange(), S.Context, Tags.data(), Tags.size(),
- Attr.getAttributeSpellingListIndex()));
+ AbiTagAttr(AL.getRange(), S.Context, Tags.data(), Tags.size(),
+ AL.getAttributeSpellingListIndex()));
}
-static void handleARMInterruptAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleARMInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Check the attribute arguments.
- if (Attr.getNumArgs() > 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
- << Attr.getName() << 1;
+ if (AL.getNumArgs() > 1) {
+ S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments)
+ << AL.getName() << 1;
return;
}
StringRef Str;
SourceLocation ArgLoc;
- if (Attr.getNumArgs() == 0)
+ if (AL.getNumArgs() == 0)
Str = "";
- else if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &ArgLoc))
+ else if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
return;
ARMInterruptAttr::InterruptType Kind;
if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
- << Attr.getName() << Str << ArgLoc;
+ S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
+ << AL.getName() << Str << ArgLoc;
return;
}
- unsigned Index = Attr.getAttributeSpellingListIndex();
+ unsigned Index = AL.getAttributeSpellingListIndex();
D->addAttr(::new (S.Context)
- ARMInterruptAttr(Attr.getLoc(), S.Context, Kind, Index));
+ ARMInterruptAttr(AL.getLoc(), S.Context, Kind, Index));
}
-static void handleMSP430InterruptAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!checkAttributeNumArgs(S, Attr, 1))
+static void handleMSP430InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!checkAttributeNumArgs(S, AL, 1))
return;
- if (!Attr.isArgExpr(0)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName()
+ if (!AL.isArgExpr(0)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type) << AL.getName()
<< AANT_ArgumentIntegerConstant;
return;
}
// FIXME: Check for decl - it should be void ()(void).
- Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
+ Expr *NumParamsExpr = static_cast<Expr *>(AL.getArgAsExpr(0));
llvm::APSInt NumParams(32);
if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
- << Attr.getName() << AANT_ArgumentIntegerConstant
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
+ << AL.getName() << AANT_ArgumentIntegerConstant
<< NumParamsExpr->getSourceRange();
return;
}
unsigned Num = NumParams.getLimitedValue(255);
if ((Num & 1) || Num > 30) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << Attr.getName() << (int)NumParams.getSExtValue()
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
+ << AL.getName() << (int)NumParams.getSExtValue()
<< NumParamsExpr->getSourceRange();
return;
}
D->addAttr(::new (S.Context)
- MSP430InterruptAttr(Attr.getLoc(), S.Context, Num,
- Attr.getAttributeSpellingListIndex()));
+ MSP430InterruptAttr(AL.getLoc(), S.Context, Num,
+ AL.getAttributeSpellingListIndex()));
D->addAttr(UsedAttr::CreateImplicit(S.Context));
}
-static void handleMipsInterruptAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleMipsInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Only one optional argument permitted.
- if (Attr.getNumArgs() > 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
- << Attr.getName() << 1;
+ if (AL.getNumArgs() > 1) {
+ S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments)
+ << AL.getName() << 1;
return;
}
StringRef Str;
SourceLocation ArgLoc;
- if (Attr.getNumArgs() == 0)
+ if (AL.getNumArgs() == 0)
Str = "";
- else if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &ArgLoc))
+ else if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
return;
// Semantic checks for a function with the 'interrupt' attribute for MIPS:
@@ -5326,23 +5266,22 @@ static void handleMipsInterruptAttr(Sema &S, Decl *D,
return;
}
- if (checkAttrMutualExclusion<Mips16Attr>(S, D, Attr.getRange(),
- Attr.getName()))
+ if (checkAttrMutualExclusion<Mips16Attr>(S, D, AL.getRange(),
+ AL.getName()))
return;
MipsInterruptAttr::InterruptType Kind;
if (!MipsInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
- << Attr.getName() << "'" + std::string(Str) + "'";
+ S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
+ << AL.getName() << "'" + std::string(Str) + "'";
return;
}
D->addAttr(::new (S.Context) MipsInterruptAttr(
- Attr.getLoc(), S.Context, Kind, Attr.getAttributeSpellingListIndex()));
+ AL.getLoc(), S.Context, Kind, AL.getAttributeSpellingListIndex()));
}
-static void handleAnyX86InterruptAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleAnyX86InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Semantic checks for a function with the 'interrupt' attribute.
// a) Must be a function.
// b) Must have the 'void' return type.
@@ -5352,8 +5291,8 @@ static void handleAnyX86InterruptAttr(Sema &S, Decl *D,
if (!isFunctionOrMethod(D) || !hasFunctionProto(D) || isInstanceMethod(D) ||
CXXMethodDecl::isStaticOverloadedOperator(
cast<NamedDecl>(D)->getDeclName().getCXXOverloadedOperator())) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionWithProtoType;
+ S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << AL.getName() << ExpectedFunctionWithProtoType;
return;
}
// Interrupt handler must have void return type.
@@ -5403,182 +5342,241 @@ static void handleAnyX86InterruptAttr(Sema &S, Decl *D,
return;
}
D->addAttr(::new (S.Context) AnyX86InterruptAttr(
- Attr.getLoc(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getLoc(), S.Context, AL.getAttributeSpellingListIndex()));
D->addAttr(UsedAttr::CreateImplicit(S.Context));
}
-static void handleAVRInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleAVRInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!isFunctionOrMethod(D)) {
S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
<< "'interrupt'" << ExpectedFunction;
return;
}
- if (!checkAttributeNumArgs(S, Attr, 0))
+ if (!checkAttributeNumArgs(S, AL, 0))
return;
- handleSimpleAttribute<AVRInterruptAttr>(S, D, Attr);
+ handleSimpleAttribute<AVRInterruptAttr>(S, D, AL);
}
-static void handleAVRSignalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleAVRSignalAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!isFunctionOrMethod(D)) {
S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
<< "'signal'" << ExpectedFunction;
return;
}
- if (!checkAttributeNumArgs(S, Attr, 0))
+ if (!checkAttributeNumArgs(S, AL, 0))
+ return;
+
+ handleSimpleAttribute<AVRSignalAttr>(S, D, AL);
+}
+
+
+static void handleRISCVInterruptAttr(Sema &S, Decl *D,
+ const ParsedAttr &AL) {
+ // Warn about repeated attributes.
+ if (const auto *A = D->getAttr<RISCVInterruptAttr>()) {
+ S.Diag(AL.getRange().getBegin(),
+ diag::warn_riscv_repeated_interrupt_attribute);
+ S.Diag(A->getLocation(), diag::note_riscv_repeated_interrupt_attribute);
+ return;
+ }
+
+ // Check the attribute argument. Argument is optional.
+ if (!checkAttributeAtMostNumArgs(S, AL, 1))
+ return;
+
+ StringRef Str;
+ SourceLocation ArgLoc;
+
+ // 'machine'is the default interrupt mode.
+ if (AL.getNumArgs() == 0)
+ Str = "machine";
+ else if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
+ return;
+
+ // Semantic checks for a function with the 'interrupt' attribute:
+ // - Must be a function.
+ // - Must have no parameters.
+ // - Must have the 'void' return type.
+ // - The attribute itself must either have no argument or one of the
+ // valid interrupt types, see [RISCVInterruptDocs].
+
+ if (D->getFunctionType() == nullptr) {
+ S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
+ << "'interrupt'" << ExpectedFunction;
+ return;
+ }
+
+ if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
+ S.Diag(D->getLocation(), diag::warn_riscv_interrupt_attribute) << 0;
+ return;
+ }
+
+ if (!getFunctionOrMethodResultType(D)->isVoidType()) {
+ S.Diag(D->getLocation(), diag::warn_riscv_interrupt_attribute) << 1;
+ return;
+ }
+
+ RISCVInterruptAttr::InterruptType Kind;
+ if (!RISCVInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
+ S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
+ << AL.getName() << Str << ArgLoc;
return;
+ }
- handleSimpleAttribute<AVRSignalAttr>(S, D, Attr);
+ D->addAttr(::new (S.Context) RISCVInterruptAttr(
+ AL.getLoc(), S.Context, Kind, AL.getAttributeSpellingListIndex()));
}
-static void handleInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Dispatch the interrupt attribute based on the current target.
switch (S.Context.getTargetInfo().getTriple().getArch()) {
case llvm::Triple::msp430:
- handleMSP430InterruptAttr(S, D, Attr);
+ handleMSP430InterruptAttr(S, D, AL);
break;
case llvm::Triple::mipsel:
case llvm::Triple::mips:
- handleMipsInterruptAttr(S, D, Attr);
+ handleMipsInterruptAttr(S, D, AL);
break;
case llvm::Triple::x86:
case llvm::Triple::x86_64:
- handleAnyX86InterruptAttr(S, D, Attr);
+ handleAnyX86InterruptAttr(S, D, AL);
break;
case llvm::Triple::avr:
- handleAVRInterruptAttr(S, D, Attr);
+ handleAVRInterruptAttr(S, D, AL);
+ break;
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
+ handleRISCVInterruptAttr(S, D, AL);
break;
default:
- handleARMInterruptAttr(S, D, Attr);
+ handleARMInterruptAttr(S, D, AL);
break;
}
}
static void handleAMDGPUFlatWorkGroupSizeAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+ const ParsedAttr &AL) {
uint32_t Min = 0;
- Expr *MinExpr = Attr.getArgAsExpr(0);
- if (!checkUInt32Argument(S, Attr, MinExpr, Min))
+ Expr *MinExpr = AL.getArgAsExpr(0);
+ if (!checkUInt32Argument(S, AL, MinExpr, Min))
return;
uint32_t Max = 0;
- Expr *MaxExpr = Attr.getArgAsExpr(1);
- if (!checkUInt32Argument(S, Attr, MaxExpr, Max))
+ Expr *MaxExpr = AL.getArgAsExpr(1);
+ if (!checkUInt32Argument(S, AL, MaxExpr, Max))
return;
if (Min == 0 && Max != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_invalid)
- << Attr.getName() << 0;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid)
+ << AL.getName() << 0;
return;
}
if (Min > Max) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_invalid)
- << Attr.getName() << 1;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid)
+ << AL.getName() << 1;
return;
}
D->addAttr(::new (S.Context)
- AMDGPUFlatWorkGroupSizeAttr(Attr.getLoc(), S.Context, Min, Max,
- Attr.getAttributeSpellingListIndex()));
+ AMDGPUFlatWorkGroupSizeAttr(AL.getLoc(), S.Context, Min, Max,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleAMDGPUWavesPerEUAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleAMDGPUWavesPerEUAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
uint32_t Min = 0;
- Expr *MinExpr = Attr.getArgAsExpr(0);
- if (!checkUInt32Argument(S, Attr, MinExpr, Min))
+ Expr *MinExpr = AL.getArgAsExpr(0);
+ if (!checkUInt32Argument(S, AL, MinExpr, Min))
return;
uint32_t Max = 0;
- if (Attr.getNumArgs() == 2) {
- Expr *MaxExpr = Attr.getArgAsExpr(1);
- if (!checkUInt32Argument(S, Attr, MaxExpr, Max))
+ if (AL.getNumArgs() == 2) {
+ Expr *MaxExpr = AL.getArgAsExpr(1);
+ if (!checkUInt32Argument(S, AL, MaxExpr, Max))
return;
}
if (Min == 0 && Max != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_invalid)
- << Attr.getName() << 0;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid)
+ << AL.getName() << 0;
return;
}
if (Max != 0 && Min > Max) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_invalid)
- << Attr.getName() << 1;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid)
+ << AL.getName() << 1;
return;
}
D->addAttr(::new (S.Context)
- AMDGPUWavesPerEUAttr(Attr.getLoc(), S.Context, Min, Max,
- Attr.getAttributeSpellingListIndex()));
+ AMDGPUWavesPerEUAttr(AL.getLoc(), S.Context, Min, Max,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleAMDGPUNumSGPRAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleAMDGPUNumSGPRAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
uint32_t NumSGPR = 0;
- Expr *NumSGPRExpr = Attr.getArgAsExpr(0);
- if (!checkUInt32Argument(S, Attr, NumSGPRExpr, NumSGPR))
+ Expr *NumSGPRExpr = AL.getArgAsExpr(0);
+ if (!checkUInt32Argument(S, AL, NumSGPRExpr, NumSGPR))
return;
D->addAttr(::new (S.Context)
- AMDGPUNumSGPRAttr(Attr.getLoc(), S.Context, NumSGPR,
- Attr.getAttributeSpellingListIndex()));
+ AMDGPUNumSGPRAttr(AL.getLoc(), S.Context, NumSGPR,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
uint32_t NumVGPR = 0;
- Expr *NumVGPRExpr = Attr.getArgAsExpr(0);
- if (!checkUInt32Argument(S, Attr, NumVGPRExpr, NumVGPR))
+ Expr *NumVGPRExpr = AL.getArgAsExpr(0);
+ if (!checkUInt32Argument(S, AL, NumVGPRExpr, NumVGPR))
return;
D->addAttr(::new (S.Context)
- AMDGPUNumVGPRAttr(Attr.getLoc(), S.Context, NumVGPR,
- Attr.getAttributeSpellingListIndex()));
+ AMDGPUNumVGPRAttr(AL.getLoc(), S.Context, NumVGPR,
+ AL.getAttributeSpellingListIndex()));
}
static void handleX86ForceAlignArgPointerAttr(Sema &S, Decl *D,
- const AttributeList& Attr) {
+ const ParsedAttr &AL) {
// If we try to apply it to a function pointer, don't warn, but don't
// do anything, either. It doesn't matter anyway, because there's nothing
// special about calling a force_align_arg_pointer function.
- ValueDecl *VD = dyn_cast<ValueDecl>(D);
+ const auto *VD = dyn_cast<ValueDecl>(D);
if (VD && VD->getType()->isFunctionPointerType())
return;
// Also don't warn on function pointer typedefs.
- TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
+ const auto *TD = dyn_cast<TypedefNameDecl>(D);
if (TD && (TD->getUnderlyingType()->isFunctionPointerType() ||
TD->getUnderlyingType()->isFunctionType()))
return;
// Attribute can only be applied to function types.
if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << /* function */0;
+ S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << AL.getName() << ExpectedFunction;
return;
}
D->addAttr(::new (S.Context)
- X86ForceAlignArgPointerAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ X86ForceAlignArgPointerAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleLayoutVersion(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleLayoutVersion(Sema &S, Decl *D, const ParsedAttr &AL) {
uint32_t Version;
- Expr *VersionExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
- if (!checkUInt32Argument(S, Attr, Attr.getArgAsExpr(0), Version))
+ Expr *VersionExpr = static_cast<Expr *>(AL.getArgAsExpr(0));
+ if (!checkUInt32Argument(S, AL, AL.getArgAsExpr(0), Version))
return;
// TODO: Investigate what happens with the next major version of MSVC.
if (Version != LangOptions::MSVC2015) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << Attr.getName() << Version << VersionExpr->getSourceRange();
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
+ << AL.getName() << Version << VersionExpr->getSourceRange();
return;
}
D->addAttr(::new (S.Context)
- LayoutVersionAttr(Attr.getRange(), S.Context, Version,
- Attr.getAttributeSpellingListIndex()));
+ LayoutVersionAttr(AL.getRange(), S.Context, Version,
+ AL.getAttributeSpellingListIndex()));
}
DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range,
@@ -5607,7 +5605,7 @@ DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range,
return ::new (Context) DLLExportAttr(Range, Context, AttrSpellingListIndex);
}
-static void handleDLLAttr(Sema &S, Decl *D, const AttributeList &A) {
+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)
@@ -5615,8 +5613,8 @@ static void handleDLLAttr(Sema &S, Decl *D, const AttributeList &A) {
return;
}
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- if (FD->isInlined() && A.getKind() == AttributeList::AT_DLLImport &&
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FD->isInlined() && A.getKind() == ParsedAttr::AT_DLLImport &&
!S.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
// MinGW doesn't allow dllimport on inline functions.
S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored_on_inline)
@@ -5625,7 +5623,7 @@ static void handleDLLAttr(Sema &S, Decl *D, const AttributeList &A) {
}
}
- if (auto *MD = dyn_cast<CXXMethodDecl>(D)) {
+ 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();
@@ -5634,7 +5632,7 @@ static void handleDLLAttr(Sema &S, Decl *D, const AttributeList &A) {
}
unsigned Index = A.getAttributeSpellingListIndex();
- Attr *NewAttr = A.getKind() == AttributeList::AT_DLLExport
+ Attr *NewAttr = A.getKind() == ParsedAttr::AT_DLLExport
? (Attr *)S.mergeDLLExportAttr(D, A.getRange(), Index)
: (Attr *)S.mergeDLLImportAttr(D, A.getRange(), Index);
if (NewAttr)
@@ -5654,7 +5652,7 @@ Sema::mergeMSInheritanceAttr(Decl *D, SourceRange Range, bool BestCase,
D->dropAttr<MSInheritanceAttr>();
}
- CXXRecordDecl *RD = cast<CXXRecordDecl>(D);
+ auto *RD = cast<CXXRecordDecl>(D);
if (RD->hasDefinition()) {
if (checkMSInheritanceAttrOnDefinition(RD, Range, BestCase,
SemanticSpelling)) {
@@ -5677,7 +5675,7 @@ Sema::mergeMSInheritanceAttr(Decl *D, SourceRange Range, bool BestCase,
MSInheritanceAttr(Range, Context, BestCase, AttrSpellingListIndex);
}
-static void handleCapabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleCapabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// The capability attributes take a single string parameter for the name of
// the capability they represent. The lockable attribute does not take any
// parameters. However, semantically, both attributes represent the same
@@ -5688,8 +5686,8 @@ static void handleCapabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// literal will be considered a "mutex."
StringRef N("mutex");
SourceLocation LiteralLoc;
- if (Attr.getKind() == AttributeList::AT_Capability &&
- !S.checkStringLiteralArgumentAttr(Attr, 0, N, &LiteralLoc))
+ if (AL.getKind() == ParsedAttr::AT_Capability &&
+ !S.checkStringLiteralArgumentAttr(AL, 0, N, &LiteralLoc))
return;
// Currently, there are only two names allowed for a capability: role and
@@ -5697,80 +5695,79 @@ static void handleCapabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (!N.equals_lower("mutex") && !N.equals_lower("role"))
S.Diag(LiteralLoc, diag::warn_invalid_capability_name) << N;
- D->addAttr(::new (S.Context) CapabilityAttr(Attr.getRange(), S.Context, N,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) CapabilityAttr(AL.getRange(), S.Context, N,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleAssertCapabilityAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleAssertCapabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
SmallVector<Expr*, 1> Args;
- if (!checkLockFunAttrCommon(S, D, Attr, Args))
+ if (!checkLockFunAttrCommon(S, D, AL, Args))
return;
- D->addAttr(::new (S.Context) AssertCapabilityAttr(Attr.getRange(), S.Context,
+ D->addAttr(::new (S.Context) AssertCapabilityAttr(AL.getRange(), S.Context,
Args.data(), Args.size(),
- Attr.getAttributeSpellingListIndex()));
+ AL.getAttributeSpellingListIndex()));
}
static void handleAcquireCapabilityAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+ const ParsedAttr &AL) {
SmallVector<Expr*, 1> Args;
- if (!checkLockFunAttrCommon(S, D, Attr, Args))
+ if (!checkLockFunAttrCommon(S, D, AL, Args))
return;
- D->addAttr(::new (S.Context) AcquireCapabilityAttr(Attr.getRange(),
+ D->addAttr(::new (S.Context) AcquireCapabilityAttr(AL.getRange(),
S.Context,
Args.data(), Args.size(),
- Attr.getAttributeSpellingListIndex()));
+ AL.getAttributeSpellingListIndex()));
}
static void handleTryAcquireCapabilityAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+ const ParsedAttr &AL) {
SmallVector<Expr*, 2> Args;
- if (!checkTryLockFunAttrCommon(S, D, Attr, Args))
+ if (!checkTryLockFunAttrCommon(S, D, AL, Args))
return;
- D->addAttr(::new (S.Context) TryAcquireCapabilityAttr(Attr.getRange(),
+ D->addAttr(::new (S.Context) TryAcquireCapabilityAttr(AL.getRange(),
S.Context,
- Attr.getArgAsExpr(0),
+ AL.getArgAsExpr(0),
Args.data(),
Args.size(),
- Attr.getAttributeSpellingListIndex()));
+ AL.getAttributeSpellingListIndex()));
}
static void handleReleaseCapabilityAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+ const ParsedAttr &AL) {
// Check that all arguments are lockable objects.
SmallVector<Expr *, 1> Args;
- checkAttrArgsAreCapabilityObjs(S, D, Attr, Args, 0, true);
+ checkAttrArgsAreCapabilityObjs(S, D, AL, Args, 0, true);
D->addAttr(::new (S.Context) ReleaseCapabilityAttr(
- Attr.getRange(), S.Context, Args.data(), Args.size(),
- Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, Args.data(), Args.size(),
+ AL.getAttributeSpellingListIndex()));
}
static void handleRequiresCapabilityAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+ const ParsedAttr &AL) {
+ if (!checkAttributeAtLeastNumArgs(S, AL, 1))
return;
// check that all arguments are lockable objects
SmallVector<Expr*, 1> Args;
- checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
+ checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
if (Args.empty())
return;
RequiresCapabilityAttr *RCA = ::new (S.Context)
- RequiresCapabilityAttr(Attr.getRange(), S.Context, Args.data(),
- Args.size(), Attr.getAttributeSpellingListIndex());
+ RequiresCapabilityAttr(AL.getRange(), S.Context, Args.data(),
+ Args.size(), AL.getAttributeSpellingListIndex());
D->addAttr(RCA);
}
-static void handleDeprecatedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (auto *NSD = dyn_cast<NamespaceDecl>(D)) {
+static void handleDeprecatedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (const auto *NSD = dyn_cast<NamespaceDecl>(D)) {
if (NSD->isAnonymousNamespace()) {
- S.Diag(Attr.getLoc(), diag::warn_deprecated_anonymous_namespace);
+ S.Diag(AL.getLoc(), diag::warn_deprecated_anonymous_namespace);
// Do not want to attach the attribute to the namespace because that will
// cause confusing diagnostic reports for uses of declarations within the
// namespace.
@@ -5780,25 +5777,25 @@ static void handleDeprecatedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// Handle the cases where the attribute has a text message.
StringRef Str, Replacement;
- if (Attr.isArgExpr(0) && Attr.getArgAsExpr(0) &&
- !S.checkStringLiteralArgumentAttr(Attr, 0, Str))
+ if (AL.isArgExpr(0) && AL.getArgAsExpr(0) &&
+ !S.checkStringLiteralArgumentAttr(AL, 0, Str))
return;
// Only support a single optional message for Declspec and CXX11.
- if (Attr.isDeclspecAttribute() || Attr.isCXX11Attribute())
- checkAttributeAtMostNumArgs(S, Attr, 1);
- else if (Attr.isArgExpr(1) && Attr.getArgAsExpr(1) &&
- !S.checkStringLiteralArgumentAttr(Attr, 1, Replacement))
+ if (AL.isDeclspecAttribute() || AL.isCXX11Attribute())
+ checkAttributeAtMostNumArgs(S, AL, 1);
+ else if (AL.isArgExpr(1) && AL.getArgAsExpr(1) &&
+ !S.checkStringLiteralArgumentAttr(AL, 1, Replacement))
return;
if (!S.getLangOpts().CPlusPlus14)
- if (Attr.isCXX11Attribute() &&
- !(Attr.hasScope() && Attr.getScopeName()->isStr("gnu")))
- S.Diag(Attr.getLoc(), diag::ext_cxx14_attr) << Attr.getName();
+ if (AL.isCXX11Attribute() &&
+ !(AL.hasScope() && AL.getScopeName()->isStr("gnu")))
+ S.Diag(AL.getLoc(), diag::ext_cxx14_attr) << AL.getName();
D->addAttr(::new (S.Context)
- DeprecatedAttr(Attr.getRange(), S.Context, Str, Replacement,
- Attr.getAttributeSpellingListIndex()));
+ DeprecatedAttr(AL.getRange(), S.Context, Str, Replacement,
+ AL.getAttributeSpellingListIndex()));
}
static bool isGlobalVar(const Decl *D) {
@@ -5807,35 +5804,35 @@ static bool isGlobalVar(const Decl *D) {
return false;
}
-static void handleNoSanitizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+static void handleNoSanitizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!checkAttributeAtLeastNumArgs(S, AL, 1))
return;
std::vector<StringRef> Sanitizers;
- for (unsigned I = 0, E = Attr.getNumArgs(); I != E; ++I) {
+ for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
StringRef SanitizerName;
SourceLocation LiteralLoc;
- if (!S.checkStringLiteralArgumentAttr(Attr, I, SanitizerName, &LiteralLoc))
+ if (!S.checkStringLiteralArgumentAttr(AL, I, SanitizerName, &LiteralLoc))
return;
if (parseSanitizerValue(SanitizerName, /*AllowGroups=*/true) == 0)
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)
- << Attr.getName() << ExpectedFunctionOrMethod;
+ << AL.getName() << ExpectedFunctionOrMethod;
Sanitizers.push_back(SanitizerName);
}
D->addAttr(::new (S.Context) NoSanitizeAttr(
- Attr.getRange(), S.Context, Sanitizers.data(), Sanitizers.size(),
- Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, Sanitizers.data(), Sanitizers.size(),
+ AL.getAttributeSpellingListIndex()));
}
static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- StringRef AttrName = Attr.getName()->getName();
+ const ParsedAttr &AL) {
+ StringRef AttrName = AL.getName()->getName();
normalizeName(AttrName);
StringRef SanitizerName = llvm::StringSwitch<StringRef>(AttrName)
.Case("no_address_safety_analysis", "address")
@@ -5844,77 +5841,78 @@ 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)
- << Attr.getName() << ExpectedFunction;
+ << AL.getName() << ExpectedFunction;
D->addAttr(::new (S.Context)
- NoSanitizeAttr(Attr.getRange(), S.Context, &SanitizerName, 1,
- Attr.getAttributeSpellingListIndex()));
+ NoSanitizeAttr(AL.getRange(), S.Context, &SanitizerName, 1,
+ AL.getAttributeSpellingListIndex()));
}
-static void handleInternalLinkageAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleInternalLinkageAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (InternalLinkageAttr *Internal =
- S.mergeInternalLinkageAttr(D, Attr.getRange(), Attr.getName(),
- Attr.getAttributeSpellingListIndex()))
+ S.mergeInternalLinkageAttr(D, AL.getRange(), AL.getName(),
+ AL.getAttributeSpellingListIndex()))
D->addAttr(Internal);
}
-static void handleOpenCLNoSVMAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+static void handleOpenCLNoSVMAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (S.LangOpts.OpenCLVersion != 200)
- S.Diag(Attr.getLoc(), diag::err_attribute_requires_opencl_version)
- << Attr.getName() << "2.0" << 0;
+ S.Diag(AL.getLoc(), diag::err_attribute_requires_opencl_version)
+ << AL.getName() << "2.0" << 0;
else
- S.Diag(Attr.getLoc(), diag::warn_opencl_attr_deprecated_ignored)
- << Attr.getName() << "2.0";
+ S.Diag(AL.getLoc(), diag::warn_opencl_attr_deprecated_ignored)
+ << AL.getName() << "2.0";
}
/// Handles semantic checking for features that are common to all attributes,
/// such as checking whether a parameter was properly specified, or the correct
/// number of arguments were passed, etc.
-static bool handleCommonAttributeFeatures(Sema &S, Scope *scope, Decl *D,
- const AttributeList &Attr) {
+static bool handleCommonAttributeFeatures(Sema &S, Decl *D,
+ const ParsedAttr &AL) {
// Several attributes carry different semantics than the parsing requires, so
// those are opted out of the common argument checks.
//
// We also bail on unknown and ignored attributes because those are handled
// as part of the target-specific handling logic.
- if (Attr.getKind() == AttributeList::UnknownAttribute)
+ if (AL.getKind() == ParsedAttr::UnknownAttribute)
return false;
// Check whether the attribute requires specific language extensions to be
// enabled.
- if (!Attr.diagnoseLangOpts(S))
+ if (!AL.diagnoseLangOpts(S))
return true;
// Check whether the attribute appertains to the given subject.
- if (!Attr.diagnoseAppertainsTo(S, D))
+ if (!AL.diagnoseAppertainsTo(S, D))
return true;
- if (Attr.hasCustomParsing())
+ if (AL.hasCustomParsing())
return false;
- if (Attr.getMinArgs() == Attr.getMaxArgs()) {
+ if (AL.getMinArgs() == AL.getMaxArgs()) {
// If there are no optional arguments, then checking for the argument count
// is trivial.
- if (!checkAttributeNumArgs(S, Attr, Attr.getMinArgs()))
+ if (!checkAttributeNumArgs(S, AL, AL.getMinArgs()))
return true;
} else {
// There are optional arguments, so checking is slightly more involved.
- if (Attr.getMinArgs() &&
- !checkAttributeAtLeastNumArgs(S, Attr, Attr.getMinArgs()))
+ if (AL.getMinArgs() &&
+ !checkAttributeAtLeastNumArgs(S, AL, AL.getMinArgs()))
return true;
- else if (!Attr.hasVariadicArg() && Attr.getMaxArgs() &&
- !checkAttributeAtMostNumArgs(S, Attr, Attr.getMaxArgs()))
+ else if (!AL.hasVariadicArg() && AL.getMaxArgs() &&
+ !checkAttributeAtMostNumArgs(S, AL, AL.getMaxArgs()))
return true;
}
+ if (S.CheckAttrTarget(AL))
+ return true;
+
return false;
}
-static void handleOpenCLAccessAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleOpenCLAccessAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (D->isInvalidDecl())
return;
// Check if there is only one access qualifier.
if (D->hasAttr<OpenCLAccessAttr>()) {
- S.Diag(Attr.getLoc(), diag::err_opencl_multiple_access_qualifiers)
+ S.Diag(AL.getLoc(), diag::err_opencl_multiple_access_qualifiers)
<< D->getSourceRange();
D->setInvalidDecl(true);
return;
@@ -5925,12 +5923,12 @@ static void handleOpenCLAccessAttr(Sema &S, Decl *D,
// OpenCL v2.0 s6.13.6 - A kernel cannot read from and write to the same pipe
// object. Using the read_write (or __read_write) qualifier with the pipe
// qualifier is a compilation error.
- if (const ParmVarDecl *PDecl = dyn_cast<ParmVarDecl>(D)) {
+ if (const auto *PDecl = dyn_cast<ParmVarDecl>(D)) {
const Type *DeclTy = PDecl->getType().getCanonicalType().getTypePtr();
- if (Attr.getName()->getName().find("read_write") != StringRef::npos) {
+ if (AL.getName()->getName().find("read_write") != StringRef::npos) {
if (S.getLangOpts().OpenCLVersion < 200 || DeclTy->isPipeType()) {
- S.Diag(Attr.getLoc(), diag::err_opencl_invalid_read_write)
- << Attr.getName() << PDecl->getType() << DeclTy->isImageType();
+ S.Diag(AL.getLoc(), diag::err_opencl_invalid_read_write)
+ << AL.getName() << PDecl->getType() << DeclTy->isImageType();
D->setInvalidDecl(true);
return;
}
@@ -5938,7 +5936,7 @@ static void handleOpenCLAccessAttr(Sema &S, Decl *D,
}
D->addAttr(::new (S.Context) OpenCLAccessAttr(
- Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
}
//===----------------------------------------------------------------------===//
@@ -5949,633 +5947,659 @@ static void handleOpenCLAccessAttr(Sema &S, Decl *D,
/// the attribute applies to decls. If the attribute is a type attribute, just
/// silently ignore it if a GNU attribute.
static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
- const AttributeList &Attr,
+ const ParsedAttr &AL,
bool IncludeCXX11Attributes) {
- if (Attr.isInvalid() || Attr.getKind() == AttributeList::IgnoredAttribute)
+ if (AL.isInvalid() || AL.getKind() == ParsedAttr::IgnoredAttribute)
return;
// Ignore C++11 attributes on declarator chunks: they appertain to the type
// instead.
- if (Attr.isCXX11Attribute() && !IncludeCXX11Attributes)
+ if (AL.isCXX11Attribute() && !IncludeCXX11Attributes)
return;
// Unknown attributes are automatically warned on. Target-specific attributes
// which do not apply to the current target architecture are treated as
// though they were unknown attributes.
- if (Attr.getKind() == AttributeList::UnknownAttribute ||
- !Attr.existsInTarget(S.Context.getTargetInfo())) {
- S.Diag(Attr.getLoc(), Attr.isDeclspecAttribute()
- ? diag::warn_unhandled_ms_attribute_ignored
- : diag::warn_unknown_attribute_ignored)
- << Attr.getName();
+ 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();
return;
}
- if (handleCommonAttributeFeatures(S, scope, D, Attr))
+ if (handleCommonAttributeFeatures(S, D, AL))
return;
- switch (Attr.getKind()) {
+ switch (AL.getKind()) {
default:
- if (!Attr.isStmtAttr()) {
+ if (!AL.isStmtAttr()) {
// Type attributes are handled elsewhere; silently move on.
- assert(Attr.isTypeAttr() && "Non-type attribute not handled");
+ assert(AL.isTypeAttr() && "Non-type attribute not handled");
break;
}
- S.Diag(Attr.getLoc(), diag::err_stmt_attribute_invalid_on_decl)
- << Attr.getName() << D->getLocation();
+ S.Diag(AL.getLoc(), diag::err_stmt_attribute_invalid_on_decl)
+ << AL.getName() << D->getLocation();
break;
- case AttributeList::AT_Interrupt:
- handleInterruptAttr(S, D, Attr);
+ case ParsedAttr::AT_Interrupt:
+ handleInterruptAttr(S, D, AL);
break;
- case AttributeList::AT_X86ForceAlignArgPointer:
- handleX86ForceAlignArgPointerAttr(S, D, Attr);
+ case ParsedAttr::AT_X86ForceAlignArgPointer:
+ handleX86ForceAlignArgPointerAttr(S, D, AL);
break;
- case AttributeList::AT_DLLExport:
- case AttributeList::AT_DLLImport:
- handleDLLAttr(S, D, Attr);
+ case ParsedAttr::AT_DLLExport:
+ case ParsedAttr::AT_DLLImport:
+ handleDLLAttr(S, D, AL);
break;
- case AttributeList::AT_Mips16:
+ case ParsedAttr::AT_Mips16:
handleSimpleAttributeWithExclusions<Mips16Attr, MicroMipsAttr,
- MipsInterruptAttr>(S, D, Attr);
+ MipsInterruptAttr>(S, D, AL);
break;
- case AttributeList::AT_NoMips16:
- handleSimpleAttribute<NoMips16Attr>(S, D, Attr);
+ case ParsedAttr::AT_NoMips16:
+ handleSimpleAttribute<NoMips16Attr>(S, D, AL);
break;
- case AttributeList::AT_MicroMips:
- handleSimpleAttributeWithExclusions<MicroMipsAttr, Mips16Attr>(S, D, Attr);
+ case ParsedAttr::AT_MicroMips:
+ handleSimpleAttributeWithExclusions<MicroMipsAttr, Mips16Attr>(S, D, AL);
break;
- case AttributeList::AT_NoMicroMips:
- handleSimpleAttribute<NoMicroMipsAttr>(S, D, Attr);
+ case ParsedAttr::AT_NoMicroMips:
+ handleSimpleAttribute<NoMicroMipsAttr>(S, D, AL);
break;
- case AttributeList::AT_MipsLongCall:
+ case ParsedAttr::AT_MipsLongCall:
handleSimpleAttributeWithExclusions<MipsLongCallAttr, MipsShortCallAttr>(
- S, D, Attr);
+ S, D, AL);
break;
- case AttributeList::AT_MipsShortCall:
+ case ParsedAttr::AT_MipsShortCall:
handleSimpleAttributeWithExclusions<MipsShortCallAttr, MipsLongCallAttr>(
- S, D, Attr);
+ S, D, AL);
+ break;
+ case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:
+ handleAMDGPUFlatWorkGroupSizeAttr(S, D, AL);
+ break;
+ case ParsedAttr::AT_AMDGPUWavesPerEU:
+ handleAMDGPUWavesPerEUAttr(S, D, AL);
break;
- case AttributeList::AT_AMDGPUFlatWorkGroupSize:
- handleAMDGPUFlatWorkGroupSizeAttr(S, D, Attr);
+ case ParsedAttr::AT_AMDGPUNumSGPR:
+ handleAMDGPUNumSGPRAttr(S, D, AL);
break;
- case AttributeList::AT_AMDGPUWavesPerEU:
- handleAMDGPUWavesPerEUAttr(S, D, Attr);
+ case ParsedAttr::AT_AMDGPUNumVGPR:
+ handleAMDGPUNumVGPRAttr(S, D, AL);
break;
- case AttributeList::AT_AMDGPUNumSGPR:
- handleAMDGPUNumSGPRAttr(S, D, Attr);
+ case ParsedAttr::AT_AVRSignal:
+ handleAVRSignalAttr(S, D, AL);
break;
- case AttributeList::AT_AMDGPUNumVGPR:
- handleAMDGPUNumVGPRAttr(S, D, Attr);
+ case ParsedAttr::AT_IBAction:
+ handleSimpleAttribute<IBActionAttr>(S, D, AL);
break;
- case AttributeList::AT_AVRSignal:
- handleAVRSignalAttr(S, D, Attr);
+ case ParsedAttr::AT_IBOutlet:
+ handleIBOutlet(S, D, AL);
break;
- case AttributeList::AT_IBAction:
- handleSimpleAttribute<IBActionAttr>(S, D, Attr);
+ case ParsedAttr::AT_IBOutletCollection:
+ handleIBOutletCollection(S, D, AL);
break;
- case AttributeList::AT_IBOutlet:
- handleIBOutlet(S, D, Attr);
+ case ParsedAttr::AT_IFunc:
+ handleIFuncAttr(S, D, AL);
break;
- case AttributeList::AT_IBOutletCollection:
- handleIBOutletCollection(S, D, Attr);
+ case ParsedAttr::AT_Alias:
+ handleAliasAttr(S, D, AL);
break;
- case AttributeList::AT_IFunc:
- handleIFuncAttr(S, D, Attr);
+ case ParsedAttr::AT_Aligned:
+ handleAlignedAttr(S, D, AL);
break;
- case AttributeList::AT_Alias:
- handleAliasAttr(S, D, Attr);
+ case ParsedAttr::AT_AlignValue:
+ handleAlignValueAttr(S, D, AL);
break;
- case AttributeList::AT_Aligned:
- handleAlignedAttr(S, D, Attr);
+ case ParsedAttr::AT_AllocSize:
+ handleAllocSizeAttr(S, D, AL);
break;
- case AttributeList::AT_AlignValue:
- handleAlignValueAttr(S, D, Attr);
+ case ParsedAttr::AT_AlwaysInline:
+ handleAlwaysInlineAttr(S, D, AL);
break;
- case AttributeList::AT_AllocSize:
- handleAllocSizeAttr(S, D, Attr);
+ case ParsedAttr::AT_Artificial:
+ handleSimpleAttribute<ArtificialAttr>(S, D, AL);
break;
- case AttributeList::AT_AlwaysInline:
- handleAlwaysInlineAttr(S, D, Attr);
+ case ParsedAttr::AT_AnalyzerNoReturn:
+ handleAnalyzerNoReturnAttr(S, D, AL);
break;
- case AttributeList::AT_AnalyzerNoReturn:
- handleAnalyzerNoReturnAttr(S, D, Attr);
+ case ParsedAttr::AT_TLSModel:
+ handleTLSModelAttr(S, D, AL);
break;
- case AttributeList::AT_TLSModel:
- handleTLSModelAttr(S, D, Attr);
+ case ParsedAttr::AT_Annotate:
+ handleAnnotateAttr(S, D, AL);
break;
- case AttributeList::AT_Annotate:
- handleAnnotateAttr(S, D, Attr);
+ case ParsedAttr::AT_Availability:
+ handleAvailabilityAttr(S, D, AL);
break;
- case AttributeList::AT_Availability:
- handleAvailabilityAttr(S, D, Attr);
+ case ParsedAttr::AT_CarriesDependency:
+ handleDependencyAttr(S, scope, D, AL);
break;
- case AttributeList::AT_CarriesDependency:
- handleDependencyAttr(S, scope, D, Attr);
+ case ParsedAttr::AT_CPUDispatch:
+ case ParsedAttr::AT_CPUSpecific:
+ handleCPUSpecificAttr(S, D, AL);
break;
- case AttributeList::AT_Common:
- handleCommonAttr(S, D, Attr);
+ case ParsedAttr::AT_Common:
+ handleCommonAttr(S, D, AL);
break;
- case AttributeList::AT_CUDAConstant:
- handleConstantAttr(S, D, Attr);
+ case ParsedAttr::AT_CUDAConstant:
+ handleConstantAttr(S, D, AL);
break;
- case AttributeList::AT_PassObjectSize:
- handlePassObjectSizeAttr(S, D, Attr);
+ case ParsedAttr::AT_PassObjectSize:
+ handlePassObjectSizeAttr(S, D, AL);
break;
- case AttributeList::AT_Constructor:
- handleConstructorAttr(S, D, Attr);
+ case ParsedAttr::AT_Constructor:
+ handleConstructorAttr(S, D, AL);
break;
- case AttributeList::AT_CXX11NoReturn:
- handleSimpleAttribute<CXX11NoReturnAttr>(S, D, Attr);
+ case ParsedAttr::AT_CXX11NoReturn:
+ handleSimpleAttribute<CXX11NoReturnAttr>(S, D, AL);
break;
- case AttributeList::AT_Deprecated:
- handleDeprecatedAttr(S, D, Attr);
+ case ParsedAttr::AT_Deprecated:
+ handleDeprecatedAttr(S, D, AL);
break;
- case AttributeList::AT_Destructor:
- handleDestructorAttr(S, D, Attr);
+ case ParsedAttr::AT_Destructor:
+ handleDestructorAttr(S, D, AL);
break;
- case AttributeList::AT_EnableIf:
- handleEnableIfAttr(S, D, Attr);
+ case ParsedAttr::AT_EnableIf:
+ handleEnableIfAttr(S, D, AL);
break;
- case AttributeList::AT_DiagnoseIf:
- handleDiagnoseIfAttr(S, D, Attr);
+ case ParsedAttr::AT_DiagnoseIf:
+ handleDiagnoseIfAttr(S, D, AL);
break;
- case AttributeList::AT_ExtVectorType:
- handleExtVectorTypeAttr(S, scope, D, Attr);
+ case ParsedAttr::AT_ExtVectorType:
+ handleExtVectorTypeAttr(S, D, AL);
break;
- case AttributeList::AT_ExternalSourceSymbol:
- handleExternalSourceSymbolAttr(S, D, Attr);
+ case ParsedAttr::AT_ExternalSourceSymbol:
+ handleExternalSourceSymbolAttr(S, D, AL);
break;
- case AttributeList::AT_MinSize:
- handleMinSizeAttr(S, D, Attr);
+ case ParsedAttr::AT_MinSize:
+ handleMinSizeAttr(S, D, AL);
break;
- case AttributeList::AT_OptimizeNone:
- handleOptimizeNoneAttr(S, D, Attr);
+ case ParsedAttr::AT_OptimizeNone:
+ handleOptimizeNoneAttr(S, D, AL);
break;
- case AttributeList::AT_FlagEnum:
- handleSimpleAttribute<FlagEnumAttr>(S, D, Attr);
+ case ParsedAttr::AT_FlagEnum:
+ handleSimpleAttribute<FlagEnumAttr>(S, D, AL);
break;
- case AttributeList::AT_EnumExtensibility:
- handleEnumExtensibilityAttr(S, D, Attr);
+ case ParsedAttr::AT_EnumExtensibility:
+ handleEnumExtensibilityAttr(S, D, AL);
break;
- case AttributeList::AT_Flatten:
- handleSimpleAttribute<FlattenAttr>(S, D, Attr);
+ case ParsedAttr::AT_Flatten:
+ handleSimpleAttribute<FlattenAttr>(S, D, AL);
break;
- case AttributeList::AT_Format:
- handleFormatAttr(S, D, Attr);
+ case ParsedAttr::AT_Format:
+ handleFormatAttr(S, D, AL);
break;
- case AttributeList::AT_FormatArg:
- handleFormatArgAttr(S, D, Attr);
+ case ParsedAttr::AT_FormatArg:
+ handleFormatArgAttr(S, D, AL);
break;
- case AttributeList::AT_CUDAGlobal:
- handleGlobalAttr(S, D, Attr);
+ case ParsedAttr::AT_CUDAGlobal:
+ handleGlobalAttr(S, D, AL);
break;
- case AttributeList::AT_CUDADevice:
+ case ParsedAttr::AT_CUDADevice:
handleSimpleAttributeWithExclusions<CUDADeviceAttr, CUDAGlobalAttr>(S, D,
- Attr);
+ AL);
break;
- case AttributeList::AT_CUDAHost:
- handleSimpleAttributeWithExclusions<CUDAHostAttr, CUDAGlobalAttr>(S, D,
- Attr);
+ case ParsedAttr::AT_CUDAHost:
+ handleSimpleAttributeWithExclusions<CUDAHostAttr, CUDAGlobalAttr>(S, D, AL);
break;
- case AttributeList::AT_GNUInline:
- handleGNUInlineAttr(S, D, Attr);
+ case ParsedAttr::AT_GNUInline:
+ handleGNUInlineAttr(S, D, AL);
break;
- case AttributeList::AT_CUDALaunchBounds:
- handleLaunchBoundsAttr(S, D, Attr);
+ case ParsedAttr::AT_CUDALaunchBounds:
+ handleLaunchBoundsAttr(S, D, AL);
break;
- case AttributeList::AT_Restrict:
- handleRestrictAttr(S, D, Attr);
+ case ParsedAttr::AT_Restrict:
+ handleRestrictAttr(S, D, AL);
break;
- case AttributeList::AT_MayAlias:
- handleSimpleAttribute<MayAliasAttr>(S, D, Attr);
+ case ParsedAttr::AT_MayAlias:
+ handleSimpleAttribute<MayAliasAttr>(S, D, AL);
break;
- case AttributeList::AT_Mode:
- handleModeAttr(S, D, Attr);
+ case ParsedAttr::AT_Mode:
+ handleModeAttr(S, D, AL);
break;
- case AttributeList::AT_NoAlias:
- handleSimpleAttribute<NoAliasAttr>(S, D, Attr);
+ case ParsedAttr::AT_NoAlias:
+ handleSimpleAttribute<NoAliasAttr>(S, D, AL);
break;
- case AttributeList::AT_NoCommon:
- handleSimpleAttribute<NoCommonAttr>(S, D, Attr);
+ case ParsedAttr::AT_NoCommon:
+ handleSimpleAttribute<NoCommonAttr>(S, D, AL);
break;
- case AttributeList::AT_NoSplitStack:
- handleSimpleAttribute<NoSplitStackAttr>(S, D, Attr);
+ case ParsedAttr::AT_NoSplitStack:
+ handleSimpleAttribute<NoSplitStackAttr>(S, D, AL);
break;
- case AttributeList::AT_NonNull:
- if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(D))
- handleNonNullAttrParameter(S, PVD, Attr);
+ case ParsedAttr::AT_NonNull:
+ if (auto *PVD = dyn_cast<ParmVarDecl>(D))
+ handleNonNullAttrParameter(S, PVD, AL);
else
- handleNonNullAttr(S, D, Attr);
+ handleNonNullAttr(S, D, AL);
+ break;
+ case ParsedAttr::AT_ReturnsNonNull:
+ handleReturnsNonNullAttr(S, D, AL);
+ break;
+ case ParsedAttr::AT_NoEscape:
+ handleNoEscapeAttr(S, D, AL);
break;
- case AttributeList::AT_ReturnsNonNull:
- handleReturnsNonNullAttr(S, D, Attr);
+ case ParsedAttr::AT_AssumeAligned:
+ handleAssumeAlignedAttr(S, D, AL);
break;
- case AttributeList::AT_NoEscape:
- handleNoEscapeAttr(S, D, Attr);
+ case ParsedAttr::AT_AllocAlign:
+ handleAllocAlignAttr(S, D, AL);
break;
- case AttributeList::AT_AssumeAligned:
- handleAssumeAlignedAttr(S, D, Attr);
+ case ParsedAttr::AT_Overloadable:
+ handleSimpleAttribute<OverloadableAttr>(S, D, AL);
break;
- case AttributeList::AT_AllocAlign:
- handleAllocAlignAttr(S, D, Attr);
+ case ParsedAttr::AT_Ownership:
+ handleOwnershipAttr(S, D, AL);
break;
- case AttributeList::AT_Overloadable:
- handleSimpleAttribute<OverloadableAttr>(S, D, Attr);
+ case ParsedAttr::AT_Cold:
+ handleSimpleAttributeWithExclusions<ColdAttr, HotAttr>(S, D, AL);
break;
- case AttributeList::AT_Ownership:
- handleOwnershipAttr(S, D, Attr);
+ case ParsedAttr::AT_Hot:
+ handleSimpleAttributeWithExclusions<HotAttr, ColdAttr>(S, D, AL);
break;
- case AttributeList::AT_Cold:
- handleColdAttr(S, D, Attr);
+ case ParsedAttr::AT_Naked:
+ handleNakedAttr(S, D, AL);
break;
- case AttributeList::AT_Hot:
- handleHotAttr(S, D, Attr);
+ case ParsedAttr::AT_NoReturn:
+ handleNoReturnAttr(S, D, AL);
break;
- case AttributeList::AT_Naked:
- handleNakedAttr(S, D, Attr);
+ case ParsedAttr::AT_AnyX86NoCfCheck:
+ handleNoCfCheckAttr(S, D, AL);
break;
- case AttributeList::AT_NoReturn:
- handleNoReturnAttr(S, D, Attr);
+ case ParsedAttr::AT_NoThrow:
+ handleSimpleAttribute<NoThrowAttr>(S, D, AL);
break;
- case AttributeList::AT_NoThrow:
- handleSimpleAttribute<NoThrowAttr>(S, D, Attr);
+ case ParsedAttr::AT_CUDAShared:
+ handleSharedAttr(S, D, AL);
break;
- case AttributeList::AT_CUDAShared:
- handleSharedAttr(S, D, Attr);
+ case ParsedAttr::AT_VecReturn:
+ handleVecReturnAttr(S, D, AL);
break;
- case AttributeList::AT_VecReturn:
- handleVecReturnAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCOwnership:
+ handleObjCOwnershipAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCOwnership:
- handleObjCOwnershipAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCPreciseLifetime:
+ handleObjCPreciseLifetimeAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCPreciseLifetime:
- handleObjCPreciseLifetimeAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCReturnsInnerPointer:
+ handleObjCReturnsInnerPointerAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCReturnsInnerPointer:
- handleObjCReturnsInnerPointerAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCRequiresSuper:
+ handleObjCRequiresSuperAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCRequiresSuper:
- handleObjCRequiresSuperAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCBridge:
+ handleObjCBridgeAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCBridge:
- handleObjCBridgeAttr(S, scope, D, Attr);
+ case ParsedAttr::AT_ObjCBridgeMutable:
+ handleObjCBridgeMutableAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCBridgeMutable:
- handleObjCBridgeMutableAttr(S, scope, D, Attr);
+ case ParsedAttr::AT_ObjCBridgeRelated:
+ handleObjCBridgeRelatedAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCBridgeRelated:
- handleObjCBridgeRelatedAttr(S, scope, D, Attr);
+ case ParsedAttr::AT_ObjCDesignatedInitializer:
+ handleObjCDesignatedInitializer(S, D, AL);
break;
- case AttributeList::AT_ObjCDesignatedInitializer:
- handleObjCDesignatedInitializer(S, D, Attr);
+ case ParsedAttr::AT_ObjCRuntimeName:
+ handleObjCRuntimeName(S, D, AL);
break;
- case AttributeList::AT_ObjCRuntimeName:
- handleObjCRuntimeName(S, D, Attr);
+ case ParsedAttr::AT_ObjCRuntimeVisible:
+ handleSimpleAttribute<ObjCRuntimeVisibleAttr>(S, D, AL);
break;
- case AttributeList::AT_ObjCRuntimeVisible:
- handleSimpleAttribute<ObjCRuntimeVisibleAttr>(S, D, Attr);
+ case ParsedAttr::AT_ObjCBoxable:
+ handleObjCBoxable(S, D, AL);
break;
- case AttributeList::AT_ObjCBoxable:
- handleObjCBoxable(S, D, Attr);
+ case ParsedAttr::AT_CFAuditedTransfer:
+ handleSimpleAttributeWithExclusions<CFAuditedTransferAttr,
+ CFUnknownTransferAttr>(S, D, AL);
break;
- case AttributeList::AT_CFAuditedTransfer:
- handleCFAuditedTransferAttr(S, D, Attr);
+ case ParsedAttr::AT_CFUnknownTransfer:
+ handleSimpleAttributeWithExclusions<CFUnknownTransferAttr,
+ CFAuditedTransferAttr>(S, D, AL);
break;
- case AttributeList::AT_CFUnknownTransfer:
- handleCFUnknownTransferAttr(S, D, Attr);
+ case ParsedAttr::AT_CFConsumed:
+ case ParsedAttr::AT_NSConsumed:
+ handleNSConsumedAttr(S, D, AL);
break;
- case AttributeList::AT_CFConsumed:
- case AttributeList::AT_NSConsumed:
- handleNSConsumedAttr(S, D, Attr);
+ case ParsedAttr::AT_NSConsumesSelf:
+ handleSimpleAttribute<NSConsumesSelfAttr>(S, D, AL);
break;
- case AttributeList::AT_NSConsumesSelf:
- handleSimpleAttribute<NSConsumesSelfAttr>(S, D, Attr);
+ case ParsedAttr::AT_NSReturnsAutoreleased:
+ case ParsedAttr::AT_NSReturnsNotRetained:
+ case ParsedAttr::AT_CFReturnsNotRetained:
+ case ParsedAttr::AT_NSReturnsRetained:
+ case ParsedAttr::AT_CFReturnsRetained:
+ handleNSReturnsRetainedAttr(S, D, AL);
break;
- case AttributeList::AT_NSReturnsAutoreleased:
- case AttributeList::AT_NSReturnsNotRetained:
- case AttributeList::AT_CFReturnsNotRetained:
- case AttributeList::AT_NSReturnsRetained:
- case AttributeList::AT_CFReturnsRetained:
- handleNSReturnsRetainedAttr(S, D, Attr);
+ case ParsedAttr::AT_WorkGroupSizeHint:
+ handleWorkGroupSize<WorkGroupSizeHintAttr>(S, D, AL);
break;
- case AttributeList::AT_WorkGroupSizeHint:
- handleWorkGroupSize<WorkGroupSizeHintAttr>(S, D, Attr);
+ case ParsedAttr::AT_ReqdWorkGroupSize:
+ handleWorkGroupSize<ReqdWorkGroupSizeAttr>(S, D, AL);
break;
- case AttributeList::AT_ReqdWorkGroupSize:
- handleWorkGroupSize<ReqdWorkGroupSizeAttr>(S, D, Attr);
+ case ParsedAttr::AT_OpenCLIntelReqdSubGroupSize:
+ handleSubGroupSize(S, D, AL);
break;
- case AttributeList::AT_OpenCLIntelReqdSubGroupSize:
- handleSubGroupSize(S, D, Attr);
+ case ParsedAttr::AT_VecTypeHint:
+ handleVecTypeHint(S, D, AL);
break;
- case AttributeList::AT_VecTypeHint:
- handleVecTypeHint(S, D, Attr);
+ case ParsedAttr::AT_RequireConstantInit:
+ handleSimpleAttribute<RequireConstantInitAttr>(S, D, AL);
break;
- case AttributeList::AT_RequireConstantInit:
- handleSimpleAttribute<RequireConstantInitAttr>(S, D, Attr);
+ case ParsedAttr::AT_InitPriority:
+ handleInitPriorityAttr(S, D, AL);
break;
- case AttributeList::AT_InitPriority:
- handleInitPriorityAttr(S, D, Attr);
+ case ParsedAttr::AT_Packed:
+ handlePackedAttr(S, D, AL);
break;
- case AttributeList::AT_Packed:
- handlePackedAttr(S, D, Attr);
+ case ParsedAttr::AT_Section:
+ handleSectionAttr(S, D, AL);
break;
- case AttributeList::AT_Section:
- handleSectionAttr(S, D, Attr);
+ case ParsedAttr::AT_CodeSeg:
+ handleCodeSegAttr(S, D, AL);
break;
- case AttributeList::AT_Target:
- handleTargetAttr(S, D, Attr);
+ case ParsedAttr::AT_Target:
+ handleTargetAttr(S, D, AL);
break;
- case AttributeList::AT_Unavailable:
- handleAttrWithMessage<UnavailableAttr>(S, D, Attr);
+ case ParsedAttr::AT_MinVectorWidth:
+ handleMinVectorWidthAttr(S, D, AL);
break;
- case AttributeList::AT_ArcWeakrefUnavailable:
- handleSimpleAttribute<ArcWeakrefUnavailableAttr>(S, D, Attr);
+ case ParsedAttr::AT_Unavailable:
+ handleAttrWithMessage<UnavailableAttr>(S, D, AL);
break;
- case AttributeList::AT_ObjCRootClass:
- handleSimpleAttribute<ObjCRootClassAttr>(S, D, Attr);
+ case ParsedAttr::AT_ArcWeakrefUnavailable:
+ handleSimpleAttribute<ArcWeakrefUnavailableAttr>(S, D, AL);
break;
- case AttributeList::AT_ObjCSubclassingRestricted:
- handleSimpleAttribute<ObjCSubclassingRestrictedAttr>(S, D, Attr);
+ case ParsedAttr::AT_ObjCRootClass:
+ handleSimpleAttribute<ObjCRootClassAttr>(S, D, AL);
break;
- case AttributeList::AT_ObjCExplicitProtocolImpl:
- handleObjCSuppresProtocolAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCSubclassingRestricted:
+ handleSimpleAttribute<ObjCSubclassingRestrictedAttr>(S, D, AL);
break;
- case AttributeList::AT_ObjCRequiresPropertyDefs:
- handleSimpleAttribute<ObjCRequiresPropertyDefsAttr>(S, D, Attr);
+ case ParsedAttr::AT_ObjCExplicitProtocolImpl:
+ handleObjCSuppresProtocolAttr(S, D, AL);
break;
- case AttributeList::AT_Unused:
- handleUnusedAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCRequiresPropertyDefs:
+ handleSimpleAttribute<ObjCRequiresPropertyDefsAttr>(S, D, AL);
break;
- case AttributeList::AT_ReturnsTwice:
- handleSimpleAttribute<ReturnsTwiceAttr>(S, D, Attr);
+ case ParsedAttr::AT_Unused:
+ handleUnusedAttr(S, D, AL);
break;
- case AttributeList::AT_NotTailCalled:
- handleNotTailCalledAttr(S, D, Attr);
+ case ParsedAttr::AT_ReturnsTwice:
+ handleSimpleAttribute<ReturnsTwiceAttr>(S, D, AL);
break;
- case AttributeList::AT_DisableTailCalls:
- handleDisableTailCallsAttr(S, D, Attr);
+ case ParsedAttr::AT_NotTailCalled:
+ handleSimpleAttributeWithExclusions<NotTailCalledAttr, AlwaysInlineAttr>(
+ S, D, AL);
break;
- case AttributeList::AT_Used:
- handleUsedAttr(S, D, Attr);
+ case ParsedAttr::AT_DisableTailCalls:
+ handleSimpleAttributeWithExclusions<DisableTailCallsAttr, NakedAttr>(S, D,
+ AL);
break;
- case AttributeList::AT_Visibility:
- handleVisibilityAttr(S, D, Attr, false);
+ case ParsedAttr::AT_Used:
+ handleSimpleAttribute<UsedAttr>(S, D, AL);
break;
- case AttributeList::AT_TypeVisibility:
- handleVisibilityAttr(S, D, Attr, true);
+ case ParsedAttr::AT_Visibility:
+ handleVisibilityAttr(S, D, AL, false);
break;
- case AttributeList::AT_WarnUnused:
- handleSimpleAttribute<WarnUnusedAttr>(S, D, Attr);
+ case ParsedAttr::AT_TypeVisibility:
+ handleVisibilityAttr(S, D, AL, true);
break;
- case AttributeList::AT_WarnUnusedResult:
- handleWarnUnusedResult(S, D, Attr);
+ case ParsedAttr::AT_WarnUnused:
+ handleSimpleAttribute<WarnUnusedAttr>(S, D, AL);
break;
- case AttributeList::AT_Weak:
- handleSimpleAttribute<WeakAttr>(S, D, Attr);
+ case ParsedAttr::AT_WarnUnusedResult:
+ handleWarnUnusedResult(S, D, AL);
break;
- case AttributeList::AT_WeakRef:
- handleWeakRefAttr(S, D, Attr);
+ case ParsedAttr::AT_Weak:
+ handleSimpleAttribute<WeakAttr>(S, D, AL);
break;
- case AttributeList::AT_WeakImport:
- handleWeakImportAttr(S, D, Attr);
+ case ParsedAttr::AT_WeakRef:
+ handleWeakRefAttr(S, D, AL);
break;
- case AttributeList::AT_TransparentUnion:
- handleTransparentUnionAttr(S, D, Attr);
+ case ParsedAttr::AT_WeakImport:
+ handleWeakImportAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCException:
- handleSimpleAttribute<ObjCExceptionAttr>(S, D, Attr);
+ case ParsedAttr::AT_TransparentUnion:
+ handleTransparentUnionAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCMethodFamily:
- handleObjCMethodFamilyAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCException:
+ handleSimpleAttribute<ObjCExceptionAttr>(S, D, AL);
break;
- case AttributeList::AT_ObjCNSObject:
- handleObjCNSObject(S, D, Attr);
+ case ParsedAttr::AT_ObjCMethodFamily:
+ handleObjCMethodFamilyAttr(S, D, AL);
break;
- case AttributeList::AT_ObjCIndependentClass:
- handleObjCIndependentClass(S, D, Attr);
+ case ParsedAttr::AT_ObjCNSObject:
+ handleObjCNSObject(S, D, AL);
break;
- case AttributeList::AT_Blocks:
- handleBlocksAttr(S, D, Attr);
+ case ParsedAttr::AT_ObjCIndependentClass:
+ handleObjCIndependentClass(S, D, AL);
break;
- case AttributeList::AT_Sentinel:
- handleSentinelAttr(S, D, Attr);
+ case ParsedAttr::AT_Blocks:
+ handleBlocksAttr(S, D, AL);
break;
- case AttributeList::AT_Const:
- handleSimpleAttribute<ConstAttr>(S, D, Attr);
+ case ParsedAttr::AT_Sentinel:
+ handleSentinelAttr(S, D, AL);
break;
- case AttributeList::AT_Pure:
- handleSimpleAttribute<PureAttr>(S, D, Attr);
+ case ParsedAttr::AT_Const:
+ handleSimpleAttribute<ConstAttr>(S, D, AL);
break;
- case AttributeList::AT_Cleanup:
- handleCleanupAttr(S, D, Attr);
+ case ParsedAttr::AT_Pure:
+ handleSimpleAttribute<PureAttr>(S, D, AL);
break;
- case AttributeList::AT_NoDebug:
- handleNoDebugAttr(S, D, Attr);
+ case ParsedAttr::AT_Cleanup:
+ handleCleanupAttr(S, D, AL);
break;
- case AttributeList::AT_NoDuplicate:
- handleSimpleAttribute<NoDuplicateAttr>(S, D, Attr);
+ case ParsedAttr::AT_NoDebug:
+ handleNoDebugAttr(S, D, AL);
break;
- case AttributeList::AT_Convergent:
- handleSimpleAttribute<ConvergentAttr>(S, D, Attr);
+ case ParsedAttr::AT_NoDuplicate:
+ handleSimpleAttribute<NoDuplicateAttr>(S, D, AL);
break;
- case AttributeList::AT_NoInline:
- handleSimpleAttribute<NoInlineAttr>(S, D, Attr);
+ case ParsedAttr::AT_Convergent:
+ handleSimpleAttribute<ConvergentAttr>(S, D, AL);
break;
- case AttributeList::AT_NoInstrumentFunction: // Interacts with -pg.
- handleSimpleAttribute<NoInstrumentFunctionAttr>(S, D, Attr);
+ case ParsedAttr::AT_NoInline:
+ handleSimpleAttribute<NoInlineAttr>(S, D, AL);
break;
- case AttributeList::AT_StdCall:
- case AttributeList::AT_CDecl:
- case AttributeList::AT_FastCall:
- case AttributeList::AT_ThisCall:
- case AttributeList::AT_Pascal:
- case AttributeList::AT_RegCall:
- case AttributeList::AT_SwiftCall:
- case AttributeList::AT_VectorCall:
- case AttributeList::AT_MSABI:
- case AttributeList::AT_SysVABI:
- case AttributeList::AT_Pcs:
- case AttributeList::AT_IntelOclBicc:
- case AttributeList::AT_PreserveMost:
- case AttributeList::AT_PreserveAll:
- handleCallConvAttr(S, D, Attr);
+ case ParsedAttr::AT_NoInstrumentFunction: // Interacts with -pg.
+ handleSimpleAttribute<NoInstrumentFunctionAttr>(S, D, AL);
break;
- case AttributeList::AT_Suppress:
- handleSuppressAttr(S, D, Attr);
+ case ParsedAttr::AT_NoStackProtector:
+ // Interacts with -fstack-protector options.
+ handleSimpleAttribute<NoStackProtectorAttr>(S, D, AL);
break;
- case AttributeList::AT_OpenCLKernel:
- handleSimpleAttribute<OpenCLKernelAttr>(S, D, Attr);
+ case ParsedAttr::AT_StdCall:
+ case ParsedAttr::AT_CDecl:
+ case ParsedAttr::AT_FastCall:
+ case ParsedAttr::AT_ThisCall:
+ case ParsedAttr::AT_Pascal:
+ case ParsedAttr::AT_RegCall:
+ case ParsedAttr::AT_SwiftCall:
+ case ParsedAttr::AT_VectorCall:
+ case ParsedAttr::AT_MSABI:
+ case ParsedAttr::AT_SysVABI:
+ case ParsedAttr::AT_Pcs:
+ case ParsedAttr::AT_IntelOclBicc:
+ case ParsedAttr::AT_PreserveMost:
+ case ParsedAttr::AT_PreserveAll:
+ handleCallConvAttr(S, D, AL);
break;
- case AttributeList::AT_OpenCLAccess:
- handleOpenCLAccessAttr(S, D, Attr);
+ case ParsedAttr::AT_Suppress:
+ handleSuppressAttr(S, D, AL);
break;
- case AttributeList::AT_OpenCLNoSVM:
- handleOpenCLNoSVMAttr(S, D, Attr);
+ case ParsedAttr::AT_OpenCLKernel:
+ handleSimpleAttribute<OpenCLKernelAttr>(S, D, AL);
break;
- case AttributeList::AT_SwiftContext:
- handleParameterABIAttr(S, D, Attr, ParameterABI::SwiftContext);
+ case ParsedAttr::AT_OpenCLAccess:
+ handleOpenCLAccessAttr(S, D, AL);
break;
- case AttributeList::AT_SwiftErrorResult:
- handleParameterABIAttr(S, D, Attr, ParameterABI::SwiftErrorResult);
+ case ParsedAttr::AT_OpenCLNoSVM:
+ handleOpenCLNoSVMAttr(S, D, AL);
break;
- case AttributeList::AT_SwiftIndirectResult:
- handleParameterABIAttr(S, D, Attr, ParameterABI::SwiftIndirectResult);
+ case ParsedAttr::AT_SwiftContext:
+ handleParameterABIAttr(S, D, AL, ParameterABI::SwiftContext);
break;
- case AttributeList::AT_InternalLinkage:
- handleInternalLinkageAttr(S, D, Attr);
+ case ParsedAttr::AT_SwiftErrorResult:
+ handleParameterABIAttr(S, D, AL, ParameterABI::SwiftErrorResult);
break;
- case AttributeList::AT_LTOVisibilityPublic:
- handleSimpleAttribute<LTOVisibilityPublicAttr>(S, D, Attr);
+ case ParsedAttr::AT_SwiftIndirectResult:
+ handleParameterABIAttr(S, D, AL, ParameterABI::SwiftIndirectResult);
+ break;
+ case ParsedAttr::AT_InternalLinkage:
+ handleInternalLinkageAttr(S, D, AL);
+ break;
+ case ParsedAttr::AT_LTOVisibilityPublic:
+ handleSimpleAttribute<LTOVisibilityPublicAttr>(S, D, AL);
break;
// Microsoft attributes:
- case AttributeList::AT_EmptyBases:
- handleSimpleAttribute<EmptyBasesAttr>(S, D, Attr);
+ case ParsedAttr::AT_EmptyBases:
+ handleSimpleAttribute<EmptyBasesAttr>(S, D, AL);
+ break;
+ case ParsedAttr::AT_LayoutVersion:
+ handleLayoutVersion(S, D, AL);
break;
- case AttributeList::AT_LayoutVersion:
- handleLayoutVersion(S, D, Attr);
+ case ParsedAttr::AT_TrivialABI:
+ handleSimpleAttribute<TrivialABIAttr>(S, D, AL);
break;
- case AttributeList::AT_MSNoVTable:
- handleSimpleAttribute<MSNoVTableAttr>(S, D, Attr);
+ case ParsedAttr::AT_MSNoVTable:
+ handleSimpleAttribute<MSNoVTableAttr>(S, D, AL);
break;
- case AttributeList::AT_MSStruct:
- handleSimpleAttribute<MSStructAttr>(S, D, Attr);
+ case ParsedAttr::AT_MSStruct:
+ handleSimpleAttribute<MSStructAttr>(S, D, AL);
break;
- case AttributeList::AT_Uuid:
- handleUuidAttr(S, D, Attr);
+ case ParsedAttr::AT_Uuid:
+ handleUuidAttr(S, D, AL);
break;
- case AttributeList::AT_MSInheritance:
- handleMSInheritanceAttr(S, D, Attr);
+ case ParsedAttr::AT_MSInheritance:
+ handleMSInheritanceAttr(S, D, AL);
break;
- case AttributeList::AT_SelectAny:
- handleSimpleAttribute<SelectAnyAttr>(S, D, Attr);
+ case ParsedAttr::AT_SelectAny:
+ handleSimpleAttribute<SelectAnyAttr>(S, D, AL);
break;
- case AttributeList::AT_Thread:
- handleDeclspecThreadAttr(S, D, Attr);
+ case ParsedAttr::AT_Thread:
+ handleDeclspecThreadAttr(S, D, AL);
break;
- case AttributeList::AT_AbiTag:
- handleAbiTagAttr(S, D, Attr);
+ case ParsedAttr::AT_AbiTag:
+ handleAbiTagAttr(S, D, AL);
break;
// Thread safety attributes:
- case AttributeList::AT_AssertExclusiveLock:
- handleAssertExclusiveLockAttr(S, D, Attr);
+ case ParsedAttr::AT_AssertExclusiveLock:
+ handleAssertExclusiveLockAttr(S, D, AL);
break;
- case AttributeList::AT_AssertSharedLock:
- handleAssertSharedLockAttr(S, D, Attr);
+ case ParsedAttr::AT_AssertSharedLock:
+ handleAssertSharedLockAttr(S, D, AL);
break;
- case AttributeList::AT_GuardedVar:
- handleSimpleAttribute<GuardedVarAttr>(S, D, Attr);
+ case ParsedAttr::AT_GuardedVar:
+ handleSimpleAttribute<GuardedVarAttr>(S, D, AL);
break;
- case AttributeList::AT_PtGuardedVar:
- handlePtGuardedVarAttr(S, D, Attr);
+ case ParsedAttr::AT_PtGuardedVar:
+ handlePtGuardedVarAttr(S, D, AL);
break;
- case AttributeList::AT_ScopedLockable:
- handleSimpleAttribute<ScopedLockableAttr>(S, D, Attr);
+ case ParsedAttr::AT_ScopedLockable:
+ handleSimpleAttribute<ScopedLockableAttr>(S, D, AL);
break;
- case AttributeList::AT_NoSanitize:
- handleNoSanitizeAttr(S, D, Attr);
+ case ParsedAttr::AT_NoSanitize:
+ handleNoSanitizeAttr(S, D, AL);
break;
- case AttributeList::AT_NoSanitizeSpecific:
- handleNoSanitizeSpecificAttr(S, D, Attr);
+ case ParsedAttr::AT_NoSanitizeSpecific:
+ handleNoSanitizeSpecificAttr(S, D, AL);
break;
- case AttributeList::AT_NoThreadSafetyAnalysis:
- handleSimpleAttribute<NoThreadSafetyAnalysisAttr>(S, D, Attr);
+ case ParsedAttr::AT_NoThreadSafetyAnalysis:
+ handleSimpleAttribute<NoThreadSafetyAnalysisAttr>(S, D, AL);
break;
- case AttributeList::AT_GuardedBy:
- handleGuardedByAttr(S, D, Attr);
+ case ParsedAttr::AT_GuardedBy:
+ handleGuardedByAttr(S, D, AL);
break;
- case AttributeList::AT_PtGuardedBy:
- handlePtGuardedByAttr(S, D, Attr);
+ case ParsedAttr::AT_PtGuardedBy:
+ handlePtGuardedByAttr(S, D, AL);
break;
- case AttributeList::AT_ExclusiveTrylockFunction:
- handleExclusiveTrylockFunctionAttr(S, D, Attr);
+ case ParsedAttr::AT_ExclusiveTrylockFunction:
+ handleExclusiveTrylockFunctionAttr(S, D, AL);
break;
- case AttributeList::AT_LockReturned:
- handleLockReturnedAttr(S, D, Attr);
+ case ParsedAttr::AT_LockReturned:
+ handleLockReturnedAttr(S, D, AL);
break;
- case AttributeList::AT_LocksExcluded:
- handleLocksExcludedAttr(S, D, Attr);
+ case ParsedAttr::AT_LocksExcluded:
+ handleLocksExcludedAttr(S, D, AL);
break;
- case AttributeList::AT_SharedTrylockFunction:
- handleSharedTrylockFunctionAttr(S, D, Attr);
+ case ParsedAttr::AT_SharedTrylockFunction:
+ handleSharedTrylockFunctionAttr(S, D, AL);
break;
- case AttributeList::AT_AcquiredBefore:
- handleAcquiredBeforeAttr(S, D, Attr);
+ case ParsedAttr::AT_AcquiredBefore:
+ handleAcquiredBeforeAttr(S, D, AL);
break;
- case AttributeList::AT_AcquiredAfter:
- handleAcquiredAfterAttr(S, D, Attr);
+ case ParsedAttr::AT_AcquiredAfter:
+ handleAcquiredAfterAttr(S, D, AL);
break;
// Capability analysis attributes.
- case AttributeList::AT_Capability:
- case AttributeList::AT_Lockable:
- handleCapabilityAttr(S, D, Attr);
+ case ParsedAttr::AT_Capability:
+ case ParsedAttr::AT_Lockable:
+ handleCapabilityAttr(S, D, AL);
break;
- case AttributeList::AT_RequiresCapability:
- handleRequiresCapabilityAttr(S, D, Attr);
+ case ParsedAttr::AT_RequiresCapability:
+ handleRequiresCapabilityAttr(S, D, AL);
break;
- case AttributeList::AT_AssertCapability:
- handleAssertCapabilityAttr(S, D, Attr);
+ case ParsedAttr::AT_AssertCapability:
+ handleAssertCapabilityAttr(S, D, AL);
break;
- case AttributeList::AT_AcquireCapability:
- handleAcquireCapabilityAttr(S, D, Attr);
+ case ParsedAttr::AT_AcquireCapability:
+ handleAcquireCapabilityAttr(S, D, AL);
break;
- case AttributeList::AT_ReleaseCapability:
- handleReleaseCapabilityAttr(S, D, Attr);
+ case ParsedAttr::AT_ReleaseCapability:
+ handleReleaseCapabilityAttr(S, D, AL);
break;
- case AttributeList::AT_TryAcquireCapability:
- handleTryAcquireCapabilityAttr(S, D, Attr);
+ case ParsedAttr::AT_TryAcquireCapability:
+ handleTryAcquireCapabilityAttr(S, D, AL);
break;
// Consumed analysis attributes.
- case AttributeList::AT_Consumable:
- handleConsumableAttr(S, D, Attr);
+ case ParsedAttr::AT_Consumable:
+ handleConsumableAttr(S, D, AL);
break;
- case AttributeList::AT_ConsumableAutoCast:
- handleSimpleAttribute<ConsumableAutoCastAttr>(S, D, Attr);
+ case ParsedAttr::AT_ConsumableAutoCast:
+ handleSimpleAttribute<ConsumableAutoCastAttr>(S, D, AL);
break;
- case AttributeList::AT_ConsumableSetOnRead:
- handleSimpleAttribute<ConsumableSetOnReadAttr>(S, D, Attr);
+ case ParsedAttr::AT_ConsumableSetOnRead:
+ handleSimpleAttribute<ConsumableSetOnReadAttr>(S, D, AL);
break;
- case AttributeList::AT_CallableWhen:
- handleCallableWhenAttr(S, D, Attr);
+ case ParsedAttr::AT_CallableWhen:
+ handleCallableWhenAttr(S, D, AL);
break;
- case AttributeList::AT_ParamTypestate:
- handleParamTypestateAttr(S, D, Attr);
+ case ParsedAttr::AT_ParamTypestate:
+ handleParamTypestateAttr(S, D, AL);
break;
- case AttributeList::AT_ReturnTypestate:
- handleReturnTypestateAttr(S, D, Attr);
+ case ParsedAttr::AT_ReturnTypestate:
+ handleReturnTypestateAttr(S, D, AL);
break;
- case AttributeList::AT_SetTypestate:
- handleSetTypestateAttr(S, D, Attr);
+ case ParsedAttr::AT_SetTypestate:
+ handleSetTypestateAttr(S, D, AL);
break;
- case AttributeList::AT_TestTypestate:
- handleTestTypestateAttr(S, D, Attr);
+ case ParsedAttr::AT_TestTypestate:
+ handleTestTypestateAttr(S, D, AL);
break;
// Type safety attributes.
- case AttributeList::AT_ArgumentWithTypeTag:
- handleArgumentWithTypeTagAttr(S, D, Attr);
+ case ParsedAttr::AT_ArgumentWithTypeTag:
+ handleArgumentWithTypeTagAttr(S, D, AL);
break;
- case AttributeList::AT_TypeTagForDatatype:
- handleTypeTagForDatatypeAttr(S, D, Attr);
+ case ParsedAttr::AT_TypeTagForDatatype:
+ handleTypeTagForDatatypeAttr(S, D, AL);
break;
- case AttributeList::AT_AnyX86NoCallerSavedRegisters:
- handleNoCallerSavedRegsAttr(S, D, Attr);
+ case ParsedAttr::AT_AnyX86NoCallerSavedRegisters:
+ handleSimpleAttribute<AnyX86NoCallerSavedRegistersAttr>(S, D, AL);
break;
- case AttributeList::AT_RenderScriptKernel:
- handleSimpleAttribute<RenderScriptKernelAttr>(S, D, Attr);
+ case ParsedAttr::AT_RenderScriptKernel:
+ handleSimpleAttribute<RenderScriptKernelAttr>(S, D, AL);
break;
// XRay attributes.
- case AttributeList::AT_XRayInstrument:
- handleSimpleAttribute<XRayInstrumentAttr>(S, D, Attr);
+ case ParsedAttr::AT_XRayInstrument:
+ handleSimpleAttribute<XRayInstrumentAttr>(S, D, AL);
break;
- case AttributeList::AT_XRayLogArgs:
- handleXRayLogArgsAttr(S, D, Attr);
+ case ParsedAttr::AT_XRayLogArgs:
+ handleXRayLogArgsAttr(S, D, AL);
break;
}
}
@@ -6583,18 +6607,21 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
/// ProcessDeclAttributeList - Apply all the decl attributes in the specified
/// attribute list to the specified decl, ignoring any type attributes.
void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
- const AttributeList *AttrList,
+ const ParsedAttributesView &AttrList,
bool IncludeCXX11Attributes) {
- for (const AttributeList* l = AttrList; l; l = l->getNext())
- ProcessDeclAttribute(*this, S, D, *l, IncludeCXX11Attributes);
+ if (AttrList.empty())
+ return;
+
+ for (const ParsedAttr &AL : AttrList)
+ ProcessDeclAttribute(*this, S, D, AL, IncludeCXX11Attributes);
// FIXME: We should be able to handle these cases in TableGen.
// GCC accepts
// static int a9 __attribute__((weakref));
// but that looks really pointless. We reject it.
if (D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) {
- Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias)
- << cast<NamedDecl>(D);
+ Diag(AttrList.begin()->getLoc(), diag::err_attribute_weakref_without_alias)
+ << cast<NamedDecl>(D);
D->dropAttr<WeakRefAttr>();
return;
}
@@ -6605,79 +6632,83 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
// attribute must never appear as a group" for attributes like cold and hot.
if (!D->hasAttr<OpenCLKernelAttr>()) {
// These attributes cannot be applied to a non-kernel function.
- if (Attr *A = D->getAttr<ReqdWorkGroupSizeAttr>()) {
+ if (const auto *A = D->getAttr<ReqdWorkGroupSizeAttr>()) {
// FIXME: This emits a different error message than
// diag::err_attribute_wrong_decl_type + ExpectedKernelFunction.
Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
D->setInvalidDecl();
- } else if (Attr *A = D->getAttr<WorkGroupSizeHintAttr>()) {
+ } else if (const auto *A = D->getAttr<WorkGroupSizeHintAttr>()) {
Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
D->setInvalidDecl();
- } else if (Attr *A = D->getAttr<VecTypeHintAttr>()) {
+ } else if (const auto *A = D->getAttr<VecTypeHintAttr>()) {
Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
D->setInvalidDecl();
- } else if (Attr *A = D->getAttr<AMDGPUFlatWorkGroupSizeAttr>()) {
- Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
- << A << ExpectedKernelFunction;
- D->setInvalidDecl();
- } else if (Attr *A = D->getAttr<AMDGPUWavesPerEUAttr>()) {
- Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
- << A << ExpectedKernelFunction;
- D->setInvalidDecl();
- } else if (Attr *A = D->getAttr<AMDGPUNumSGPRAttr>()) {
- Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
- << A << ExpectedKernelFunction;
- D->setInvalidDecl();
- } else if (Attr *A = D->getAttr<AMDGPUNumVGPRAttr>()) {
- Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
- << A << ExpectedKernelFunction;
- D->setInvalidDecl();
- } else if (Attr *A = D->getAttr<OpenCLIntelReqdSubGroupSizeAttr>()) {
+ } else if (const auto *A = D->getAttr<OpenCLIntelReqdSubGroupSizeAttr>()) {
Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
D->setInvalidDecl();
+ } else if (!D->hasAttr<CUDAGlobalAttr>()) {
+ if (const auto *A = D->getAttr<AMDGPUFlatWorkGroupSizeAttr>()) {
+ Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
+ << A << ExpectedKernelFunction;
+ D->setInvalidDecl();
+ } else if (const auto *A = D->getAttr<AMDGPUWavesPerEUAttr>()) {
+ Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
+ << A << ExpectedKernelFunction;
+ D->setInvalidDecl();
+ } else if (const auto *A = D->getAttr<AMDGPUNumSGPRAttr>()) {
+ Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
+ << A << ExpectedKernelFunction;
+ D->setInvalidDecl();
+ } else if (const auto *A = D->getAttr<AMDGPUNumVGPRAttr>()) {
+ Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
+ << A << ExpectedKernelFunction;
+ D->setInvalidDecl();
+ }
}
}
}
// Helper for delayed processing TransparentUnion attribute.
-void Sema::ProcessDeclAttributeDelayed(Decl *D, const AttributeList *AttrList) {
- for (const AttributeList *Attr = AttrList; Attr; Attr = Attr->getNext())
- if (Attr->getKind() == AttributeList::AT_TransparentUnion) {
- handleTransparentUnionAttr(*this, D, *Attr);
+void Sema::ProcessDeclAttributeDelayed(Decl *D,
+ const ParsedAttributesView &AttrList) {
+ for (const ParsedAttr &AL : AttrList)
+ if (AL.getKind() == ParsedAttr::AT_TransparentUnion) {
+ handleTransparentUnionAttr(*this, D, AL);
break;
}
}
// Annotation attributes are the only attributes allowed after an access
// specifier.
-bool Sema::ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl,
- const AttributeList *AttrList) {
- for (const AttributeList* l = AttrList; l; l = l->getNext()) {
- if (l->getKind() == AttributeList::AT_Annotate) {
- ProcessDeclAttribute(*this, nullptr, ASDecl, *l, l->isCXX11Attribute());
+bool Sema::ProcessAccessDeclAttributeList(
+ AccessSpecDecl *ASDecl, const ParsedAttributesView &AttrList) {
+ for (const ParsedAttr &AL : AttrList) {
+ if (AL.getKind() == ParsedAttr::AT_Annotate) {
+ ProcessDeclAttribute(*this, nullptr, ASDecl, AL, AL.isCXX11Attribute());
} else {
- Diag(l->getLoc(), diag::err_only_annotate_after_access_spec);
+ Diag(AL.getLoc(), diag::err_only_annotate_after_access_spec);
return true;
}
}
-
return false;
}
/// checkUnusedDeclAttributes - Check a list of attributes to see if it
/// contains any decl attributes that we should warn about.
-static void checkUnusedDeclAttributes(Sema &S, const AttributeList *A) {
- for ( ; A; A = A->getNext()) {
+static void checkUnusedDeclAttributes(Sema &S, const ParsedAttributesView &A) {
+ for (const ParsedAttr &AL : A) {
// Only warn if the attribute is an unignored, non-type attribute.
- if (A->isUsedAsTypeAttr() || A->isInvalid()) continue;
- if (A->getKind() == AttributeList::IgnoredAttribute) continue;
+ if (AL.isUsedAsTypeAttr() || AL.isInvalid())
+ continue;
+ if (AL.getKind() == ParsedAttr::IgnoredAttribute)
+ continue;
- if (A->getKind() == AttributeList::UnknownAttribute) {
- S.Diag(A->getLoc(), diag::warn_unknown_attribute_ignored)
- << A->getName() << A->getRange();
+ if (AL.getKind() == ParsedAttr::UnknownAttribute) {
+ S.Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored)
+ << AL.getName() << AL.getRange();
} else {
- S.Diag(A->getLoc(), diag::warn_attribute_not_on_decl)
- << A->getName() << A->getRange();
+ S.Diag(AL.getLoc(), diag::warn_attribute_not_on_decl)
+ << AL.getName() << AL.getRange();
}
}
}
@@ -6686,7 +6717,7 @@ static void checkUnusedDeclAttributes(Sema &S, const AttributeList *A) {
/// used to build a declaration, complain about any decl attributes
/// which might be lying around on it.
void Sema::checkUnusedDeclAttributes(Declarator &D) {
- ::checkUnusedDeclAttributes(*this, D.getDeclSpec().getAttributes().getList());
+ ::checkUnusedDeclAttributes(*this, D.getDeclSpec().getAttributes());
::checkUnusedDeclAttributes(*this, D.getAttributes());
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i)
::checkUnusedDeclAttributes(*this, D.getTypeObject(i).getAttrs());
@@ -6698,7 +6729,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
SourceLocation Loc) {
assert(isa<FunctionDecl>(ND) || isa<VarDecl>(ND));
NamedDecl *NewD = nullptr;
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
+ if (auto *FD = dyn_cast<FunctionDecl>(ND)) {
FunctionDecl *NewFD;
// FIXME: Missing call to CheckFunctionDeclaration().
// FIXME: Mangling?
@@ -6718,7 +6749,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
// Fake up parameter variables; they are declared as if this were
// a typedef.
QualType FDTy = FD->getType();
- if (const FunctionProtoType *FT = FDTy->getAs<FunctionProtoType>()) {
+ if (const auto *FT = FDTy->getAs<FunctionProtoType>()) {
SmallVector<ParmVarDecl*, 16> Params;
for (const auto &AI : FT->param_types()) {
ParmVarDecl *Param = BuildParmVarDeclForTypedef(NewFD, Loc, AI);
@@ -6727,15 +6758,13 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
}
NewFD->setParams(Params);
}
- } else if (VarDecl *VD = dyn_cast<VarDecl>(ND)) {
+ } else if (auto *VD = dyn_cast<VarDecl>(ND)) {
NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(),
VD->getInnerLocStart(), VD->getLocation(), II,
VD->getType(), VD->getTypeSourceInfo(),
VD->getStorageClass());
- if (VD->getQualifier()) {
- VarDecl *NewVD = cast<VarDecl>(NewD);
- NewVD->setQualifierInfo(VD->getQualifierLoc());
- }
+ if (VD->getQualifier())
+ cast<VarDecl>(NewD)->setQualifierInfo(VD->getQualifierLoc());
}
return NewD;
}
@@ -6771,10 +6800,10 @@ void Sema::ProcessPragmaWeak(Scope *S, Decl *D) {
LoadExternalWeakUndeclaredIdentifiers();
if (!WeakUndeclaredIdentifiers.empty()) {
NamedDecl *ND = nullptr;
- if (VarDecl *VD = dyn_cast<VarDecl>(D))
+ if (auto *VD = dyn_cast<VarDecl>(D))
if (VD->isExternC())
ND = VD;
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ if (auto *FD = dyn_cast<FunctionDecl>(D))
if (FD->isExternC())
ND = FD;
if (ND) {
@@ -6795,20 +6824,19 @@ void Sema::ProcessPragmaWeak(Scope *S, Decl *D) {
/// specified in many different places, and we need to find and apply them all.
void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
// Apply decl attributes from the DeclSpec if present.
- if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes().getList())
- ProcessDeclAttributeList(S, D, Attrs);
+ if (!PD.getDeclSpec().getAttributes().empty())
+ ProcessDeclAttributeList(S, D, PD.getDeclSpec().getAttributes());
// Walk the declarator structure, applying decl attributes that were in a type
// position to the decl itself. This handles cases like:
// int *__attr__(x)** D;
// when X is a decl attribute.
for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)
- if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs())
- ProcessDeclAttributeList(S, D, Attrs, /*IncludeCXX11Attributes=*/false);
+ ProcessDeclAttributeList(S, D, PD.getTypeObject(i).getAttrs(),
+ /*IncludeCXX11Attributes=*/false);
// Finally, apply any attributes on the decl itself.
- if (const AttributeList *Attrs = PD.getAttributes())
- ProcessDeclAttributeList(S, D, Attrs);
+ ProcessDeclAttributeList(S, D, PD.getAttributes());
// Apply additional attributes specified by '#pragma clang attribute'.
AddPragmaAttributes(S, D);
@@ -6817,14 +6845,14 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
/// Is the given declaration allowed to use a forbidden type?
/// If so, it'll still be annotated with an attribute that makes it
/// illegal to actually use.
-static bool isForbiddenTypeAllowed(Sema &S, Decl *decl,
+static bool isForbiddenTypeAllowed(Sema &S, Decl *D,
const DelayedDiagnostic &diag,
UnavailableAttr::ImplicitReason &reason) {
// Private ivars are always okay. Unfortunately, people don't
// always properly make their ivars private, even in system headers.
// Plus we need to make fields okay, too.
- if (!isa<FieldDecl>(decl) && !isa<ObjCPropertyDecl>(decl) &&
- !isa<FunctionDecl>(decl))
+ if (!isa<FieldDecl>(D) && !isa<ObjCPropertyDecl>(D) &&
+ !isa<FunctionDecl>(D))
return false;
// Silently accept unsupported uses of __weak in both user and system
@@ -6832,7 +6860,7 @@ static bool isForbiddenTypeAllowed(Sema &S, Decl *decl,
// -fno-objc-arc files. We do have to take some care against attempts
// to define such things; for now, we've only done that for ivars
// and properties.
- if ((isa<ObjCIvarDecl>(decl) || isa<ObjCPropertyDecl>(decl))) {
+ if ((isa<ObjCIvarDecl>(D) || isa<ObjCPropertyDecl>(D))) {
if (diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_disabled ||
diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_no_runtime) {
reason = UnavailableAttr::IR_ForbiddenWeak;
@@ -6841,7 +6869,7 @@ static bool isForbiddenTypeAllowed(Sema &S, Decl *decl,
}
// Allow all sorts of things in system headers.
- if (S.Context.getSourceManager().isInSystemHeader(decl->getLocation())) {
+ if (S.Context.getSourceManager().isInSystemHeader(D->getLocation())) {
// Currently, all the failures dealt with this way are due to ARC
// restrictions.
reason = UnavailableAttr::IR_ARCForbiddenType;
@@ -6852,30 +6880,29 @@ static bool isForbiddenTypeAllowed(Sema &S, Decl *decl,
}
/// Handle a delayed forbidden-type diagnostic.
-static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &diag,
- Decl *decl) {
- auto reason = UnavailableAttr::IR_None;
- if (decl && isForbiddenTypeAllowed(S, decl, diag, reason)) {
- assert(reason && "didn't set reason?");
- decl->addAttr(UnavailableAttr::CreateImplicit(S.Context, "", reason,
- diag.Loc));
+static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &DD,
+ Decl *D) {
+ auto Reason = UnavailableAttr::IR_None;
+ if (D && isForbiddenTypeAllowed(S, D, DD, Reason)) {
+ assert(Reason && "didn't set reason?");
+ D->addAttr(UnavailableAttr::CreateImplicit(S.Context, "", Reason, DD.Loc));
return;
}
if (S.getLangOpts().ObjCAutoRefCount)
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(decl)) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
// FIXME: we may want to suppress diagnostics for all
- // kind of forbidden type messages on unavailable functions.
+ // kind of forbidden type messages on unavailable functions.
if (FD->hasAttr<UnavailableAttr>() &&
- diag.getForbiddenTypeDiagnostic() ==
- diag::err_arc_array_param_no_ownership) {
- diag.Triggered = true;
+ DD.getForbiddenTypeDiagnostic() ==
+ diag::err_arc_array_param_no_ownership) {
+ DD.Triggered = true;
return;
}
}
- S.Diag(diag.Loc, diag.getForbiddenTypeDiagnostic())
- << diag.getForbiddenTypeOperand() << diag.getForbiddenTypeArgument();
- diag.Triggered = true;
+ S.Diag(DD.Loc, DD.getForbiddenTypeDiagnostic())
+ << DD.getForbiddenTypeOperand() << DD.getForbiddenTypeArgument();
+ DD.Triggered = true;
}
static const AvailabilityAttr *getAttrForPlatform(ASTContext &Context,
@@ -6918,9 +6945,9 @@ ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, std::string *Message) {
// For typedefs, if the typedef declaration appears available look
// to the underlying type to see if it is more restrictive.
- while (const TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
+ while (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
if (Result == AR_Available) {
- if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) {
+ if (const auto *TT = TD->getUnderlyingType()->getAs<TagType>()) {
D = TT->getDecl();
Result = D->getAvailability(Message);
continue;
@@ -6930,7 +6957,7 @@ ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, std::string *Message) {
}
// Forward class declarations get their attributes from their definition.
- if (const ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(D)) {
+ if (const auto *IDecl = dyn_cast<ObjCInterfaceDecl>(D)) {
if (IDecl->getDefinition()) {
D = IDecl->getDefinition();
Result = D->getAvailability(Message);
@@ -6950,7 +6977,7 @@ ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, std::string *Message) {
}
-/// \brief whether we should emit a diagnostic for \c K and \c DeclVersion in
+/// 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,
@@ -6973,40 +7000,24 @@ static bool ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K,
return false;
};
- // FIXME: This is a temporary workaround! Some existing Apple headers depends
- // on nested declarations in an @interface having the availability of the
- // interface when they really shouldn't: they are members of the enclosing
- // context, and can referenced from there.
- if (S.OriginalLexicalContext && cast<Decl>(S.OriginalLexicalContext) != Ctx) {
- auto *OrigCtx = cast<Decl>(S.OriginalLexicalContext);
- if (CheckContext(OrigCtx))
- return false;
-
- // An implementation implicitly has the availability of the interface.
- if (auto *CatOrImpl = dyn_cast<ObjCImplDecl>(OrigCtx)) {
- if (const ObjCInterfaceDecl *Interface = CatOrImpl->getClassInterface())
- if (CheckContext(Interface))
- return false;
- }
- // A category implicitly has the availability of the interface.
- else if (auto *CatD = dyn_cast<ObjCCategoryDecl>(OrigCtx))
- if (const ObjCInterfaceDecl *Interface = CatD->getClassInterface())
- if (CheckContext(Interface))
- return false;
- }
-
do {
if (CheckContext(Ctx))
return false;
// An implementation implicitly has the availability of the interface.
- if (auto *CatOrImpl = dyn_cast<ObjCImplDecl>(Ctx)) {
+ // Unless it is "+load" method.
+ if (const auto *MethodD = dyn_cast<ObjCMethodDecl>(Ctx))
+ if (MethodD->isClassMethod() &&
+ MethodD->getSelector().getAsString() == "load")
+ return true;
+
+ if (const auto *CatOrImpl = dyn_cast<ObjCImplDecl>(Ctx)) {
if (const ObjCInterfaceDecl *Interface = CatOrImpl->getClassInterface())
if (CheckContext(Interface))
return false;
}
// A category implicitly has the availability of the interface.
- else if (auto *CatD = dyn_cast<ObjCCategoryDecl>(Ctx))
+ else if (const auto *CatD = dyn_cast<ObjCCategoryDecl>(Ctx))
if (const ObjCInterfaceDecl *Interface = CatD->getClassInterface())
if (CheckContext(Interface))
return false;
@@ -7076,6 +7087,45 @@ struct AttributeInsertion {
} // end anonymous namespace
+/// Tries to parse a string as ObjC method name.
+///
+/// \param Name The string to parse. Expected to originate from availability
+/// attribute argument.
+/// \param SlotNames The vector that will be populated with slot names. In case
+/// of unsuccessful parsing can contain invalid data.
+/// \returns A number of method parameters if parsing was successful, None
+/// otherwise.
+static Optional<unsigned>
+tryParseObjCMethodName(StringRef Name, SmallVectorImpl<StringRef> &SlotNames,
+ const LangOptions &LangOpts) {
+ // Accept replacements starting with - or + as valid ObjC method names.
+ if (!Name.empty() && (Name.front() == '-' || Name.front() == '+'))
+ Name = Name.drop_front(1);
+ if (Name.empty())
+ return None;
+ Name.split(SlotNames, ':');
+ unsigned NumParams;
+ if (Name.back() == ':') {
+ // Remove an empty string at the end that doesn't represent any slot.
+ SlotNames.pop_back();
+ NumParams = SlotNames.size();
+ } else {
+ if (SlotNames.size() != 1)
+ // Not a valid method name, just a colon-separated string.
+ return None;
+ NumParams = 0;
+ }
+ // Verify all slot names are valid.
+ bool AllowDollar = LangOpts.DollarIdents;
+ for (StringRef S : SlotNames) {
+ if (S.empty())
+ continue;
+ if (!isValidIdentifier(S, AllowDollar))
+ return None;
+ }
+ return NumParams;
+}
+
/// Returns a source location in which it's appropriate to insert a new
/// attribute for the given declaration \D.
static Optional<AttributeInsertion>
@@ -7105,14 +7155,15 @@ createAttributeInsertion(const NamedDecl *D, const SourceManager &SM,
/// \param Ctx The context that the reference occurred in
/// \param ReferringDecl The exact declaration that was referenced.
/// \param OffendingDecl A related decl to \c ReferringDecl that has an
-/// availability attribute corrisponding to \c K attached to it. Note that this
+/// availability attribute corresponding to \c K attached to it. Note that this
/// may not be the same as ReferringDecl, i.e. if an EnumDecl is annotated and
/// we refer to a member EnumConstantDecl, ReferringDecl is the EnumConstantDecl
/// and OffendingDecl is the EnumDecl.
static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
Decl *Ctx, const NamedDecl *ReferringDecl,
const NamedDecl *OffendingDecl,
- StringRef Message, SourceLocation Loc,
+ StringRef Message,
+ ArrayRef<SourceLocation> Locs,
const ObjCInterfaceDecl *UnknownObjCClass,
const ObjCPropertyDecl *ObjCProperty,
bool ObjCPropertyAccess) {
@@ -7134,6 +7185,8 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
if (!ShouldDiagnoseAvailabilityInContext(S, K, DeclVersion, Ctx))
return;
+ SourceLocation Loc = Locs.front();
+
// The declaration can have multiple availability attributes, we are looking
// at one of them.
const AvailabilityAttr *A = getAttrForPlatform(S.Context, OffendingDecl);
@@ -7177,7 +7230,7 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
<< OffendingDecl << /* partial */ 3;
if (const auto *Enclosing = findEnclosingDeclToAnnotate(Ctx)) {
- if (auto *TD = dyn_cast<TagDecl>(Enclosing))
+ if (const auto *TD = dyn_cast<TagDecl>(Enclosing))
if (TD->getDeclName().isEmpty()) {
S.Diag(TD->getLocation(),
diag::note_decl_unguarded_availability_silence)
@@ -7218,8 +7271,8 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
diag_fwdclass_message = diag::warn_deprecated_fwdclass_message;
property_note_select = /* deprecated */ 0;
available_here_select_kind = /* deprecated */ 2;
- if (const auto *Attr = OffendingDecl->getAttr<DeprecatedAttr>())
- NoteLocation = Attr->getLocation();
+ if (const auto *AL = OffendingDecl->getAttr<DeprecatedAttr>())
+ NoteLocation = AL->getLocation();
break;
case AR_Unavailable:
@@ -7230,8 +7283,8 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
property_note_select = /* unavailable */ 1;
available_here_select_kind = /* unavailable */ 0;
- if (auto Attr = OffendingDecl->getAttr<UnavailableAttr>()) {
- if (Attr->isImplicit() && Attr->getImplicitReason()) {
+ if (auto AL = OffendingDecl->getAttr<UnavailableAttr>()) {
+ if (AL->isImplicit() && AL->getImplicitReason()) {
// Most of these failures are due to extra restrictions in ARC;
// reflect that in the primary diagnostic when applicable.
auto flagARCError = [&] {
@@ -7241,7 +7294,7 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
diag = diag::err_unavailable_in_arc;
};
- switch (Attr->getImplicitReason()) {
+ switch (AL->getImplicitReason()) {
case UnavailableAttr::IR_None: break;
case UnavailableAttr::IR_ARCForbiddenType:
@@ -7279,37 +7332,55 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
llvm_unreachable("Warning for availability of available declaration?");
}
- CharSourceRange UseRange;
- StringRef Replacement;
+ SmallVector<FixItHint, 12> FixIts;
if (K == AR_Deprecated) {
- if (auto Attr = OffendingDecl->getAttr<DeprecatedAttr>())
- Replacement = Attr->getReplacement();
- if (auto Attr = getAttrForPlatform(S.Context, OffendingDecl))
- Replacement = Attr->getReplacement();
+ StringRef Replacement;
+ if (auto AL = OffendingDecl->getAttr<DeprecatedAttr>())
+ Replacement = AL->getReplacement();
+ if (auto AL = getAttrForPlatform(S.Context, OffendingDecl))
+ Replacement = AL->getReplacement();
+ CharSourceRange UseRange;
if (!Replacement.empty())
UseRange =
CharSourceRange::getCharRange(Loc, S.getLocForEndOfToken(Loc));
+ if (UseRange.isValid()) {
+ if (const auto *MethodDecl = dyn_cast<ObjCMethodDecl>(ReferringDecl)) {
+ Selector Sel = MethodDecl->getSelector();
+ SmallVector<StringRef, 12> SelectorSlotNames;
+ Optional<unsigned> NumParams = tryParseObjCMethodName(
+ Replacement, SelectorSlotNames, S.getLangOpts());
+ if (NumParams && NumParams.getValue() == Sel.getNumArgs()) {
+ assert(SelectorSlotNames.size() == Locs.size());
+ for (unsigned I = 0; I < Locs.size(); ++I) {
+ if (!Sel.getNameForSlot(I).empty()) {
+ CharSourceRange NameRange = CharSourceRange::getCharRange(
+ Locs[I], S.getLocForEndOfToken(Locs[I]));
+ FixIts.push_back(FixItHint::CreateReplacement(
+ NameRange, SelectorSlotNames[I]));
+ } else
+ FixIts.push_back(
+ FixItHint::CreateInsertion(Locs[I], SelectorSlotNames[I]));
+ }
+ } else
+ FixIts.push_back(FixItHint::CreateReplacement(UseRange, Replacement));
+ } else
+ FixIts.push_back(FixItHint::CreateReplacement(UseRange, Replacement));
+ }
}
if (!Message.empty()) {
- S.Diag(Loc, diag_message) << ReferringDecl << Message
- << (UseRange.isValid() ?
- FixItHint::CreateReplacement(UseRange, Replacement) : FixItHint());
+ S.Diag(Loc, diag_message) << ReferringDecl << Message << FixIts;
if (ObjCProperty)
S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
<< ObjCProperty->getDeclName() << property_note_select;
} else if (!UnknownObjCClass) {
- S.Diag(Loc, diag) << ReferringDecl
- << (UseRange.isValid() ?
- FixItHint::CreateReplacement(UseRange, Replacement) : FixItHint());
+ S.Diag(Loc, diag) << ReferringDecl << FixIts;
if (ObjCProperty)
S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
<< ObjCProperty->getDeclName() << property_note_select;
} else {
- S.Diag(Loc, diag_fwdclass_message) << ReferringDecl
- << (UseRange.isValid() ?
- FixItHint::CreateReplacement(UseRange, Replacement) : FixItHint());
+ S.Diag(Loc, diag_fwdclass_message) << ReferringDecl << FixIts;
S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class);
}
@@ -7325,8 +7396,9 @@ static void handleDelayedAvailabilityCheck(Sema &S, DelayedDiagnostic &DD,
DD.Triggered = true;
DoEmitAvailabilityWarning(
S, DD.getAvailabilityResult(), Ctx, DD.getAvailabilityReferringDecl(),
- DD.getAvailabilityOffendingDecl(), DD.getAvailabilityMessage(), DD.Loc,
- DD.getUnknownObjCClass(), DD.getObjCProperty(), false);
+ DD.getAvailabilityOffendingDecl(), DD.getAvailabilityMessage(),
+ DD.getAvailabilitySelectorLocs(), DD.getUnknownObjCClass(),
+ DD.getObjCProperty(), false);
}
void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
@@ -7387,7 +7459,8 @@ void Sema::redelayDiagnostics(DelayedDiagnosticPool &pool) {
static void EmitAvailabilityWarning(Sema &S, AvailabilityResult AR,
const NamedDecl *ReferringDecl,
const NamedDecl *OffendingDecl,
- StringRef Message, SourceLocation Loc,
+ StringRef Message,
+ ArrayRef<SourceLocation> Locs,
const ObjCInterfaceDecl *UnknownObjCClass,
const ObjCPropertyDecl *ObjCProperty,
bool ObjCPropertyAccess) {
@@ -7395,14 +7468,14 @@ static void EmitAvailabilityWarning(Sema &S, AvailabilityResult AR,
if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
S.DelayedDiagnostics.add(
DelayedDiagnostic::makeAvailability(
- AR, Loc, ReferringDecl, OffendingDecl, UnknownObjCClass,
+ AR, Locs, ReferringDecl, OffendingDecl, UnknownObjCClass,
ObjCProperty, Message, ObjCPropertyAccess));
return;
}
Decl *Ctx = cast<Decl>(S.getCurLexicalContext());
DoEmitAvailabilityWarning(S, AR, Ctx, ReferringDecl, OffendingDecl,
- Message, Loc, UnknownObjCClass, ObjCProperty,
+ Message, Locs, UnknownObjCClass, ObjCProperty,
ObjCPropertyAccess);
}
@@ -7471,7 +7544,7 @@ public:
}
};
-/// \brief This class implements -Wunguarded-availability.
+/// This class implements -Wunguarded-availability.
///
/// This is done with a traversal of the AST of a function that makes reference
/// to a partially available declaration. Whenever we encounter an \c if of the
@@ -7642,7 +7715,7 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
SourceLocation StmtEndLoc =
SM.getExpansionRange(
(LastStmtOfUse ? LastStmtOfUse : StmtOfUse)->getLocEnd())
- .second;
+ .getEnd();
if (SM.getFileID(IfInsertionLoc) != SM.getFileID(StmtEndLoc))
return;
@@ -7681,11 +7754,11 @@ bool DiagnoseUnguardedAvailability::VisitTypeLoc(TypeLoc Ty) {
if (Range.isInvalid())
return true;
- if (const TagType *TT = dyn_cast<TagType>(TyPtr)) {
+ if (const auto *TT = dyn_cast<TagType>(TyPtr)) {
TagDecl *TD = TT->getDecl();
DiagnoseDeclAvailability(TD, Range);
- } else if (const TypedefType *TD = dyn_cast<TypedefType>(TyPtr)) {
+ } else if (const auto *TD = dyn_cast<TypedefType>(TyPtr)) {
TypedefNameDecl *D = TD->getDecl();
DiagnoseDeclAvailability(D, Range);
@@ -7740,7 +7813,8 @@ void Sema::DiagnoseUnguardedAvailabilityViolations(Decl *D) {
DiagnoseUnguardedAvailability(*this, D).IssueDiagnostics(Body);
}
-void Sema::DiagnoseAvailabilityOfDecl(NamedDecl *D, SourceLocation Loc,
+void Sema::DiagnoseAvailabilityOfDecl(NamedDecl *D,
+ ArrayRef<SourceLocation> Locs,
const ObjCInterfaceDecl *UnknownObjCClass,
bool ObjCPropertyAccess,
bool AvoidPartialAvailabilityChecks) {
@@ -7769,7 +7843,7 @@ void Sema::DiagnoseAvailabilityOfDecl(NamedDecl *D, SourceLocation Loc,
}
const ObjCPropertyDecl *ObjCPDecl = nullptr;
- if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
if (const ObjCPropertyDecl *PD = MD->findPropertyDecl()) {
AvailabilityResult PDeclResult = PD->getAvailability(nullptr);
if (PDeclResult == Result)
@@ -7777,6 +7851,6 @@ void Sema::DiagnoseAvailabilityOfDecl(NamedDecl *D, SourceLocation Loc,
}
}
- EmitAvailabilityWarning(*this, Result, D, OffendingDecl, Message, Loc,
+ EmitAvailabilityWarning(*this, Result, D, OffendingDecl, Message, Locs,
UnknownObjCClass, ObjCPDecl, ObjCPropertyAccess);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
index 5e24649c71be..4cf3abdf5745 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/CharUnits.h"
+#include "clang/AST/ComparisonCategories.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecordLayout.h"
@@ -170,43 +171,40 @@ Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc,
if (EST == EST_None && Method->hasAttr<NoThrowAttr>())
EST = EST_BasicNoexcept;
- switch(EST) {
+ switch (EST) {
+ case EST_Unparsed:
+ case EST_Uninstantiated:
+ case EST_Unevaluated:
+ llvm_unreachable("should not see unresolved exception specs here");
+
// If this function can throw any exceptions, make a note of that.
case EST_MSAny:
case EST_None:
+ // FIXME: Whichever we see last of MSAny and None determines our result.
+ // We should make a consistent, order-independent choice here.
ClearExceptions();
ComputedEST = EST;
return;
+ case EST_NoexceptFalse:
+ ClearExceptions();
+ ComputedEST = EST_None;
+ return;
// FIXME: If the call to this decl is using any of its default arguments, we
// need to search them for potentially-throwing calls.
// If this function has a basic noexcept, it doesn't affect the outcome.
case EST_BasicNoexcept:
+ case EST_NoexceptTrue:
return;
- // If we're still at noexcept(true) and there's a nothrow() callee,
+ // If we're still at noexcept(true) and there's a throw() callee,
// change to that specification.
case EST_DynamicNone:
if (ComputedEST == EST_BasicNoexcept)
ComputedEST = EST_DynamicNone;
return;
- // Check out noexcept specs.
- case EST_ComputedNoexcept:
- {
- FunctionProtoType::NoexceptResult NR =
- Proto->getNoexceptSpec(Self->Context);
- assert(NR != FunctionProtoType::NR_NoNoexcept &&
- "Must have noexcept result for EST_ComputedNoexcept.");
- assert(NR != FunctionProtoType::NR_Dependent &&
- "Should not generate implicit declarations for dependent cases, "
- "and don't know how to handle them anyway.");
- // noexcept(false) -> no spec on the new function
- if (NR == FunctionProtoType::NR_Throw) {
- ClearExceptions();
- ComputedEST = EST_None;
- }
- // noexcept(true) won't change anything either.
- return;
- }
- default:
+ case EST_DependentNoexcept:
+ llvm_unreachable(
+ "should not generate implicit declarations for dependent cases");
+ case EST_Dynamic:
break;
}
assert(EST == EST_Dynamic && "EST case not considered earlier.");
@@ -1459,7 +1457,7 @@ void Sema::CheckCompleteDecompositionDeclaration(DecompositionDecl *DD) {
DD->setInvalidDecl();
}
-/// \brief Merge the exception specifications of two variable declarations.
+/// Merge the exception specifications of two variable declarations.
///
/// This is called when there's a redeclaration of a VarDecl. The function
/// checks if the redeclaration might have an exception specification and
@@ -1575,7 +1573,7 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef,
return true;
}
-/// \brief Get diagnostic %select index for tag kind for
+/// Get diagnostic %select index for tag kind for
/// record diagnostic message.
/// WARNING: Indexes apply to particular diagnostics only!
///
@@ -2061,27 +2059,39 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) {
return true;
}
+/// Get the class that is directly named by the current context. This is the
+/// class for which an unqualified-id in this scope could name a constructor
+/// or destructor.
+///
+/// If the scope specifier denotes a class, this will be that class.
+/// If the scope specifier is empty, this will be the class whose
+/// member-specification we are currently within. Otherwise, there
+/// is no such class.
+CXXRecordDecl *Sema::getCurrentClass(Scope *, const CXXScopeSpec *SS) {
+ assert(getLangOpts().CPlusPlus && "No class names in C!");
+
+ if (SS && SS->isInvalid())
+ return nullptr;
+
+ if (SS && SS->isNotEmpty()) {
+ DeclContext *DC = computeDeclContext(*SS, true);
+ return dyn_cast_or_null<CXXRecordDecl>(DC);
+ }
+
+ return dyn_cast_or_null<CXXRecordDecl>(CurContext);
+}
+
/// isCurrentClassName - Determine whether the identifier II is the
/// name of the class type currently being defined. In the case of
/// nested classes, this will only return true if II is the name of
/// the innermost class.
-bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *,
+bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *S,
const CXXScopeSpec *SS) {
- assert(getLangOpts().CPlusPlus && "No class names in C!");
-
- CXXRecordDecl *CurDecl;
- if (SS && SS->isSet() && !SS->isInvalid()) {
- DeclContext *DC = computeDeclContext(*SS, true);
- CurDecl = dyn_cast_or_null<CXXRecordDecl>(DC);
- } else
- CurDecl = dyn_cast_or_null<CXXRecordDecl>(CurContext);
-
- if (CurDecl && CurDecl->getIdentifier())
- return &II == CurDecl->getIdentifier();
- return false;
+ CXXRecordDecl *CurDecl = getCurrentClass(S, SS);
+ return CurDecl && &II == CurDecl->getIdentifier();
}
-/// \brief Determine whether the identifier II is a typo for the name of
+/// Determine whether the identifier II is a typo for the name of
/// the class type currently being defined. If so, update it to the identifier
/// that should have been used.
bool Sema::isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS) {
@@ -2107,7 +2117,7 @@ bool Sema::isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS) {
return false;
}
-/// \brief Determine whether the given class is a base class of the given
+/// Determine whether the given class is a base class of the given
/// class, including looking at dependent bases.
static bool findCircularInheritance(const CXXRecordDecl *Class,
const CXXRecordDecl *Current) {
@@ -2139,7 +2149,7 @@ static bool findCircularInheritance(const CXXRecordDecl *Class,
return false;
}
-/// \brief Check the validity of a C++ base class specifier.
+/// Check the validity of a C++ base class specifier.
///
/// \returns a new CXXBaseSpecifier if well-formed, emits diagnostics
/// and returns NULL otherwise.
@@ -2233,6 +2243,19 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
CXXRecordDecl *CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl);
assert(CXXBaseDecl && "Base type is not a C++ type");
+ // Microsoft docs say:
+ // "If a base-class has a code_seg attribute, derived classes must have the
+ // same attribute."
+ const auto *BaseCSA = CXXBaseDecl->getAttr<CodeSegAttr>();
+ const auto *DerivedCSA = Class->getAttr<CodeSegAttr>();
+ if ((DerivedCSA || BaseCSA) &&
+ (!BaseCSA || !DerivedCSA || BaseCSA->getName() != DerivedCSA->getName())) {
+ Diag(Class->getLocation(), diag::err_mismatched_code_seg_base);
+ Diag(CXXBaseDecl->getLocation(), diag::note_base_class_specified_here)
+ << CXXBaseDecl;
+ return nullptr;
+ }
+
// A class which contains a flexible array member is not suitable for use as a
// base class:
// - If the layout determines that a base comes before another base,
@@ -2290,18 +2313,13 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
// We do not support any C++11 attributes on base-specifiers yet.
// Diagnose any attributes we see.
- if (!Attributes.empty()) {
- for (AttributeList *Attr = Attributes.getList(); Attr;
- Attr = Attr->getNext()) {
- if (Attr->isInvalid() ||
- Attr->getKind() == AttributeList::IgnoredAttribute)
- continue;
- Diag(Attr->getLoc(),
- Attr->getKind() == AttributeList::UnknownAttribute
- ? diag::warn_unknown_attribute_ignored
- : diag::err_base_specifier_attribute)
- << Attr->getName();
- }
+ for (const ParsedAttr &AL : Attributes) {
+ 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)
+ << AL.getName();
}
TypeSourceInfo *TInfo = nullptr;
@@ -2326,7 +2344,7 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
/// locally, there's no need to abstract the small size parameter.
typedef llvm::SmallPtrSet<QualType, 4> IndirectBaseSet;
-/// \brief Recursively add the bases of Type. Don't add Type itself.
+/// Recursively add the bases of Type. Don't add Type itself.
static void
NoteIndirectBases(ASTContext &Context, IndirectBaseSet &Set,
const QualType &Type)
@@ -2347,7 +2365,7 @@ NoteIndirectBases(ASTContext &Context, IndirectBaseSet &Set,
}
}
-/// \brief Performs the actual work of attaching the given base class
+/// Performs the actual work of attaching the given base class
/// specifiers to a C++ class.
bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class,
MutableArrayRef<CXXBaseSpecifier *> Bases) {
@@ -2404,7 +2422,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class,
// 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->getName()
+ << getRecordDiagFromTagKind(RD->getTagKind()) << RD
<< RD->getSourceRange();
Invalid = true;
}
@@ -2417,9 +2435,16 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class,
// Attach the remaining base class specifiers to the derived class.
Class->setBases(Bases.data(), NumGoodBases);
+ // Check that the only base classes that are duplicate are virtual.
for (unsigned idx = 0; idx < NumGoodBases; ++idx) {
// Check whether this direct base is inaccessible due to ambiguity.
QualType BaseType = Bases[idx]->getType();
+
+ // Skip all dependent types in templates being used as base specifiers.
+ // Checks below assume that the base specifier is a CXXRecord.
+ if (BaseType->isDependentType())
+ continue;
+
CanQualType CanonicalBase = Context.getCanonicalType(BaseType)
.getUnqualifiedType();
@@ -2459,7 +2484,7 @@ void Sema::ActOnBaseSpecifiers(Decl *ClassDecl,
AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl), Bases);
}
-/// \brief Determine whether the type \p Derived is a C++ class that is
+/// Determine whether the type \p Derived is a C++ class that is
/// derived from the type \p Base.
bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base) {
if (!getLangOpts().CPlusPlus)
@@ -2486,7 +2511,7 @@ bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base) {
return DerivedRD->isDerivedFrom(BaseRD);
}
-/// \brief Determine whether the type \p Derived is a C++ class that is
+/// Determine whether the type \p Derived is a C++ class that is
/// derived from the type \p Base.
bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base,
CXXBasePaths &Paths) {
@@ -2638,7 +2663,7 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
}
-/// @brief Builds a string representing ambiguous paths from a
+/// Builds a string representing ambiguous paths from a
/// specific derived class to different subobjects of the same base
/// class.
///
@@ -2674,10 +2699,9 @@ std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) {
//===----------------------------------------------------------------------===//
/// ActOnAccessSpecifier - Parsed an access specifier followed by a colon.
-bool Sema::ActOnAccessSpecifier(AccessSpecifier Access,
- SourceLocation ASLoc,
+bool Sema::ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc,
SourceLocation ColonLoc,
- AttributeList *Attrs) {
+ const ParsedAttributesView &Attrs) {
assert(Access != AS_none && "Invalid kind for syntactic access specifier!");
AccessSpecDecl *ASDecl = AccessSpecDecl::Create(Context, Access, CurContext,
ASLoc, ColonLoc);
@@ -2764,7 +2788,7 @@ void Sema::DiagnoseAbsenceOfOverrideControl(NamedDecl *D) {
SourceLocation Loc = MD->getLocation();
SourceLocation SpellingLoc = Loc;
if (getSourceManager().isMacroArgExpansion(Loc))
- SpellingLoc = getSourceManager().getImmediateExpansionRange(Loc).first;
+ SpellingLoc = getSourceManager().getImmediateExpansionRange(Loc).getBegin();
SpellingLoc = getSourceManager().getSpellingLoc(SpellingLoc);
if (SpellingLoc.isValid() && getSourceManager().isInSystemHeader(SpellingLoc))
return;
@@ -2805,10 +2829,13 @@ static bool InitializationHasSideEffects(const FieldDecl &FD) {
return false;
}
-static AttributeList *getMSPropertyAttr(AttributeList *list) {
- for (AttributeList *it = list; it != nullptr; it = it->getNext())
- if (it->isDeclspecPropertyAttribute())
- return it;
+static const ParsedAttr *getMSPropertyAttr(const ParsedAttributesView &list) {
+ ParsedAttributesView::const_iterator Itr =
+ llvm::find_if(list, [](const ParsedAttr &AL) {
+ return AL.isDeclspecPropertyAttribute();
+ });
+ if (Itr != list.end())
+ return &*Itr;
return nullptr;
}
@@ -2855,7 +2882,7 @@ void Sema::CheckShadowInheritedFields(const SourceLocation &Loc,
if (AS_none !=
CXXRecordDecl::MergeAccess(P.Access, BaseField->getAccess())) {
Diag(Loc, diag::warn_shadow_field)
- << FieldName.getAsString() << RD->getName() << Base->getName();
+ << FieldName << RD << Base;
Diag(BaseField->getLocation(), diag::note_shadow_field);
Bases.erase(It);
}
@@ -2887,8 +2914,8 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
assert(!DS.isFriendSpecified());
bool isFunc = D.isDeclarationOfFunction();
- AttributeList *MSPropertyAttr =
- getMSPropertyAttr(D.getDeclSpec().getAttributes().getList());
+ const ParsedAttr *MSPropertyAttr =
+ getMSPropertyAttr(D.getDeclSpec().getAttributes());
if (cast<CXXRecordDecl>(CurContext)->isInterface()) {
// The Microsoft extension __interface only permits public member functions
@@ -3044,7 +3071,9 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
// int X::member;
// };
if (DeclContext *DC = computeDeclContext(SS, false))
- diagnoseQualifiedDeclaration(SS, DC, Name, D.getIdentifierLoc());
+ diagnoseQualifiedDeclaration(SS, DC, Name, D.getIdentifierLoc(),
+ D.getName().getKind() ==
+ UnqualifiedIdKind::IK_TemplateId);
else
Diag(D.getIdentifierLoc(), diag::err_member_qualification)
<< Name << SS.getRange();
@@ -3054,7 +3083,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
if (MSPropertyAttr) {
Member = HandleMSProperty(S, cast<CXXRecordDecl>(CurContext), Loc, D,
- BitWidth, InitStyle, AS, MSPropertyAttr);
+ BitWidth, InitStyle, AS, *MSPropertyAttr);
if (!Member)
return nullptr;
isInstField = false;
@@ -3096,14 +3125,38 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
Member->setInvalidDecl();
}
+ NamedDecl *NonTemplateMember = Member;
+ if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Member))
+ NonTemplateMember = FunTmpl->getTemplatedDecl();
+ else if (VarTemplateDecl *VarTmpl = dyn_cast<VarTemplateDecl>(Member))
+ NonTemplateMember = VarTmpl->getTemplatedDecl();
+
Member->setAccess(AS);
// If we have declared a member function template or static data member
// template, set the access of the templated declaration as well.
- if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Member))
- FunTmpl->getTemplatedDecl()->setAccess(AS);
- else if (VarTemplateDecl *VarTmpl = dyn_cast<VarTemplateDecl>(Member))
- VarTmpl->getTemplatedDecl()->setAccess(AS);
+ if (NonTemplateMember != Member)
+ NonTemplateMember->setAccess(AS);
+
+ // C++ [temp.deduct.guide]p3:
+ // A deduction guide [...] for a member class template [shall be
+ // declared] with the same access [as the template].
+ 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();
+ 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;
+ }
+ }
}
if (VS.isOverrideSpecified())
@@ -3544,7 +3597,7 @@ namespace {
}
} // namespace
-/// \brief Enter a new C++ default initializer scope. After calling this, the
+/// Enter a new C++ default initializer scope. After calling this, the
/// caller must call \ref ActOnFinishCXXInClassMemberInitializer, even if
/// parsing or instantiating the initializer failed.
void Sema::ActOnStartCXXInClassMemberInitializer() {
@@ -3553,7 +3606,7 @@ void Sema::ActOnStartCXXInClassMemberInitializer() {
PushFunctionScope();
}
-/// \brief This is invoked after parsing an in-class initializer for a
+/// This is invoked after parsing an in-class initializer for a
/// non-static C++ class member, and after instantiating an in-class initializer
/// in a class template. Such actions are deferred until the class is complete.
void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D,
@@ -3581,10 +3634,14 @@ void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D,
ExprResult Init = InitExpr;
if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) {
- InitializedEntity Entity = InitializedEntity::InitializeMember(FD);
- InitializationKind Kind = FD->getInClassInitStyle() == ICIS_ListInit
- ? InitializationKind::CreateDirectList(InitExpr->getLocStart())
- : InitializationKind::CreateCopy(InitExpr->getLocStart(), InitLoc);
+ InitializedEntity Entity =
+ InitializedEntity::InitializeMemberFromDefaultMemberInitializer(FD);
+ InitializationKind Kind =
+ FD->getInClassInitStyle() == ICIS_ListInit
+ ? InitializationKind::CreateDirectList(InitExpr->getLocStart(),
+ InitExpr->getLocStart(),
+ InitExpr->getLocEnd())
+ : InitializationKind::CreateCopy(InitExpr->getLocStart(), InitLoc);
InitializationSequence Seq(*this, Entity, Kind, InitExpr);
Init = Seq.Perform(*this, Entity, Kind, InitExpr);
if (Init.isInvalid()) {
@@ -3607,7 +3664,7 @@ void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D,
FD->setInClassInitializer(InitExpr);
}
-/// \brief Find the direct and/or virtual base specifiers that
+/// Find the direct and/or virtual base specifiers that
/// correspond to the given base type, for use in base initialization
/// within a constructor.
static bool FindBaseInitializer(Sema &SemaRef,
@@ -3651,7 +3708,7 @@ static bool FindBaseInitializer(Sema &SemaRef,
return DirectBaseSpec || VirtualBaseSpec;
}
-/// \brief Handle a C++ member initializer using braced-init-list syntax.
+/// Handle a C++ member initializer using braced-init-list syntax.
MemInitResult
Sema::ActOnMemInitializer(Decl *ConstructorD,
Scope *S,
@@ -3667,7 +3724,7 @@ Sema::ActOnMemInitializer(Decl *ConstructorD,
EllipsisLoc);
}
-/// \brief Handle a C++ member initializer using parentheses syntax.
+/// Handle a C++ member initializer using parentheses syntax.
MemInitResult
Sema::ActOnMemInitializer(Decl *ConstructorD,
Scope *S,
@@ -3710,7 +3767,7 @@ private:
}
-/// \brief Handle a C++ member initializer.
+/// Handle a C++ member initializer.
MemInitResult
Sema::BuildMemInitializer(Decl *ConstructorD,
Scope *S,
@@ -3889,53 +3946,6 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
return BuildBaseInitializer(BaseType, TInfo, Init, ClassDecl, EllipsisLoc);
}
-/// Checks a member initializer expression for cases where reference (or
-/// pointer) members are bound to by-value parameters (or their addresses).
-static void CheckForDanglingReferenceOrPointer(Sema &S, ValueDecl *Member,
- Expr *Init,
- SourceLocation IdLoc) {
- QualType MemberTy = Member->getType();
-
- // We only handle pointers and references currently.
- // FIXME: Would this be relevant for ObjC object pointers? Or block pointers?
- if (!MemberTy->isReferenceType() && !MemberTy->isPointerType())
- return;
-
- const bool IsPointer = MemberTy->isPointerType();
- if (IsPointer) {
- if (const UnaryOperator *Op
- = dyn_cast<UnaryOperator>(Init->IgnoreParenImpCasts())) {
- // The only case we're worried about with pointers requires taking the
- // address.
- if (Op->getOpcode() != UO_AddrOf)
- return;
-
- Init = Op->getSubExpr();
- } else {
- // We only handle address-of expression initializers for pointers.
- return;
- }
- }
-
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Init->IgnoreParens())) {
- // We only warn when referring to a non-reference parameter declaration.
- const ParmVarDecl *Parameter = dyn_cast<ParmVarDecl>(DRE->getDecl());
- if (!Parameter || Parameter->getType()->isReferenceType())
- return;
-
- S.Diag(Init->getExprLoc(),
- IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
- : diag::warn_bind_ref_member_to_parameter)
- << Member << Parameter << Init->getSourceRange();
- } else {
- // Other initializers are fine.
- return;
- }
-
- S.Diag(Member->getLocation(), diag::note_ref_or_ptr_member_declared_here)
- << (unsigned)IsPointer;
-}
-
MemInitResult
Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
SourceLocation IdLoc) {
@@ -3979,9 +3989,10 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
: InitializedEntity::InitializeMember(IndirectMember,
nullptr);
InitializationKind Kind =
- InitList ? InitializationKind::CreateDirectList(IdLoc)
- : InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(),
- InitRange.getEnd());
+ InitList ? InitializationKind::CreateDirectList(
+ IdLoc, Init->getLocStart(), Init->getLocEnd())
+ : InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(),
+ InitRange.getEnd());
InitializationSequence InitSeq(*this, MemberEntity, Kind, Args);
ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind, Args,
@@ -3989,8 +4000,6 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
if (MemberInit.isInvalid())
return true;
- CheckForDanglingReferenceOrPointer(*this, Member, MemberInit.get(), IdLoc);
-
// C++11 [class.base.init]p7:
// The initialization of each base and member constitutes a
// full-expression.
@@ -4033,9 +4042,10 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init,
InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation(
QualType(ClassDecl->getTypeForDecl(), 0));
InitializationKind Kind =
- InitList ? InitializationKind::CreateDirectList(NameLoc)
- : InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(),
- InitRange.getEnd());
+ InitList ? InitializationKind::CreateDirectList(
+ NameLoc, Init->getLocStart(), Init->getLocEnd())
+ : InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(),
+ InitRange.getEnd());
InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args);
ExprResult DelegationInit = InitSeq.Perform(*this, DelegationEntity, Kind,
Args, nullptr);
@@ -4167,9 +4177,9 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
InitializedEntity BaseEntity =
InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec);
InitializationKind Kind =
- InitList ? InitializationKind::CreateDirectList(BaseLoc)
- : InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(),
- InitRange.getEnd());
+ InitList ? InitializationKind::CreateDirectList(BaseLoc)
+ : InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(),
+ InitRange.getEnd());
InitializationSequence InitSeq(*this, BaseEntity, Kind, Args);
ExprResult BaseInit = InitSeq.Perform(*this, BaseEntity, Kind, Args, nullptr);
if (BaseInit.isInvalid())
@@ -4321,7 +4331,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
QualType ParamType = Param->getType().getNonReferenceType();
// Suppress copying zero-width bitfields.
- if (Field->isBitField() && Field->getBitWidthValue(SemaRef.Context) == 0)
+ if (Field->isZeroLengthBitField(SemaRef.Context))
return false;
Expr *MemberExprBase =
@@ -4536,7 +4546,7 @@ struct BaseAndFieldInfo {
return !FieldRD->hasInClassInitializer();
}
- /// \brief Determine whether the given field is, or is within, a union member
+ /// Determine whether the given field is, or is within, a union member
/// that is inactive (because there was an initializer given for a different
/// member of the union, or because the union was not initialized at all).
bool isWithinInactiveUnionMember(FieldDecl *Field,
@@ -4554,7 +4564,7 @@ struct BaseAndFieldInfo {
};
}
-/// \brief Determine whether the given type is an incomplete or zero-lenfgth
+/// Determine whether the given type is an incomplete or zero-lenfgth
/// array type.
static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) {
if (T->isIncompleteArrayType())
@@ -4601,6 +4611,10 @@ static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
SemaRef.BuildCXXDefaultInitExpr(Info.Ctor->getLocation(), Field);
if (DIE.isInvalid())
return true;
+
+ auto Entity = InitializedEntity::InitializeMember(Field, nullptr, true);
+ SemaRef.checkInitializerLifetime(Entity, DIE.get());
+
CXXCtorInitializer *Init;
if (Indirect)
Init = new (SemaRef.Context)
@@ -5464,7 +5478,7 @@ static void CheckAbstractClassUsage(AbstractUsageInfo &Info,
}
}
-static void ReferenceDllExportedMethods(Sema &S, CXXRecordDecl *Class) {
+static void ReferenceDllExportedMembers(Sema &S, CXXRecordDecl *Class) {
Attr *ClassAttr = getDLLAttr(Class);
if (!ClassAttr)
return;
@@ -5479,6 +5493,14 @@ static void ReferenceDllExportedMethods(Sema &S, CXXRecordDecl *Class) {
return;
for (Decl *Member : Class->decls()) {
+ // Defined static variables that are members of an exported base
+ // class must be marked export too.
+ auto *VD = dyn_cast<VarDecl>(Member);
+ if (VD && Member->getAttr<DLLExportAttr>() &&
+ VD->getStorageClass() == SC_Static &&
+ TSK == TSK_ImplicitInstantiation)
+ S.MarkVariableReferenced(VD->getLocation(), VD);
+
auto *MD = dyn_cast<CXXMethodDecl>(Member);
if (!MD)
continue;
@@ -5506,7 +5528,7 @@ static void ReferenceDllExportedMethods(Sema &S, CXXRecordDecl *Class) {
S.MarkFunctionReferenced(Class->getLocation(), MD);
if (Trap.hasErrorOccurred()) {
S.Diag(ClassAttr->getLocation(), diag::note_due_to_dllexported_class)
- << Class->getName() << !S.getLangOpts().CPlusPlus11;
+ << Class << !S.getLangOpts().CPlusPlus11;
break;
}
@@ -5556,7 +5578,17 @@ static void checkForMultipleExportedDefaultConstructors(Sema &S,
}
}
-/// \brief Check class-level dllimport/dllexport attribute.
+void Sema::checkClassLevelCodeSegAttribute(CXXRecordDecl *Class) {
+ // Mark any compiler-generated routines with the implicit code_seg attribute.
+ for (auto *Method : Class->methods()) {
+ if (Method->isUserProvided())
+ continue;
+ if (Attr *A = getImplicitCodeSegOrSectionAttrForFunction(Method, /*IsDefinition=*/true))
+ Method->addAttr(A);
+ }
+}
+
+/// Check class-level dllimport/dllexport attribute.
void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
Attr *ClassAttr = getDLLAttr(Class);
@@ -5606,6 +5638,13 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
// The class is either imported or exported.
const bool ClassExported = ClassAttr->getKind() == attr::DLLExport;
+ // Check if this was a dllimport attribute propagated from a derived class to
+ // a base class template specialization. We don't apply these attributes to
+ // static data members.
+ const bool PropagatedImport =
+ !ClassExported &&
+ cast<DLLImportAttr>(ClassAttr)->wasPropagatedToBaseTemplate();
+
TemplateSpecializationKind TSK = Class->getTemplateSpecializationKind();
// Ignore explicit dllexport on explicit class template instantiation declarations.
@@ -5657,6 +5696,11 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
}
}
+ // Don't apply dllimport attributes to static data members of class template
+ // instantiations when the attribute is propagated from a derived class.
+ if (VD && PropagatedImport)
+ continue;
+
if (!cast<NamedDecl>(Member)->isExternallyVisible())
continue;
@@ -5665,6 +5709,21 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
NewAttr->setInherited(true);
Member->addAttr(NewAttr);
+
+ if (MD) {
+ // Propagate DLLAttr to friend re-declarations of MD that have already
+ // been constructed.
+ for (FunctionDecl *FD = MD->getMostRecentDecl(); FD;
+ FD = FD->getPreviousDecl()) {
+ if (FD->getFriendObjectKind() == Decl::FOK_None)
+ continue;
+ assert(!getDLLAttr(FD) &&
+ "friend re-decl should not already have a DLLAttr");
+ NewAttr = cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
+ NewAttr->setInherited(true);
+ FD->addAttr(NewAttr);
+ }
+ }
}
}
@@ -5672,7 +5731,7 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
DelayedDllExportClasses.push_back(Class);
}
-/// \brief Perform propagation of DLL attributes from a derived class to a
+/// Perform propagation of DLL attributes from a derived class to a
/// templated base class for MS compatibility.
void Sema::propagateDLLAttrToBaseClassTemplate(
CXXRecordDecl *Class, Attr *ClassAttr,
@@ -5694,6 +5753,11 @@ void Sema::propagateDLLAttrToBaseClassTemplate(
NewAttr->setInherited(true);
BaseTemplateSpec->addAttr(NewAttr);
+ // If this was an import, mark that we propagated it from a derived class to
+ // a base class template specialization.
+ if (auto *ImportAttr = dyn_cast<DLLImportAttr>(NewAttr))
+ ImportAttr->setPropagatedToBaseTemplate();
+
// If the template is already instantiated, checkDLLAttributeRedeclaration()
// needs to be run again to work see the new attribute. Otherwise this will
// get run whenever the template is instantiated.
@@ -5756,10 +5820,74 @@ static void DefineImplicitSpecialMember(Sema &S, CXXMethodDecl *MD,
/// Determine whether a type is permitted to be passed or returned in
/// registers, per C++ [class.temporary]p3.
-static bool computeCanPassInRegisters(Sema &S, CXXRecordDecl *D) {
+static bool canPassInRegisters(Sema &S, CXXRecordDecl *D,
+ TargetInfo::CallingConvKind CCK) {
if (D->isDependentType() || D->isInvalidDecl())
return false;
+ // 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)
+ return !D->hasNonTrivialDestructorForCall() &&
+ !D->hasNonTrivialCopyConstructorForCall();
+
+ if (CCK == TargetInfo::CCK_MicrosoftWin64) {
+ bool CopyCtorIsTrivial = false, CopyCtorIsTrivialForCall = false;
+ bool DtorIsTrivialForCall = false;
+
+ // If a class has at least one non-deleted, trivial copy constructor, it
+ // is passed according to the C ABI. Otherwise, it is passed indirectly.
+ //
+ // Note: This permits classes with non-trivial copy or move ctors to be
+ // passed in registers, so long as they *also* have a trivial copy ctor,
+ // which is non-conforming.
+ if (D->needsImplicitCopyConstructor()) {
+ if (!D->defaultedCopyConstructorIsDeleted()) {
+ if (D->hasTrivialCopyConstructor())
+ CopyCtorIsTrivial = true;
+ if (D->hasTrivialCopyConstructorForCall())
+ CopyCtorIsTrivialForCall = true;
+ }
+ } else {
+ for (const CXXConstructorDecl *CD : D->ctors()) {
+ if (CD->isCopyConstructor() && !CD->isDeleted()) {
+ if (CD->isTrivial())
+ CopyCtorIsTrivial = true;
+ if (CD->isTrivialForCall())
+ CopyCtorIsTrivialForCall = true;
+ }
+ }
+ }
+
+ if (D->needsImplicitDestructor()) {
+ if (!D->defaultedDestructorIsDeleted() &&
+ D->hasTrivialDestructorForCall())
+ DtorIsTrivialForCall = true;
+ } else if (const auto *DD = D->getDestructor()) {
+ if (!DD->isDeleted() && DD->isTrivialForCall())
+ DtorIsTrivialForCall = true;
+ }
+
+ // If the copy ctor and dtor are both trivial-for-calls, pass direct.
+ if (CopyCtorIsTrivialForCall && DtorIsTrivialForCall)
+ return true;
+
+ // If a class has a destructor, we'd really like to pass it indirectly
+ // because it allows us to elide copies. Unfortunately, MSVC makes that
+ // impossible for small types, which it will pass in a single register or
+ // stack slot. Most objects with dtors are large-ish, so handle that early.
+ // We can't call out all large objects as being indirect because there are
+ // multiple x64 calling conventions and the C++ ABI code shouldn't dictate
+ // how we pass large POD types.
+
+ // Note: This permits small classes with nontrivial destructors to be
+ // passed in registers, which is non-conforming.
+ if (CopyCtorIsTrivial &&
+ S.getASTContext().getTypeSize(D->getTypeForDecl()) <= 64)
+ return true;
+ return false;
+ }
+
// Per C++ [class.temporary]p3, the relevant condition is:
// each copy constructor, move constructor, and destructor of X is
// either trivial or deleted, and X has at least one non-deleted copy
@@ -5768,20 +5896,20 @@ static bool computeCanPassInRegisters(Sema &S, CXXRecordDecl *D) {
if (D->needsImplicitCopyConstructor() &&
!D->defaultedCopyConstructorIsDeleted()) {
- if (!D->hasTrivialCopyConstructor())
+ if (!D->hasTrivialCopyConstructorForCall())
return false;
HasNonDeletedCopyOrMove = true;
}
if (S.getLangOpts().CPlusPlus11 && D->needsImplicitMoveConstructor() &&
!D->defaultedMoveConstructorIsDeleted()) {
- if (!D->hasTrivialMoveConstructor())
+ if (!D->hasTrivialMoveConstructorForCall())
return false;
HasNonDeletedCopyOrMove = true;
}
if (D->needsImplicitDestructor() && !D->defaultedDestructorIsDeleted() &&
- !D->hasTrivialDestructor())
+ !D->hasTrivialDestructorForCall())
return false;
for (const CXXMethodDecl *MD : D->methods()) {
@@ -5794,14 +5922,14 @@ static bool computeCanPassInRegisters(Sema &S, CXXRecordDecl *D) {
else if (!isa<CXXDestructorDecl>(MD))
continue;
- if (!MD->isTrivial())
+ if (!MD->isTrivialForCall())
return false;
}
return HasNonDeletedCopyOrMove;
}
-/// \brief Perform semantic checks on a class definition that has been
+/// Perform semantic checks on a class definition that has been
/// completing, introducing implicitly-declared members, checking for
/// abstract types, etc.
void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
@@ -5851,10 +5979,11 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
DeclContext::lookup_result R = Record->lookup(Record->getDeclName());
for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
++I) {
- NamedDecl *D = *I;
- if ((isa<FieldDecl>(D) && Record->hasUserDeclaredConstructor()) ||
+ NamedDecl *D = (*I)->getUnderlyingDecl();
+ if (((isa<FieldDecl>(D) || isa<UnresolvedUsingValueDecl>(D)) &&
+ Record->hasUserDeclaredConstructor()) ||
isa<IndirectFieldDecl>(D)) {
- Diag(D->getLocation(), diag::err_member_name_of_class)
+ Diag((*I)->getLocation(), diag::err_member_name_of_class)
<< D->getDeclName();
break;
}
@@ -5878,6 +6007,17 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
}
}
+ // See if trivial_abi has to be dropped.
+ if (Record->hasAttr<TrivialABIAttr>())
+ checkIllFormedTrivialABIStruct(*Record);
+
+ // Set HasTrivialSpecialMemberForCall if the record has attribute
+ // "trivial_abi".
+ bool HasTrivialABI = Record->hasAttr<TrivialABIAttr>();
+
+ if (HasTrivialABI)
+ Record->setHasTrivialSpecialMemberForCall();
+
bool HasMethodWithOverrideControl = false,
HasOverridingMethodWithoutOverrideControl = false;
if (!Record->isDependentType()) {
@@ -5900,12 +6040,23 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
if (!M->isImplicit() && !M->isUserProvided()) {
if (CSM != CXXInvalid) {
M->setTrivial(SpecialMemberIsTrivial(M, CSM));
-
// Inform the class that we've finished declaring this member.
Record->finishedDefaultedOrDeletedMember(M);
+ M->setTrivialForCall(
+ HasTrivialABI ||
+ SpecialMemberIsTrivial(M, CSM, TAH_ConsiderTrivialABI));
+ Record->setTrivialForCallFlags(M);
}
}
+ // Set triviality for the purpose of calls if this is a user-provided
+ // copy/move constructor or destructor.
+ if ((CSM == CXXCopyConstructor || CSM == CXXMoveConstructor ||
+ CSM == CXXDestructor) && M->isUserProvided()) {
+ M->setTrivialForCall(HasTrivialABI);
+ Record->setTrivialForCallFlags(M);
+ }
+
if (!M->isInvalidDecl() && M->isExplicitlyDefaulted() &&
M->hasAttr<DLLExportAttr>()) {
if (getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) &&
@@ -5945,8 +6096,35 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
}
checkClassLevelDLLAttribute(Record);
+ checkClassLevelCodeSegAttribute(Record);
- Record->setCanPassInRegisters(computeCanPassInRegisters(*this, Record));
+ bool ClangABICompat4 =
+ Context.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver4;
+ TargetInfo::CallingConvKind CCK =
+ Context.getTargetInfo().getCallingConvKind(ClangABICompat4);
+ bool CanPass = canPassInRegisters(*this, Record, CCK);
+
+ // Do not change ArgPassingRestrictions if it has already been set to
+ // APK_CanNeverPassInRegs.
+ if (Record->getArgPassingRestrictions() != RecordDecl::APK_CanNeverPassInRegs)
+ Record->setArgPassingRestrictions(CanPass
+ ? RecordDecl::APK_CanPassInRegs
+ : RecordDecl::APK_CannotPassInRegs);
+
+ // If canPassInRegisters returns true despite the record having a non-trivial
+ // destructor, the record is destructed in the callee. This happens only when
+ // the record or one of its subobjects has a field annotated with trivial_abi
+ // or a field qualified with ObjC __strong/__weak.
+ if (Context.getTargetInfo().getCXXABI().areArgsDestroyedLeftToRightInCallee())
+ Record->setParamDestroyedInCallee(true);
+ else if (Record->hasNonTrivialDestructor())
+ Record->setParamDestroyedInCallee(CanPass);
+
+ if (getLangOpts().ForceEmitVTables) {
+ // If we want to emit all the vtables, we need to mark it as used. This
+ // is especially required for cases like vtable assumption loads.
+ MarkVTableUsed(Record->getInnerLocStart(), Record);
+ }
}
/// Look up the special member function that would be called by a special
@@ -7017,9 +7195,14 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
///
/// If \p Selected is not \c NULL, \c *Selected will be filled in with the
/// member that was most likely to be intended to be trivial, if any.
+///
+/// If \p ForCall is true, look at CXXRecord::HasTrivialSpecialMembersForCall to
+/// determine whether the special member is trivial.
static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
Sema::CXXSpecialMember CSM, unsigned Quals,
- bool ConstRHS, CXXMethodDecl **Selected) {
+ bool ConstRHS,
+ Sema::TrivialABIHandling TAH,
+ CXXMethodDecl **Selected) {
if (Selected)
*Selected = nullptr;
@@ -7060,7 +7243,9 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
// C++11 [class.dtor]p5:
// A destructor is trivial if:
// - all the direct [subobjects] have trivial destructors
- if (RD->hasTrivialDestructor())
+ if (RD->hasTrivialDestructor() ||
+ (TAH == Sema::TAH_ConsiderTrivialABI &&
+ RD->hasTrivialDestructorForCall()))
return true;
if (Selected) {
@@ -7075,7 +7260,9 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
// C++11 [class.copy]p12:
// A copy constructor is trivial if:
// - the constructor selected to copy each direct [subobject] is trivial
- if (RD->hasTrivialCopyConstructor()) {
+ if (RD->hasTrivialCopyConstructor() ||
+ (TAH == Sema::TAH_ConsiderTrivialABI &&
+ RD->hasTrivialCopyConstructorForCall())) {
if (Quals == Qualifiers::Const)
// We must either select the trivial copy constructor or reach an
// ambiguity; no need to actually perform overload resolution.
@@ -7128,6 +7315,10 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
// not supposed to!
if (Selected)
*Selected = SMOR.getMethod();
+
+ if (TAH == Sema::TAH_ConsiderTrivialABI &&
+ (CSM == Sema::CXXCopyConstructor || CSM == Sema::CXXMoveConstructor))
+ return SMOR.getMethod()->isTrivialForCall();
return SMOR.getMethod()->isTrivial();
}
@@ -7166,14 +7357,14 @@ static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc,
QualType SubType, bool ConstRHS,
Sema::CXXSpecialMember CSM,
TrivialSubobjectKind Kind,
- bool Diagnose) {
+ Sema::TrivialABIHandling TAH, bool Diagnose) {
CXXRecordDecl *SubRD = SubType->getAsCXXRecordDecl();
if (!SubRD)
return true;
CXXMethodDecl *Selected;
if (findTrivialSpecialMember(S, SubRD, CSM, SubType.getCVRQualifiers(),
- ConstRHS, Diagnose ? &Selected : nullptr))
+ ConstRHS, TAH, Diagnose ? &Selected : nullptr))
return true;
if (Diagnose) {
@@ -7203,7 +7394,8 @@ static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc,
<< Kind << SubType.getUnqualifiedType() << CSM;
// Explain why the defaulted or deleted special member isn't trivial.
- S.SpecialMemberIsTrivial(Selected, CSM, Diagnose);
+ S.SpecialMemberIsTrivial(Selected, CSM, Sema::TAH_IgnoreTrivialABI,
+ Diagnose);
}
}
@@ -7214,7 +7406,9 @@ static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc,
/// trivial.
static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD,
Sema::CXXSpecialMember CSM,
- bool ConstArg, bool Diagnose) {
+ bool ConstArg,
+ Sema::TrivialABIHandling TAH,
+ bool Diagnose) {
for (const auto *FI : RD->fields()) {
if (FI->isInvalidDecl() || FI->isUnnamedBitfield())
continue;
@@ -7224,7 +7418,7 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD,
// Pretend anonymous struct or union members are members of this class.
if (FI->isAnonymousStructOrUnion()) {
if (!checkTrivialClassMembers(S, FieldType->getAsCXXRecordDecl(),
- CSM, ConstArg, Diagnose))
+ CSM, ConstArg, TAH, Diagnose))
return false;
continue;
}
@@ -7252,7 +7446,7 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD,
bool ConstRHS = ConstArg && !FI->isMutable();
if (!checkTrivialSubobjectCall(S, FI->getLocation(), FieldType, ConstRHS,
- CSM, TSK_Field, Diagnose))
+ CSM, TSK_Field, TAH, Diagnose))
return false;
}
@@ -7266,14 +7460,15 @@ void Sema::DiagnoseNontrivial(const CXXRecordDecl *RD, CXXSpecialMember CSM) {
bool ConstArg = (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment);
checkTrivialSubobjectCall(*this, RD->getLocation(), Ty, ConstArg, CSM,
- TSK_CompleteObject, /*Diagnose*/true);
+ TSK_CompleteObject, TAH_IgnoreTrivialABI,
+ /*Diagnose*/true);
}
/// Determine whether a defaulted or deleted special member function is trivial,
/// as specified in C++11 [class.ctor]p5, C++11 [class.copy]p12,
/// C++11 [class.copy]p25, and C++11 [class.dtor]p5.
bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
- bool Diagnose) {
+ TrivialABIHandling TAH, bool Diagnose) {
assert(!MD->isUserProvided() && CSM != CXXInvalid && "not special enough");
CXXRecordDecl *RD = MD->getParent();
@@ -7350,7 +7545,7 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
// destructors]
for (const auto &BI : RD->bases())
if (!checkTrivialSubobjectCall(*this, BI.getLocStart(), BI.getType(),
- ConstArg, CSM, TSK_BaseClass, Diagnose))
+ ConstArg, CSM, TSK_BaseClass, TAH, Diagnose))
return false;
// C++11 [class.ctor]p5, C++11 [class.dtor]p5:
@@ -7365,7 +7560,7 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
// -- for all of the non-static data members of its class that are of class
// type (or array thereof), each such class has a trivial [default
// constructor or destructor]
- if (!checkTrivialClassMembers(*this, RD, CSM, ConstArg, Diagnose))
+ if (!checkTrivialClassMembers(*this, RD, CSM, ConstArg, TAH, Diagnose))
return false;
// C++11 [class.dtor]p5:
@@ -7477,7 +7672,7 @@ public:
};
} // end anonymous namespace
-/// \brief Add the most overriden methods from MD to Methods
+/// Add the most overriden methods from MD to Methods
static void AddMostOverridenMethods(const CXXMethodDecl *MD,
llvm::SmallPtrSetImpl<const CXXMethodDecl *>& Methods) {
if (MD->size_overridden_methods() == 0)
@@ -7487,7 +7682,7 @@ static void AddMostOverridenMethods(const CXXMethodDecl *MD,
AddMostOverridenMethods(O, Methods);
}
-/// \brief Check if a method overloads virtual methods in a base class without
+/// Check if a method overloads virtual methods in a base class without
/// overriding any.
void Sema::FindHiddenVirtualMethods(CXXMethodDecl *MD,
SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods) {
@@ -7528,7 +7723,7 @@ void Sema::NoteHiddenVirtualMethods(CXXMethodDecl *MD,
}
}
-/// \brief Diagnose methods which overload virtual methods in a base class
+/// Diagnose methods which overload virtual methods in a base class
/// without overriding any.
void Sema::DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD) {
if (MD->isInvalidDecl())
@@ -7547,22 +7742,64 @@ void Sema::DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD) {
}
}
-void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
- Decl *TagDecl,
- SourceLocation LBrac,
- SourceLocation RBrac,
- AttributeList *AttrList) {
+void Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl &RD) {
+ auto PrintDiagAndRemoveAttr = [&]() {
+ // No diagnostics if this is a template instantiation.
+ if (!isTemplateInstantiation(RD.getTemplateSpecializationKind()))
+ Diag(RD.getAttr<TrivialABIAttr>()->getLocation(),
+ diag::ext_cannot_use_trivial_abi) << &RD;
+ RD.dropAttr<TrivialABIAttr>();
+ };
+
+ // Ill-formed if the struct has virtual functions.
+ if (RD.isPolymorphic()) {
+ PrintDiagAndRemoveAttr();
+ return;
+ }
+
+ for (const auto &B : RD.bases()) {
+ // Ill-formed if the base class is non-trivial for the purpose of calls or a
+ // virtual base.
+ if ((!B.getType()->isDependentType() &&
+ !B.getType()->getAsCXXRecordDecl()->canPassInRegisters()) ||
+ B.isVirtual()) {
+ PrintDiagAndRemoveAttr();
+ return;
+ }
+ }
+
+ for (const auto *FD : RD.fields()) {
+ // Ill-formed if the field is an ObjectiveC pointer or of a type that is
+ // non-trivial for the purpose of calls.
+ QualType FT = FD->getType();
+ if (FT.getObjCLifetime() == Qualifiers::OCL_Weak) {
+ PrintDiagAndRemoveAttr();
+ return;
+ }
+
+ if (const auto *RT = FT->getBaseElementTypeUnsafe()->getAs<RecordType>())
+ if (!RT->isDependentType() &&
+ !cast<CXXRecordDecl>(RT->getDecl())->canPassInRegisters()) {
+ PrintDiagAndRemoveAttr();
+ return;
+ }
+ }
+}
+
+void Sema::ActOnFinishCXXMemberSpecification(
+ Scope *S, SourceLocation RLoc, Decl *TagDecl, SourceLocation LBrac,
+ SourceLocation RBrac, const ParsedAttributesView &AttrList) {
if (!TagDecl)
return;
AdjustDeclIfTemplate(TagDecl);
- for (const AttributeList* l = AttrList; l; l = l->getNext()) {
- if (l->getKind() != AttributeList::AT_Visibility)
+ for (const ParsedAttr &AL : AttrList) {
+ if (AL.getKind() != ParsedAttr::AT_Visibility)
continue;
- l->setInvalid();
- Diag(l->getLoc(), diag::warn_attribute_after_definition_ignored) <<
- l->getName();
+ AL.setInvalid();
+ Diag(AL.getLoc(), diag::warn_attribute_after_definition_ignored)
+ << AL.getName();
}
ActOnFields(S, RLoc, TagDecl, llvm::makeArrayRef(
@@ -7570,7 +7807,7 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
reinterpret_cast<Decl**>(FieldCollector->getCurFields()),
FieldCollector->getCurNumFields()), LBrac, RBrac, AttrList);
- CheckCompletedCXXClass(dyn_cast_or_null<CXXRecordDecl>(TagDecl));
+ CheckCompletedCXXClass(cast<CXXRecordDecl>(TagDecl));
}
/// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared
@@ -8108,7 +8345,8 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
QualType ConvType =
GetTypeFromParser(D.getName().ConversionFunctionId, &ConvTSI);
- if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) {
+ const DeclSpec &DS = D.getDeclSpec();
+ if (DS.hasTypeSpecifier() && !D.isInvalidType()) {
// Conversion functions don't have return types, but the parser will
// happily parse something like:
//
@@ -8118,9 +8356,18 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
//
// The return type will be changed later anyway.
Diag(D.getIdentifierLoc(), diag::err_conv_function_return_type)
- << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
+ << SourceRange(DS.getTypeSpecTypeLoc())
<< SourceRange(D.getIdentifierLoc());
D.setInvalidType();
+ } else if (DS.getTypeQualifiers() && !D.isInvalidType()) {
+ // It's also plausible that the user writes type qualifiers in the wrong
+ // place, such as:
+ // struct S { const operator int(); };
+ // FIXME: we could provide a fixit to move the qualifiers onto the
+ // conversion type.
+ Diag(D.getIdentifierLoc(), diag::err_conv_function_with_complex_decl)
+ << SourceRange(D.getIdentifierLoc()) << 0;
+ D.setInvalidType();
}
const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
@@ -8233,12 +8480,12 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
R = Context.getFunctionType(ConvType, None, Proto->getExtProtoInfo());
// C++0x explicit conversion operators.
- if (D.getDeclSpec().isExplicitSpecified())
- Diag(D.getDeclSpec().getExplicitSpecLoc(),
- getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_explicit_conversion_functions :
- diag::ext_explicit_conversion_functions)
- << SourceRange(D.getDeclSpec().getExplicitSpecLoc());
+ if (DS.isExplicitSpecified())
+ Diag(DS.getExplicitSpecLoc(),
+ getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_explicit_conversion_functions
+ : diag::ext_explicit_conversion_functions)
+ << SourceRange(DS.getExplicitSpecLoc());
}
/// ActOnConversionDeclarator - Called by ActOnDeclarator to complete
@@ -8437,7 +8684,7 @@ void Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R,
// Namespace Handling
//===----------------------------------------------------------------------===//
-/// \brief Diagnose a mismatch in 'inline' qualifiers when a namespace is
+/// Diagnose a mismatch in 'inline' qualifiers when a namespace is
/// reopened.
static void DiagnoseNamespaceInlineMismatch(Sema &S, SourceLocation KeywordLoc,
SourceLocation Loc,
@@ -8479,14 +8726,10 @@ static void DiagnoseNamespaceInlineMismatch(Sema &S, SourceLocation KeywordLoc,
/// ActOnStartNamespaceDef - This is called at the start of a namespace
/// definition.
-Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
- SourceLocation InlineLoc,
- SourceLocation NamespaceLoc,
- SourceLocation IdentLoc,
- IdentifierInfo *II,
- SourceLocation LBrace,
- AttributeList *AttrList,
- UsingDirectiveDecl *&UD) {
+Decl *Sema::ActOnStartNamespaceDef(
+ Scope *NamespcScope, SourceLocation InlineLoc, SourceLocation NamespaceLoc,
+ SourceLocation IdentLoc, IdentifierInfo *II, SourceLocation LBrace,
+ const ParsedAttributesView &AttrList, UsingDirectiveDecl *&UD) {
SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc;
// For anonymous namespace, take the location of the left brace.
SourceLocation Loc = II ? IdentLoc : LBrace;
@@ -8673,7 +8916,137 @@ NamespaceDecl *Sema::lookupStdExperimentalNamespace() {
return StdExperimentalNamespaceCache;
}
-/// \brief Retrieve the special "std" namespace, which may require us to
+namespace {
+
+enum UnsupportedSTLSelect {
+ USS_InvalidMember,
+ USS_MissingMember,
+ USS_NonTrivial,
+ USS_Other
+};
+
+struct InvalidSTLDiagnoser {
+ Sema &S;
+ SourceLocation Loc;
+ QualType TyForDiags;
+
+ QualType operator()(UnsupportedSTLSelect Sel = USS_Other, StringRef Name = "",
+ const VarDecl *VD = nullptr) {
+ {
+ auto D = S.Diag(Loc, diag::err_std_compare_type_not_supported)
+ << TyForDiags << ((int)Sel);
+ if (Sel == USS_InvalidMember || Sel == USS_MissingMember) {
+ assert(!Name.empty());
+ D << Name;
+ }
+ }
+ if (Sel == USS_InvalidMember) {
+ S.Diag(VD->getLocation(), diag::note_var_declared_here)
+ << VD << VD->getSourceRange();
+ }
+ return QualType();
+ }
+};
+} // namespace
+
+QualType Sema::CheckComparisonCategoryType(ComparisonCategoryType Kind,
+ SourceLocation Loc) {
+ assert(getLangOpts().CPlusPlus &&
+ "Looking for comparison category type outside of C++.");
+
+ // Check if we've already successfully checked the comparison category type
+ // before. If so, skip checking it again.
+ ComparisonCategoryInfo *Info = Context.CompCategories.lookupInfo(Kind);
+ if (Info && FullyCheckedComparisonCategories[static_cast<unsigned>(Kind)])
+ return Info->getType();
+
+ // If lookup failed
+ if (!Info) {
+ std::string NameForDiags = "std::";
+ NameForDiags += ComparisonCategories::getCategoryString(Kind);
+ Diag(Loc, diag::err_implied_comparison_category_type_not_found)
+ << NameForDiags;
+ return QualType();
+ }
+
+ assert(Info->Kind == Kind);
+ assert(Info->Record);
+
+ // Update the Record decl in case we encountered a forward declaration on our
+ // first pass. FIXME: This is a bit of a hack.
+ if (Info->Record->hasDefinition())
+ Info->Record = Info->Record->getDefinition();
+
+ // Use an elaborated type for diagnostics which has a name containing the
+ // prepended 'std' namespace but not any inline namespace names.
+ QualType TyForDiags = [&]() {
+ auto *NNS =
+ NestedNameSpecifier::Create(Context, nullptr, getStdNamespace());
+ return Context.getElaboratedType(ETK_None, NNS, Info->getType());
+ }();
+
+ if (RequireCompleteType(Loc, TyForDiags, diag::err_incomplete_type))
+ return QualType();
+
+ InvalidSTLDiagnoser UnsupportedSTLError{*this, Loc, TyForDiags};
+
+ if (!Info->Record->isTriviallyCopyable())
+ return UnsupportedSTLError(USS_NonTrivial);
+
+ for (const CXXBaseSpecifier &BaseSpec : Info->Record->bases()) {
+ CXXRecordDecl *Base = BaseSpec.getType()->getAsCXXRecordDecl();
+ // Tolerate empty base classes.
+ if (Base->isEmpty())
+ continue;
+ // Reject STL implementations which have at least one non-empty base.
+ return UnsupportedSTLError();
+ }
+
+ // Check that the STL has implemented the types using a single integer field.
+ // This expectation allows better codegen for builtin operators. We require:
+ // (1) The class has exactly one field.
+ // (2) The field is an integral or enumeration type.
+ auto FIt = Info->Record->field_begin(), FEnd = Info->Record->field_end();
+ if (std::distance(FIt, FEnd) != 1 ||
+ !FIt->getType()->isIntegralOrEnumerationType()) {
+ return UnsupportedSTLError();
+ }
+
+ // Build each of the require values and store them in Info.
+ for (ComparisonCategoryResult CCR :
+ ComparisonCategories::getPossibleResultsForType(Kind)) {
+ StringRef MemName = ComparisonCategories::getResultString(CCR);
+ ComparisonCategoryInfo::ValueInfo *ValInfo = Info->lookupValueInfo(CCR);
+
+ if (!ValInfo)
+ return UnsupportedSTLError(USS_MissingMember, MemName);
+
+ VarDecl *VD = ValInfo->VD;
+ assert(VD && "should not be null!");
+
+ // Attempt to diagnose reasons why the STL definition of this type
+ // might be foobar, including it failing to be a constant expression.
+ // TODO Handle more ways the lookup or result can be invalid.
+ if (!VD->isStaticDataMember() || !VD->isConstexpr() || !VD->hasInit() ||
+ !VD->checkInitIsICE())
+ return UnsupportedSTLError(USS_InvalidMember, MemName, VD);
+
+ // Attempt to evaluate the var decl as a constant expression and extract
+ // the value of its first field as a ICE. If this fails, the STL
+ // implementation is not supported.
+ if (!ValInfo->hasValidIntValue())
+ return UnsupportedSTLError();
+
+ MarkVariableReferenced(Loc, VD);
+ }
+
+ // We've successfully built the required types and expressions. Update
+ // the cache and return the newly cached value.
+ FullyCheckedComparisonCategories[static_cast<unsigned>(Kind)] = true;
+ return Info->getType();
+}
+
+/// Retrieve the special "std" namespace, which may require us to
/// implicitly define the namespace.
NamespaceDecl *Sema::getOrCreateStdNamespace() {
if (!StdNamespace) {
@@ -8816,7 +9189,7 @@ bool Sema::isInitListConstructor(const FunctionDecl *Ctor) {
return isStdInitializerList(ArgType, nullptr);
}
-/// \brief Determine whether a using statement is in a context where it will be
+/// Determine whether a using statement is in a context where it will be
/// apply in all contexts.
static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) {
switch (CurContext->getDeclKind()) {
@@ -8871,13 +9244,11 @@ static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc,
return false;
}
-Decl *Sema::ActOnUsingDirective(Scope *S,
- SourceLocation UsingLoc,
- SourceLocation NamespcLoc,
- CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- IdentifierInfo *NamespcName,
- AttributeList *AttrList) {
+Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc,
+ SourceLocation NamespcLoc, CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *NamespcName,
+ const ParsedAttributesView &AttrList) {
assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
assert(NamespcName && "Invalid NamespcName.");
assert(IdentLoc.isValid() && "Invalid NamespceName location.");
@@ -8932,7 +9303,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
// Find enclosing context containing both using-directive and
// nominated namespace.
- DeclContext *CommonAncestor = cast<DeclContext>(NS);
+ DeclContext *CommonAncestor = NS;
while (CommonAncestor && !CommonAncestor->Encloses(CurContext))
CommonAncestor = CommonAncestor->getParent();
@@ -8969,15 +9340,12 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) {
S->PushUsingDirective(UDir);
}
-
-Decl *Sema::ActOnUsingDeclaration(Scope *S,
- AccessSpecifier AS,
+Decl *Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS,
SourceLocation UsingLoc,
- SourceLocation TypenameLoc,
- CXXScopeSpec &SS,
+ SourceLocation TypenameLoc, CXXScopeSpec &SS,
UnqualifiedId &Name,
SourceLocation EllipsisLoc,
- AttributeList *AttrList) {
+ const ParsedAttributesView &AttrList) {
assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
if (SS.isEmpty()) {
@@ -9056,7 +9424,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
return UD;
}
-/// \brief Determine whether a using declaration considers the given
+/// Determine whether a using declaration considers the given
/// declarations as "equivalent", e.g., if they are redeclarations of
/// the same entity or are both typedefs of the same type.
static bool
@@ -9149,6 +9517,19 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
if (isa<UsingDecl>(D) || isa<UsingPackDecl>(D))
continue;
+ if (auto *RD = dyn_cast<CXXRecordDecl>(D)) {
+ // C++ [class.mem]p19:
+ // If T is the name of a class, then [every named member other than
+ // a non-static data member] shall have a name different from T
+ if (RD->isInjectedClassName() && !isa<FieldDecl>(Target) &&
+ !isa<IndirectFieldDecl>(Target) &&
+ !isa<UnresolvedUsingValueDecl>(Target) &&
+ DiagnoseClassNameShadow(
+ CurContext,
+ DeclarationNameInfo(Using->getDeclName(), Using->getLocation())))
+ return true;
+ }
+
if (IsEquivalentForUsingDecl(Context, D, Target)) {
if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(*I))
PrevShadow = Shadow;
@@ -9421,15 +9802,11 @@ private:
/// \param IsInstantiation - Whether this call arises from an
/// instantiation of an unresolved using declaration. We treat
/// the lookup differently for these declarations.
-NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
- SourceLocation UsingLoc,
- bool HasTypenameKeyword,
- SourceLocation TypenameLoc,
- CXXScopeSpec &SS,
- DeclarationNameInfo NameInfo,
- SourceLocation EllipsisLoc,
- AttributeList *AttrList,
- bool IsInstantiation) {
+NamedDecl *Sema::BuildUsingDeclaration(
+ Scope *S, AccessSpecifier AS, SourceLocation UsingLoc,
+ bool HasTypenameKeyword, SourceLocation TypenameLoc, CXXScopeSpec &SS,
+ DeclarationNameInfo NameInfo, SourceLocation EllipsisLoc,
+ const ParsedAttributesView &AttrList, bool IsInstantiation) {
assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
SourceLocation IdentLoc = NameInfo.getLoc();
assert(IdentLoc.isValid() && "Invalid TargetName location.");
@@ -9995,14 +10372,11 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
return true;
}
-Decl *Sema::ActOnAliasDeclaration(Scope *S,
- AccessSpecifier AS,
+Decl *Sema::ActOnAliasDeclaration(Scope *S, AccessSpecifier AS,
MultiTemplateParamsArg TemplateParamLists,
- SourceLocation UsingLoc,
- UnqualifiedId &Name,
- AttributeList *AttrList,
- TypeResult Type,
- Decl *DeclFromDeclSpec) {
+ SourceLocation UsingLoc, UnqualifiedId &Name,
+ const ParsedAttributesView &AttrList,
+ TypeResult Type, Decl *DeclFromDeclSpec) {
// Skip up to the relevant declaration scope.
while (S->isTemplateParamScope())
S = S->getParent();
@@ -10378,7 +10752,7 @@ struct DeclaringSpecialMember {
}
}
- /// \brief Are we already trying to declare this special member?
+ /// Are we already trying to declare this special member?
bool isAlreadyBeingDeclared() const {
return WasAlreadyBeingDeclared;
}
@@ -10720,6 +11094,8 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
// We don't need to use SpecialMemberIsTrivial here; triviality for
// destructors is easy to compute.
Destructor->setTrivial(ClassDecl->hasTrivialDestructor());
+ Destructor->setTrivialForCall(ClassDecl->hasAttr<TrivialABIAttr>() ||
+ ClassDecl->hasTrivialDestructorForCall());
// Note that we have declared this destructor.
++ASTContext::NumImplicitDestructorsDeclared;
@@ -10784,7 +11160,7 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
}
}
-/// \brief Perform any semantic analysis which needs to be delayed until all
+/// Perform any semantic analysis which needs to be delayed until all
/// pending class member declarations have been parsed.
void Sema::ActOnFinishCXXMemberDecls() {
// If the context is an invalid C++ class, just suppress these checks.
@@ -10804,12 +11180,12 @@ void Sema::ActOnFinishCXXNonNestedClass(Decl *D) {
void Sema::referenceDLLExportedClassMethods() {
if (!DelayedDllExportClasses.empty()) {
- // Calling ReferenceDllExportedMethods might cause the current function to
+ // Calling ReferenceDllExportedMembers might cause the current function to
// be called again, so use a local copy of DelayedDllExportClasses.
SmallVector<CXXRecordDecl *, 4> WorkList;
std::swap(DelayedDllExportClasses, WorkList);
for (CXXRecordDecl *Class : WorkList)
- ReferenceDllExportedMethods(*this, Class);
+ ReferenceDllExportedMembers(*this, Class);
}
}
@@ -10843,7 +11219,7 @@ void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
}
namespace {
-/// \brief An abstract base class for all helper classes used in building the
+/// An abstract base class for all helper classes used in building the
// copy/move operators. These classes serve as factory functions and help us
// avoid using the same Expr* in the AST twice.
class ExprBuilder {
@@ -10990,11 +11366,11 @@ buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T,
Expr *From = FromB.build(S, Loc);
From = new (S.Context) UnaryOperator(From, UO_AddrOf,
S.Context.getPointerType(From->getType()),
- VK_RValue, OK_Ordinary, Loc);
+ VK_RValue, OK_Ordinary, Loc, false);
Expr *To = ToB.build(S, Loc);
To = new (S.Context) UnaryOperator(To, UO_AddrOf,
S.Context.getPointerType(To->getType()),
- VK_RValue, OK_Ordinary, Loc);
+ VK_RValue, OK_Ordinary, Loc, false);
const Type *E = T->getBaseElementTypeUnsafe();
bool NeedsCollectableMemCpy =
@@ -11028,7 +11404,7 @@ buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T,
return Call.getAs<Stmt>();
}
-/// \brief Builds a statement that copies/moves the given entity from \p From to
+/// Builds a statement that copies/moves the given entity from \p From to
/// \c To.
///
/// This routine is used to copy/move the members of a class with an
@@ -11233,10 +11609,12 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
BO_NE, S.Context.BoolTy,
VK_RValue, OK_Ordinary, Loc, FPOptions());
- // Create the pre-increment of the iteration variable.
- Expr *Increment
- = new (S.Context) UnaryOperator(IterationVarRef.build(S, Loc), UO_PreInc,
- SizeType, VK_LValue, OK_Ordinary, Loc);
+ // Create the pre-increment of the iteration variable. We can determine
+ // whether the increment will overflow based on the value of the array
+ // bound.
+ Expr *Increment = new (S.Context)
+ UnaryOperator(IterationVarRef.build(S, Loc), UO_PreInc, SizeType,
+ VK_LValue, OK_Ordinary, Loc, Upper.isMaxValue());
// Construct the loop that copies all elements of this array.
return S.ActOnForStmt(
@@ -11525,7 +11903,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
}
// Suppress assigning zero-width bitfields.
- if (Field->isBitField() && Field->getBitWidthValue(Context) == 0)
+ if (Field->isZeroLengthBitField(Context))
continue;
QualType FieldType = Field->getType().getNonReferenceType();
@@ -11892,7 +12270,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
}
// Suppress assigning zero-width bitfields.
- if (Field->isBitField() && Field->getBitWidthValue(Context) == 0)
+ if (Field->isZeroLengthBitField(Context))
continue;
QualType FieldType = Field->getType().getNonReferenceType();
@@ -12021,9 +12399,16 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
CopyConstructor->setParams(FromParam);
CopyConstructor->setTrivial(
- ClassDecl->needsOverloadResolutionForCopyConstructor()
- ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor)
- : ClassDecl->hasTrivialCopyConstructor());
+ ClassDecl->needsOverloadResolutionForCopyConstructor()
+ ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor)
+ : ClassDecl->hasTrivialCopyConstructor());
+
+ CopyConstructor->setTrivialForCall(
+ ClassDecl->hasAttr<TrivialABIAttr>() ||
+ (ClassDecl->needsOverloadResolutionForCopyConstructor()
+ ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor,
+ TAH_ConsiderTrivialABI)
+ : ClassDecl->hasTrivialCopyConstructorForCall()));
// Note that we have declared this constructor.
++ASTContext::NumImplicitCopyConstructorsDeclared;
@@ -12144,9 +12529,16 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
MoveConstructor->setParams(FromParam);
MoveConstructor->setTrivial(
- ClassDecl->needsOverloadResolutionForMoveConstructor()
- ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor)
- : ClassDecl->hasTrivialMoveConstructor());
+ ClassDecl->needsOverloadResolutionForMoveConstructor()
+ ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor)
+ : ClassDecl->hasTrivialMoveConstructor());
+
+ MoveConstructor->setTrivialForCall(
+ ClassDecl->hasAttr<TrivialABIAttr>() ||
+ (ClassDecl->needsOverloadResolutionForMoveConstructor()
+ ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor,
+ TAH_ConsiderTrivialABI)
+ : ClassDecl->hasTrivialMoveConstructorForCall()));
// Note that we have declared this constructor.
++ASTContext::NumImplicitMoveConstructorsDeclared;
@@ -12321,7 +12713,7 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion(
}
}
-/// \brief Determine whether the given list arguments contains exactly one
+/// Determine whether the given list arguments contains exactly one
/// "real" (non-default) argument.
static bool hasOneRealArgument(MultiExprArg Args) {
switch (Args.size()) {
@@ -12532,7 +12924,7 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) {
Diag(VD->getLocation(), diag::warn_global_destructor);
}
-/// \brief Given a constructor and the set of arguments provided for the
+/// Given a constructor and the set of arguments provided for the
/// constructor, convert the arguments and add any required default arguments
/// to form a proper call to this constructor.
///
@@ -12599,6 +12991,13 @@ CheckOperatorNewDeleteDeclarationScope(Sema &SemaRef,
return false;
}
+static QualType
+RemoveAddressSpaceFromPtr(Sema &SemaRef, const PointerType *PtrTy) {
+ QualType QTy = PtrTy->getPointeeType();
+ QTy = SemaRef.Context.removeAddrSpaceQualType(QTy);
+ return SemaRef.Context.getPointerType(QTy);
+}
+
static inline bool
CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl,
CanQualType ExpectedResultType,
@@ -12614,6 +13013,13 @@ CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl,
diag::err_operator_new_delete_dependent_result_type)
<< FnDecl->getDeclName() << ExpectedResultType;
+ // OpenCL C++: the operator is valid on any address space.
+ if (SemaRef.getLangOpts().OpenCLCPlusPlus) {
+ if (auto *PtrTy = ResultType->getAs<PointerType>()) {
+ ResultType = RemoveAddressSpaceFromPtr(SemaRef, PtrTy);
+ }
+ }
+
// Check that the result type is what we expect.
if (SemaRef.Context.getCanonicalType(ResultType) != ExpectedResultType)
return SemaRef.Diag(FnDecl->getLocation(),
@@ -12639,6 +13045,13 @@ CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl,
<< FnDecl->getDeclName() << ExpectedFirstParamType;
// Check that the first parameter type is what we expect.
+ if (SemaRef.getLangOpts().OpenCLCPlusPlus) {
+ // OpenCL C++: the operator is valid on any address space.
+ if (auto *PtrTy =
+ FnDecl->getParamDecl(0)->getType()->getAs<PointerType>()) {
+ FirstParamType = RemoveAddressSpaceFromPtr(SemaRef, PtrTy);
+ }
+ }
if (SemaRef.Context.getCanonicalType(FirstParamType).getUnqualifiedType() !=
ExpectedFirstParamType)
return SemaRef.Diag(FnDecl->getLocation(), InvalidParamTypeDiag)
@@ -12948,6 +13361,7 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
ParamType->isSpecificBuiltinType(BuiltinType::LongDouble) ||
Context.hasSameType(ParamType, Context.CharTy) ||
Context.hasSameType(ParamType, Context.WideCharTy) ||
+ Context.hasSameType(ParamType, Context.Char8Ty) ||
Context.hasSameType(ParamType, Context.Char16Ty) ||
Context.hasSameType(ParamType, Context.Char32Ty)) {
} else if (const PointerType *Ptr = ParamType->getAs<PointerType>()) {
@@ -13008,10 +13422,12 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
}
QualType InnerType = PointeeType.getUnqualifiedType();
- // Only const char *, const wchar_t*, const char16_t*, and const char32_t*
- // are allowed as the first parameter to a two-parameter function
+ // Only const char *, const wchar_t*, const char8_t*, const char16_t*, and
+ // const char32_t* are allowed as the first parameter to a two-parameter
+ // function
if (!(Context.hasSameType(InnerType, Context.CharTy) ||
Context.hasSameType(InnerType, Context.WideCharTy) ||
+ Context.hasSameType(InnerType, Context.Char8Ty) ||
Context.hasSameType(InnerType, Context.Char16Ty) ||
Context.hasSameType(InnerType, Context.Char32Ty))) {
Diag((*Param)->getSourceRange().getBegin(),
@@ -13118,19 +13534,18 @@ Decl *Sema::ActOnFinishLinkageSpecification(Scope *S,
}
Decl *Sema::ActOnEmptyDeclaration(Scope *S,
- AttributeList *AttrList,
+ const ParsedAttributesView &AttrList,
SourceLocation SemiLoc) {
Decl *ED = EmptyDecl::Create(Context, CurContext, SemiLoc);
// Attribute declarations appertain to empty declaration so we handle
// them here.
- if (AttrList)
- ProcessDeclAttributeList(S, ED, AttrList);
+ ProcessDeclAttributeList(S, ED, AttrList);
CurContext->addDecl(ED);
return ED;
}
-/// \brief Perform semantic analysis for the variable declaration that
+/// Perform semantic analysis for the variable declaration that
/// occurs within a C++ catch clause, returning the newly-created
/// variable.
VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
@@ -13386,7 +13801,7 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
return Decl;
}
-/// \brief Perform semantic analysis of the given friend type declaration.
+/// Perform semantic analysis of the given friend type declaration.
///
/// \returns A friend declaration that.
FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart,
@@ -13463,10 +13878,9 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart,
/// templated.
Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
unsigned TagSpec, SourceLocation TagLoc,
- CXXScopeSpec &SS,
- IdentifierInfo *Name,
+ CXXScopeSpec &SS, IdentifierInfo *Name,
SourceLocation NameLoc,
- AttributeList *Attr,
+ const ParsedAttributesView &Attr,
MultiTemplateParamsArg TempParamLists) {
TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
@@ -13579,7 +13993,6 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
return Friend;
}
-
/// Handle a friend type declaration. This works in tandem with
/// ActOnTag.
///
@@ -14151,6 +14564,16 @@ bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
}
}
+ // Virtual overrides must have the same code_seg.
+ const auto *OldCSA = Old->getAttr<CodeSegAttr>();
+ const auto *NewCSA = New->getAttr<CodeSegAttr>();
+ if ((NewCSA || OldCSA) &&
+ (!OldCSA || !NewCSA || NewCSA->getName() != OldCSA->getName())) {
+ Diag(New->getLocation(), diag::err_mismatched_code_seg_override);
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ return true;
+ }
+
CallingConv NewCC = NewFT->getCallConv(), OldCC = OldFT->getCallConv();
// If the calling conventions match, everything is fine
@@ -14277,7 +14700,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
return false;
}
-/// \brief Mark the given method pure.
+/// Mark the given method pure.
///
/// \param Method the method to be marked pure.
///
@@ -14307,7 +14730,7 @@ void Sema::ActOnPureSpecifier(Decl *D, SourceLocation ZeroLoc) {
Diag(D->getLocation(), diag::err_illegal_initializer);
}
-/// \brief Determine whether the given declaration is a global variable or
+/// Determine whether the given declaration is a global variable or
/// static data member.
static bool isNonlocalVariable(const Decl *D) {
if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(D))
@@ -14414,7 +14837,7 @@ void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
// Try to insert this class into the map.
LoadExternalVTableUses();
- Class = cast<CXXRecordDecl>(Class->getCanonicalDecl());
+ Class = Class->getCanonicalDecl();
std::pair<llvm::DenseMap<CXXRecordDecl *, bool>::iterator, bool>
Pos = VTablesUsed.insert(std::make_pair(Class, DefinitionRequired));
if (!Pos.second) {
@@ -14526,7 +14949,7 @@ bool Sema::DefineUsedVTables() {
// vtable for this class is required.
DefinedAnything = true;
MarkVirtualMembersReferenced(Loc, Class);
- CXXRecordDecl *Canonical = cast<CXXRecordDecl>(Class->getCanonicalDecl());
+ CXXRecordDecl *Canonical = Class->getCanonicalDecl();
if (VTablesUsed[Canonical])
Consumer.HandleVTable(Class);
@@ -14649,9 +15072,9 @@ void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {
static
void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
- llvm::SmallSet<CXXConstructorDecl*, 4> &Valid,
- llvm::SmallSet<CXXConstructorDecl*, 4> &Invalid,
- llvm::SmallSet<CXXConstructorDecl*, 4> &Current,
+ llvm::SmallPtrSet<CXXConstructorDecl*, 4> &Valid,
+ llvm::SmallPtrSet<CXXConstructorDecl*, 4> &Invalid,
+ llvm::SmallPtrSet<CXXConstructorDecl*, 4> &Current,
Sema &S) {
if (Ctor->isInvalidDecl())
return;
@@ -14713,7 +15136,7 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
void Sema::CheckDelegatingCtorCycles() {
- llvm::SmallSet<CXXConstructorDecl*, 4> Valid, Invalid, Current;
+ llvm::SmallPtrSet<CXXConstructorDecl*, 4> Valid, Invalid, Current;
for (DelegatingCtorDeclsType::iterator
I = DelegatingCtorDecls.begin(ExternalSource),
@@ -14721,14 +15144,12 @@ void Sema::CheckDelegatingCtorCycles() {
I != E; ++I)
DelegatingCycleHelper(*I, Valid, Invalid, Current, *this);
- for (llvm::SmallSet<CXXConstructorDecl *, 4>::iterator CI = Invalid.begin(),
- CE = Invalid.end();
- CI != CE; ++CI)
+ for (auto CI = Invalid.begin(), CE = Invalid.end(); CI != CE; ++CI)
(*CI)->setInvalidDecl();
}
namespace {
- /// \brief AST visitor that finds references to the 'this' expression.
+ /// AST visitor that finds references to the 'this' expression.
class FindCXXThisExpr : public RecursiveASTVisitor<FindCXXThisExpr> {
Sema &S;
@@ -14798,7 +15219,9 @@ bool Sema::checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method) {
case EST_None:
break;
- case EST_ComputedNoexcept:
+ case EST_DependentNoexcept:
+ case EST_NoexceptFalse:
+ case EST_NoexceptTrue:
if (!Finder.TraverseStmt(Proto->getNoexceptExpr()))
return true;
LLVM_FALLTHROUGH;
@@ -14895,31 +15318,17 @@ void Sema::checkExceptionSpecification(
return;
}
- if (EST == EST_ComputedNoexcept) {
- // If an error occurred, there's no expression here.
- if (NoexceptExpr) {
- assert((NoexceptExpr->isTypeDependent() ||
- NoexceptExpr->getType()->getCanonicalTypeUnqualified() ==
- Context.BoolTy) &&
- "Parser should have made sure that the expression is boolean");
- if (IsTopLevel && NoexceptExpr &&
- DiagnoseUnexpandedParameterPack(NoexceptExpr)) {
- ESI.Type = EST_BasicNoexcept;
- return;
- }
-
- if (!NoexceptExpr->isValueDependent()) {
- ExprResult Result = VerifyIntegerConstantExpression(
- NoexceptExpr, nullptr, diag::err_noexcept_needs_constant_expression,
- /*AllowFold*/ false);
- if (Result.isInvalid()) {
- ESI.Type = EST_BasicNoexcept;
- return;
- }
- NoexceptExpr = Result.get();
- }
- ESI.NoexceptExpr = NoexceptExpr;
+ if (isComputedNoexcept(EST)) {
+ assert((NoexceptExpr->isTypeDependent() ||
+ NoexceptExpr->getType()->getCanonicalTypeUnqualified() ==
+ Context.BoolTy) &&
+ "Parser should have made sure that the expression is boolean");
+ if (IsTopLevel && DiagnoseUnexpandedParameterPack(NoexceptExpr)) {
+ ESI.Type = EST_BasicNoexcept;
+ return;
}
+
+ ESI.NoexceptExpr = NoexceptExpr;
return;
}
}
@@ -14964,11 +15373,11 @@ void Sema::actOnDelayedExceptionSpecification(Decl *MethodD,
/// HandleMSProperty - Analyze a __delcspec(property) field of a C++ class.
///
MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record,
- SourceLocation DeclStart,
- Declarator &D, Expr *BitWidth,
+ SourceLocation DeclStart, Declarator &D,
+ Expr *BitWidth,
InClassInitStyle InitStyle,
AccessSpecifier AS,
- AttributeList *MSPropertyAttr) {
+ const ParsedAttr &MSPropertyAttr) {
IdentifierInfo *II = D.getIdentifier();
if (!II) {
Diag(DeclStart, diag::err_anonymous_property);
@@ -15031,7 +15440,7 @@ MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record,
PrevDecl = nullptr;
SourceLocation TSSL = D.getLocStart();
- const AttributeList::PropertyData &Data = MSPropertyAttr->getPropertyData();
+ const ParsedAttr::PropertyData &Data = MSPropertyAttr.getPropertyData();
MSPropertyDecl *NewPD = MSPropertyDecl::Create(
Context, Record, Loc, II, T, TInfo, TSSL, Data.GetterId, Data.SetterId);
ProcessDeclAttributes(TUScope, NewPD, D);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
index ff3c07e938a8..e1b033ea8282 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
@@ -156,23 +156,23 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
Diag(Overridden->getLocation(),
diag::note_related_result_type_overridden);
}
- if (getLangOpts().ObjCAutoRefCount) {
- Diags.setSeverity(diag::warn_nsreturns_retained_attribute_mismatch,
- diag::Severity::Error, SourceLocation());
- Diags.setSeverity(diag::warn_nsconsumed_attribute_mismatch,
- diag::Severity::Error, SourceLocation());
- }
if ((NewMethod->hasAttr<NSReturnsRetainedAttr>() !=
Overridden->hasAttr<NSReturnsRetainedAttr>())) {
Diag(NewMethod->getLocation(),
- diag::warn_nsreturns_retained_attribute_mismatch) << 1;
+ getLangOpts().ObjCAutoRefCount
+ ? diag::err_nsreturns_retained_attribute_mismatch
+ : diag::warn_nsreturns_retained_attribute_mismatch)
+ << 1;
Diag(Overridden->getLocation(), diag::note_previous_decl) << "method";
}
if ((NewMethod->hasAttr<NSReturnsNotRetainedAttr>() !=
Overridden->hasAttr<NSReturnsNotRetainedAttr>())) {
Diag(NewMethod->getLocation(),
- diag::warn_nsreturns_retained_attribute_mismatch) << 0;
+ getLangOpts().ObjCAutoRefCount
+ ? diag::err_nsreturns_retained_attribute_mismatch
+ : diag::warn_nsreturns_retained_attribute_mismatch)
+ << 0;
Diag(Overridden->getLocation(), diag::note_previous_decl) << "method";
}
@@ -185,7 +185,10 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
ParmVarDecl *newDecl = (*ni);
if (newDecl->hasAttr<NSConsumedAttr>() !=
oldDecl->hasAttr<NSConsumedAttr>()) {
- Diag(newDecl->getLocation(), diag::warn_nsconsumed_attribute_mismatch);
+ Diag(newDecl->getLocation(),
+ getLangOpts().ObjCAutoRefCount
+ ? diag::err_nsconsumed_attribute_mismatch
+ : diag::warn_nsconsumed_attribute_mismatch);
Diag(oldDecl->getLocation(), diag::note_previous_decl) << "parameter";
}
@@ -199,7 +202,7 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
}
}
-/// \brief Check a method declaration for compatibility with the Objective-C
+/// Check a method declaration for compatibility with the Objective-C
/// ARC conventions.
bool Sema::CheckARCMethodDecl(ObjCMethodDecl *method) {
ObjCMethodFamily family = method->getMethodFamily();
@@ -263,12 +266,20 @@ static void DiagnoseObjCImplementedDeprecations(Sema &S, const NamedDecl *ND,
if (!ND)
return;
bool IsCategory = false;
- AvailabilityResult Availability = ND->getAvailability();
+ StringRef RealizedPlatform;
+ AvailabilityResult Availability = ND->getAvailability(
+ /*Message=*/nullptr, /*EnclosingVersion=*/VersionTuple(),
+ &RealizedPlatform);
if (Availability != AR_Deprecated) {
if (isa<ObjCMethodDecl>(ND)) {
if (Availability != AR_Unavailable)
return;
- // Warn about implementing unavailable methods.
+ if (RealizedPlatform.empty())
+ RealizedPlatform = S.Context.getTargetInfo().getPlatformName();
+ // Warn about implementing unavailable methods, unless the unavailable
+ // is for an app extension.
+ if (RealizedPlatform.endswith("_app_extension"))
+ return;
S.Diag(ImplLoc, diag::warn_unavailable_def);
S.Diag(ND->getLocation(), diag::note_method_declared_at)
<< ND->getDeclName();
@@ -338,6 +349,13 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
if (!MDecl)
return;
+ QualType ResultType = MDecl->getReturnType();
+ if (!ResultType->isDependentType() && !ResultType->isVoidType() &&
+ !MDecl->isInvalidDecl() &&
+ RequireCompleteType(MDecl->getLocation(), ResultType,
+ diag::err_func_def_incomplete_result))
+ MDecl->setInvalidDecl();
+
// Allow all of Sema to see that we are entering a method definition.
PushDeclContext(FnBodyScope, MDecl);
PushFunctionScope();
@@ -930,16 +948,14 @@ static bool checkTypeParamListConsistency(Sema &S,
return false;
}
-Decl *Sema::
-ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc,
- IdentifierInfo *ClassName, SourceLocation ClassLoc,
- ObjCTypeParamList *typeParamList,
- IdentifierInfo *SuperName, SourceLocation SuperLoc,
- ArrayRef<ParsedType> SuperTypeArgs,
- SourceRange SuperTypeArgsRange,
- Decl * const *ProtoRefs, unsigned NumProtoRefs,
- const SourceLocation *ProtoLocs,
- SourceLocation EndProtoLoc, AttributeList *AttrList) {
+Decl *Sema::ActOnStartClassInterface(
+ Scope *S, SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName,
+ SourceLocation ClassLoc, ObjCTypeParamList *typeParamList,
+ IdentifierInfo *SuperName, SourceLocation SuperLoc,
+ ArrayRef<ParsedType> SuperTypeArgs, SourceRange SuperTypeArgsRange,
+ Decl *const *ProtoRefs, unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,
+ const ParsedAttributesView &AttrList) {
assert(ClassName && "Missing class identifier");
// Check for another declaration kind with the same name.
@@ -1024,9 +1040,8 @@ ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc,
IDecl->setInvalidDecl();
}
}
-
- if (AttrList)
- ProcessDeclAttributeList(TUScope, IDecl, AttrList);
+
+ ProcessDeclAttributeList(TUScope, IDecl, AttrList);
AddPragmaAttributes(TUScope, IDecl);
PushOnScopeChains(IDecl, TUScope);
@@ -1165,15 +1180,11 @@ bool Sema::CheckForwardProtocolDeclarationForCircularDependency(
return res;
}
-Decl *
-Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
- IdentifierInfo *ProtocolName,
- SourceLocation ProtocolLoc,
- Decl * const *ProtoRefs,
- unsigned NumProtoRefs,
- const SourceLocation *ProtoLocs,
- SourceLocation EndProtoLoc,
- AttributeList *AttrList) {
+Decl *Sema::ActOnStartProtocolInterface(
+ SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName,
+ SourceLocation ProtocolLoc, Decl *const *ProtoRefs, unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,
+ const ParsedAttributesView &AttrList) {
bool err = false;
// FIXME: Deal with AttrList.
assert(ProtocolName && "Missing protocol identifier");
@@ -1192,6 +1203,11 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName,
ProtocolLoc, AtProtoInterfaceLoc,
/*PrevDecl=*/nullptr);
+
+ // If we are using modules, add the decl to the context in order to
+ // serialize something meaningful.
+ if (getLangOpts().Modules)
+ PushOnScopeChains(PDecl, TUScope);
PDecl->startDefinition();
} else {
if (PrevDecl) {
@@ -1211,9 +1227,8 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
PushOnScopeChains(PDecl, TUScope);
PDecl->startDefinition();
}
-
- if (AttrList)
- ProcessDeclAttributeList(TUScope, PDecl, AttrList);
+
+ ProcessDeclAttributeList(TUScope, PDecl, AttrList);
AddPragmaAttributes(TUScope, PDecl);
// Merge attributes from previous declarations.
@@ -1544,14 +1559,12 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers(
// add the '*'.
if (type->getAs<ObjCInterfaceType>()) {
SourceLocation starLoc = getLocForEndOfToken(loc);
- ParsedAttributes parsedAttrs(attrFactory);
D.AddTypeInfo(DeclaratorChunk::getPointer(/*typeQuals=*/0, starLoc,
SourceLocation(),
SourceLocation(),
SourceLocation(),
SourceLocation(),
SourceLocation()),
- parsedAttrs,
starLoc);
// Diagnose the missing '*'.
@@ -1729,7 +1742,7 @@ void Sema::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
Sema::DeclGroupPtrTy
Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
ArrayRef<IdentifierLocPair> IdentList,
- AttributeList *attrList) {
+ const ParsedAttributesView &attrList) {
SmallVector<Decl *, 8> DeclsInGroup;
for (const IdentifierLocPair &IdentPair : IdentList) {
IdentifierInfo *Ident = IdentPair.first;
@@ -1742,9 +1755,8 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
PushOnScopeChains(PDecl, TUScope);
CheckObjCDeclScope(PDecl);
-
- if (attrList)
- ProcessDeclAttributeList(TUScope, PDecl, attrList);
+
+ ProcessDeclAttributeList(TUScope, PDecl, attrList);
AddPragmaAttributes(TUScope, PDecl);
if (PrevDecl)
@@ -1756,17 +1768,13 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
return BuildDeclaratorGroup(DeclsInGroup);
}
-Decl *Sema::
-ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
- IdentifierInfo *ClassName, SourceLocation ClassLoc,
- ObjCTypeParamList *typeParamList,
- IdentifierInfo *CategoryName,
- SourceLocation CategoryLoc,
- Decl * const *ProtoRefs,
- unsigned NumProtoRefs,
- const SourceLocation *ProtoLocs,
- SourceLocation EndProtoLoc,
- AttributeList *AttrList) {
+Decl *Sema::ActOnStartCategoryInterface(
+ SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName,
+ SourceLocation ClassLoc, ObjCTypeParamList *typeParamList,
+ IdentifierInfo *CategoryName, SourceLocation CategoryLoc,
+ Decl *const *ProtoRefs, unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,
+ const ParsedAttributesView &AttrList) {
ObjCCategoryDecl *CDecl;
ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true);
@@ -1832,6 +1840,12 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
// FIXME: PushOnScopeChains?
CurContext->addDecl(CDecl);
+ // Process the attributes before looking at protocols to ensure that the
+ // availability attribute is attached to the category to provide availability
+ // checking for protocol uses.
+ ProcessDeclAttributeList(TUScope, CDecl, AttrList);
+ AddPragmaAttributes(TUScope, CDecl);
+
if (NumProtoRefs) {
diagnoseUseOfProtocols(*this, CDecl, (ObjCProtocolDecl*const*)ProtoRefs,
NumProtoRefs, ProtoLocs);
@@ -1843,10 +1857,6 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
NumProtoRefs, Context);
}
- if (AttrList)
- ProcessDeclAttributeList(TUScope, CDecl, AttrList);
- AddPragmaAttributes(TUScope, CDecl);
-
CheckObjCDeclScope(CDecl);
return ActOnObjCContainerStartDefinition(CDecl);
}
@@ -2162,17 +2172,9 @@ static void WarnUndefinedMethod(Sema &S, SourceLocation ImpLoc,
unsigned DiagID,
NamedDecl *NeededFor = nullptr) {
// No point warning no definition of method which is 'unavailable'.
- switch (method->getAvailability()) {
- case AR_Available:
- case AR_Deprecated:
- break;
-
- // Don't warn about unavailable or not-yet-introduced methods.
- case AR_NotYetIntroduced:
- case AR_Unavailable:
+ if (method->getAvailability() == AR_Unavailable)
return;
- }
-
+
// FIXME: For now ignore 'IncompleteImpl'.
// Previously we grouped all unimplemented methods under a single
// warning, but some users strongly voiced that they would prefer
@@ -2717,7 +2719,7 @@ static void CheckProtocolMethodDefs(Sema &S,
// This is because method will be implemented in the primary class
// or one of its super class implementation.
- // Ugly, but necessary. Method declared in protcol might have
+ // Ugly, but necessary. Method declared in protocol might have
// have been synthesized due to a property declared in the class which
// uses the protocol.
if (ObjCMethodDecl *MethodInClass =
@@ -3345,7 +3347,7 @@ void Sema::addMethodToGlobalList(ObjCMethodList *List,
Previous->setNext(new (Mem) ObjCMethodList(Method));
}
-/// \brief Read the contents of the method pool for a given selector from
+/// Read the contents of the method pool for a given selector from
/// external storage.
void Sema::ReadMethodPool(Selector Sel) {
assert(ExternalSource && "We need an external AST source");
@@ -3427,7 +3429,7 @@ static bool FilterMethodsByTypeBound(ObjCMethodDecl *Method,
MethodInterface->isSuperClassOf(BoundInterface) ||
BoundInterface->isSuperClassOf(MethodInterface);
}
- llvm_unreachable("unknow method context");
+ llvm_unreachable("unknown method context");
}
/// We first select the type of the method: Instance or Factory, then collect
@@ -3859,9 +3861,9 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
assert(AtEnd.isValid() && "Invalid location for '@end'");
- ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
- Decl *ClassDecl = cast<Decl>(OCD);
-
+ auto *OCD = cast<ObjCContainerDecl>(CurContext);
+ Decl *ClassDecl = OCD;
+
bool isInterfaceDeclKind =
isa<ObjCInterfaceDecl>(ClassDecl) || isa<ObjCCategoryDecl>(ClassDecl)
|| isa<ObjCProtocolDecl>(ClassDecl);
@@ -4084,7 +4086,7 @@ CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) {
return (Decl::ObjCDeclQualifier) (unsigned) PQTVal;
}
-/// \brief Check whether the declared result type of the given Objective-C
+/// Check whether the declared result type of the given Objective-C
/// method declaration is compatible with the method's class.
///
static Sema::ResultTypeCompatibilityKind
@@ -4130,7 +4132,7 @@ class OverrideSearch {
public:
Sema &S;
ObjCMethodDecl *Method;
- llvm::SmallPtrSet<ObjCMethodDecl*, 4> Overridden;
+ llvm::SmallSetVector<ObjCMethodDecl*, 4> Overridden;
bool Recursive;
public:
@@ -4167,7 +4169,7 @@ public:
}
}
- typedef llvm::SmallPtrSetImpl<ObjCMethodDecl*>::iterator iterator;
+ typedef decltype(Overridden)::iterator iterator;
iterator begin() const { return Overridden.begin(); }
iterator end() const { return Overridden.end(); }
@@ -4335,10 +4337,6 @@ void Sema::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod,
// Then merge the declarations.
mergeObjCMethodDecls(ObjCMethod, overridden);
- }
-
- for (ObjCMethodDecl *overridden : overrides) {
- CheckObjCMethodOverride(ObjCMethod, overridden);
if (ObjCMethod->isImplicit() && overridden->isImplicit())
continue; // Conflicting properties are detected elsewhere.
@@ -4502,25 +4500,21 @@ static void checkObjCMethodX86VectorTypes(Sema &SemaRef,
}
Decl *Sema::ActOnMethodDeclaration(
- Scope *S,
- SourceLocation MethodLoc, SourceLocation EndLoc,
- tok::TokenKind MethodType,
- ObjCDeclSpec &ReturnQT, ParsedType ReturnType,
- ArrayRef<SourceLocation> SelectorLocs,
- Selector Sel,
+ Scope *S, SourceLocation MethodLoc, SourceLocation EndLoc,
+ tok::TokenKind MethodType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType,
+ ArrayRef<SourceLocation> SelectorLocs, Selector Sel,
// optional arguments. The number of types/arguments is obtained
// from the Sel.getNumArgs().
- ObjCArgInfo *ArgInfo,
- DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args
- AttributeList *AttrList, tok::ObjCKeywordKind MethodDeclKind,
+ ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo,
+ unsigned CNumArgs, // c-style args
+ const ParsedAttributesView &AttrList, tok::ObjCKeywordKind MethodDeclKind,
bool isVariadic, bool MethodDefinition) {
// Make sure we can establish a context for the method.
if (!CurContext->isObjCContainer()) {
Diag(MethodLoc, diag::err_missing_method_context);
return nullptr;
}
- ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
- Decl *ClassDecl = cast<Decl>(OCD);
+ Decl *ClassDecl = cast<ObjCContainerDecl>(CurContext);
QualType resultDeclType;
bool HasRelatedResultType = false;
@@ -4621,8 +4615,7 @@ Decl *Sema::ActOnMethodDeclaration(
ObjCMethod->setObjCDeclQualifier(
CvtQTToAstBitMask(ReturnQT.getObjCDeclQualifier()));
- if (AttrList)
- ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList);
+ ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList);
AddPragmaAttributes(TUScope, ObjCMethod);
// Add the method now.
@@ -4726,6 +4719,17 @@ Decl *Sema::ActOnMethodDeclaration(
Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86)
checkObjCMethodX86VectorTypes(*this, ObjCMethod);
+ // + load method cannot have availability attributes. It get called on
+ // startup, so it has to have the availability of the deployment target.
+ if (const auto *attr = ObjCMethod->getAttr<AvailabilityAttr>()) {
+ if (ObjCMethod->isClassMethod() &&
+ ObjCMethod->getSelector().getAsString() == "load") {
+ Diag(attr->getLocation(), diag::warn_availability_on_static_initializer)
+ << 0;
+ ObjCMethod->dropAttr<AvailabilityAttr>();
+ }
+ }
+
ActOnDocumentableDecl(ObjCMethod);
return ObjCMethod;
@@ -4769,7 +4773,7 @@ void Sema::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart,
Context.DeepCollectObjCIvars(Class, true, Ivars);
// For each ivar, create a fresh ObjCAtDefsFieldDecl.
for (unsigned i = 0; i < Ivars.size(); i++) {
- const FieldDecl* ID = cast<FieldDecl>(Ivars[i]);
+ const FieldDecl* ID = Ivars[i];
RecordDecl *Record = dyn_cast<RecordDecl>(TagD);
Decl *FD = ObjCAtDefsFieldDecl::Create(Context, Record,
/*FIXME: StartL=*/ID->getLocation(),
@@ -4784,13 +4788,13 @@ void Sema::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart,
D != Decls.end(); ++D) {
FieldDecl *FD = cast<FieldDecl>(*D);
if (getLangOpts().CPlusPlus)
- PushOnScopeChains(cast<FieldDecl>(FD), S);
+ PushOnScopeChains(FD, S);
else if (RecordDecl *Record = dyn_cast<RecordDecl>(TagD))
Record->addDecl(FD);
}
}
-/// \brief Build a type-check a new Objective-C exception variable declaration.
+/// Build a type-check a new Objective-C exception variable declaration.
VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T,
SourceLocation StartLoc,
SourceLocation IdLoc,
@@ -4811,12 +4815,17 @@ VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T,
// Don't do any further checking.
} else if (T->isDependentType()) {
// Okay: we don't know what this type will instantiate to.
- } else if (!T->isObjCObjectPointerType()) {
- Invalid = true;
- Diag(IdLoc ,diag::err_catch_param_not_objc_type);
} else if (T->isObjCQualifiedIdType()) {
Invalid = true;
Diag(IdLoc, diag::err_illegal_qualifiers_on_catch_parm);
+ } else if (T->isObjCIdType()) {
+ // Okay: we don't know what this type will instantiate to.
+ } else if (!T->isObjCObjectPointerType()) {
+ Invalid = true;
+ Diag(IdLoc, diag::err_catch_param_not_objc_type);
+ } else if (!T->getAs<ObjCObjectPointerType>()->getInterfaceType()) {
+ Invalid = true;
+ Diag(IdLoc, diag::err_catch_param_not_objc_type);
}
VarDecl *New = VarDecl::Create(Context, CurContext, StartLoc, IdLoc, Id,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
index 67d1b02d1fca..df5bc9b82b96 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -76,6 +76,29 @@ bool Sema::isLibstdcxxEagerExceptionSpecHack(const Declarator &D) {
.Default(false);
}
+ExprResult Sema::ActOnNoexceptSpec(SourceLocation NoexceptLoc,
+ Expr *NoexceptExpr,
+ ExceptionSpecificationType &EST) {
+ // FIXME: This is bogus, a noexcept expression is not a condition.
+ ExprResult Converted = CheckBooleanCondition(NoexceptLoc, NoexceptExpr);
+ if (Converted.isInvalid())
+ return Converted;
+
+ if (Converted.get()->isValueDependent()) {
+ EST = EST_DependentNoexcept;
+ return Converted;
+ }
+
+ llvm::APSInt Result;
+ Converted = VerifyIntegerConstantExpression(
+ Converted.get(), &Result,
+ diag::err_noexcept_needs_constant_expression,
+ /*AllowFold*/ false);
+ if (!Converted.isInvalid())
+ EST = !Result ? EST_NoexceptFalse : EST_NoexceptTrue;
+ return Converted;
+}
+
/// CheckSpecifiedExceptionType - Check if the given type is valid in an
/// exception specification. Incomplete types, or pointers to incomplete types
/// other than void are not allowed.
@@ -203,8 +226,8 @@ Sema::UpdateExceptionSpec(FunctionDecl *FD,
if (auto *Listener = getASTMutationListener())
Listener->ResolvedExceptionSpec(FD);
- for (auto *Redecl : FD->redecls())
- Context.adjustExceptionSpec(cast<FunctionDecl>(Redecl), ESI);
+ for (FunctionDecl *Redecl : FD->redecls())
+ Context.adjustExceptionSpec(Redecl, ESI);
}
static bool CheckEquivalentExceptionSpecImpl(
@@ -309,13 +332,19 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
FunctionProtoType::ExceptionSpecInfo ESI = OldProto->getExceptionSpecType();
if (ESI.Type == EST_Dynamic) {
+ // FIXME: What if the exceptions are described in terms of the old
+ // prototype's parameters?
ESI.Exceptions = OldProto->exceptions();
}
- if (ESI.Type == EST_ComputedNoexcept) {
- // For computed noexcept, we can't just take the expression from the old
- // prototype. It likely contains references to the old prototype's
- // parameters.
+ if (ESI.Type == EST_NoexceptFalse)
+ ESI.Type = EST_None;
+ if (ESI.Type == EST_NoexceptTrue)
+ ESI.Type = EST_BasicNoexcept;
+
+ // For dependent noexcept, we can't just take the expression from the old
+ // prototype. It likely contains references to the old prototype's parameters.
+ if (ESI.Type == EST_DependentNoexcept) {
New->setInvalidDecl();
} else {
// Update the type of the function with the appropriate exception
@@ -325,12 +354,12 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
NewProto->getExtProtoInfo().withExceptionSpec(ESI)));
}
- if (getLangOpts().MicrosoftExt && ESI.Type != EST_ComputedNoexcept) {
+ if (getLangOpts().MicrosoftExt && ESI.Type != EST_DependentNoexcept) {
// Allow missing exception specifications in redeclarations as an extension.
DiagID = diag::ext_ms_missing_exception_specification;
ReturnValueOnError = false;
} else if (New->isReplaceableGlobalAllocationFunction() &&
- ESI.Type != EST_ComputedNoexcept) {
+ ESI.Type != EST_DependentNoexcept) {
// Allow missing exception specifications in redeclarations as an extension,
// when declaring a replaceable global allocation function.
DiagID = diag::ext_missing_exception_specification;
@@ -367,7 +396,9 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
OS << "noexcept";
break;
- case EST_ComputedNoexcept:
+ case EST_DependentNoexcept:
+ case EST_NoexceptFalse:
+ case EST_NoexceptTrue:
OS << "noexcept(";
assert(OldProto->getNoexceptExpr() != nullptr && "Expected non-null Expr");
OldProto->getNoexceptExpr()->printPretty(OS, nullptr, getPrintingPolicy());
@@ -478,63 +509,62 @@ static bool CheckEquivalentExceptionSpecImpl(
!isUnresolvedExceptionSpec(NewEST) &&
"Shouldn't see unknown exception specifications here");
- // Shortcut the case where both have no spec.
- if (OldEST == EST_None && NewEST == EST_None)
- return false;
+ CanThrowResult OldCanThrow = Old->canThrow();
+ CanThrowResult NewCanThrow = New->canThrow();
- FunctionProtoType::NoexceptResult OldNR = Old->getNoexceptSpec(S.Context);
- FunctionProtoType::NoexceptResult NewNR = New->getNoexceptSpec(S.Context);
- if (OldNR == FunctionProtoType::NR_BadNoexcept ||
- NewNR == FunctionProtoType::NR_BadNoexcept)
+ // Any non-throwing specifications are compatible.
+ if (OldCanThrow == CT_Cannot && NewCanThrow == CT_Cannot)
return false;
- // Dependent noexcept specifiers are compatible with each other, but nothing
- // else.
- // One noexcept is compatible with another if the argument is the same
- if (OldNR == NewNR &&
- OldNR != FunctionProtoType::NR_NoNoexcept &&
- NewNR != FunctionProtoType::NR_NoNoexcept)
- return false;
- if (OldNR != NewNR &&
- OldNR != FunctionProtoType::NR_NoNoexcept &&
- NewNR != FunctionProtoType::NR_NoNoexcept) {
- S.Diag(NewLoc, DiagID);
- if (NoteID.getDiagID() != 0 && OldLoc.isValid())
- S.Diag(OldLoc, NoteID);
- return true;
+ // Any throws-anything specifications are usually compatible.
+ if (OldCanThrow == CT_Can && OldEST != EST_Dynamic &&
+ NewCanThrow == CT_Can && NewEST != EST_Dynamic) {
+ // The exception is that the absence of an exception specification only
+ // matches noexcept(false) for functions, as described above.
+ if (!AllowNoexceptAllMatchWithNoSpec &&
+ ((OldEST == EST_None && NewEST == EST_NoexceptFalse) ||
+ (OldEST == EST_NoexceptFalse && NewEST == EST_None))) {
+ // This is the disallowed case.
+ } else {
+ return false;
+ }
}
- // The MS extension throw(...) is compatible with itself.
- if (OldEST == EST_MSAny && NewEST == EST_MSAny)
- return false;
-
- // It's also compatible with no spec.
- if ((OldEST == EST_None && NewEST == EST_MSAny) ||
- (OldEST == EST_MSAny && NewEST == EST_None))
- return false;
+ // C++14 [except.spec]p3:
+ // Two exception-specifications are compatible if [...] both have the form
+ // noexcept(constant-expression) and the constant-expressions are equivalent
+ if (OldEST == EST_DependentNoexcept && NewEST == EST_DependentNoexcept) {
+ llvm::FoldingSetNodeID OldFSN, NewFSN;
+ Old->getNoexceptExpr()->Profile(OldFSN, S.Context, true);
+ New->getNoexceptExpr()->Profile(NewFSN, S.Context, true);
+ if (OldFSN == NewFSN)
+ return false;
+ }
- // It's also compatible with noexcept(false).
- if (OldEST == EST_MSAny && NewNR == FunctionProtoType::NR_Throw)
- return false;
- if (NewEST == EST_MSAny && OldNR == FunctionProtoType::NR_Throw)
- return false;
+ // Dynamic exception specifications with the same set of adjusted types
+ // are compatible.
+ if (OldEST == EST_Dynamic && NewEST == EST_Dynamic) {
+ bool Success = true;
+ // Both have a dynamic exception spec. Collect the first set, then compare
+ // to the second.
+ llvm::SmallPtrSet<CanQualType, 8> OldTypes, NewTypes;
+ for (const auto &I : Old->exceptions())
+ OldTypes.insert(S.Context.getCanonicalType(I).getUnqualifiedType());
+
+ for (const auto &I : New->exceptions()) {
+ CanQualType TypePtr = S.Context.getCanonicalType(I).getUnqualifiedType();
+ if (OldTypes.count(TypePtr))
+ NewTypes.insert(TypePtr);
+ else {
+ Success = false;
+ break;
+ }
+ }
- // As described above, noexcept(false) matches no spec only for functions.
- if (AllowNoexceptAllMatchWithNoSpec) {
- if (OldEST == EST_None && NewNR == FunctionProtoType::NR_Throw)
- return false;
- if (NewEST == EST_None && OldNR == FunctionProtoType::NR_Throw)
+ if (Success && OldTypes.size() == NewTypes.size())
return false;
}
- // Any non-throwing specifications are compatible.
- bool OldNonThrowing = OldNR == FunctionProtoType::NR_Nothrow ||
- OldEST == EST_DynamicNone;
- bool NewNonThrowing = NewNR == FunctionProtoType::NR_Nothrow ||
- NewEST == EST_DynamicNone;
- if (OldNonThrowing && NewNonThrowing)
- return false;
-
// As a special compatibility feature, under C++0x we accept no spec and
// throw(std::bad_alloc) as equivalent for operator new and operator new[].
// This is because the implicit declaration changed, but old code would break.
@@ -560,54 +590,24 @@ static bool CheckEquivalentExceptionSpecImpl(
}
}
- // At this point, the only remaining valid case is two matching dynamic
- // specifications. We return here unless both specifications are dynamic.
- if (OldEST != EST_Dynamic || NewEST != EST_Dynamic) {
- if (MissingExceptionSpecification && Old->hasExceptionSpec() &&
- !New->hasExceptionSpec()) {
- // The old type has an exception specification of some sort, but
- // the new type does not.
- *MissingExceptionSpecification = true;
-
- if (MissingEmptyExceptionSpecification && OldNonThrowing) {
- // The old type has a throw() or noexcept(true) exception specification
- // and the new type has no exception specification, and the caller asked
- // to handle this itself.
- *MissingEmptyExceptionSpecification = true;
- }
-
- return true;
+ // If the caller wants to handle the case that the new function is
+ // incompatible due to a missing exception specification, let it.
+ if (MissingExceptionSpecification && OldEST != EST_None &&
+ NewEST == EST_None) {
+ // The old type has an exception specification of some sort, but
+ // the new type does not.
+ *MissingExceptionSpecification = true;
+
+ if (MissingEmptyExceptionSpecification && OldCanThrow == CT_Cannot) {
+ // The old type has a throw() or noexcept(true) exception specification
+ // and the new type has no exception specification, and the caller asked
+ // to handle this itself.
+ *MissingEmptyExceptionSpecification = true;
}
- S.Diag(NewLoc, DiagID);
- if (NoteID.getDiagID() != 0 && OldLoc.isValid())
- S.Diag(OldLoc, NoteID);
return true;
}
- assert(OldEST == EST_Dynamic && NewEST == EST_Dynamic &&
- "Exception compatibility logic error: non-dynamic spec slipped through.");
-
- bool Success = true;
- // Both have a dynamic exception spec. Collect the first set, then compare
- // to the second.
- llvm::SmallPtrSet<CanQualType, 8> OldTypes, NewTypes;
- for (const auto &I : Old->exceptions())
- OldTypes.insert(S.Context.getCanonicalType(I).getUnqualifiedType());
-
- for (const auto &I : New->exceptions()) {
- CanQualType TypePtr = S.Context.getCanonicalType(I).getUnqualifiedType();
- if (OldTypes.count(TypePtr))
- NewTypes.insert(TypePtr);
- else
- Success = false;
- }
-
- Success = Success && OldTypes.size() == NewTypes.size();
-
- if (Success) {
- return false;
- }
S.Diag(NewLoc, DiagID);
if (NoteID.getDiagID() != 0 && OldLoc.isValid())
S.Diag(OldLoc, NoteID);
@@ -626,6 +626,90 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
New, NewLoc);
}
+bool Sema::handlerCanCatch(QualType HandlerType, QualType ExceptionType) {
+ // [except.handle]p3:
+ // A handler is a match for an exception object of type E if:
+
+ // HandlerType must be ExceptionType or derived from it, or pointer or
+ // reference to such types.
+ const ReferenceType *RefTy = HandlerType->getAs<ReferenceType>();
+ if (RefTy)
+ HandlerType = RefTy->getPointeeType();
+
+ // -- the handler is of type cv T or cv T& and E and T are the same type
+ if (Context.hasSameUnqualifiedType(ExceptionType, HandlerType))
+ return true;
+
+ // FIXME: ObjC pointer types?
+ if (HandlerType->isPointerType() || HandlerType->isMemberPointerType()) {
+ if (RefTy && (!HandlerType.isConstQualified() ||
+ HandlerType.isVolatileQualified()))
+ return false;
+
+ // -- the handler is of type cv T or const T& where T is a pointer or
+ // pointer to member type and E is std::nullptr_t
+ if (ExceptionType->isNullPtrType())
+ return true;
+
+ // -- the handler is of type cv T or const T& where T is a pointer or
+ // pointer to member type and E is a pointer or pointer to member type
+ // that can be converted to T by one or more of
+ // -- a qualification conversion
+ // -- a function pointer conversion
+ bool LifetimeConv;
+ QualType Result;
+ // FIXME: Should we treat the exception as catchable if a lifetime
+ // conversion is required?
+ if (IsQualificationConversion(ExceptionType, HandlerType, false,
+ LifetimeConv) ||
+ IsFunctionConversion(ExceptionType, HandlerType, Result))
+ return true;
+
+ // -- a standard pointer conversion [...]
+ if (!ExceptionType->isPointerType() || !HandlerType->isPointerType())
+ return false;
+
+ // Handle the "qualification conversion" portion.
+ Qualifiers EQuals, HQuals;
+ ExceptionType = Context.getUnqualifiedArrayType(
+ ExceptionType->getPointeeType(), EQuals);
+ HandlerType = Context.getUnqualifiedArrayType(
+ HandlerType->getPointeeType(), HQuals);
+ if (!HQuals.compatiblyIncludes(EQuals))
+ return false;
+
+ if (HandlerType->isVoidType() && ExceptionType->isObjectType())
+ return true;
+
+ // The only remaining case is a derived-to-base conversion.
+ }
+
+ // -- the handler is of type cg T or cv T& and T is an unambiguous public
+ // base class of E
+ if (!ExceptionType->isRecordType() || !HandlerType->isRecordType())
+ return false;
+ CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+ /*DetectVirtual=*/false);
+ if (!IsDerivedFrom(SourceLocation(), ExceptionType, HandlerType, Paths) ||
+ Paths.isAmbiguous(Context.getCanonicalType(HandlerType)))
+ return false;
+
+ // Do this check from a context without privileges.
+ switch (CheckBaseClassAccess(SourceLocation(), HandlerType, ExceptionType,
+ Paths.front(),
+ /*Diagnostic*/ 0,
+ /*ForceCheck*/ true,
+ /*ForceUnprivileged*/ true)) {
+ case AR_accessible: return true;
+ case AR_inaccessible: return false;
+ case AR_dependent:
+ llvm_unreachable("access check dependent for unprivileged context");
+ case AR_delayed:
+ llvm_unreachable("access check delayed in non-declaration");
+ }
+ llvm_unreachable("unexpected access check result");
+}
+
/// CheckExceptionSpecSubset - Check whether the second function type's
/// exception specification is a subset (or equivalent) of the first function
/// type. This is used by override and pointer assignment checks.
@@ -656,62 +740,32 @@ bool Sema::CheckExceptionSpecSubset(const PartialDiagnostic &DiagID,
return false;
ExceptionSpecificationType SuperEST = Superset->getExceptionSpecType();
-
- // If superset contains everything, we're done.
- if (SuperEST == EST_None || SuperEST == EST_MSAny)
- return CheckParamExceptionSpec(NestedDiagID, NoteID, Superset, SuperLoc,
- Subset, SubLoc);
-
- // If there are dependent noexcept specs, assume everything is fine. Unlike
- // with the equivalency check, this is safe in this case, because we don't
- // want to merge declarations. Checks after instantiation will catch any
- // omissions we make here.
- // We also shortcut checking if a noexcept expression was bad.
-
- FunctionProtoType::NoexceptResult SuperNR =Superset->getNoexceptSpec(Context);
- if (SuperNR == FunctionProtoType::NR_BadNoexcept ||
- SuperNR == FunctionProtoType::NR_Dependent)
- return false;
-
- // Another case of the superset containing everything.
- if (SuperNR == FunctionProtoType::NR_Throw)
- return CheckParamExceptionSpec(NestedDiagID, NoteID, Superset, SuperLoc,
- Subset, SubLoc);
-
ExceptionSpecificationType SubEST = Subset->getExceptionSpecType();
-
assert(!isUnresolvedExceptionSpec(SuperEST) &&
!isUnresolvedExceptionSpec(SubEST) &&
"Shouldn't see unknown exception specifications here");
- // It does not. If the subset contains everything, we've failed.
- if (SubEST == EST_None || SubEST == EST_MSAny) {
- Diag(SubLoc, DiagID);
- if (NoteID.getDiagID() != 0)
- Diag(SuperLoc, NoteID);
- return true;
- }
-
- FunctionProtoType::NoexceptResult SubNR = Subset->getNoexceptSpec(Context);
- if (SubNR == FunctionProtoType::NR_BadNoexcept ||
- SubNR == FunctionProtoType::NR_Dependent)
+ // If there are dependent noexcept specs, assume everything is fine. Unlike
+ // with the equivalency check, this is safe in this case, because we don't
+ // want to merge declarations. Checks after instantiation will catch any
+ // omissions we make here.
+ if (SuperEST == EST_DependentNoexcept || SubEST == EST_DependentNoexcept)
return false;
- // Another case of the subset containing everything.
- if (SubNR == FunctionProtoType::NR_Throw) {
- Diag(SubLoc, DiagID);
- if (NoteID.getDiagID() != 0)
- Diag(SuperLoc, NoteID);
- return true;
- }
+ CanThrowResult SuperCanThrow = Superset->canThrow();
+ CanThrowResult SubCanThrow = Subset->canThrow();
- // If the subset contains nothing, we're done.
- if (SubEST == EST_DynamicNone || SubNR == FunctionProtoType::NR_Nothrow)
+ // If the superset contains everything or the subset contains nothing, we're
+ // done.
+ if ((SuperCanThrow == CT_Can && SuperEST != EST_Dynamic) ||
+ SubCanThrow == CT_Cannot)
return CheckParamExceptionSpec(NestedDiagID, NoteID, Superset, SuperLoc,
Subset, SubLoc);
- // Otherwise, if the superset contains nothing, we've failed.
- if (SuperEST == EST_DynamicNone || SuperNR == FunctionProtoType::NR_Nothrow) {
+ // If the subset contains everything or the superset contains nothing, we've
+ // failed.
+ if ((SubCanThrow == CT_Can && SubEST != EST_Dynamic) ||
+ SuperCanThrow == CT_Cannot) {
Diag(SubLoc, DiagID);
if (NoteID.getDiagID() != 0)
Diag(SuperLoc, NoteID);
@@ -722,75 +776,23 @@ bool Sema::CheckExceptionSpecSubset(const PartialDiagnostic &DiagID,
"Exception spec subset: non-dynamic case slipped through.");
// Neither contains everything or nothing. Do a proper comparison.
- for (const auto &SubI : Subset->exceptions()) {
- // Take one type from the subset.
- QualType CanonicalSubT = Context.getCanonicalType(SubI);
- // Unwrap pointers and references so that we can do checks within a class
- // hierarchy. Don't unwrap member pointers; they don't have hierarchy
- // conversions on the pointee.
- bool SubIsPointer = false;
- if (const ReferenceType *RefTy = CanonicalSubT->getAs<ReferenceType>())
- CanonicalSubT = RefTy->getPointeeType();
- if (const PointerType *PtrTy = CanonicalSubT->getAs<PointerType>()) {
- CanonicalSubT = PtrTy->getPointeeType();
- SubIsPointer = true;
- }
- bool SubIsClass = CanonicalSubT->isRecordType();
- CanonicalSubT = CanonicalSubT.getLocalUnqualifiedType();
+ for (QualType SubI : Subset->exceptions()) {
+ if (const ReferenceType *RefTy = SubI->getAs<ReferenceType>())
+ SubI = RefTy->getPointeeType();
- CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
- /*DetectVirtual=*/false);
-
- bool Contained = false;
// Make sure it's in the superset.
- for (const auto &SuperI : Superset->exceptions()) {
- QualType CanonicalSuperT = Context.getCanonicalType(SuperI);
- // SubT must be SuperT or derived from it, or pointer or reference to
- // such types.
- if (const ReferenceType *RefTy = CanonicalSuperT->getAs<ReferenceType>())
- CanonicalSuperT = RefTy->getPointeeType();
- if (SubIsPointer) {
- if (const PointerType *PtrTy = CanonicalSuperT->getAs<PointerType>())
- CanonicalSuperT = PtrTy->getPointeeType();
- else {
- continue;
- }
- }
- CanonicalSuperT = CanonicalSuperT.getLocalUnqualifiedType();
- // If the types are the same, move on to the next type in the subset.
- if (CanonicalSubT == CanonicalSuperT) {
+ bool Contained = false;
+ for (QualType SuperI : Superset->exceptions()) {
+ // [except.spec]p5:
+ // the target entity shall allow at least the exceptions allowed by the
+ // source
+ //
+ // We interpret this as meaning that a handler for some target type would
+ // catch an exception of each source type.
+ if (handlerCanCatch(SuperI, SubI)) {
Contained = true;
break;
}
-
- // Otherwise we need to check the inheritance.
- if (!SubIsClass || !CanonicalSuperT->isRecordType())
- continue;
-
- Paths.clear();
- if (!IsDerivedFrom(SubLoc, CanonicalSubT, CanonicalSuperT, Paths))
- continue;
-
- if (Paths.isAmbiguous(Context.getCanonicalType(CanonicalSuperT)))
- continue;
-
- // Do this check from a context without privileges.
- switch (CheckBaseClassAccess(SourceLocation(),
- CanonicalSuperT, CanonicalSubT,
- Paths.front(),
- /*Diagnostic*/ 0,
- /*ForceCheck*/ true,
- /*ForceUnprivileged*/ true)) {
- case AR_accessible: break;
- case AR_inaccessible: continue;
- case AR_dependent:
- llvm_unreachable("access check dependent for unprivileged context");
- case AR_delayed:
- llvm_unreachable("access check delayed in non-declaration");
- }
-
- Contained = true;
- break;
}
if (!Contained) {
Diag(SubLoc, DiagID);
@@ -994,7 +996,7 @@ static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, const Decl *D) {
if (!FT)
return CT_Can;
- return FT->isNothrow(S.Context) ? CT_Cannot : CT_Can;
+ return FT->canThrow();
}
static CanThrowResult canDynamicCastThrow(const CXXDynamicCastExpr *DC) {
@@ -1262,6 +1264,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
case Expr::ImaginaryLiteralClass:
case Expr::ImplicitValueInitExprClass:
case Expr::IntegerLiteralClass:
+ case Expr::FixedPointLiteralClass:
case Expr::ArrayInitIndexExprClass:
case Expr::NoInitExprClass:
case Expr::ObjCEncodeExprClass:
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
index a6e43765e106..60abd718e228 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
@@ -37,6 +37,7 @@
#include "clang/Sema/Designator.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Overload.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
@@ -47,7 +48,7 @@
using namespace clang;
using namespace sema;
-/// \brief Determine whether the use of this declaration is valid, without
+/// Determine whether the use of this declaration is valid, without
/// emitting diagnostics.
bool Sema::CanUseDecl(NamedDecl *D, bool TreatUnavailableAsInvalid) {
// See if this is an auto-typed variable whose initializer we are parsing.
@@ -88,7 +89,7 @@ static void DiagnoseUnusedOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc) {
}
}
-/// \brief Emit a note explaining that this function is deleted.
+/// Emit a note explaining that this function is deleted.
void Sema::NoteDeletedFunction(FunctionDecl *Decl) {
assert(Decl->isDeleted());
@@ -116,7 +117,7 @@ void Sema::NoteDeletedFunction(FunctionDecl *Decl) {
<< Decl << true;
}
-/// \brief Determine whether a FunctionDecl was ever declared with an
+/// Determine whether a FunctionDecl was ever declared with an
/// explicit storage class.
static bool hasAnyExplicitStorageClass(const FunctionDecl *D) {
for (auto I : D->redecls()) {
@@ -126,7 +127,7 @@ static bool hasAnyExplicitStorageClass(const FunctionDecl *D) {
return false;
}
-/// \brief Check whether we're in an extern inline function and referring to a
+/// Check whether we're in an extern inline function and referring to a
/// variable or function with internal linkage (C11 6.7.4p3).
///
/// This is only a warning because we used to silently accept this code, but
@@ -189,7 +190,7 @@ void Sema::MaybeSuggestAddingStaticToDecl(const FunctionDecl *Cur) {
}
}
-/// \brief Determine whether the use of this declaration is valid, and
+/// Determine whether the use of this declaration is valid, and
/// emit any corresponding diagnostics.
///
/// This routine diagnoses various problems with referencing
@@ -201,10 +202,11 @@ void Sema::MaybeSuggestAddingStaticToDecl(const FunctionDecl *Cur) {
/// \returns true if there was an error (this declaration cannot be
/// referenced), false otherwise.
///
-bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
+bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
const ObjCInterfaceDecl *UnknownObjCClass,
bool ObjCPropertyAccess,
bool AvoidPartialAvailabilityChecks) {
+ SourceLocation Loc = Locs.front();
if (getLangOpts().CPlusPlus && isa<FunctionDecl>(D)) {
// If there were any diagnostics suppressed by template argument deduction,
// emit them now.
@@ -288,7 +290,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
return true;
}
- DiagnoseAvailabilityOfDecl(D, Loc, UnknownObjCClass, ObjCPropertyAccess,
+ DiagnoseAvailabilityOfDecl(D, Locs, UnknownObjCClass, ObjCPropertyAccess,
AvoidPartialAvailabilityChecks);
DiagnoseUnusedOfDecl(*this, D, Loc);
@@ -298,7 +300,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
return false;
}
-/// \brief Retrieve the message suffix that should be added to a
+/// Retrieve the message suffix that should be added to a
/// diagnostic complaining about the given function being deleted or
/// unavailable.
std::string Sema::getDeletedOrUnavailableSuffix(const FunctionDecl *FD) {
@@ -776,6 +778,9 @@ Sema::VarArgKind Sema::isValidVarArgType(const QualType &Ty) {
return VAK_Valid;
}
+ if (Ty.isDestructedType() == QualType::DK_nontrivial_c_struct)
+ return VAK_Invalid;
+
if (Ty.isCXX98PODType(Context))
return VAK_Valid;
@@ -837,7 +842,10 @@ void Sema::checkVariadicArgument(const Expr *E, VariadicCallType CT) {
break;
case VAK_Invalid:
- if (Ty->isObjCObjectType())
+ if (Ty.isDestructedType() == QualType::DK_nontrivial_c_struct)
+ Diag(E->getLocStart(),
+ 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)
@@ -909,7 +917,7 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,
return E;
}
-/// \brief Converts an integer to complex float type. Helper function of
+/// Converts an integer to complex float type. Helper function of
/// UsualArithmeticConversions()
///
/// \return false if the integer expression is an integer type and is
@@ -934,7 +942,7 @@ static bool handleIntegerToComplexFloatConversion(Sema &S, ExprResult &IntExpr,
return false;
}
-/// \brief Handle arithmetic conversion with complex types. Helper function of
+/// Handle arithmetic conversion with complex types. Helper function of
/// UsualArithmeticConversions()
static QualType handleComplexFloatConversion(Sema &S, ExprResult &LHS,
ExprResult &RHS, QualType LHSType,
@@ -990,7 +998,7 @@ static QualType handleComplexFloatConversion(Sema &S, ExprResult &LHS,
return ResultType;
}
-/// \brief Handle arithmetic conversion from integer to float. Helper function
+/// Handle arithmetic conversion from integer to float. Helper function
/// of UsualArithmeticConversions()
static QualType handleIntToFloatConversion(Sema &S, ExprResult &FloatExpr,
ExprResult &IntExpr,
@@ -1021,7 +1029,7 @@ static QualType handleIntToFloatConversion(Sema &S, ExprResult &FloatExpr,
return result;
}
-/// \brief Handle arithmethic conversion with floating point types. Helper
+/// Handle arithmethic conversion with floating point types. Helper
/// function of UsualArithmeticConversions()
static QualType handleFloatConversion(Sema &S, ExprResult &LHS,
ExprResult &RHS, QualType LHSType,
@@ -1059,7 +1067,7 @@ static QualType handleFloatConversion(Sema &S, ExprResult &LHS,
/*convertFloat=*/!IsCompAssign);
}
-/// \brief Diagnose attempts to convert between __float128 and long double if
+/// Diagnose attempts to convert between __float128 and long double if
/// there is no support for such conversion. Helper function of
/// UsualArithmeticConversions().
static bool unsupportedTypeConversion(const Sema &S, QualType LHSType,
@@ -1092,13 +1100,12 @@ static bool unsupportedTypeConversion(const Sema &S, QualType LHSType,
Float128AndLongDouble |= (LHSElemType == S.Context.LongDoubleTy &&
RHSElemType == S.Context.Float128Ty);
- /* We've handled the situation where __float128 and long double have the same
- representation. The only other allowable conversion is if long double is
- really just double.
- */
+ // We've handled the situation where __float128 and long double have the same
+ // representation. We allow all conversions for all possible long double types
+ // except PPC's double double.
return Float128AndLongDouble &&
- (&S.Context.getFloatTypeSemantics(S.Context.LongDoubleTy) !=
- &llvm::APFloat::IEEEdouble());
+ (&S.Context.getFloatTypeSemantics(S.Context.LongDoubleTy) ==
+ &llvm::APFloat::PPCDoubleDouble());
}
typedef ExprResult PerformCastFn(Sema &S, Expr *operand, QualType toType);
@@ -1116,7 +1123,7 @@ ExprResult doComplexIntegralCast(Sema &S, Expr *op, QualType toType) {
}
}
-/// \brief Handle integer arithmetic conversions. Helper function of
+/// Handle integer arithmetic conversions. Helper function of
/// UsualArithmeticConversions()
template <PerformCastFn doLHSCast, PerformCastFn doRHSCast>
static QualType handleIntegerConversion(Sema &S, ExprResult &LHS,
@@ -1167,7 +1174,7 @@ static QualType handleIntegerConversion(Sema &S, ExprResult &LHS,
}
}
-/// \brief Handle conversions with GCC complex int extension. Helper function
+/// Handle conversions with GCC complex int extension. Helper function
/// of UsualArithmeticConversions()
static QualType handleComplexIntConversion(Sema &S, ExprResult &LHS,
ExprResult &RHS, QualType LHSType,
@@ -1529,6 +1536,8 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) {
CharTy = Context.getWideCharType();
Kind = StringLiteral::Wide;
} else if (Literal.isUTF8()) {
+ if (getLangOpts().Char8)
+ CharTy = Context.Char8Ty;
Kind = StringLiteral::UTF8;
} else if (Literal.isUTF16()) {
CharTy = Context.Char16Ty;
@@ -1545,17 +1554,14 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) {
if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings)
CharTyConst.addConst();
+ CharTyConst = Context.adjustStringLiteralBaseType(CharTyConst);
+
// Get an array type for the string, according to C99 6.4.5. This includes
// the nul terminator character as well as the string length for pascal
// strings.
- QualType StrTy = Context.getConstantArrayType(CharTyConst,
- llvm::APInt(32, Literal.GetNumStringChars()+1),
- ArrayType::Normal, 0);
-
- // OpenCL v1.1 s6.5.3: a string literal is in the constant address space.
- if (getLangOpts().OpenCL) {
- StrTy = Context.getAddrSpaceQualType(StrTy, LangAS::opencl_constant);
- }
+ QualType StrTy = Context.getConstantArrayType(
+ CharTyConst, llvm::APInt(32, Literal.GetNumStringChars() + 1),
+ ArrayType::Normal, 0);
// Pass &StringTokLocs[0], StringTokLocs.size() to factory!
StringLiteral *Lit = StringLiteral::Create(Context, Literal.GetString(),
@@ -1674,9 +1680,9 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
MarkDeclRefReferenced(E);
if (getLangOpts().ObjCWeak && isa<VarDecl>(D) &&
- Ty.getObjCLifetime() == Qualifiers::OCL_Weak &&
+ Ty.getObjCLifetime() == Qualifiers::OCL_Weak && !isUnevaluatedContext() &&
!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getLocStart()))
- recordUseOfEvaluatedWeak(E);
+ getCurFunction()->recordUseOfWeak(E);
FieldDecl *FD = dyn_cast<FieldDecl>(D);
if (IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(D))
@@ -2074,16 +2080,17 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
(Id.getKind() == UnqualifiedIdKind::IK_ImplicitSelfParam)
? LookupObjCImplicitSelfParam
: LookupOrdinaryName);
- if (TemplateArgs) {
+ if (TemplateKWLoc.isValid() || TemplateArgs) {
// Lookup the template name again to correctly establish the context in
// which it was found. This is really unfortunate as we already did the
// lookup to determine that it was a template name in the first place. If
// this becomes a performance hit, we can work harder to preserve those
// results until we get here but it's likely not worth it.
bool MemberOfUnknownSpecialization;
- LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false,
- MemberOfUnknownSpecialization);
-
+ if (LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false,
+ MemberOfUnknownSpecialization, TemplateKWLoc))
+ return ExprError();
+
if (MemberOfUnknownSpecialization ||
(R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation))
return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo,
@@ -2149,6 +2156,9 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
if (SS.isValid())
CCC->setTypoNNS(SS.getScopeRep());
}
+ // FIXME: DiagnoseEmptyLookup produces bad diagnostics if we're looking for
+ // a template name, but we happen to have always already looked up the name
+ // before we get here if it must be a template name.
if (DiagnoseEmptyLookup(S, SS, R,
CCC ? std::move(CCC) : std::move(DefaultValidator),
nullptr, None, &TE)) {
@@ -2426,8 +2436,9 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
IV->getLocation(), SelfExpr.get(), true, true);
if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
- if (!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc))
- recordUseOfEvaluatedWeak(Result);
+ if (!isUnevaluatedContext() &&
+ !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc))
+ getCurFunction()->recordUseOfWeak(Result);
}
if (getLangOpts().ObjCAutoRefCount) {
if (CurContext->isClosure())
@@ -2471,7 +2482,7 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
return ExprResult((Expr *)nullptr);
}
-/// \brief Cast a base object to a member's actual type.
+/// Cast a base object to a member's actual type.
///
/// Logically this happens in three phases:
///
@@ -2717,12 +2728,23 @@ static bool CheckDeclInExpr(Sema &S, SourceLocation Loc, NamedDecl *D) {
return false;
}
+// Certain multiversion types should be treated as overloaded even when there is
+// only one result.
+static bool ShouldLookupResultBeMultiVersionOverload(const LookupResult &R) {
+ assert(R.isSingleResult() && "Expected only a single result");
+ const auto *FD = dyn_cast<FunctionDecl>(R.getFoundDecl());
+ return FD &&
+ (FD->isCPUDispatchMultiVersion() || FD->isCPUSpecificMultiVersion());
+}
+
ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
LookupResult &R, bool NeedsADL,
bool AcceptInvalidDecl) {
// If this is a single, fully-resolved result and we don't need ADL,
// just build an ordinary singleton decl ref.
- if (!NeedsADL && R.isSingleResult() && !R.getAsSingle<FunctionTemplateDecl>())
+ if (!NeedsADL && R.isSingleResult() &&
+ !R.getAsSingle<FunctionTemplateDecl>() &&
+ !ShouldLookupResultBeMultiVersionOverload(R))
return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), R.getFoundDecl(),
R.getRepresentativeDecl(), nullptr,
AcceptInvalidDecl);
@@ -2730,7 +2752,7 @@ ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
// We only need to check the declaration if there's exactly one
// result, because in the overloaded case the results can only be
// functions and function templates.
- if (R.isSingleResult() &&
+ if (R.isSingleResult() && !ShouldLookupResultBeMultiVersionOverload(R) &&
CheckDeclInExpr(*this, R.getNameLoc(), R.getFoundDecl()))
return ExprError();
@@ -2753,7 +2775,7 @@ static void
diagnoseUncapturableValueReference(Sema &S, SourceLocation loc,
ValueDecl *var, DeclContext *DC);
-/// \brief Complete semantic analysis for a reference to the given declaration.
+/// Complete semantic analysis for a reference to the given declaration.
ExprResult Sema::BuildDeclarationNameExpr(
const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D,
NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs,
@@ -2769,9 +2791,7 @@ ExprResult Sema::BuildDeclarationNameExpr(
if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) {
// Specifically diagnose references to class templates that are missing
// a template argument list.
- Diag(Loc, diag::err_template_decl_ref) << (isa<VarTemplateDecl>(D) ? 1 : 0)
- << Template << SS.getRange();
- Diag(Template->getLocation(), diag::note_template_decl_here);
+ diagnoseMissingTemplateArguments(TemplateName(Template), Loc);
return ExprError();
}
@@ -3034,8 +3054,9 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
unsigned Length = Str.length();
llvm::APInt LengthI(32, Length + 1);
- if (IT == PredefinedExpr::LFunction) {
- ResTy = Context.WideCharTy.withConst();
+ if (IT == PredefinedExpr::LFunction || IT == PredefinedExpr::LFuncSig) {
+ ResTy =
+ Context.adjustStringLiteralBaseType(Context.WideCharTy.withConst());
SmallString<32> RawChars;
ConvertUTF8ToWideString(Context.getTypeSizeInChars(ResTy).getQuantity(),
Str, RawChars);
@@ -3044,7 +3065,7 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
SL = StringLiteral::Create(Context, RawChars, StringLiteral::Wide,
/*Pascal*/ false, ResTy, Loc);
} else {
- ResTy = Context.CharTy.withConst();
+ ResTy = Context.adjustStringLiteralBaseType(Context.CharTy.withConst());
ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal,
/*IndexTypeQuals*/ 0);
SL = StringLiteral::Create(Context, Str, StringLiteral::Ascii,
@@ -3064,7 +3085,8 @@ ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
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;
+ 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;
}
@@ -3086,6 +3108,8 @@ ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) {
QualType Ty;
if (Literal.isWide())
Ty = Context.WideCharTy; // L'x' -> wchar_t in C and C++.
+ else if (Literal.isUTF8() && getLangOpts().Char8)
+ Ty = Context.Char8Ty; // u8'x' -> char8_t when it exists.
else if (Literal.isUTF16())
Ty = Context.Char16Ty; // u'x' -> char16_t in C11 and C++11.
else if (Literal.isUTF32())
@@ -3281,8 +3305,8 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
// operator "" X ("n")
unsigned Length = Literal.getUDSuffixOffset();
QualType StrTy = Context.getConstantArrayType(
- Context.CharTy.withConst(), llvm::APInt(32, Length + 1),
- ArrayType::Normal, 0);
+ Context.adjustStringLiteralBaseType(Context.CharTy.withConst()),
+ llvm::APInt(32, Length + 1), ArrayType::Normal, 0);
Expr *Lit = StringLiteral::Create(
Context, StringRef(TokSpelling.data(), Length), StringLiteral::Ascii,
/*Pascal*/false, StrTy, &TokLoc, 1);
@@ -3314,7 +3338,52 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
Expr *Res;
- if (Literal.isFloatingLiteral()) {
+ if (Literal.isFixedPointLiteral()) {
+ QualType Ty;
+
+ if (Literal.isAccum) {
+ if (Literal.isHalf) {
+ Ty = Context.ShortAccumTy;
+ } else if (Literal.isLong) {
+ Ty = Context.LongAccumTy;
+ } else {
+ Ty = Context.AccumTy;
+ }
+ } else if (Literal.isFract) {
+ if (Literal.isHalf) {
+ Ty = Context.ShortFractTy;
+ } else if (Literal.isLong) {
+ Ty = Context.LongFractTy;
+ } else {
+ Ty = Context.FractTy;
+ }
+ }
+
+ if (Literal.isUnsigned) Ty = Context.getCorrespondingUnsignedType(Ty);
+
+ 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);
+
+ // 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)
+ // 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
+ // the maximal value for the type.
+ --Val;
+ else if (Val.ugt(MaxVal) || Overflowed)
+ Diag(Tok.getLocation(), diag::err_too_large_for_fixed_point);
+
+ Res = FixedPointLiteral::CreateFromRawInt(Context, Val, Ty,
+ Tok.getLocation(), scale);
+ } else if (Literal.isFloatingLiteral()) {
QualType Ty;
if (Literal.isHalf){
if (getOpenCLOptions().isEnabled("cl_khr_fp16"))
@@ -3554,7 +3623,7 @@ static bool CheckObjCTraitOperandConstraints(Sema &S, QualType T,
return false;
}
-/// \brief Check whether E is a pointer from a decayed array type (the decayed
+/// Check whether E is a pointer from a decayed array type (the decayed
/// pointer type is equal to T) and emit a warning if it is.
static void warnOnSizeofOnArrayDecay(Sema &S, SourceLocation Loc, QualType T,
Expr *E) {
@@ -3572,7 +3641,7 @@ static void warnOnSizeofOnArrayDecay(Sema &S, SourceLocation Loc, QualType T,
<< ICE->getSubExpr()->getType();
}
-/// \brief Check the constraints on expression operands to unary type expression
+/// Check the constraints on expression operands to unary type expression
/// and type traits.
///
/// Completes any types necessary and validates the constraints on the operand
@@ -3656,7 +3725,7 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
return false;
}
-/// \brief Check the constraints on operands to unary expression and type
+/// Check the constraints on operands to unary expression and type
/// traits.
///
/// This will complete any types necessary, and validate the various constraints
@@ -3910,7 +3979,7 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T,
} while (!T.isNull() && T->isVariablyModifiedType());
}
-/// \brief Build a sizeof or alignof expression given a type operand.
+/// Build a sizeof or alignof expression given a type operand.
ExprResult
Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
SourceLocation OpLoc,
@@ -3954,7 +4023,7 @@ Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
ExprKind, TInfo, Context.getSizeType(), OpLoc, R.getEnd());
}
-/// \brief Build a sizeof or alignof expression given an expression
+/// Build a sizeof or alignof expression given an expression
/// operand.
ExprResult
Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
@@ -4072,7 +4141,7 @@ Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
return BuildUnaryOp(S, OpLoc, Opc, Input);
}
-/// \brief Diagnose if arithmetic on the given ObjC pointer is illegal.
+/// Diagnose if arithmetic on the given ObjC pointer is illegal.
///
/// \return true on error
static bool checkArithmeticOnObjCPointer(Sema &S,
@@ -4328,10 +4397,13 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
// Per C++ core issue 1213, the result is an xvalue if either operand is
// a non-lvalue array, and an lvalue otherwise.
- if (getLangOpts().CPlusPlus11 &&
- ((LHSExp->getType()->isArrayType() && !LHSExp->isLValue()) ||
- (RHSExp->getType()->isArrayType() && !RHSExp->isLValue())))
- VK = VK_XValue;
+ if (getLangOpts().CPlusPlus11) {
+ for (auto *Op : {LHSExp, RHSExp}) {
+ Op = Op->IgnoreImplicit();
+ if (Op->getType()->isArrayType() && !Op->isLValue())
+ VK = VK_XValue;
+ }
+ }
// Perform default conversions.
if (!LHSExp->getType()->getAs<VectorType>()) {
@@ -4392,12 +4464,24 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
} else if (const VectorType *VTy = LHSTy->getAs<VectorType>()) {
BaseExpr = LHSExp; // vectors: V[123]
IndexExpr = RHSExp;
+ // We apply C++ DR1213 to vector subscripting too.
+ if (getLangOpts().CPlusPlus11 && LHSExp->getValueKind() == VK_RValue) {
+ ExprResult Materialized = TemporaryMaterializationConversion(LHSExp);
+ if (Materialized.isInvalid())
+ return ExprError();
+ LHSExp = Materialized.get();
+ }
VK = LHSExp->getValueKind();
if (VK != VK_RValue)
OK = OK_VectorComponent;
- // FIXME: need to deal with const...
ResultType = VTy->getElementType();
+ QualType BaseType = BaseExpr->getType();
+ Qualifiers BaseQuals = BaseType.getQualifiers();
+ Qualifiers MemberQuals = ResultType.getQualifiers();
+ Qualifiers Combined = BaseQuals + MemberQuals;
+ if (Combined != MemberQuals)
+ ResultType = Context.getQualifiedType(ResultType, Combined);
} else if (LHSTy->isArrayType()) {
// If we see an array that wasn't promoted by
// DefaultFunctionArrayLvalueConversion, it must be an array that
@@ -4831,6 +4915,10 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl,
(!Param || !Param->hasAttr<CFConsumedAttr>()))
CFAudited = true;
+ if (Proto->getExtParameterInfo(i).isNoEscape())
+ if (auto *BE = dyn_cast<BlockExpr>(Arg->IgnoreParenNoopCasts(Context)))
+ BE->getBlockDecl()->setDoesNotEscape();
+
InitializedEntity Entity =
Param ? InitializedEntity::InitializeParameter(Context, Param,
ProtoArgType)
@@ -5496,7 +5584,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
// CUDA: Kernel calls must be to global functions
if (FDecl && !FDecl->hasAttr<CUDAGlobalAttr>())
return ExprError(Diag(LParenLoc,diag::err_kern_call_not_global_function)
- << FDecl->getName() << Fn->getSourceRange());
+ << FDecl << Fn->getSourceRange());
// CUDA: Kernel function must have 'void' return type
if (!FuncT->getReturnType()->isVoidType())
@@ -5506,7 +5594,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
// CUDA: Calls to global functions must be configured
if (FDecl && FDecl->hasAttr<CUDAGlobalAttr>())
return ExprError(Diag(LParenLoc, diag::err_global_call_not_config)
- << FDecl->getName() << Fn->getSourceRange());
+ << FDecl << Fn->getSourceRange());
}
}
@@ -5705,7 +5793,7 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList,
}
// Semantic analysis for initializers is done by ActOnDeclarator() and
- // CheckInitializer() - it requires knowledge of the object being intialized.
+ // CheckInitializer() - it requires knowledge of the object being initialized.
InitListExpr *E = new (Context) InitListExpr(Context, LBraceLoc, InitArgList,
RBraceLoc);
@@ -6239,7 +6327,7 @@ ExprResult Sema::ActOnParenListExpr(SourceLocation L,
return expr;
}
-/// \brief Emit a specialized diagnostic when one expression is a null pointer
+/// Emit a specialized diagnostic when one expression is a null pointer
/// constant and the other is not a pointer. Returns true if a diagnostic is
/// emitted.
bool Sema::DiagnoseConditionalForNull(Expr *LHSExpr, Expr *RHSExpr,
@@ -6280,7 +6368,7 @@ bool Sema::DiagnoseConditionalForNull(Expr *LHSExpr, Expr *RHSExpr,
return true;
}
-/// \brief Return false if the condition expression is valid, true otherwise.
+/// Return false if the condition expression is valid, true otherwise.
static bool checkCondition(Sema &S, Expr *Cond, SourceLocation QuestionLoc) {
QualType CondTy = Cond->getType();
@@ -6299,7 +6387,7 @@ static bool checkCondition(Sema &S, Expr *Cond, SourceLocation QuestionLoc) {
return true;
}
-/// \brief Handle when one or both operands are void type.
+/// Handle when one or both operands are void type.
static QualType checkConditionalVoidType(Sema &S, ExprResult &LHS,
ExprResult &RHS) {
Expr *LHSExpr = LHS.get();
@@ -6316,7 +6404,7 @@ static QualType checkConditionalVoidType(Sema &S, ExprResult &LHS,
return S.Context.VoidTy;
}
-/// \brief Return false if the NullExpr can be promoted to PointerTy,
+/// Return false if the NullExpr can be promoted to PointerTy,
/// true otherwise.
static bool checkConditionalNullPointer(Sema &S, ExprResult &NullExpr,
QualType PointerTy) {
@@ -6329,7 +6417,7 @@ static bool checkConditionalNullPointer(Sema &S, ExprResult &NullExpr,
return false;
}
-/// \brief Checks compatibility between two pointers and return the resulting
+/// Checks compatibility between two pointers and return the resulting
/// type.
static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS,
ExprResult &RHS,
@@ -6463,7 +6551,7 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS,
return ResultTy;
}
-/// \brief Return the resulting type when the operands are both block pointers.
+/// Return the resulting type when the operands are both block pointers.
static QualType checkConditionalBlockPointerCompatibility(Sema &S,
ExprResult &LHS,
ExprResult &RHS,
@@ -6488,7 +6576,7 @@ static QualType checkConditionalBlockPointerCompatibility(Sema &S,
return checkConditionalPointerCompatibility(S, LHS, RHS, Loc);
}
-/// \brief Return the resulting type when the operands are both pointers.
+/// Return the resulting type when the operands are both pointers.
static QualType
checkConditionalObjectPointersCompatibility(Sema &S, ExprResult &LHS,
ExprResult &RHS,
@@ -6527,7 +6615,7 @@ checkConditionalObjectPointersCompatibility(Sema &S, ExprResult &LHS,
return checkConditionalPointerCompatibility(S, LHS, RHS, Loc);
}
-/// \brief Return false if the first expression is not an integer and the second
+/// Return false if the first expression is not an integer and the second
/// expression is not a pointer, true otherwise.
static bool checkPointerIntegerMismatch(Sema &S, ExprResult &Int,
Expr* PointerExpr, SourceLocation Loc,
@@ -6547,7 +6635,7 @@ static bool checkPointerIntegerMismatch(Sema &S, ExprResult &Int,
return true;
}
-/// \brief Simple conversion between integer and floating point types.
+/// Simple conversion between integer and floating point types.
///
/// Used when handling the OpenCL conditional operator where the
/// condition is a vector while the other operands are scalar.
@@ -6602,7 +6690,7 @@ static QualType OpenCLArithmeticConversions(Sema &S, ExprResult &LHS,
(S, LHS, RHS, LHSType, RHSType, /*IsCompAssign = */ false);
}
-/// \brief Convert scalar operands to a vector that matches the
+/// Convert scalar operands to a vector that matches the
/// condition in length.
///
/// Used when handling the OpenCL conditional operator where the
@@ -6647,7 +6735,7 @@ OpenCLConvertScalarsToVectors(Sema &S, ExprResult &LHS, ExprResult &RHS,
return VectorTy;
}
-/// \brief Return false if this is a valid OpenCL condition vector
+/// Return false if this is a valid OpenCL condition vector
static bool checkOpenCLConditionVector(Sema &S, Expr *Cond,
SourceLocation QuestionLoc) {
// OpenCL v1.1 s6.11.6 says the elements of the vector must be of
@@ -6662,7 +6750,7 @@ static bool checkOpenCLConditionVector(Sema &S, Expr *Cond,
return true;
}
-/// \brief Return false if the vector condition type and the vector
+/// Return false if the vector condition type and the vector
/// result type are compatible.
///
/// OpenCL v1.1 s6.11.6 requires that both vector types have the same
@@ -6692,7 +6780,7 @@ static bool checkVectorResult(Sema &S, QualType CondTy, QualType VecResTy,
return false;
}
-/// \brief Return the resulting type for the conditional operator in
+/// Return the resulting type for the conditional operator in
/// OpenCL (aka "ternary selection operator", OpenCL v1.1
/// s6.3.i) when the condition is a vector type.
static QualType
@@ -6727,7 +6815,7 @@ OpenCLCheckVectorConditional(Sema &S, ExprResult &Cond,
return OpenCLConvertScalarsToVectors(S, LHS, RHS, CondTy, QuestionLoc);
}
-/// \brief Return true if the Expr is block type
+/// Return true if the Expr is block type
static bool checkBlockType(Sema &S, const Expr *E) {
if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
QualType Ty = CE->getCallee()->getType();
@@ -7050,6 +7138,10 @@ static bool IsArithmeticBinaryExpr(Expr *E, BinaryOperatorKind *Opcode,
E = E->IgnoreImpCasts();
E = E->IgnoreConversionOperator();
E = E->IgnoreImpCasts();
+ if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) {
+ E = MTE->GetTemporaryExpr();
+ E = E->IgnoreImpCasts();
+ }
// Built-in binary operator.
if (BinaryOperator *OP = dyn_cast<BinaryOperator>(E)) {
@@ -7097,6 +7189,8 @@ static bool ExprLooksBoolean(Expr *E) {
return OP->getOpcode() == UO_LNot;
if (E->getType()->isPointerType())
return true;
+ // FIXME: What about overloaded operator calls returning "unspecified boolean
+ // type"s (commonly pointer-to-members)?
return false;
}
@@ -7848,7 +7942,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
return Incompatible;
}
-/// \brief Constructs a transparent union from an expression that is
+/// Constructs a transparent union from an expression that is
/// used to initialize the transparent union.
static void ConstructTransparentUnion(Sema &S, ASTContext &C,
ExprResult &EResult, QualType UnionType,
@@ -8015,7 +8109,7 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS,
if (Diagnose && isa<ObjCProtocolExpr>(PRE)) {
ObjCProtocolDecl *PDecl = cast<ObjCProtocolExpr>(PRE)->getProtocol();
if (PDecl && !PDecl->hasDefinition()) {
- Diag(PRE->getExprLoc(), diag::warn_atprotocol_protocol) << PDecl->getName();
+ Diag(PRE->getExprLoc(), diag::warn_atprotocol_protocol) << PDecl;
Diag(PDecl->getLocation(), diag::note_entity_declared_at) << PDecl;
}
}
@@ -8054,18 +8148,57 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS,
RHS = E;
return Compatible;
}
-
+
if (ConvertRHS)
RHS = ImpCastExprToType(E, Ty, Kind);
}
return result;
}
+namespace {
+/// The original operand to an operator, prior to the application of the usual
+/// arithmetic conversions and converting the arguments of a builtin operator
+/// candidate.
+struct OriginalOperand {
+ explicit OriginalOperand(Expr *Op) : Orig(Op), Conversion(nullptr) {
+ if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Op))
+ Op = MTE->GetTemporaryExpr();
+ if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(Op))
+ Op = BTE->getSubExpr();
+ if (auto *ICE = dyn_cast<ImplicitCastExpr>(Op)) {
+ Orig = ICE->getSubExprAsWritten();
+ Conversion = ICE->getConversionFunction();
+ }
+ }
+
+ QualType getType() const { return Orig->getType(); }
+
+ Expr *Orig;
+ NamedDecl *Conversion;
+};
+}
+
QualType Sema::InvalidOperands(SourceLocation Loc, ExprResult &LHS,
ExprResult &RHS) {
+ OriginalOperand OrigLHS(LHS.get()), OrigRHS(RHS.get());
+
Diag(Loc, diag::err_typecheck_invalid_operands)
- << LHS.get()->getType() << RHS.get()->getType()
+ << OrigLHS.getType() << OrigRHS.getType()
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+
+ // If a user-defined conversion was applied to either of the operands prior
+ // to applying the built-in operator rules, tell the user about it.
+ if (OrigLHS.Conversion) {
+ Diag(OrigLHS.Conversion->getLocation(),
+ diag::note_typecheck_invalid_operands_converted)
+ << 0 << LHS.get()->getType();
+ }
+ if (OrigRHS.Conversion) {
+ Diag(OrigRHS.Conversion->getLocation(),
+ diag::note_typecheck_invalid_operands_converted)
+ << 1 << RHS.get()->getType();
+ }
+
return QualType();
}
@@ -8216,7 +8349,7 @@ static bool canConvertIntTyToFloatTy(Sema &S, ExprResult *Int,
QualType IntTy = Int->get()->getType().getUnqualifiedType();
// Determine if the integer constant can be expressed as a floating point
- // number of the appropiate type.
+ // number of the appropriate type.
llvm::APSInt Result;
bool CstInt = Int->get()->EvaluateAsInt(Result, S.Context);
uint64_t Bits = 0;
@@ -8594,7 +8727,7 @@ QualType Sema::CheckRemainderOperands(
return compType;
}
-/// \brief Diagnose invalid arithmetic on two void pointers.
+/// Diagnose invalid arithmetic on two void pointers.
static void diagnoseArithmeticOnTwoVoidPointers(Sema &S, SourceLocation Loc,
Expr *LHSExpr, Expr *RHSExpr) {
S.Diag(Loc, S.getLangOpts().CPlusPlus
@@ -8604,7 +8737,7 @@ static void diagnoseArithmeticOnTwoVoidPointers(Sema &S, SourceLocation Loc,
<< RHSExpr->getSourceRange();
}
-/// \brief Diagnose invalid arithmetic on a void pointer.
+/// Diagnose invalid arithmetic on a void pointer.
static void diagnoseArithmeticOnVoidPointer(Sema &S, SourceLocation Loc,
Expr *Pointer) {
S.Diag(Loc, S.getLangOpts().CPlusPlus
@@ -8613,7 +8746,7 @@ static void diagnoseArithmeticOnVoidPointer(Sema &S, SourceLocation Loc,
<< 0 /* one pointer */ << Pointer->getSourceRange();
}
-/// \brief Diagnose invalid arithmetic on a null pointer.
+/// Diagnose invalid arithmetic on a null pointer.
///
/// If \p IsGNUIdiom is true, the operation is using the 'p = (i8*)nullptr + n'
/// idiom, which we recognize as a GNU extension.
@@ -8628,7 +8761,7 @@ static void diagnoseArithmeticOnNullPointer(Sema &S, SourceLocation Loc,
<< S.getLangOpts().CPlusPlus << Pointer->getSourceRange();
}
-/// \brief Diagnose invalid arithmetic on two function pointers.
+/// Diagnose invalid arithmetic on two function pointers.
static void diagnoseArithmeticOnTwoFunctionPointers(Sema &S, SourceLocation Loc,
Expr *LHS, Expr *RHS) {
assert(LHS->getType()->isAnyPointerType());
@@ -8644,7 +8777,7 @@ static void diagnoseArithmeticOnTwoFunctionPointers(Sema &S, SourceLocation Loc,
<< LHS->getSourceRange() << RHS->getSourceRange();
}
-/// \brief Diagnose invalid arithmetic on a function pointer.
+/// Diagnose invalid arithmetic on a function pointer.
static void diagnoseArithmeticOnFunctionPointer(Sema &S, SourceLocation Loc,
Expr *Pointer) {
assert(Pointer->getType()->isAnyPointerType());
@@ -8656,7 +8789,7 @@ static void diagnoseArithmeticOnFunctionPointer(Sema &S, SourceLocation Loc,
<< Pointer->getSourceRange();
}
-/// \brief Emit error if Operand is incomplete pointer type
+/// Emit error if Operand is incomplete pointer type
///
/// \returns True if pointer has incomplete type
static bool checkArithmeticIncompletePointerType(Sema &S, SourceLocation Loc,
@@ -8672,7 +8805,7 @@ static bool checkArithmeticIncompletePointerType(Sema &S, SourceLocation Loc,
PointeeTy, Operand->getSourceRange());
}
-/// \brief Check the validity of an arithmetic pointer operand.
+/// Check the validity of an arithmetic pointer operand.
///
/// If the operand has pointer type, this code will check for pointer types
/// which are invalid in arithmetic operations. These will be diagnosed
@@ -8703,7 +8836,7 @@ static bool checkArithmeticOpPointerOperand(Sema &S, SourceLocation Loc,
return true;
}
-/// \brief Check the validity of a binary arithmetic operation w.r.t. pointer
+/// Check the validity of a binary arithmetic operation w.r.t. pointer
/// operands.
///
/// This routine will diagnose any invalid arithmetic on pointer operands much
@@ -8805,7 +8938,7 @@ static void diagnoseStringPlusInt(Sema &Self, SourceLocation OpLoc,
Self.Diag(OpLoc, diag::note_string_plus_scalar_silence);
}
-/// \brief Emit a warning when adding a char literal to a string.
+/// Emit a warning when adding a char literal to a string.
static void diagnoseStringPlusChar(Sema &Self, SourceLocation OpLoc,
Expr *LHSExpr, Expr *RHSExpr) {
const Expr *StringRefExpr = LHSExpr;
@@ -8856,7 +8989,7 @@ static void diagnoseStringPlusChar(Sema &Self, SourceLocation OpLoc,
}
}
-/// \brief Emit error when two pointers are incompatible.
+/// Emit error when two pointers are incompatible.
static void diagnosePointerIncompatibility(Sema &S, SourceLocation Loc,
Expr *LHSExpr, Expr *RHSExpr) {
assert(LHSExpr->getType()->isAnyPointerType());
@@ -9154,7 +9287,7 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
<< RHS.get()->getSourceRange();
}
-/// \brief Return the resulting type when a vector is shifted
+/// Return the resulting type when a vector is shifted
/// by a scalar or vector shift amount.
static QualType checkVectorShift(Sema &S, ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc, bool IsCompAssign) {
@@ -9300,16 +9433,6 @@ QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS,
return LHSType;
}
-static bool IsWithinTemplateSpecialization(Decl *D) {
- if (DeclContext *DC = D->getDeclContext()) {
- if (isa<ClassTemplateSpecializationDecl>(DC))
- return true;
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
- return FD->isFunctionTemplateSpecialization();
- }
- return false;
-}
-
/// If two different enums are compared, raise a warning.
static void checkEnumComparison(Sema &S, SourceLocation Loc, Expr *LHS,
Expr *RHS) {
@@ -9339,7 +9462,7 @@ static void checkEnumComparison(Sema &S, SourceLocation Loc, Expr *LHS,
<< LHS->getSourceRange() << RHS->getSourceRange();
}
-/// \brief Diagnose bad pointer comparisons.
+/// Diagnose bad pointer comparisons.
static void diagnoseDistinctPointerComparison(Sema &S, SourceLocation Loc,
ExprResult &LHS, ExprResult &RHS,
bool IsError) {
@@ -9349,7 +9472,7 @@ static void diagnoseDistinctPointerComparison(Sema &S, SourceLocation Loc,
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
}
-/// \brief Returns false if the pointers are converted to a composite type,
+/// Returns false if the pointers are converted to a composite type,
/// true otherwise.
static bool convertPointersToCompositeType(Sema &S, SourceLocation Loc,
ExprResult &LHS, ExprResult &RHS) {
@@ -9587,137 +9710,368 @@ static void diagnoseLogicalNotOnLHSofCheck(Sema &S, ExprResult &LHS,
// Get the decl for a simple expression: a reference to a variable,
// an implicit C++ field reference, or an implicit ObjC ivar reference.
static ValueDecl *getCompareDecl(Expr *E) {
- if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E))
+ if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E))
return DR->getDecl();
- if (ObjCIvarRefExpr* Ivar = dyn_cast<ObjCIvarRefExpr>(E)) {
+ if (ObjCIvarRefExpr *Ivar = dyn_cast<ObjCIvarRefExpr>(E)) {
if (Ivar->isFreeIvar())
return Ivar->getDecl();
}
- if (MemberExpr* Mem = dyn_cast<MemberExpr>(E)) {
+ if (MemberExpr *Mem = dyn_cast<MemberExpr>(E)) {
if (Mem->isImplicitAccess())
return Mem->getMemberDecl();
}
return nullptr;
}
-// C99 6.5.8, C++ [expr.rel]
-QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
- SourceLocation Loc, BinaryOperatorKind Opc,
- bool IsRelational) {
- checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/true);
+/// Diagnose some forms of syntactically-obvious tautological comparison.
+static void diagnoseTautologicalComparison(Sema &S, SourceLocation Loc,
+ Expr *LHS, Expr *RHS,
+ BinaryOperatorKind Opc) {
+ Expr *LHSStripped = LHS->IgnoreParenImpCasts();
+ Expr *RHSStripped = RHS->IgnoreParenImpCasts();
+
+ QualType LHSType = LHS->getType();
+ QualType RHSType = RHS->getType();
+ if (LHSType->hasFloatingRepresentation() ||
+ (LHSType->isBlockPointerType() && !BinaryOperator::isEqualityOp(Opc)) ||
+ LHS->getLocStart().isMacroID() || RHS->getLocStart().isMacroID() ||
+ S.inTemplateInstantiation())
+ return;
- // Handle vector comparisons separately.
- if (LHS.get()->getType()->isVectorType() ||
- RHS.get()->getType()->isVectorType())
- return CheckVectorCompareOperands(LHS, RHS, Loc, IsRelational);
+ // Comparisons between two array types are ill-formed for operator<=>, so
+ // we shouldn't emit any additional warnings about it.
+ if (Opc == BO_Cmp && LHSType->isArrayType() && RHSType->isArrayType())
+ return;
+
+ // For non-floating point types, check for self-comparisons of the form
+ // x == x, x != x, x < x, etc. These always evaluate to a constant, and
+ // often indicate logic errors in the program.
+ //
+ // NOTE: Don't warn about comparison expressions resulting from macro
+ // expansion. Also don't warn about comparisons which are only self
+ // comparisons within a template instantiation. The warnings should catch
+ // obvious cases in the definition of the template anyways. The idea is to
+ // warn when the typed comparison operator will always evaluate to the same
+ // result.
+ ValueDecl *DL = getCompareDecl(LHSStripped);
+ ValueDecl *DR = getCompareDecl(RHSStripped);
+ if (DL && DR && declaresSameEntity(DL, DR)) {
+ StringRef Result;
+ switch (Opc) {
+ case BO_EQ: case BO_LE: case BO_GE:
+ Result = "true";
+ break;
+ case BO_NE: case BO_LT: case BO_GT:
+ Result = "false";
+ break;
+ case BO_Cmp:
+ Result = "'std::strong_ordering::equal'";
+ break;
+ default:
+ break;
+ }
+ S.DiagRuntimeBehavior(Loc, nullptr,
+ S.PDiag(diag::warn_comparison_always)
+ << 0 /*self-comparison*/ << !Result.empty()
+ << Result);
+ } else if (DL && DR &&
+ DL->getType()->isArrayType() && DR->getType()->isArrayType() &&
+ !DL->isWeak() && !DR->isWeak()) {
+ // What is it always going to evaluate to?
+ StringRef Result;
+ switch(Opc) {
+ case BO_EQ: // e.g. array1 == array2
+ Result = "false";
+ break;
+ case BO_NE: // e.g. array1 != array2
+ Result = "true";
+ break;
+ default: // e.g. array1 <= array2
+ // The best we can say is 'a constant'
+ break;
+ }
+ S.DiagRuntimeBehavior(Loc, nullptr,
+ S.PDiag(diag::warn_comparison_always)
+ << 1 /*array comparison*/
+ << !Result.empty() << Result);
+ }
+
+ if (isa<CastExpr>(LHSStripped))
+ LHSStripped = LHSStripped->IgnoreParenCasts();
+ if (isa<CastExpr>(RHSStripped))
+ RHSStripped = RHSStripped->IgnoreParenCasts();
+
+ // Warn about comparisons against a string constant (unless the other
+ // operand is null); the user probably wants strcmp.
+ Expr *LiteralString = nullptr;
+ Expr *LiteralStringStripped = nullptr;
+ if ((isa<StringLiteral>(LHSStripped) || isa<ObjCEncodeExpr>(LHSStripped)) &&
+ !RHSStripped->isNullPointerConstant(S.Context,
+ Expr::NPC_ValueDependentIsNull)) {
+ LiteralString = LHS;
+ LiteralStringStripped = LHSStripped;
+ } else if ((isa<StringLiteral>(RHSStripped) ||
+ isa<ObjCEncodeExpr>(RHSStripped)) &&
+ !LHSStripped->isNullPointerConstant(S.Context,
+ Expr::NPC_ValueDependentIsNull)) {
+ LiteralString = RHS;
+ LiteralStringStripped = RHSStripped;
+ }
+
+ if (LiteralString) {
+ S.DiagRuntimeBehavior(Loc, nullptr,
+ S.PDiag(diag::warn_stringcompare)
+ << isa<ObjCEncodeExpr>(LiteralStringStripped)
+ << LiteralString->getSourceRange());
+ }
+}
+
+static ImplicitConversionKind castKindToImplicitConversionKind(CastKind CK) {
+ switch (CK) {
+ default: {
+#ifndef NDEBUG
+ llvm::errs() << "unhandled cast kind: " << CastExpr::getCastKindName(CK)
+ << "\n";
+#endif
+ llvm_unreachable("unhandled cast kind");
+ }
+ case CK_UserDefinedConversion:
+ return ICK_Identity;
+ case CK_LValueToRValue:
+ return ICK_Lvalue_To_Rvalue;
+ case CK_ArrayToPointerDecay:
+ return ICK_Array_To_Pointer;
+ case CK_FunctionToPointerDecay:
+ return ICK_Function_To_Pointer;
+ case CK_IntegralCast:
+ return ICK_Integral_Conversion;
+ case CK_FloatingCast:
+ return ICK_Floating_Conversion;
+ case CK_IntegralToFloating:
+ case CK_FloatingToIntegral:
+ return ICK_Floating_Integral;
+ case CK_IntegralComplexCast:
+ case CK_FloatingComplexCast:
+ case CK_FloatingComplexToIntegralComplex:
+ case CK_IntegralComplexToFloatingComplex:
+ return ICK_Complex_Conversion;
+ case CK_FloatingComplexToReal:
+ case CK_FloatingRealToComplex:
+ case CK_IntegralComplexToReal:
+ case CK_IntegralRealToComplex:
+ return ICK_Complex_Real;
+ }
+}
+
+static bool checkThreeWayNarrowingConversion(Sema &S, QualType ToType, Expr *E,
+ QualType FromType,
+ SourceLocation Loc) {
+ // Check for a narrowing implicit conversion.
+ StandardConversionSequence SCS;
+ SCS.setAsIdentityConversion();
+ SCS.setToType(0, FromType);
+ SCS.setToType(1, ToType);
+ if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
+ SCS.Second = castKindToImplicitConversionKind(ICE->getCastKind());
+
+ APValue PreNarrowingValue;
+ QualType PreNarrowingType;
+ switch (SCS.getNarrowingKind(S.Context, E, PreNarrowingValue,
+ PreNarrowingType,
+ /*IgnoreFloatToIntegralConversion*/ true)) {
+ case NK_Dependent_Narrowing:
+ // Implicit conversion to a narrower type, but the expression is
+ // value-dependent so we can't tell whether it's actually narrowing.
+ case NK_Not_Narrowing:
+ return false;
+
+ 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)
+ << /*Constant*/ 1
+ << PreNarrowingValue.getAsString(S.Context, PreNarrowingType) << ToType;
+ return true;
+
+ case NK_Variable_Narrowing:
+ // 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)
+ << /*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?
+ return true;
+ }
+ llvm_unreachable("unhandled case in switch");
+}
+
+static QualType checkArithmeticOrEnumeralThreeWayCompare(Sema &S,
+ ExprResult &LHS,
+ ExprResult &RHS,
+ SourceLocation Loc) {
+ using CCT = ComparisonCategoryType;
QualType LHSType = LHS.get()->getType();
QualType RHSType = RHS.get()->getType();
+ // Dig out the original argument type and expression before implicit casts
+ // were applied. These are the types/expressions we need to check the
+ // [expr.spaceship] requirements against.
+ ExprResult LHSStripped = LHS.get()->IgnoreParenImpCasts();
+ ExprResult RHSStripped = RHS.get()->IgnoreParenImpCasts();
+ QualType LHSStrippedType = LHSStripped.get()->getType();
+ QualType RHSStrippedType = RHSStripped.get()->getType();
+
+ // C++2a [expr.spaceship]p3: If one of the operands is of type bool and the
+ // other is not, the program is ill-formed.
+ if (LHSStrippedType->isBooleanType() != RHSStrippedType->isBooleanType()) {
+ S.InvalidOperands(Loc, LHSStripped, RHSStripped);
+ return QualType();
+ }
- Expr *LHSStripped = LHS.get()->IgnoreParenImpCasts();
- Expr *RHSStripped = RHS.get()->IgnoreParenImpCasts();
+ int NumEnumArgs = (int)LHSStrippedType->isEnumeralType() +
+ RHSStrippedType->isEnumeralType();
+ if (NumEnumArgs == 1) {
+ bool LHSIsEnum = LHSStrippedType->isEnumeralType();
+ QualType OtherTy = LHSIsEnum ? RHSStrippedType : LHSStrippedType;
+ if (OtherTy->hasFloatingRepresentation()) {
+ S.InvalidOperands(Loc, LHSStripped, RHSStripped);
+ return QualType();
+ }
+ }
+ if (NumEnumArgs == 2) {
+ // C++2a [expr.spaceship]p5: If both operands have the same enumeration
+ // type E, the operator yields the result of converting the operands
+ // to the underlying type of E and applying <=> to the converted operands.
+ if (!S.Context.hasSameUnqualifiedType(LHSStrippedType, RHSStrippedType)) {
+ S.InvalidOperands(Loc, LHS, RHS);
+ return QualType();
+ }
+ QualType IntType =
+ LHSStrippedType->getAs<EnumType>()->getDecl()->getIntegerType();
+ assert(IntType->isArithmeticType());
- checkEnumComparison(*this, Loc, LHS.get(), RHS.get());
- diagnoseLogicalNotOnLHSofCheck(*this, LHS, RHS, Loc, Opc);
+ // We can't use `CK_IntegralCast` when the underlying type is 'bool', so we
+ // promote the boolean type, and all other promotable integer types, to
+ // avoid this.
+ if (IntType->isPromotableIntegerType())
+ IntType = S.Context.getPromotedIntegerType(IntType);
- if (!LHSType->hasFloatingRepresentation() &&
- !(LHSType->isBlockPointerType() && IsRelational) &&
- !LHS.get()->getLocStart().isMacroID() &&
- !RHS.get()->getLocStart().isMacroID() &&
- !inTemplateInstantiation()) {
- // For non-floating point types, check for self-comparisons of the form
- // x == x, x != x, x < x, etc. These always evaluate to a constant, and
- // often indicate logic errors in the program.
- //
- // NOTE: Don't warn about comparison expressions resulting from macro
- // expansion. Also don't warn about comparisons which are only self
- // comparisons within a template specialization. The warnings should catch
- // obvious cases in the definition of the template anyways. The idea is to
- // warn when the typed comparison operator will always evaluate to the same
- // result.
- ValueDecl *DL = getCompareDecl(LHSStripped);
- ValueDecl *DR = getCompareDecl(RHSStripped);
- if (DL && DR && DL == DR && !IsWithinTemplateSpecialization(DL)) {
- DiagRuntimeBehavior(Loc, nullptr, PDiag(diag::warn_comparison_always)
- << 0 // self-
- << (Opc == BO_EQ
- || Opc == BO_LE
- || Opc == BO_GE));
- } else if (DL && DR && LHSType->isArrayType() && RHSType->isArrayType() &&
- !DL->getType()->isReferenceType() &&
- !DR->getType()->isReferenceType()) {
- // what is it always going to eval to?
- char always_evals_to;
- switch(Opc) {
- case BO_EQ: // e.g. array1 == array2
- always_evals_to = 0; // false
- break;
- case BO_NE: // e.g. array1 != array2
- always_evals_to = 1; // true
- break;
- default:
- // best we can say is 'a constant'
- always_evals_to = 2; // e.g. array1 <= array2
- break;
- }
- DiagRuntimeBehavior(Loc, nullptr, PDiag(diag::warn_comparison_always)
- << 1 // array
- << always_evals_to);
- }
+ LHS = S.ImpCastExprToType(LHS.get(), IntType, CK_IntegralCast);
+ RHS = S.ImpCastExprToType(RHS.get(), IntType, CK_IntegralCast);
+ LHSType = RHSType = IntType;
+ }
+
+ // C++2a [expr.spaceship]p4: If both operands have arithmetic types, the
+ // usual arithmetic conversions are applied to the operands.
+ QualType Type = S.UsualArithmeticConversions(LHS, RHS);
+ if (LHS.isInvalid() || RHS.isInvalid())
+ return QualType();
+ if (Type.isNull())
+ return S.InvalidOperands(Loc, LHS, RHS);
+ 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());
+ if (HasNarrowing)
+ return QualType();
- if (isa<CastExpr>(LHSStripped))
- LHSStripped = LHSStripped->IgnoreParenCasts();
- if (isa<CastExpr>(RHSStripped))
- RHSStripped = RHSStripped->IgnoreParenCasts();
+ assert(!Type.isNull() && "composite type for <=> has not been set");
- // Warn about comparisons against a string constant (unless the other
- // operand is null), the user probably wants strcmp.
- Expr *literalString = nullptr;
- Expr *literalStringStripped = nullptr;
- if ((isa<StringLiteral>(LHSStripped) || isa<ObjCEncodeExpr>(LHSStripped)) &&
- !RHSStripped->isNullPointerConstant(Context,
- Expr::NPC_ValueDependentIsNull)) {
- literalString = LHS.get();
- literalStringStripped = LHSStripped;
- } else if ((isa<StringLiteral>(RHSStripped) ||
- isa<ObjCEncodeExpr>(RHSStripped)) &&
- !LHSStripped->isNullPointerConstant(Context,
- Expr::NPC_ValueDependentIsNull)) {
- literalString = RHS.get();
- literalStringStripped = RHSStripped;
+ auto TypeKind = [&]() {
+ if (const ComplexType *CT = Type->getAs<ComplexType>()) {
+ if (CT->getElementType()->hasFloatingRepresentation())
+ return CCT::WeakEquality;
+ return CCT::StrongEquality;
}
+ if (Type->isIntegralOrEnumerationType())
+ return CCT::StrongOrdering;
+ if (Type->hasFloatingRepresentation())
+ return CCT::PartialOrdering;
+ llvm_unreachable("other types are unimplemented");
+ }();
- if (literalString) {
- DiagRuntimeBehavior(Loc, nullptr,
- PDiag(diag::warn_stringcompare)
- << isa<ObjCEncodeExpr>(literalStringStripped)
- << literalString->getSourceRange());
- }
- }
+ return S.CheckComparisonCategoryType(TypeKind, Loc);
+}
+
+static QualType checkArithmeticOrEnumeralCompare(Sema &S, ExprResult &LHS,
+ ExprResult &RHS,
+ SourceLocation Loc,
+ BinaryOperatorKind Opc) {
+ if (Opc == BO_Cmp)
+ return checkArithmeticOrEnumeralThreeWayCompare(S, LHS, RHS, Loc);
// C99 6.5.8p3 / C99 6.5.9p4
- UsualArithmeticConversions(LHS, RHS);
+ QualType Type = S.UsualArithmeticConversions(LHS, RHS);
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
+ if (Type.isNull())
+ return S.InvalidOperands(Loc, LHS, RHS);
+ assert(Type->isArithmeticType() || Type->isEnumeralType());
- LHSType = LHS.get()->getType();
- RHSType = RHS.get()->getType();
+ checkEnumComparison(S, Loc, LHS.get(), RHS.get());
+
+ if (Type->isAnyComplexType() && BinaryOperator::isRelationalOp(Opc))
+ return S.InvalidOperands(Loc, LHS, RHS);
+
+ // Check for comparisons of floating point operands using != and ==.
+ if (Type->hasFloatingRepresentation() && BinaryOperator::isEqualityOp(Opc))
+ S.CheckFloatComparison(Loc, LHS.get(), RHS.get());
// The result of comparisons is 'bool' in C++, 'int' in C.
- QualType ResultTy = Context.getLogicalOperationType();
+ return S.Context.getLogicalOperationType();
+}
- if (IsRelational) {
- if (LHSType->isRealType() && RHSType->isRealType())
- return ResultTy;
- } else {
- // Check for comparisons of floating point operands using != and ==.
- if (LHSType->hasFloatingRepresentation())
- CheckFloatComparison(Loc, LHS.get(), RHS.get());
+// C99 6.5.8, C++ [expr.rel]
+QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
+ SourceLocation Loc,
+ BinaryOperatorKind Opc) {
+ bool IsRelational = BinaryOperator::isRelationalOp(Opc);
+ bool IsThreeWay = Opc == BO_Cmp;
+ auto IsAnyPointerType = [](ExprResult E) {
+ QualType Ty = E.get()->getType();
+ return Ty->isPointerType() || Ty->isMemberPointerType();
+ };
- if (LHSType->isArithmeticType() && RHSType->isArithmeticType())
- return ResultTy;
+ // C++2a [expr.spaceship]p6: If at least one of the operands is of pointer
+ // type, array-to-pointer, ..., conversions are performed on both operands to
+ // bring them to their composite type.
+ // Otherwise, all comparisons expect an rvalue, so convert to rvalue before
+ // any type-related checks.
+ if (!IsThreeWay || IsAnyPointerType(LHS) || IsAnyPointerType(RHS)) {
+ LHS = DefaultFunctionArrayLvalueConversion(LHS.get());
+ if (LHS.isInvalid())
+ return QualType();
+ RHS = DefaultFunctionArrayLvalueConversion(RHS.get());
+ if (RHS.isInvalid())
+ return QualType();
+ } else {
+ LHS = DefaultLvalueConversion(LHS.get());
+ if (LHS.isInvalid())
+ return QualType();
+ RHS = DefaultLvalueConversion(RHS.get());
+ if (RHS.isInvalid())
+ return QualType();
}
+ checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/true);
+
+ // Handle vector comparisons separately.
+ if (LHS.get()->getType()->isVectorType() ||
+ RHS.get()->getType()->isVectorType())
+ return CheckVectorCompareOperands(LHS, RHS, Loc, Opc);
+
+ diagnoseLogicalNotOnLHSofCheck(*this, LHS, RHS, Loc, Opc);
+ diagnoseTautologicalComparison(*this, Loc, LHS.get(), RHS.get(), Opc);
+
+ QualType LHSType = LHS.get()->getType();
+ QualType RHSType = RHS.get()->getType();
+ if ((LHSType->isArithmeticType() || LHSType->isEnumeralType()) &&
+ (RHSType->isArithmeticType() || RHSType->isEnumeralType()))
+ return checkArithmeticOrEnumeralCompare(*this, LHS, RHS, Loc, Opc);
+
const Expr::NullPointerConstantKind LHSNullKind =
LHS.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull);
const Expr::NullPointerConstantKind RHSNullKind =
@@ -9725,6 +10079,44 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
bool LHSIsNull = LHSNullKind != Expr::NPCK_NotNull;
bool RHSIsNull = RHSNullKind != Expr::NPCK_NotNull;
+ auto computeResultTy = [&]() {
+ if (Opc != BO_Cmp)
+ return Context.getLogicalOperationType();
+ assert(getLangOpts().CPlusPlus);
+ assert(Context.hasSameType(LHS.get()->getType(), RHS.get()->getType()));
+
+ QualType CompositeTy = LHS.get()->getType();
+ assert(!CompositeTy->isReferenceType());
+
+ auto buildResultTy = [&](ComparisonCategoryType Kind) {
+ return CheckComparisonCategoryType(Kind, Loc);
+ };
+
+ // C++2a [expr.spaceship]p7: If the composite pointer type is a function
+ // pointer type, a pointer-to-member type, or std::nullptr_t, the
+ // result is of type std::strong_equality
+ if (CompositeTy->isFunctionPointerType() ||
+ CompositeTy->isMemberPointerType() || CompositeTy->isNullPtrType())
+ // FIXME: consider making the function pointer case produce
+ // strong_ordering not strong_equality, per P0946R0-Jax18 discussion
+ // and direction polls
+ return buildResultTy(ComparisonCategoryType::StrongEquality);
+
+ // C++2a [expr.spaceship]p8: If the composite pointer type is an object
+ // pointer type, p <=> q is of type std::strong_ordering.
+ if (CompositeTy->isPointerType()) {
+ // P0946R0: Comparisons between a null pointer constant and an object
+ // pointer result in std::strong_equality
+ if (LHSIsNull != RHSIsNull)
+ return buildResultTy(ComparisonCategoryType::StrongEquality);
+ return buildResultTy(ComparisonCategoryType::StrongOrdering);
+ }
+ // C++2a [expr.spaceship]p9: Otherwise, the program is ill-formed.
+ // TODO: Extend support for operator<=> to ObjC types.
+ return InvalidOperands(Loc, LHS, RHS);
+ };
+
+
if (!IsRelational && LHSIsNull != RHSIsNull) {
bool IsEquality = Opc == BO_EQ;
if (RHSIsNull)
@@ -9752,29 +10144,30 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
// conformance with the C++ standard.
diagnoseFunctionPointerToVoidComparison(
*this, Loc, LHS, RHS, /*isError*/ (bool)isSFINAEContext());
-
+
if (isSFINAEContext())
return QualType();
-
+
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BitCast);
- return ResultTy;
+ return computeResultTy();
}
// C++ [expr.eq]p2:
// If at least one operand is a pointer [...] bring them to their
// composite pointer type.
+ // C++ [expr.spaceship]p6
+ // If at least one of the operands is of pointer type, [...] bring them
+ // to their composite pointer type.
// C++ [expr.rel]p2:
// If both operands are pointers, [...] bring them to their composite
// pointer type.
if ((int)LHSType->isPointerType() + (int)RHSType->isPointerType() >=
(IsRelational ? 2 : 1) &&
- (!LangOpts.ObjCAutoRefCount ||
- !(LHSType->isObjCObjectPointerType() ||
- RHSType->isObjCObjectPointerType()))) {
+ (!LangOpts.ObjCAutoRefCount || !(LHSType->isObjCObjectPointerType() ||
+ RHSType->isObjCObjectPointerType()))) {
if (convertPointersToCompositeType(*this, Loc, LHS, RHS))
return QualType();
- else
- return ResultTy;
+ return computeResultTy();
}
} else if (LHSType->isPointerType() &&
RHSType->isPointerType()) { // C99 6.5.8p2
@@ -9825,7 +10218,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
else
RHS = ImpCastExprToType(RHS.get(), LHSType, Kind);
}
- return ResultTy;
+ return computeResultTy();
}
if (getLangOpts().CPlusPlus) {
@@ -9835,11 +10228,11 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
if (!IsRelational && LHSIsNull && RHSIsNull) {
if (LHSType->isNullPtrType()) {
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
- return ResultTy;
+ return computeResultTy();
}
if (RHSType->isNullPtrType()) {
LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer);
- return ResultTy;
+ return computeResultTy();
}
}
@@ -9848,12 +10241,12 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
if (!IsRelational && RHSType->isNullPtrType() &&
(LHSType->isObjCObjectPointerType() || LHSType->isBlockPointerType())) {
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
- return ResultTy;
+ return computeResultTy();
}
if (!IsRelational && LHSType->isNullPtrType() &&
(RHSType->isObjCObjectPointerType() || RHSType->isBlockPointerType())) {
LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer);
- return ResultTy;
+ return computeResultTy();
}
if (IsRelational &&
@@ -9876,7 +10269,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
else
LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer);
- return ResultTy;
+ return computeResultTy();
}
}
}
@@ -9889,15 +10282,8 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
if (convertPointersToCompositeType(*this, Loc, LHS, RHS))
return QualType();
else
- return ResultTy;
+ return computeResultTy();
}
-
- // Handle scoped enumeration types specifically, since they don't promote
- // to integers.
- if (LHS.get()->getType()->isEnumeralType() &&
- Context.hasSameUnqualifiedType(LHS.get()->getType(),
- RHS.get()->getType()))
- return ResultTy;
}
// Handle block pointer types.
@@ -9913,7 +10299,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
<< RHS.get()->getSourceRange();
}
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BitCast);
- return ResultTy;
+ return computeResultTy();
}
// Allow block pointers to be compared with null pointer constants.
@@ -9937,7 +10323,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
RHS = ImpCastExprToType(RHS.get(), LHSType,
LHSType->isPointerType() ? CK_BitCast
: CK_AnyPointerToBlockPointerCast);
- return ResultTy;
+ return computeResultTy();
}
if (LHSType->isObjCObjectPointerType() ||
@@ -9970,7 +10356,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
RHS = ImpCastExprToType(E, LHSType,
LPT ? CK_BitCast :CK_CPointerToObjCPointerCast);
}
- return ResultTy;
+ return computeResultTy();
}
if (LHSType->isObjCObjectPointerType() &&
RHSType->isObjCObjectPointerType()) {
@@ -9984,7 +10370,20 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
LHS = ImpCastExprToType(LHS.get(), RHSType, CK_BitCast);
else
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BitCast);
- return ResultTy;
+ return computeResultTy();
+ }
+
+ if (!IsRelational && LHSType->isBlockPointerType() &&
+ RHSType->isBlockCompatibleObjCPointerType(Context)) {
+ LHS = ImpCastExprToType(LHS.get(), RHSType,
+ CK_BlockPointerToObjCPointerCast);
+ return computeResultTy();
+ } else if (!IsRelational &&
+ LHSType->isBlockCompatibleObjCPointerType(Context) &&
+ RHSType->isBlockPointerType()) {
+ RHS = ImpCastExprToType(RHS.get(), LHSType,
+ CK_BlockPointerToObjCPointerCast);
+ return computeResultTy();
}
}
if ((LHSType->isAnyPointerType() && RHSType->isIntegerType()) ||
@@ -10024,30 +10423,30 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
else
RHS = ImpCastExprToType(RHS.get(), LHSType,
RHSIsNull ? CK_NullToPointer : CK_IntegralToPointer);
- return ResultTy;
+ return computeResultTy();
}
// Handle block pointers.
if (!IsRelational && RHSIsNull
&& LHSType->isBlockPointerType() && RHSType->isIntegerType()) {
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
- return ResultTy;
+ return computeResultTy();
}
if (!IsRelational && LHSIsNull
&& LHSType->isIntegerType() && RHSType->isBlockPointerType()) {
LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer);
- return ResultTy;
+ return computeResultTy();
}
if (getLangOpts().OpenCLVersion >= 200) {
if (LHSIsNull && RHSType->isQueueT()) {
LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer);
- return ResultTy;
+ return computeResultTy();
}
if (LHSType->isQueueT() && RHSIsNull) {
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
- return ResultTy;
+ return computeResultTy();
}
}
@@ -10101,7 +10500,7 @@ QualType Sema::GetSignedVectorType(QualType V) {
/// types.
QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc,
- bool IsRelational) {
+ BinaryOperatorKind Opc) {
// Check to make sure we're operating on vectors of the same type and width,
// Allowing one side to be a scalar of element type.
QualType vType = CheckVectorOperands(LHS, RHS, Loc, /*isCompAssign*/false,
@@ -10121,22 +10520,12 @@ QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
// For non-floating point types, check for self-comparisons of the form
// x == x, x != x, x < x, etc. These always evaluate to a constant, and
// often indicate logic errors in the program.
- if (!LHSType->hasFloatingRepresentation() && !inTemplateInstantiation()) {
- if (DeclRefExpr* DRL
- = dyn_cast<DeclRefExpr>(LHS.get()->IgnoreParenImpCasts()))
- if (DeclRefExpr* DRR
- = dyn_cast<DeclRefExpr>(RHS.get()->IgnoreParenImpCasts()))
- if (DRL->getDecl() == DRR->getDecl())
- DiagRuntimeBehavior(Loc, nullptr,
- PDiag(diag::warn_comparison_always)
- << 0 // self-
- << 2 // "a constant"
- );
- }
+ diagnoseTautologicalComparison(*this, Loc, LHS.get(), RHS.get(), Opc);
// Check for comparisons of floating point operands using != and ==.
- if (!IsRelational && LHSType->hasFloatingRepresentation()) {
- assert (RHS.get()->getType()->hasFloatingRepresentation());
+ if (BinaryOperator::isEqualityOp(Opc) &&
+ LHSType->hasFloatingRepresentation()) {
+ assert(RHS.get()->getType()->hasFloatingRepresentation());
CheckFloatComparison(Loc, LHS.get(), RHS.get());
}
@@ -10418,8 +10807,16 @@ static void DiagnoseConstAssignment(Sema &S, const Expr *E,
// Static fields do not inherit constness from parents.
break;
}
- break;
- } // End MemberExpr
+ break; // End MemberExpr
+ } else if (const ArraySubscriptExpr *ASE =
+ dyn_cast<ArraySubscriptExpr>(E)) {
+ E = ASE->getBase()->IgnoreParenImpCasts();
+ continue;
+ } else if (const ExtVectorElementExpr *EVE =
+ dyn_cast<ExtVectorElementExpr>(E)) {
+ E = EVE->getBase()->IgnoreParenImpCasts();
+ continue;
+ }
break;
}
@@ -10660,12 +11057,34 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
static void CheckIdentityFieldAssignment(Expr *LHSExpr, Expr *RHSExpr,
SourceLocation Loc,
Sema &Sema) {
+ if (Sema.inTemplateInstantiation())
+ return;
+ if (Sema.isUnevaluatedContext())
+ return;
+ if (Loc.isInvalid() || Loc.isMacroID())
+ return;
+ if (LHSExpr->getExprLoc().isMacroID() || RHSExpr->getExprLoc().isMacroID())
+ return;
+
// C / C++ fields
MemberExpr *ML = dyn_cast<MemberExpr>(LHSExpr);
MemberExpr *MR = dyn_cast<MemberExpr>(RHSExpr);
- if (ML && MR && ML->getMemberDecl() == MR->getMemberDecl()) {
- if (isa<CXXThisExpr>(ML->getBase()) && isa<CXXThisExpr>(MR->getBase()))
- Sema.Diag(Loc, diag::warn_identity_field_assign) << 0;
+ if (ML && MR) {
+ if (!(isa<CXXThisExpr>(ML->getBase()) && isa<CXXThisExpr>(MR->getBase())))
+ return;
+ const ValueDecl *LHSDecl =
+ cast<ValueDecl>(ML->getMemberDecl()->getCanonicalDecl());
+ const ValueDecl *RHSDecl =
+ cast<ValueDecl>(MR->getMemberDecl()->getCanonicalDecl());
+ if (LHSDecl != RHSDecl)
+ return;
+ if (LHSDecl->getType().isVolatileQualified())
+ return;
+ if (const ReferenceType *RefTy = LHSDecl->getType()->getAs<ReferenceType>())
+ if (RefTy->getPointeeType().isVolatileQualified())
+ return;
+
+ Sema.Diag(Loc, diag::warn_identity_field_assign) << 0;
}
// Objective-C instance variables
@@ -11046,7 +11465,7 @@ namespace {
AO_No_Error = 4
};
}
-/// \brief Diagnose invalid operand for address of operations.
+/// Diagnose invalid operand for address of operations.
///
/// \param Type The type of operand which cannot have its address taken.
static void diagnoseAddressOfInvalidType(Sema &S, SourceLocation Loc,
@@ -11419,12 +11838,13 @@ static inline UnaryOperatorKind ConvertTokenKindToUnaryOpcode(
}
/// DiagnoseSelfAssignment - Emits a warning if a value is assigned to itself.
-/// This warning is only emitted for builtin assignment operations. It is also
-/// suppressed in the event of macro expansions.
+/// This warning suppressed in the event of macro expansions.
static void DiagnoseSelfAssignment(Sema &S, Expr *LHSExpr, Expr *RHSExpr,
- SourceLocation OpLoc) {
+ SourceLocation OpLoc, bool IsBuiltin) {
if (S.inTemplateInstantiation())
return;
+ if (S.isUnevaluatedContext())
+ return;
if (OpLoc.isInvalid() || OpLoc.isMacroID())
return;
LHSExpr = LHSExpr->IgnoreParenImpCasts();
@@ -11447,9 +11867,10 @@ static void DiagnoseSelfAssignment(Sema &S, Expr *LHSExpr, Expr *RHSExpr,
if (RefTy->getPointeeType().isVolatileQualified())
return;
- S.Diag(OpLoc, diag::warn_self_assignment)
- << LHSDeclRef->getType()
- << LHSExpr->getSourceRange() << RHSExpr->getSourceRange();
+ S.Diag(OpLoc, IsBuiltin ? diag::warn_self_assignment_builtin
+ : diag::warn_self_assignment_overloaded)
+ << LHSDeclRef->getType() << LHSExpr->getSourceRange()
+ << RHSExpr->getSourceRange();
}
/// Check if a bitwise-& is performed on an Objective-C pointer. This
@@ -11584,8 +12005,8 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
// C++11 5.17p9:
// The meaning of x = {v} [...] is that of x = T(v) [...]. The meaning
// of x = {} is x = T().
- InitializationKind Kind =
- InitializationKind::CreateDirectList(RHSExpr->getLocStart());
+ InitializationKind Kind = InitializationKind::CreateDirectList(
+ RHSExpr->getLocStart(), RHSExpr->getLocStart(), RHSExpr->getLocEnd());
InitializedEntity Entity =
InitializedEntity::InitializeTemporary(LHSExpr->getType());
InitializationSequence InitSeq(*this, Entity, Kind, RHSExpr);
@@ -11642,7 +12063,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
OK = LHS.get()->getObjectKind();
}
if (!ResultTy.isNull()) {
- DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc);
+ DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc, true);
DiagnoseSelfMove(LHS.get(), RHS.get(), OpLoc);
}
RecordModifiableNonNullParam(*this, LHS.get());
@@ -11678,19 +12099,17 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
case BO_GE:
case BO_GT:
ConvertHalfVec = true;
- ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc, true);
+ ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc);
break;
case BO_EQ:
case BO_NE:
ConvertHalfVec = true;
- ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc, false);
+ ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc);
break;
case BO_Cmp:
- // FIXME: Implement proper semantic checking of '<=>'.
ConvertHalfVec = true;
- ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc, true);
- if (!ResultTy.isNull())
- ResultTy = Context.VoidTy;
+ ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc);
+ assert(ResultTy.isNull() || ResultTy->getAsCXXRecordDecl());
break;
case BO_And:
checkObjCPointerIntrospection(*this, LHS, RHS, OpLoc);
@@ -11740,7 +12159,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
break;
case BO_AndAssign:
case BO_OrAssign: // fallthrough
- DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc);
+ DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc, true);
LLVM_FALLTHROUGH;
case BO_XorAssign:
CompResultTy = CheckBitwiseOperands(LHS, RHS, OpLoc, Opc);
@@ -11858,7 +12277,7 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc,
ParensRange);
}
-/// \brief It accepts a '&&' expr that is inside a '||' one.
+/// It accepts a '&&' expr that is inside a '||' one.
/// Emit a diagnostic together with a fixit hint that wraps the '&&' expression
/// in parentheses.
static void
@@ -11873,7 +12292,7 @@ EmitDiagnosticForLogicalAndInLogicalOr(Sema &Self, SourceLocation OpLoc,
Bop->getSourceRange());
}
-/// \brief Returns true if the given expression can be evaluated as a constant
+/// Returns true if the given expression can be evaluated as a constant
/// 'true'.
static bool EvaluatesAsTrue(Sema &S, Expr *E) {
bool Res;
@@ -11881,7 +12300,7 @@ static bool EvaluatesAsTrue(Sema &S, Expr *E) {
E->EvaluateAsBooleanCondition(Res, S.getASTContext()) && Res;
}
-/// \brief Returns true if the given expression can be evaluated as a constant
+/// Returns true if the given expression can be evaluated as a constant
/// 'false'.
static bool EvaluatesAsFalse(Sema &S, Expr *E) {
bool Res;
@@ -11889,7 +12308,7 @@ static bool EvaluatesAsFalse(Sema &S, Expr *E) {
E->EvaluateAsBooleanCondition(Res, S.getASTContext()) && !Res;
}
-/// \brief Look for '&&' in the left hand of a '||' expr.
+/// Look for '&&' in the left hand of a '||' expr.
static void DiagnoseLogicalAndInLogicalOrLHS(Sema &S, SourceLocation OpLoc,
Expr *LHSExpr, Expr *RHSExpr) {
if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(LHSExpr)) {
@@ -11911,7 +12330,7 @@ static void DiagnoseLogicalAndInLogicalOrLHS(Sema &S, SourceLocation OpLoc,
}
}
-/// \brief Look for '&&' in the right hand of a '||' expr.
+/// Look for '&&' in the right hand of a '||' expr.
static void DiagnoseLogicalAndInLogicalOrRHS(Sema &S, SourceLocation OpLoc,
Expr *LHSExpr, Expr *RHSExpr) {
if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(RHSExpr)) {
@@ -11926,7 +12345,7 @@ static void DiagnoseLogicalAndInLogicalOrRHS(Sema &S, SourceLocation OpLoc,
}
}
-/// \brief Look for bitwise op in the left or right hand of a bitwise op with
+/// Look for bitwise op in the left or right hand of a bitwise op with
/// lower precedence and emit a diagnostic together with a fixit hint that wraps
/// the '&' expression in parentheses.
static void DiagnoseBitwiseOpInBitwiseOp(Sema &S, BinaryOperatorKind Opc,
@@ -12039,6 +12458,21 @@ ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
static ExprResult BuildOverloadedBinOp(Sema &S, Scope *Sc, SourceLocation OpLoc,
BinaryOperatorKind Opc,
Expr *LHS, Expr *RHS) {
+ switch (Opc) {
+ case BO_Assign:
+ case BO_DivAssign:
+ case BO_RemAssign:
+ case BO_SubAssign:
+ case BO_AndAssign:
+ case BO_OrAssign:
+ case BO_XorAssign:
+ DiagnoseSelfAssignment(S, LHS, RHS, OpLoc, false);
+ CheckIdentityFieldAssignment(LHS, RHS, OpLoc, S);
+ break;
+ default:
+ break;
+ }
+
// Find all of the overloaded operators visible from this
// point. We perform both an operator-name lookup from the local
// scope and an argument-dependent lookup based on the types of
@@ -12161,6 +12595,16 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
return CreateBuiltinBinOp(OpLoc, Opc, LHSExpr, RHSExpr);
}
+static bool isOverflowingIntegerType(ASTContext &Ctx, QualType T) {
+ if (T.isNull() || T->isDependentType())
+ return false;
+
+ if (!T->isPromotableIntegerType())
+ return true;
+
+ return Ctx.getIntWidth(T) >= Ctx.getIntWidth(Ctx.IntTy);
+}
+
ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
UnaryOperatorKind Opc,
Expr *InputExpr) {
@@ -12168,6 +12612,8 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
ExprValueKind VK = VK_RValue;
ExprObjectKind OK = OK_Ordinary;
QualType resultType;
+ bool CanOverflow = false;
+
bool ConvertHalfVec = false;
if (getLangOpts().OpenCL) {
QualType Ty = InputExpr->getType();
@@ -12193,6 +12639,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
Opc == UO_PostInc,
Opc == UO_PreInc ||
Opc == UO_PreDec);
+ CanOverflow = isOverflowingIntegerType(Context, resultType);
break;
case UO_AddrOf:
resultType = CheckAddressOfOperand(Input, OpLoc);
@@ -12206,6 +12653,8 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
}
case UO_Plus:
case UO_Minus:
+ CanOverflow = Opc == UO_Minus &&
+ isOverflowingIntegerType(Context, Input.get()->getType());
Input = UsualUnaryConversions(Input.get());
if (Input.isInvalid()) return ExprError();
// Unary plus and minus require promoting an operand of half vector to a
@@ -12242,6 +12691,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
if (Input.isInvalid())
return ExprError();
resultType = Input.get()->getType();
+
if (resultType->isDependentType())
break;
// C99 6.5.3.3p1. We allow complex int and float as a GCC extension.
@@ -12338,7 +12788,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
OK = Input.get()->getObjectKind();
break;
case UO_Coawait:
- // It's unnessesary to represent the pass-through operator co_await in the
+ // It's unnecessary to represent the pass-through operator co_await in the
// AST; just return the input expression instead.
assert(!Input.get()->getType()->isDependentType() &&
"the co_await expression must be non-dependant before "
@@ -12356,17 +12806,17 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
CheckArrayAccess(Input.get());
auto *UO = new (Context)
- UnaryOperator(Input.get(), Opc, resultType, VK, OK, OpLoc);
+ UnaryOperator(Input.get(), Opc, resultType, VK, OK, OpLoc, CanOverflow);
// Convert the result back to a half vector.
if (ConvertHalfVec)
return convertVector(UO, Context.HalfTy, *this);
return UO;
}
-/// \brief Determine whether the given expression is a qualified member
+/// Determine whether the given expression is a qualified member
/// access expression, of a form that could be turned into a pointer to member
/// with the address-of operator.
-static bool isQualifiedMemberAccess(Expr *E) {
+bool Sema::isQualifiedMemberAccess(Expr *E) {
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
if (!DRE->getQualifier())
return false;
@@ -12549,11 +12999,8 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
LastExpr = rebuiltLastStmt;
} else {
LastExpr = PerformCopyInitialization(
- InitializedEntity::InitializeResult(LPLoc,
- Ty,
- false),
- SourceLocation(),
- LastExpr);
+ InitializedEntity::InitializeStmtExprResult(LPLoc, Ty),
+ SourceLocation(), LastExpr);
}
if (LastExpr.isInvalid())
@@ -12784,7 +13231,7 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
CondExpr = CondICE.get();
CondIsTrue = condEval.getZExtValue();
- // If the condition is > zero, then the AST type is the same as the LSHExpr.
+ // If the condition is > zero, then the AST type is the same as the LHSExpr.
Expr *ActiveExpr = CondIsTrue ? LHSExpr : RHSExpr;
resType = ActiveExpr->getType();
@@ -12990,7 +13437,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
// Set the captured variables on the block.
// FIXME: Share capture structure between BlockDecl and CapturingScopeInfo!
SmallVector<BlockDecl::Capture, 4> Captures;
- for (CapturingScopeInfo::Capture &Cap : BSI->Captures) {
+ for (Capture &Cap : BSI->Captures) {
if (Cap.isThisCapture())
continue;
BlockDecl::Capture NewCap(Cap.getVariable(), Cap.isBlockCapture(),
@@ -13070,7 +13517,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
for (const auto &CI : Result->getBlockDecl()->captures()) {
const VarDecl *var = CI.getVariable();
if (var->getType().isDestructedType() != QualType::DK_none) {
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
break;
}
}
@@ -13336,7 +13783,6 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
DiagKind = diag::err_typecheck_incompatible_address_space;
break;
-
} else if (lhq.getObjCLifetime() != rhq.getObjCLifetime()) {
DiagKind = diag::err_typecheck_incompatible_ownership;
break;
@@ -13460,7 +13906,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
if (DiagKind == diag::warn_incompatible_qualified_id &&
PDecl && IFace && !IFace->hasDefinition())
Diag(IFace->getLocation(), diag::note_incomplete_class_and_qualified_id)
- << IFace->getName() << PDecl->getName();
+ << IFace << PDecl;
if (SecondType == Context.OverloadTy)
NoteAllOverloadCandidates(OverloadExpr::find(SrcExpr).Expression,
@@ -13701,22 +14147,22 @@ ExprResult Sema::TransformToPotentiallyEvaluated(Expr *E) {
}
void
-Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
- Decl *LambdaContextDecl,
- bool IsDecltype) {
+Sema::PushExpressionEvaluationContext(
+ ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl,
+ ExpressionEvaluationContextRecord::ExpressionKind ExprContext) {
ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), Cleanup,
- LambdaContextDecl, IsDecltype);
+ LambdaContextDecl, ExprContext);
Cleanup.reset();
if (!MaybeODRUseExprs.empty())
std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs);
}
void
-Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
- ReuseLambdaContextDecl_t,
- bool IsDecltype) {
+Sema::PushExpressionEvaluationContext(
+ ExpressionEvaluationContext NewContext, ReuseLambdaContextDecl_t,
+ ExpressionEvaluationContextRecord::ExpressionKind ExprContext) {
Decl *ClosureContextDecl = ExprEvalContexts.back().ManglingContextDecl;
- PushExpressionEvaluationContext(NewContext, ClosureContextDecl, IsDecltype);
+ PushExpressionEvaluationContext(NewContext, ClosureContextDecl, ExprContext);
}
void Sema::PopExpressionEvaluationContext() {
@@ -13724,30 +14170,30 @@ void Sema::PopExpressionEvaluationContext() {
unsigned NumTypos = Rec.NumTypos;
if (!Rec.Lambdas.empty()) {
- if (Rec.isUnevaluated() || Rec.isConstantEvaluated()) {
+ using ExpressionKind = ExpressionEvaluationContextRecord::ExpressionKind;
+ if (Rec.ExprContext == ExpressionKind::EK_TemplateArgument || Rec.isUnevaluated() ||
+ (Rec.isConstantEvaluated() && !getLangOpts().CPlusPlus17)) {
unsigned D;
if (Rec.isUnevaluated()) {
// C++11 [expr.prim.lambda]p2:
// A lambda-expression shall not appear in an unevaluated operand
// (Clause 5).
D = diag::err_lambda_unevaluated_operand;
- } else {
+ } else if (Rec.isConstantEvaluated() && !getLangOpts().CPlusPlus17) {
// C++1y [expr.const]p2:
// A conditional-expression e is a core constant expression unless the
// evaluation of e, following the rules of the abstract machine, would
// evaluate [...] a lambda-expression.
D = diag::err_lambda_in_constant_expression;
- }
+ } else if (Rec.ExprContext == ExpressionKind::EK_TemplateArgument) {
+ // C++17 [expr.prim.lamda]p2:
+ // A lambda-expression shall not appear [...] in a template-argument.
+ D = diag::err_lambda_in_invalid_context;
+ } else
+ llvm_unreachable("Couldn't infer lambda error message.");
- // C++1z allows lambda expressions as core constant expressions.
- // FIXME: In C++1z, reinstate the restrictions on lambda expressions (CWG
- // 1607) from appearing within template-arguments and array-bounds that
- // are part of function-signatures. Be mindful that P0315 (Lambdas in
- // unevaluated contexts) might lift some of these restrictions in a
- // future version.
- if (!Rec.isConstantEvaluated() || !getLangOpts().CPlusPlus17)
- for (const auto *L : Rec.Lambdas)
- Diag(L->getLocStart(), D);
+ for (const auto *L : Rec.Lambdas)
+ Diag(L->getLocStart(), D);
} else {
// Mark the capture expressions odr-used. This was deferred
// during lambda expression creation.
@@ -13806,13 +14252,13 @@ static bool isEvaluatableContext(Sema &SemaRef) {
switch (SemaRef.ExprEvalContexts.back().Context) {
case Sema::ExpressionEvaluationContext::Unevaluated:
case Sema::ExpressionEvaluationContext::UnevaluatedAbstract:
- case Sema::ExpressionEvaluationContext::DiscardedStatement:
// Expressions in this context are never evaluated.
return false;
case Sema::ExpressionEvaluationContext::UnevaluatedList:
case Sema::ExpressionEvaluationContext::ConstantEvaluated:
case Sema::ExpressionEvaluationContext::PotentiallyEvaluated:
+ case Sema::ExpressionEvaluationContext::DiscardedStatement:
// Expressions in this context could be evaluated.
return true;
@@ -13856,7 +14302,7 @@ static bool isImplicitlyDefinableConstexprFunction(FunctionDecl *Func) {
(Func->isImplicitlyInstantiable() || (MD && !MD->isUserProvided()));
}
-/// \brief Mark a function referenced, and check whether it is odr-used
+/// Mark a function referenced, and check whether it is odr-used
/// (C++ [basic.def.odr]p2, C99 6.9p3)
void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
bool MightBeOdrUse) {
@@ -14089,7 +14535,7 @@ static bool isVariableAlreadyCapturedInScopeInfo(CapturingScopeInfo *CSI, VarDec
// Similarly to mutable captures in lambda, all the OpenMP captures by copy
// are mutable in the sense that user can change their value - they are
// private instances of the captured declarations.
- const CapturingScopeInfo::Capture &Cap = CSI->getCapture(Var);
+ const Capture &Cap = CSI->getCapture(Var);
if (Cap.isCopyCapture() &&
!(isa<LambdaScopeInfo>(CSI) && cast<LambdaScopeInfo>(CSI)->Mutable) &&
!(isa<CapturedRegionScopeInfo>(CSI) &&
@@ -14242,30 +14688,6 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
if (BuildAndDiagnose) {
SourceLocation VarLoc = Var->getLocation();
S.Diag(Loc, diag::warn_block_capture_autoreleasing);
- {
- auto AddAutoreleaseNote =
- S.Diag(VarLoc, diag::note_declare_parameter_autoreleasing);
- // Provide a fix-it for the '__autoreleasing' keyword at the
- // appropriate location in the variable's type.
- if (const auto *TSI = Var->getTypeSourceInfo()) {
- PointerTypeLoc PTL =
- TSI->getTypeLoc().getAsAdjusted<PointerTypeLoc>();
- if (PTL) {
- SourceLocation Loc = PTL.getPointeeLoc().getEndLoc();
- Loc = Lexer::getLocForEndOfToken(Loc, 0, S.getSourceManager(),
- S.getLangOpts());
- if (Loc.isValid()) {
- StringRef CharAtLoc = Lexer::getSourceText(
- CharSourceRange::getCharRange(Loc, Loc.getLocWithOffset(1)),
- S.getSourceManager(), S.getLangOpts());
- AddAutoreleaseNote << FixItHint::CreateInsertion(
- Loc, CharAtLoc.empty() || !isWhitespace(CharAtLoc[0])
- ? " __autoreleasing "
- : " __autoreleasing");
- }
- }
- }
- }
S.Diag(VarLoc, diag::note_declare_parameter_strong);
}
}
@@ -14273,7 +14695,7 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
const bool HasBlocksAttr = Var->hasAttr<BlocksAttr>();
if (HasBlocksAttr || CaptureType->isReferenceType() ||
- (S.getLangOpts().OpenMP && S.IsOpenMPCapturedDecl(Var))) {
+ (S.getLangOpts().OpenMP && S.isOpenMPCapturedDecl(Var))) {
// Block capture by reference does not change the capture or
// declaration reference types.
ByRef = true;
@@ -14333,7 +14755,7 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
}
-/// \brief Capture the given variable in the captured region.
+/// Capture the given variable in the captured region.
static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
VarDecl *Var,
SourceLocation Loc,
@@ -14346,14 +14768,14 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
bool ByRef = true;
// Using an LValue reference type is consistent with Lambdas (see below).
if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP) {
- if (S.IsOpenMPCapturedDecl(Var)) {
+ if (S.isOpenMPCapturedDecl(Var)) {
bool HasConst = DeclRefType.isConstQualified();
DeclRefType = DeclRefType.getUnqualifiedType();
// Don't lose diagnostics about assignments to const.
if (HasConst)
DeclRefType.addConst();
}
- ByRef = S.IsOpenMPCapturedByRef(Var, RSI->OpenMPLevel);
+ ByRef = S.isOpenMPCapturedByRef(Var, RSI->OpenMPLevel);
}
if (ByRef)
@@ -14393,7 +14815,7 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
return true;
}
-/// \brief Create a field within the lambda class for the variable
+/// Create a field within the lambda class for the variable
/// being captured.
static void addAsFieldToClosureType(Sema &S, LambdaScopeInfo *LSI,
QualType FieldType, QualType DeclRefType,
@@ -14411,7 +14833,7 @@ static void addAsFieldToClosureType(Sema &S, LambdaScopeInfo *LSI,
Lambda->addDecl(Field);
}
-/// \brief Capture the given variable in the lambda.
+/// Capture the given variable in the lambda.
static bool captureInLambda(LambdaScopeInfo *LSI,
VarDecl *Var,
SourceLocation Loc,
@@ -14545,7 +14967,7 @@ bool Sema::tryCaptureVariable(
// Capture global variables if it is required to use private copy of this
// variable.
bool IsGlobal = !Var->hasLocalStorage();
- if (IsGlobal && !(LangOpts.OpenMP && IsOpenMPCapturedDecl(Var)))
+ if (IsGlobal && !(LangOpts.OpenMP && isOpenMPCapturedDecl(Var)))
return true;
Var = Var->getCanonicalDecl();
@@ -14910,7 +15332,7 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
// A reference initialized by a constant expression can never be
// odr-used, so simply ignore it.
if (!Var->getType()->isReferenceType() ||
- (SemaRef.LangOpts.OpenMP && SemaRef.IsOpenMPCapturedDecl(Var)))
+ (SemaRef.LangOpts.OpenMP && SemaRef.isOpenMPCapturedDecl(Var)))
SemaRef.MaybeODRUseExprs.insert(E);
} else if (OdrUseContext) {
MarkVarDeclODRUsed(Var, Loc, SemaRef,
@@ -14945,7 +15367,7 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
}
}
-/// \brief Mark a variable referenced, and check whether it is odr-used
+/// Mark a variable referenced, and check whether it is odr-used
/// (C++ [basic.def.odr]p2, C99 6.9p3). Note that this should not be
/// used directly for normal expressions referring to VarDecl.
void Sema::MarkVariableReferenced(SourceLocation Loc, VarDecl *Var) {
@@ -14986,7 +15408,7 @@ static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc,
SemaRef.MarkAnyDeclReferenced(Loc, DM, MightBeOdrUse);
}
-/// \brief Perform reference-marking and odr-use handling for a DeclRefExpr.
+/// Perform reference-marking and odr-use handling for a DeclRefExpr.
void Sema::MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base) {
// TODO: update this with DR# once a defect report is filed.
// C++11 defect. The address of a pure member should not be an ODR use, even
@@ -14999,7 +15421,7 @@ void Sema::MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base) {
MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E, OdrUse);
}
-/// \brief Perform reference-marking and odr-use handling for a MemberExpr.
+/// Perform reference-marking and odr-use handling for a MemberExpr.
void Sema::MarkMemberReferenced(MemberExpr *E) {
// C++11 [basic.def.odr]p2:
// A non-overloaded function whose name appears as a potentially-evaluated
@@ -15018,7 +15440,7 @@ void Sema::MarkMemberReferenced(MemberExpr *E) {
MarkExprReferenced(*this, Loc, E->getMemberDecl(), E, MightBeOdrUse);
}
-/// \brief Perform marking for a reference to an arbitrary declaration. It
+/// Perform marking for a reference to an arbitrary declaration. It
/// marks the declaration referenced, and performs odr-use checking for
/// functions and variables. This method should not be used when building a
/// normal expression which refers to a variable.
@@ -15081,7 +15503,7 @@ void Sema::MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T) {
}
namespace {
- /// \brief Helper class that marks all of the declarations referenced by
+ /// Helper class that marks all of the declarations referenced by
/// potentially-evaluated subexpressions as "referenced".
class EvaluatedExprMarker : public EvaluatedExprVisitor<EvaluatedExprMarker> {
Sema &S;
@@ -15154,7 +15576,7 @@ namespace {
};
}
-/// \brief Mark any declarations that appear within this expression or any
+/// Mark any declarations that appear within this expression or any
/// potentially-evaluated subexpressions as "referenced".
///
/// \param SkipLocalVariables If true, don't mark local variables as
@@ -15164,7 +15586,7 @@ void Sema::MarkDeclarationsReferencedInExpr(Expr *E,
EvaluatedExprMarker(*this, SkipLocalVariables).Visit(E);
}
-/// \brief Emit a diagnostic that describes an effect on the run-time behavior
+/// Emit a diagnostic that describes an effect on the run-time behavior
/// of the program being compiled.
///
/// This routine emits the given diagnostic when the code currently being
@@ -15230,7 +15652,8 @@ bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc,
// If we're inside a decltype's expression, don't check for a valid return
// type or construct temporaries until we know whether this is the last call.
- if (ExprEvalContexts.back().IsDecltype) {
+ if (ExprEvalContexts.back().ExprContext ==
+ ExpressionEvaluationContextRecord::EK_Decltype) {
ExprEvalContexts.back().DelayedDecltypeCalls.push_back(CE);
return false;
}
@@ -15321,7 +15744,7 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) {
<< FixItHint::CreateReplacement(Loc, "==");
}
-/// \brief Redundant parentheses over an equality comparison can indicate
+/// Redundant parentheses over an equality comparison can indicate
/// that the user intended an assignment used as condition.
void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *ParenE) {
// Don't warn if the parens came from a macro.
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
index 89055aecd4b6..a1168fa34d56 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Implements semantic analysis for C++ expressions.
+/// Implements semantic analysis for C++ expressions.
///
//===----------------------------------------------------------------------===//
@@ -42,7 +42,7 @@
using namespace clang;
using namespace sema;
-/// \brief Handle the result of the special case name lookup for inheriting
+/// Handle the result of the special case name lookup for inheriting
/// constructor declarations. 'NS::X::X' and 'NS::X<...>::X' are treated as
/// constructor names in member using declarations, even if 'X' is not the
/// name of the corresponding type.
@@ -80,6 +80,50 @@ ParsedType Sema::getInheritingConstructorName(CXXScopeSpec &SS,
Context.getTrivialTypeSourceInfo(Type, NameLoc));
}
+ParsedType Sema::getConstructorName(IdentifierInfo &II,
+ SourceLocation NameLoc,
+ Scope *S, CXXScopeSpec &SS,
+ bool EnteringContext) {
+ CXXRecordDecl *CurClass = getCurrentClass(S, &SS);
+ assert(CurClass && &II == CurClass->getIdentifier() &&
+ "not a constructor name");
+
+ // When naming a constructor as a member of a dependent context (eg, in a
+ // friend declaration or an inherited constructor declaration), form an
+ // unresolved "typename" type.
+ if (CurClass->isDependentContext() && !EnteringContext) {
+ QualType T = Context.getDependentNameType(ETK_None, SS.getScopeRep(), &II);
+ return ParsedType::make(T);
+ }
+
+ if (SS.isNotEmpty() && RequireCompleteDeclContext(SS, CurClass))
+ return ParsedType();
+
+ // Find the injected-class-name declaration. Note that we make no attempt to
+ // diagnose cases where the injected-class-name is shadowed: the only
+ // declaration that can validly shadow the injected-class-name is a
+ // non-static data member, and if the class contains both a non-static data
+ // member and a constructor then it is ill-formed (we check that in
+ // CheckCompletedCXXClass).
+ CXXRecordDecl *InjectedClassName = nullptr;
+ for (NamedDecl *ND : CurClass->lookup(&II)) {
+ auto *RD = dyn_cast<CXXRecordDecl>(ND);
+ if (RD && RD->isInjectedClassName()) {
+ InjectedClassName = RD;
+ break;
+ }
+ }
+ if (!InjectedClassName && CurClass->isInvalidDecl())
+ return ParsedType();
+ assert(InjectedClassName && "couldn't find injected class name");
+
+ QualType T = Context.getTypeDeclType(InjectedClassName);
+ DiagnoseUseOfDecl(InjectedClassName, NameLoc);
+ MarkAnyDeclReferenced(NameLoc, InjectedClassName, /*OdrUse=*/false);
+
+ return ParsedType::make(T);
+}
+
ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
IdentifierInfo &II,
SourceLocation NameLoc,
@@ -383,7 +427,7 @@ bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS,
llvm_unreachable("unknown nested name specifier kind");
}
-/// \brief Build a C++ typeid expression with a type operand.
+/// Build a C++ typeid expression with a type operand.
ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
SourceLocation TypeidLoc,
TypeSourceInfo *Operand,
@@ -408,7 +452,7 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
SourceRange(TypeidLoc, RParenLoc));
}
-/// \brief Build a C++ typeid expression with an expression operand.
+/// Build a C++ typeid expression with an expression operand.
ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
SourceLocation TypeidLoc,
Expr *E,
@@ -480,6 +524,12 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
ExprResult
Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
bool isType, void *TyOrExpr, SourceLocation RParenLoc) {
+ // OpenCL C++ 1.0 s2.9: typeid is not supported.
+ if (getLangOpts().OpenCLCPlusPlus) {
+ return ExprError(Diag(OpLoc, diag::err_openclcxx_not_supported)
+ << "typeid");
+ }
+
// Find the std::type_info type.
if (!getStdNamespace())
return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid));
@@ -560,7 +610,7 @@ getUuidAttrOfType(Sema &SemaRef, QualType QT,
}
}
-/// \brief Build a Microsoft __uuidof expression with a type operand.
+/// Build a Microsoft __uuidof expression with a type operand.
ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType,
SourceLocation TypeidLoc,
TypeSourceInfo *Operand,
@@ -580,7 +630,7 @@ ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType,
SourceRange(TypeidLoc, RParenLoc));
}
-/// \brief Build a Microsoft __uuidof expression with an expression operand.
+/// Build a Microsoft __uuidof expression with an expression operand.
ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType,
SourceLocation TypeidLoc,
Expr *E,
@@ -695,7 +745,11 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex,
bool IsThrownVarInScope) {
// Don't report an error if 'throw' is used in system headers.
if (!getLangOpts().CXXExceptions &&
- !getSourceManager().isInSystemHeader(OpLoc))
+ !getSourceManager().isInSystemHeader(OpLoc) &&
+ (!getLangOpts().OpenMPIsDevice ||
+ !getLangOpts().OpenMPHostCXXExceptions ||
+ isInOpenMPTargetExecutionDirective() ||
+ isInOpenMPDeclareTargetContext()))
Diag(OpLoc, diag::err_exceptions_disabled) << "throw";
// Exceptions aren't allowed in CUDA device code.
@@ -728,7 +782,7 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex,
// exception object
const VarDecl *NRVOVariable = nullptr;
if (IsThrownVarInScope)
- NRVOVariable = getCopyElisionCandidate(QualType(), Ex, false);
+ NRVOVariable = getCopyElisionCandidate(QualType(), Ex, CES_Strict);
InitializedEntity Entity = InitializedEntity::InitializeException(
OpLoc, ExceptionObjectTy,
@@ -1114,8 +1168,9 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit,
assert((!ByCopy || Explicit) && "cannot implicitly capture *this by value");
- const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt ?
- *FunctionScopeIndexToStopAt : FunctionScopes.size() - 1;
+ const int MaxFunctionScopesIndex = FunctionScopeIndexToStopAt
+ ? *FunctionScopeIndexToStopAt
+ : FunctionScopes.size() - 1;
// Check that we can capture the *enclosing object* (referred to by '*this')
// by the capturing-entity/closure (lambda/block/etc) at
@@ -1141,7 +1196,7 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit,
unsigned NumCapturingClosures = 0;
- for (unsigned idx = MaxFunctionScopesIndex; idx != 0; idx--) {
+ for (int idx = MaxFunctionScopesIndex; idx >= 0; idx--) {
if (CapturingScopeInfo *CSI =
dyn_cast<CapturingScopeInfo>(FunctionScopes[idx])) {
if (CSI->CXXThisCaptureIndex != 0) {
@@ -1196,8 +1251,8 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit,
// FIXME: We need to delay this marking in PotentiallyPotentiallyEvaluated
// contexts.
QualType ThisTy = getCurrentThisType();
- for (unsigned idx = MaxFunctionScopesIndex; NumCapturingClosures;
- --idx, --NumCapturingClosures) {
+ for (int idx = MaxFunctionScopesIndex; NumCapturingClosures;
+ --idx, --NumCapturingClosures) {
CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[idx]);
Expr *ThisExpr = nullptr;
@@ -1244,11 +1299,16 @@ bool Sema::isThisOutsideMemberFunctionBody(QualType BaseType) {
return Class && Class->isBeingDefined();
}
+/// Parse construction of a specified type.
+/// Can be interpreted either as function-style casting ("int(x)")
+/// or class type construction ("ClassType(x,y,z)")
+/// or creation of a value-initialized type ("int()").
ExprResult
Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep,
- SourceLocation LParenLoc,
+ SourceLocation LParenOrBraceLoc,
MultiExprArg exprs,
- SourceLocation RParenLoc) {
+ SourceLocation RParenOrBraceLoc,
+ bool ListInitialization) {
if (!TypeRep)
return ExprError();
@@ -1257,7 +1317,8 @@ Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep,
if (!TInfo)
TInfo = Context.getTrivialTypeSourceInfo(Ty, SourceLocation());
- auto Result = BuildCXXTypeConstructExpr(TInfo, LParenLoc, exprs, RParenLoc);
+ auto Result = BuildCXXTypeConstructExpr(TInfo, LParenOrBraceLoc, exprs,
+ RParenOrBraceLoc, ListInitialization);
// Avoid creating a non-type-dependent expression that contains typos.
// Non-type-dependent expressions are liable to be discarded without
// checking for embedded typos.
@@ -1267,38 +1328,40 @@ Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep,
return Result;
}
-/// ActOnCXXTypeConstructExpr - Parse construction of a specified type.
-/// Can be interpreted either as function-style casting ("int(x)")
-/// or class type construction ("ClassType(x,y,z)")
-/// or creation of a value-initialized type ("int()").
ExprResult
Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
- SourceLocation LParenLoc,
+ SourceLocation LParenOrBraceLoc,
MultiExprArg Exprs,
- SourceLocation RParenLoc) {
+ SourceLocation RParenOrBraceLoc,
+ bool ListInitialization) {
QualType Ty = TInfo->getType();
SourceLocation TyBeginLoc = TInfo->getTypeLoc().getBeginLoc();
if (Ty->isDependentType() || CallExpr::hasAnyTypeDependentArguments(Exprs)) {
- return CXXUnresolvedConstructExpr::Create(Context, TInfo, LParenLoc, Exprs,
- RParenLoc);
+ // FIXME: CXXUnresolvedConstructExpr does not model list-initialization
+ // directly. We work around this by dropping the locations of the braces.
+ SourceRange Locs = ListInitialization
+ ? SourceRange()
+ : SourceRange(LParenOrBraceLoc, RParenOrBraceLoc);
+ return CXXUnresolvedConstructExpr::Create(Context, TInfo, Locs.getBegin(),
+ Exprs, Locs.getEnd());
}
- bool ListInitialization = LParenLoc.isInvalid();
assert((!ListInitialization ||
(Exprs.size() == 1 && isa<InitListExpr>(Exprs[0]))) &&
"List initialization must have initializer list as expression.");
- SourceRange FullRange = SourceRange(TyBeginLoc,
- ListInitialization ? Exprs[0]->getSourceRange().getEnd() : RParenLoc);
+ SourceRange FullRange = SourceRange(TyBeginLoc, RParenOrBraceLoc);
InitializedEntity Entity = InitializedEntity::InitializeTemporary(TInfo);
InitializationKind Kind =
Exprs.size()
? ListInitialization
- ? InitializationKind::CreateDirectList(TyBeginLoc)
- : InitializationKind::CreateDirect(TyBeginLoc, LParenLoc,
- RParenLoc)
- : InitializationKind::CreateValue(TyBeginLoc, LParenLoc, RParenLoc);
+ ? InitializationKind::CreateDirectList(
+ TyBeginLoc, LParenOrBraceLoc, RParenOrBraceLoc)
+ : InitializationKind::CreateDirect(TyBeginLoc, LParenOrBraceLoc,
+ RParenOrBraceLoc)
+ : InitializationKind::CreateValue(TyBeginLoc, LParenOrBraceLoc,
+ RParenOrBraceLoc);
// C++1z [expr.type.conv]p1:
// If the type is a placeholder for a deduced class type, [...perform class
@@ -1319,7 +1382,8 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
if (Exprs.size() == 1 && !ListInitialization &&
!isa<InitListExpr>(Exprs[0])) {
Expr *Arg = Exprs[0];
- return BuildCXXFunctionalCastExpr(TInfo, Ty, LParenLoc, Arg, RParenLoc);
+ return BuildCXXFunctionalCastExpr(TInfo, Ty, LParenOrBraceLoc, Arg,
+ RParenOrBraceLoc);
}
// For an expression of the form T(), T shall not be an array type.
@@ -1367,15 +1431,18 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
// CXXTemporaryObjectExpr. It's also weird that the functional cast
// is sometimes handled by initialization and sometimes not.
QualType ResultType = Result.get()->getType();
+ SourceRange Locs = ListInitialization
+ ? SourceRange()
+ : SourceRange(LParenOrBraceLoc, RParenOrBraceLoc);
Result = CXXFunctionalCastExpr::Create(
- Context, ResultType, Expr::getValueKindForType(Ty), TInfo,
- CK_NoOp, Result.get(), /*Path=*/nullptr, LParenLoc, RParenLoc);
+ Context, ResultType, Expr::getValueKindForType(Ty), TInfo, CK_NoOp,
+ Result.get(), /*Path=*/nullptr, Locs.getBegin(), Locs.getEnd());
}
return Result;
}
-/// \brief Determine whether the given function is a non-placement
+/// 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))
@@ -1430,7 +1497,7 @@ namespace {
CUDAPref = S.IdentifyCUDAPreference(Caller, FD);
}
- operator bool() const { return FD; }
+ explicit operator bool() const { return FD; }
bool isBetterThan(const UsualDeallocFnInfo &Other, bool WantSize,
bool WantAlign) const {
@@ -1543,7 +1610,7 @@ static bool doesUsualArrayDeleteWantSize(Sema &S, SourceLocation loc,
return Best && Best.HasSizeT;
}
-/// \brief Parsed a C++ 'new' expression (C++ 5.3.4).
+/// Parsed a C++ 'new' expression (C++ 5.3.4).
///
/// E.g.:
/// @code new (memory) int[size][4] @endcode
@@ -1593,9 +1660,9 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
if (Expr *NumElts = (Expr *)Array.NumElts) {
if (!NumElts->isTypeDependent() && !NumElts->isValueDependent()) {
if (getLangOpts().CPlusPlus14) {
- // C++1y [expr.new]p6: Every constant-expression in a noptr-new-declarator
- // shall be a converted constant expression (5.19) of type std::size_t
- // and shall evaluate to a strictly positive value.
+ // C++1y [expr.new]p6: Every constant-expression in a noptr-new-declarator
+ // shall be a converted constant expression (5.19) of type std::size_t
+ // and shall evaluate to a strictly positive value.
unsigned IntWidth = Context.getTargetInfo().getIntWidth();
assert(IntWidth && "Builtin type of size 0?");
llvm::APSInt Value(IntWidth);
@@ -1728,7 +1795,9 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
// - Otherwise, the new-initializer is interpreted according to the
// initialization rules of 8.5 for direct-initialization.
: initStyle == CXXNewExpr::ListInit
- ? InitializationKind::CreateDirectList(TypeRange.getBegin())
+ ? InitializationKind::CreateDirectList(TypeRange.getBegin(),
+ Initializer->getLocStart(),
+ Initializer->getLocEnd())
: InitializationKind::CreateDirect(TypeRange.getBegin(),
DirectInitRange.getBegin(),
DirectInitRange.getEnd());
@@ -1795,13 +1864,6 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
if (CheckAllocatedType(AllocType, TypeRange.getBegin(), TypeRange))
return ExprError();
- if (initStyle == CXXNewExpr::ListInit &&
- isStdInitializerList(AllocType, nullptr)) {
- Diag(AllocTypeInfo->getTypeLoc().getBeginLoc(),
- diag::warn_dangling_std_initializer_list)
- << /*at end of FE*/0 << Inits[0]->getSourceRange();
- }
-
// In ARC, infer 'retaining' for the allocated
if (getLangOpts().ObjCAutoRefCount &&
AllocType.getObjCLifetime() == Qualifiers::OCL_None &&
@@ -1831,7 +1893,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
assert(Context.getTargetInfo().getIntWidth() && "Builtin type of size 0?");
ConvertedSize = PerformImplicitConversion(ArraySize, Context.getSizeType(),
- AA_Converting);
+ AA_Converting);
if (!ConvertedSize.isInvalid() &&
ArraySize->getType()->getAs<RecordType>())
@@ -1960,11 +2022,12 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
bool PassAlignment = getLangOpts().AlignedAllocation &&
Alignment > NewAlignment;
+ AllocationFunctionScope Scope = UseGlobal ? AFS_Global : AFS_Both;
if (!AllocType->isDependentType() &&
!Expr::hasAnyTypeDependentArguments(PlacementArgs) &&
FindAllocationFunctions(StartLoc,
SourceRange(PlacementLParen, PlacementRParen),
- UseGlobal, AllocType, ArraySize, PassAlignment,
+ Scope, Scope, AllocType, ArraySize, PassAlignment,
PlacementArgs, OperatorNew, OperatorDelete))
return ExprError();
@@ -2099,7 +2162,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
Range, DirectInitRange);
}
-/// \brief Checks that a type is suitable as the allocated type
+/// Checks that a type is suitable as the allocated type
/// in a new-expression.
bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc,
SourceRange R) {
@@ -2120,7 +2183,8 @@ bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc,
else if (AllocType->isVariablyModifiedType())
return Diag(Loc, diag::err_variably_modified_new_type)
<< AllocType;
- else if (AllocType.getAddressSpace() != LangAS::Default)
+ else if (AllocType.getAddressSpace() != LangAS::Default &&
+ !getLangOpts().OpenCLCPlusPlus)
return Diag(Loc, diag::err_address_space_qualified_new)
<< AllocType.getUnqualifiedType()
<< AllocType.getQualifiers().getAddressSpaceAttributePrintValue();
@@ -2137,12 +2201,10 @@ bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc,
return false;
}
-static bool
-resolveAllocationOverload(Sema &S, LookupResult &R, SourceRange Range,
- SmallVectorImpl<Expr *> &Args, bool &PassAlignment,
- FunctionDecl *&Operator,
- OverloadCandidateSet *AlignedCandidates = nullptr,
- Expr *AlignArg = nullptr) {
+static bool resolveAllocationOverload(
+ Sema &S, LookupResult &R, SourceRange Range, SmallVectorImpl<Expr *> &Args,
+ bool &PassAlignment, FunctionDecl *&Operator,
+ OverloadCandidateSet *AlignedCandidates, Expr *AlignArg, bool Diagnose) {
OverloadCandidateSet Candidates(R.getNameLoc(),
OverloadCandidateSet::CSK_Normal);
for (LookupResult::iterator Alloc = R.begin(), AllocEnd = R.end();
@@ -2188,7 +2250,8 @@ resolveAllocationOverload(Sema &S, LookupResult &R, SourceRange Range,
AlignArg = Args[1];
Args.erase(Args.begin() + 1);
return resolveAllocationOverload(S, R, Range, Args, PassAlignment,
- Operator, &Candidates, AlignArg);
+ Operator, &Candidates, AlignArg,
+ Diagnose);
}
// MSVC will fall back on trying to find a matching global operator new
@@ -2204,67 +2267,72 @@ resolveAllocationOverload(Sema &S, LookupResult &R, SourceRange Range,
S.LookupQualifiedName(R, S.Context.getTranslationUnitDecl());
// FIXME: This will give bad diagnostics pointing at the wrong functions.
return resolveAllocationOverload(S, R, Range, Args, PassAlignment,
- Operator, nullptr);
+ Operator, /*Candidates=*/nullptr,
+ /*AlignArg=*/nullptr, Diagnose);
}
- S.Diag(R.getNameLoc(), diag::err_ovl_no_viable_function_in_call)
- << R.getLookupName() << Range;
-
- // If we have aligned candidates, only note the align_val_t candidates
- // from AlignedCandidates and the non-align_val_t candidates from
- // Candidates.
- if (AlignedCandidates) {
- auto IsAligned = [](OverloadCandidate &C) {
- return C.Function->getNumParams() > 1 &&
- C.Function->getParamDecl(1)->getType()->isAlignValT();
- };
- auto IsUnaligned = [&](OverloadCandidate &C) { return !IsAligned(C); };
-
- // This was an overaligned allocation, so list the aligned candidates
- // first.
- Args.insert(Args.begin() + 1, AlignArg);
- AlignedCandidates->NoteCandidates(S, OCD_AllCandidates, Args, "",
- R.getNameLoc(), IsAligned);
- Args.erase(Args.begin() + 1);
- Candidates.NoteCandidates(S, OCD_AllCandidates, Args, "", R.getNameLoc(),
- IsUnaligned);
- } else {
- Candidates.NoteCandidates(S, OCD_AllCandidates, Args);
+ if (Diagnose) {
+ S.Diag(R.getNameLoc(), diag::err_ovl_no_viable_function_in_call)
+ << R.getLookupName() << Range;
+
+ // If we have aligned candidates, only note the align_val_t candidates
+ // from AlignedCandidates and the non-align_val_t candidates from
+ // Candidates.
+ if (AlignedCandidates) {
+ auto IsAligned = [](OverloadCandidate &C) {
+ return C.Function->getNumParams() > 1 &&
+ C.Function->getParamDecl(1)->getType()->isAlignValT();
+ };
+ auto IsUnaligned = [&](OverloadCandidate &C) { return !IsAligned(C); };
+
+ // This was an overaligned allocation, so list the aligned candidates
+ // first.
+ Args.insert(Args.begin() + 1, AlignArg);
+ AlignedCandidates->NoteCandidates(S, OCD_AllCandidates, Args, "",
+ R.getNameLoc(), IsAligned);
+ Args.erase(Args.begin() + 1);
+ Candidates.NoteCandidates(S, OCD_AllCandidates, Args, "", R.getNameLoc(),
+ IsUnaligned);
+ } else {
+ Candidates.NoteCandidates(S, OCD_AllCandidates, Args);
+ }
}
return true;
case OR_Ambiguous:
- S.Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call)
- << R.getLookupName() << Range;
- Candidates.NoteCandidates(S, OCD_ViableCandidates, Args);
+ if (Diagnose) {
+ S.Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call)
+ << R.getLookupName() << Range;
+ Candidates.NoteCandidates(S, OCD_ViableCandidates, Args);
+ }
return true;
case OR_Deleted: {
- S.Diag(R.getNameLoc(), diag::err_ovl_deleted_call)
- << Best->Function->isDeleted()
- << R.getLookupName()
- << S.getDeletedOrUnavailableSuffix(Best->Function)
- << Range;
- Candidates.NoteCandidates(S, OCD_AllCandidates, Args);
+ if (Diagnose) {
+ S.Diag(R.getNameLoc(), diag::err_ovl_deleted_call)
+ << Best->Function->isDeleted() << R.getLookupName()
+ << S.getDeletedOrUnavailableSuffix(Best->Function) << Range;
+ Candidates.NoteCandidates(S, OCD_AllCandidates, Args);
+ }
return true;
}
}
llvm_unreachable("Unreachable, bad result from BestViableFunction");
}
-
-/// FindAllocationFunctions - Finds the overloads of operator new and delete
-/// that are appropriate for the allocation.
bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
- bool UseGlobal, QualType AllocType,
- bool IsArray, bool &PassAlignment,
- MultiExprArg PlaceArgs,
+ AllocationFunctionScope NewScope,
+ AllocationFunctionScope DeleteScope,
+ QualType AllocType, bool IsArray,
+ bool &PassAlignment, MultiExprArg PlaceArgs,
FunctionDecl *&OperatorNew,
- FunctionDecl *&OperatorDelete) {
+ FunctionDecl *&OperatorDelete,
+ bool Diagnose) {
// --- Choosing an allocation function ---
// C++ 5.3.4p8 - 14 & 18
- // 1) If UseGlobal is true, only look in the global scope. Else, also look
- // in the scope of the allocated class.
+ // 1) If looking in AFS_Global scope for allocation functions, only look in
+ // the global scope. Else, if AFS_Class, only look in the scope of the
+ // allocated class. If AFS_Both, look in both.
// 2) If an array size is given, look for operator new[], else look for
// operator new.
// 3) The first argument is always size_t. Append the arguments from the
@@ -2314,7 +2382,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
// function's name is looked up in the global scope. Otherwise, if the
// allocated type is a class type T or array thereof, the allocation
// function's name is looked up in the scope of T.
- if (AllocElemType->isRecordType() && !UseGlobal)
+ if (AllocElemType->isRecordType() && NewScope != AFS_Global)
LookupQualifiedName(R, AllocElemType->getAsCXXRecordDecl());
// We can see ambiguity here if the allocation function is found in
@@ -2325,8 +2393,17 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
// If this lookup fails to find the name, or if the allocated type is not
// a class type, the allocation function's name is looked up in the
// global scope.
- if (R.empty())
+ if (R.empty()) {
+ if (NewScope == AFS_Class)
+ return true;
+
LookupQualifiedName(R, Context.getTranslationUnitDecl());
+ }
+
+ if (getLangOpts().OpenCLCPlusPlus && R.empty()) {
+ Diag(StartLoc, diag::err_openclcxx_not_supported) << "default new";
+ return true;
+ }
assert(!R.empty() && "implicitly declared allocation functions not found");
assert(!R.isAmbiguous() && "global allocation functions are ambiguous");
@@ -2335,7 +2412,8 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
R.suppressDiagnostics();
if (resolveAllocationOverload(*this, R, Range, AllocArgs, PassAlignment,
- OperatorNew))
+ OperatorNew, /*Candidates=*/nullptr,
+ /*AlignArg=*/nullptr, Diagnose))
return true;
}
@@ -2362,7 +2440,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
// the allocated type is not a class type or array thereof, the
// deallocation function's name is looked up in the global scope.
LookupResult FoundDelete(*this, DeleteName, StartLoc, LookupOrdinaryName);
- if (AllocElemType->isRecordType() && !UseGlobal) {
+ if (AllocElemType->isRecordType() && DeleteScope != AFS_Global) {
CXXRecordDecl *RD
= cast<CXXRecordDecl>(AllocElemType->getAs<RecordType>()->getDecl());
LookupQualifiedName(FoundDelete, RD);
@@ -2372,6 +2450,9 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
bool FoundGlobalDelete = FoundDelete.empty();
if (FoundDelete.empty()) {
+ if (DeleteScope == AFS_Class)
+ return true;
+
DeclareGlobalNewDelete();
LookupQualifiedName(FoundDelete, Context.getTranslationUnitDecl());
}
@@ -2559,6 +2640,11 @@ void Sema::DeclareGlobalNewDelete() {
if (GlobalNewDeleteDeclared)
return;
+ // OpenCL C++ 1.0 s2.9: the implicitly declared new and delete operators
+ // are not supported.
+ if (getLangOpts().OpenCLCPlusPlus)
+ return;
+
// C++ [basic.std.dynamic]p2:
// [...] The following allocation and deallocation functions (18.4) are
// implicitly declared in global scope in each translation unit of a
@@ -2845,7 +2931,7 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
}
namespace {
-/// \brief Checks whether delete-expression, and new-expression used for
+/// Checks whether delete-expression, and new-expression used for
/// initializing deletee have the same array form.
class MismatchingNewDeleteDetector {
public:
@@ -2868,7 +2954,7 @@ public:
: Field(nullptr), IsArrayForm(false), EndOfTU(EndOfTU),
HasUndefinedConstructors(false) {}
- /// \brief Checks whether pointee of a delete-expression is initialized with
+ /// Checks whether pointee of a delete-expression is initialized with
/// matching form of new-expression.
///
/// If return value is \c VarInitMismatches or \c MemberInitMismatches at the
@@ -2879,7 +2965,7 @@ public:
/// couldn't be analyzed. If at least one constructor initializes the member
/// with matching type of new, the return value is \c NoMismatch.
MismatchResult analyzeDeleteExpr(const CXXDeleteExpr *DE);
- /// \brief Analyzes a class member.
+ /// Analyzes a class member.
/// \param Field Class member to analyze.
/// \param DeleteWasArrayForm Array form-ness of the delete-expression used
/// for deleting the \p Field.
@@ -2892,13 +2978,13 @@ public:
private:
const bool EndOfTU;
- /// \brief Indicates that there is at least one constructor without body.
+ /// Indicates that there is at least one constructor without body.
bool HasUndefinedConstructors;
- /// \brief Returns \c CXXNewExpr from given initialization expression.
+ /// Returns \c CXXNewExpr from given initialization expression.
/// \param E Expression used for initializing pointee in delete-expression.
/// E can be a single-element \c InitListExpr consisting of new-expression.
const CXXNewExpr *getNewExprFromInitListOrExpr(const Expr *E);
- /// \brief Returns whether member is initialized with mismatching form of
+ /// Returns whether member is initialized with mismatching form of
/// \c new either by the member initializer or in-class initialization.
///
/// If bodies of all constructors are not visible at the end of translation
@@ -2906,7 +2992,7 @@ private:
/// form of \c new, mismatch cannot be proven, and this function will return
/// \c NoMismatch.
MismatchResult analyzeMemberExpr(const MemberExpr *ME);
- /// \brief Returns whether variable is initialized with mismatching form of
+ /// Returns whether variable is initialized with mismatching form of
/// \c new.
///
/// If variable is initialized with matching form of \c new or variable is not
@@ -2914,7 +3000,7 @@ private:
/// If variable is initialized with mismatching form of \c new, returns false.
/// \param D Variable to analyze.
bool hasMatchingVarInit(const DeclRefExpr *D);
- /// \brief Checks whether the constructor initializes pointee with mismatching
+ /// Checks whether the constructor initializes pointee with mismatching
/// form of \c new.
///
/// Returns true, if member is initialized with matching form of \c new in
@@ -2923,7 +3009,7 @@ private:
/// constructor isn't defined at the point where delete-expression is seen, or
/// member isn't initialized by the constructor.
bool hasMatchingNewInCtor(const CXXConstructorDecl *CD);
- /// \brief Checks whether member is initialized with matching form of
+ /// Checks whether member is initialized with matching form of
/// \c new in member initializer list.
bool hasMatchingNewInCtorInit(const CXXCtorInitializer *CI);
/// Checks whether member is initialized with mismatching form of \c new by
@@ -3192,7 +3278,8 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
QualType Pointee = Type->getAs<PointerType>()->getPointeeType();
QualType PointeeElem = Context.getBaseElementType(Pointee);
- if (Pointee.getAddressSpace() != LangAS::Default)
+ if (Pointee.getAddressSpace() != LangAS::Default &&
+ !getLangOpts().OpenCLCPlusPlus)
return Diag(Ex.get()->getLocStart(),
diag::err_address_space_qualified_delete)
<< Pointee.getUnqualifiedType()
@@ -3267,6 +3354,11 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
}
if (!OperatorDelete) {
+ if (getLangOpts().OpenCLCPlusPlus) {
+ Diag(StartLoc, diag::err_openclcxx_not_supported) << "default delete";
+ return ExprError();
+ }
+
bool IsComplete = isCompleteType(StartLoc, Pointee);
bool CanProvideSize =
IsComplete && (!ArrayForm || UsualArrayDeleteWantsSize ||
@@ -3322,6 +3414,128 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
return Result;
}
+static bool resolveBuiltinNewDeleteOverload(Sema &S, CallExpr *TheCall,
+ bool IsDelete,
+ FunctionDecl *&Operator) {
+
+ DeclarationName NewName = S.Context.DeclarationNames.getCXXOperatorName(
+ IsDelete ? OO_Delete : OO_New);
+
+ LookupResult R(S, NewName, TheCall->getLocStart(), 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");
+
+ // We do our own custom access checks below.
+ R.suppressDiagnostics();
+
+ SmallVector<Expr *, 8> Args(TheCall->arg_begin(), TheCall->arg_end());
+ OverloadCandidateSet Candidates(R.getNameLoc(),
+ OverloadCandidateSet::CSK_Normal);
+ for (LookupResult::iterator FnOvl = R.begin(), FnOvlEnd = R.end();
+ FnOvl != FnOvlEnd; ++FnOvl) {
+ // Even member operator new/delete are implicitly treated as
+ // static, so don't use AddMemberCandidate.
+ NamedDecl *D = (*FnOvl)->getUnderlyingDecl();
+
+ if (FunctionTemplateDecl *FnTemplate = dyn_cast<FunctionTemplateDecl>(D)) {
+ S.AddTemplateOverloadCandidate(FnTemplate, FnOvl.getPair(),
+ /*ExplicitTemplateArgs=*/nullptr, Args,
+ Candidates,
+ /*SuppressUserConversions=*/false);
+ continue;
+ }
+
+ FunctionDecl *Fn = cast<FunctionDecl>(D);
+ S.AddOverloadCandidate(Fn, FnOvl.getPair(), Args, Candidates,
+ /*SuppressUserConversions=*/false);
+ }
+
+ SourceRange Range = TheCall->getSourceRange();
+
+ // Do the resolution.
+ OverloadCandidateSet::iterator Best;
+ switch (Candidates.BestViableFunction(S, R.getNameLoc(), Best)) {
+ case OR_Success: {
+ // Got one!
+ FunctionDecl *FnDecl = Best->Function;
+ assert(R.getNamingClass() == nullptr &&
+ "class members should not be considered");
+
+ if (!FnDecl->isReplaceableGlobalAllocationFunction()) {
+ S.Diag(R.getNameLoc(), diag::err_builtin_operator_new_delete_not_usual)
+ << (IsDelete ? 1 : 0) << Range;
+ S.Diag(FnDecl->getLocation(), diag::note_non_usual_function_declared_here)
+ << R.getLookupName() << FnDecl->getSourceRange();
+ return true;
+ }
+
+ Operator = FnDecl;
+ return false;
+ }
+
+ case OR_No_Viable_Function:
+ S.Diag(R.getNameLoc(), diag::err_ovl_no_viable_function_in_call)
+ << R.getLookupName() << Range;
+ Candidates.NoteCandidates(S, OCD_AllCandidates, Args);
+ return true;
+
+ case OR_Ambiguous:
+ S.Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call)
+ << R.getLookupName() << Range;
+ Candidates.NoteCandidates(S, OCD_ViableCandidates, Args);
+ return true;
+
+ case OR_Deleted: {
+ S.Diag(R.getNameLoc(), diag::err_ovl_deleted_call)
+ << Best->Function->isDeleted() << R.getLookupName()
+ << S.getDeletedOrUnavailableSuffix(Best->Function) << Range;
+ Candidates.NoteCandidates(S, OCD_AllCandidates, Args);
+ return true;
+ }
+ }
+ llvm_unreachable("Unreachable, bad result from BestViableFunction");
+}
+
+ExprResult
+Sema::SemaBuiltinOperatorNewDeleteOverloaded(ExprResult TheCallResult,
+ bool IsDelete) {
+ CallExpr *TheCall = cast<CallExpr>(TheCallResult.get());
+ if (!getLangOpts().CPlusPlus) {
+ Diag(TheCall->getExprLoc(), diag::err_builtin_requires_language)
+ << (IsDelete ? "__builtin_operator_delete" : "__builtin_operator_new")
+ << "C++";
+ return ExprError();
+ }
+ // CodeGen assumes it can find the global new and delete to call,
+ // so ensure that they are declared.
+ DeclareGlobalNewDelete();
+
+ FunctionDecl *OperatorNewOrDelete = nullptr;
+ if (resolveBuiltinNewDeleteOverload(*this, TheCall, IsDelete,
+ OperatorNewOrDelete))
+ return ExprError();
+ assert(OperatorNewOrDelete && "should be found");
+
+ 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));
+ if (Arg.isInvalid())
+ return ExprError();
+ TheCall->setArg(i, Arg.get());
+ }
+ auto Callee = dyn_cast<ImplicitCastExpr>(TheCall->getCallee());
+ assert(Callee && Callee->getCastKind() == CK_BuiltinFnToFnPtr &&
+ "Callee expected to be implicit cast to a builtin function pointer");
+ Callee->setType(OperatorNewOrDelete->getType());
+
+ return TheCallResult;
+}
+
void Sema::CheckVirtualDtorCall(CXXDestructorDecl *dtor, SourceLocation Loc,
bool IsDelete, bool CallCanBeVirtual,
bool WarnOnNonAbstractTypes,
@@ -3378,7 +3592,7 @@ Sema::ConditionResult Sema::ActOnConditionVariable(Decl *ConditionVar,
CK == ConditionKind::ConstexprIf);
}
-/// \brief Check the use of the given variable as a C++ condition in an if,
+/// Check the use of the given variable as a C++ condition in an if,
/// while, do-while, or switch statement.
ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar,
SourceLocation StmtLoc,
@@ -3548,6 +3762,10 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
const ImplicitConversionSequence &ICS,
AssignmentAction Action,
CheckedConversionKind CCK) {
+ // C++ [over.match.oper]p7: [...] operands of class type are converted [...]
+ if (CCK == CCK_ForBuiltinOverloadedOp && !From->getType()->isRecordType())
+ return From;
+
switch (ICS.getKind()) {
case ImplicitConversionSequence::StandardConversion: {
ExprResult Res = PerformImplicitConversion(From, ToType, ICS.Standard,
@@ -3607,6 +3825,12 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
From = CastArg.get();
+ // C++ [over.match.oper]p7:
+ // [...] the second standard conversion sequence of a user-defined
+ // conversion sequence is not applied.
+ if (CCK == CCK_ForBuiltinOverloadedOp)
+ return From;
+
return PerformImplicitConversion(From, ToType, ICS.UserDefined.After,
AA_Converting, CCK);
}
@@ -4070,14 +4294,14 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
// If this conversion sequence succeeded and involved implicitly converting a
// _Nullable type to a _Nonnull one, complain.
- if (CCK == CCK_ImplicitConversion)
+ if (!isCast(CCK))
diagnoseNullableToNonnullConversion(ToType, InitialFromType,
From->getLocStart());
return From;
}
-/// \brief Check the completeness of a type in a unary type trait.
+/// Check the completeness of a type in a unary type trait.
///
/// If the particular type trait requires a complete type, tries to complete
/// it. If completing the type fails, a diagnostic is emitted and false
@@ -4227,7 +4451,7 @@ static bool HasNoThrowOperator(const RecordType *RT, OverloadedOperatorKind Op,
const FunctionProtoType *CPT =
Operator->getType()->getAs<FunctionProtoType>();
CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
- if (!CPT || !CPT->isNothrow(C))
+ if (!CPT || !CPT->isNothrow())
return false;
}
}
@@ -4475,7 +4699,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
const FunctionProtoType *CPT =
Destructor->getType()->getAs<FunctionProtoType>();
CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
- if (!CPT || !CPT->isNothrow(C))
+ if (!CPT || !CPT->isNothrow())
return false;
}
}
@@ -4568,7 +4792,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
return false;
// TODO: check whether evaluating default arguments can throw.
// For now, we'll be conservative and assume that they can throw.
- if (!CPT->isNothrow(C) || CPT->getNumParams() > 1)
+ if (!CPT->isNothrow() || CPT->getNumParams() > 1)
return false;
}
}
@@ -4607,7 +4831,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
return false;
// FIXME: check whether evaluating default arguments can throw.
// For now, we'll be conservative and assume that they can throw.
- if (!CPT->isNothrow(C) || CPT->getNumParams() > 0)
+ if (!CPT->isNothrow() || CPT->getNumParams() > 0)
return false;
}
}
@@ -4645,11 +4869,14 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
if (Kind <= UTT_Last)
return EvaluateUnaryTypeTrait(S, Kind, KWLoc, Args[0]->getType());
- if (Kind <= BTT_Last)
+ // Evaluate BTT_ReferenceBindsToTemporary alongside the IsConstructible
+ // traits to avoid duplication.
+ if (Kind <= BTT_Last && Kind != BTT_ReferenceBindsToTemporary)
return EvaluateBinaryTypeTrait(S, Kind, Args[0]->getType(),
Args[1]->getType(), RParenLoc);
switch (Kind) {
+ case clang::BTT_ReferenceBindsToTemporary:
case clang::TT_IsConstructible:
case clang::TT_IsNothrowConstructible:
case clang::TT_IsTriviallyConstructible: {
@@ -4726,6 +4953,13 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
if (Kind == clang::TT_IsConstructible)
return true;
+ if (Kind == clang::BTT_ReferenceBindsToTemporary) {
+ if (!T->isReferenceType())
+ return false;
+
+ return !Init.isDirectReferenceBinding();
+ }
+
if (Kind == clang::TT_IsNothrowConstructible)
return S.canThrow(Result.get()) == CT_Cannot;
@@ -5231,8 +5465,9 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS,
case RQ_LValue:
if (!isIndirect && !LHS.get()->Classify(Context).isLValue()) {
- // C++2a allows functions with ref-qualifier & if they are also 'const'.
- if (Proto->isConst())
+ // C++2a allows functions with ref-qualifier & if their cv-qualifier-seq
+ // is (exactly) 'const'.
+ if (Proto->isConst() && !Proto->isVolatile())
Diag(Loc, getLangOpts().CPlusPlus2a
? diag::warn_cxx17_compat_pointer_to_const_ref_member_on_rvalue
: diag::ext_pointer_to_const_ref_member_on_rvalue);
@@ -5269,7 +5504,7 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS,
return Result;
}
-/// \brief Try to convert a type to another according to C++11 5.16p3.
+/// Try to convert a type to another according to C++11 5.16p3.
///
/// This is part of the parameter validation for the ? operator. If either
/// value operand is a class type, the two operands are attempted to be
@@ -5294,7 +5529,7 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To,
// constraint that in the conversion the reference must bind directly to
// an lvalue.
// -- If E2 is an xvalue: E1 can be converted to match E2 if E1 can be
- // implicitly conveted to the type "rvalue reference to R2", subject to
+ // implicitly converted to the type "rvalue reference to R2", subject to
// the constraint that the reference must bind directly.
if (To->isLValue() || To->isXValue()) {
QualType T = To->isLValue() ? Self.Context.getLValueReferenceType(ToType)
@@ -5363,7 +5598,7 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To,
return false;
}
-/// \brief Try to find a common type for two according to C++0x 5.16p5.
+/// Try to find a common type for two according to C++0x 5.16p5.
///
/// This is part of the parameter validation for the ? operator. If either
/// value operand is a class type, overload resolution is used to find a
@@ -5425,7 +5660,7 @@ static bool FindConditionalOverload(Sema &Self, ExprResult &LHS, ExprResult &RHS
return true;
}
-/// \brief Perform an "extended" implicit conversion as returned by
+/// Perform an "extended" implicit conversion as returned by
/// TryClassUnification.
static bool ConvertForConditional(Sema &Self, ExprResult &E, QualType T) {
InitializedEntity Entity = InitializedEntity::InitializeTemporary(T);
@@ -5441,7 +5676,7 @@ static bool ConvertForConditional(Sema &Self, ExprResult &E, QualType T) {
return false;
}
-/// \brief Check the operands of ?: under C++ semantics.
+/// Check the operands of ?: under C++ semantics.
///
/// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y
/// extension. In this case, LHS == Cond. (But they're not aliases.)
@@ -5745,27 +5980,23 @@ mergeExceptionSpecs(Sema &S, FunctionProtoType::ExceptionSpecInfo ESI1,
if (EST2 == EST_None) return ESI2;
if (EST1 == EST_MSAny) return ESI1;
if (EST2 == EST_MSAny) return ESI2;
+ if (EST1 == EST_NoexceptFalse) return ESI1;
+ if (EST2 == EST_NoexceptFalse) return ESI2;
// If either of them is non-throwing, the result is the other.
if (EST1 == EST_DynamicNone) return ESI2;
if (EST2 == EST_DynamicNone) return ESI1;
if (EST1 == EST_BasicNoexcept) return ESI2;
if (EST2 == EST_BasicNoexcept) return ESI1;
+ if (EST1 == EST_NoexceptTrue) return ESI2;
+ if (EST2 == EST_NoexceptTrue) return ESI1;
- // If either of them is a non-value-dependent computed noexcept, that
- // determines the result.
- if (EST2 == EST_ComputedNoexcept && ESI2.NoexceptExpr &&
- !ESI2.NoexceptExpr->isValueDependent())
- return !ESI2.NoexceptExpr->EvaluateKnownConstInt(S.Context) ? ESI2 : ESI1;
- if (EST1 == EST_ComputedNoexcept && ESI1.NoexceptExpr &&
- !ESI1.NoexceptExpr->isValueDependent())
- return !ESI1.NoexceptExpr->EvaluateKnownConstInt(S.Context) ? ESI1 : ESI2;
// If we're left with value-dependent computed noexcept expressions, we're
// stuck. Before C++17, we can just drop the exception specification entirely,
// since it's not actually part of the canonical type. And this should never
// happen in C++17, because it would mean we were computing the composite
// pointer type of dependent types, which should never happen.
- if (EST1 == EST_ComputedNoexcept || EST2 == EST_ComputedNoexcept) {
+ if (EST1 == EST_DependentNoexcept || EST2 == EST_DependentNoexcept) {
assert(!S.getLangOpts().CPlusPlus17 &&
"computing composite pointer type of dependent types");
return FunctionProtoType::ExceptionSpecInfo();
@@ -5778,7 +6009,9 @@ mergeExceptionSpecs(Sema &S, FunctionProtoType::ExceptionSpecInfo ESI1,
case EST_DynamicNone:
case EST_MSAny:
case EST_BasicNoexcept:
- case EST_ComputedNoexcept:
+ case EST_DependentNoexcept:
+ case EST_NoexceptFalse:
+ case EST_NoexceptTrue:
llvm_unreachable("handled above");
case EST_Dynamic: {
@@ -5805,7 +6038,7 @@ mergeExceptionSpecs(Sema &S, FunctionProtoType::ExceptionSpecInfo ESI1,
llvm_unreachable("invalid ExceptionSpecificationType");
}
-/// \brief Find a merged pointer type and convert the two expressions to it.
+/// Find a merged pointer type and convert the two expressions to it.
///
/// This finds the composite pointer type (or member pointer type) for @p E1
/// and @p E2 according to C++1z 5p14. It converts both expressions to this
@@ -6195,7 +6428,8 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) {
if (RD->isInvalidDecl() || RD->isDependentContext())
return E;
- bool IsDecltype = ExprEvalContexts.back().IsDecltype;
+ bool IsDecltype = ExprEvalContexts.back().ExprContext ==
+ ExpressionEvaluationContextRecord::EK_Decltype;
CXXDestructorDecl *Destructor = IsDecltype ? nullptr : LookupDestructor(RD);
if (Destructor) {
@@ -6277,7 +6511,9 @@ Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) {
/// are omitted for the 'topmost' call in the decltype expression. If the
/// topmost call bound a temporary, strip that temporary off the expression.
ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
- assert(ExprEvalContexts.back().IsDecltype && "not in a decltype expression");
+ assert(ExprEvalContexts.back().ExprContext ==
+ ExpressionEvaluationContextRecord::EK_Decltype &&
+ "not in a decltype expression");
// C++11 [expr.call]p11:
// If a function call is a prvalue of object type,
@@ -6319,7 +6555,8 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
TopBind = nullptr;
// Disable the special decltype handling now.
- ExprEvalContexts.back().IsDecltype = false;
+ ExprEvalContexts.back().ExprContext =
+ ExpressionEvaluationContextRecord::EK_Other;
// In MS mode, don't perform any extra checking of call return types within a
// decltype expression.
@@ -6572,7 +6809,7 @@ static bool CheckArrow(Sema& S, QualType& ObjectType, Expr *&Base,
return false;
}
-/// \brief Check if it's ok to try and recover dot pseudo destructor calls on
+/// Check if it's ok to try and recover dot pseudo destructor calls on
/// pointer objects.
static bool
canRecoverDotPseudoDestructorCallsOnPointerObjects(Sema &SemaRef,
@@ -6877,10 +7114,17 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,
CXXConversionDecl *Method,
bool HadMultipleCandidates) {
+ // Convert the expression to match the conversion function's implicit object
+ // parameter.
+ ExprResult Exp = PerformObjectArgumentInitialization(E, /*Qualifier=*/nullptr,
+ FoundDecl, Method);
+ if (Exp.isInvalid())
+ return true;
+
if (Method->getParent()->isLambda() &&
Method->getConversionType()->isBlockPointerType()) {
// This is a lambda coversion to block pointer; check if the argument
- // is a LambdaExpr.
+ // was a LambdaExpr.
Expr *SubE = E;
CastExpr *CE = dyn_cast<CastExpr>(SubE);
if (CE && CE->getCastKind() == CK_NoOp)
@@ -6897,22 +7141,16 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,
DiagnosticErrorTrap Trap(Diags);
PushExpressionEvaluationContext(
ExpressionEvaluationContext::PotentiallyEvaluated);
- ExprResult Exp = BuildBlockForLambdaConversion(E->getExprLoc(),
- E->getExprLoc(),
- Method, E);
+ ExprResult BlockExp = BuildBlockForLambdaConversion(
+ Exp.get()->getExprLoc(), Exp.get()->getExprLoc(), Method, Exp.get());
PopExpressionEvaluationContext();
- if (Exp.isInvalid())
- Diag(E->getExprLoc(), diag::note_lambda_to_block_conv);
- return Exp;
+ if (BlockExp.isInvalid())
+ Diag(Exp.get()->getExprLoc(), diag::note_lambda_to_block_conv);
+ return BlockExp;
}
}
- ExprResult Exp = PerformObjectArgumentInitialization(E, /*Qualifier=*/nullptr,
- FoundDecl, Method);
- if (Exp.isInvalid())
- return true;
-
MemberExpr *ME = new (Context) MemberExpr(
Exp.get(), /*IsArrow=*/false, SourceLocation(), Method, SourceLocation(),
Context.BoundMemberTy, VK_RValue, OK_Ordinary);
@@ -7123,7 +7361,7 @@ static inline bool VariableCanNeverBeAConstantExpression(VarDecl *Var,
return !IsVariableAConstantExpression(Var, Context);
}
-/// \brief Check if the current lambda has any potential captures
+/// Check if the current lambda has any potential captures
/// that must be captured by any of its enclosing lambdas that are ready to
/// capture. If there is a lambda that can capture a nested
/// potential-capture, go ahead and do so. Also, check to see if any
@@ -7146,9 +7384,6 @@ static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(
const bool IsFullExprInstantiationDependent = FE->isInstantiationDependent();
- ArrayRef<const FunctionScopeInfo *> FunctionScopesArrayRef(
- S.FunctionScopes.data(), S.FunctionScopes.size());
-
// All the potentially captureable variables in the current nested
// lambda (within a generic outer lambda), must be captured by an
// outer lambda that is enclosed within a non-dependent context.
@@ -7177,7 +7412,7 @@ static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(
// capture the variable in that lambda (and all its enclosing lambdas).
if (const Optional<unsigned> Index =
getStackIndexOfNearestEnclosingCaptureCapableLambda(
- FunctionScopesArrayRef, Var, S)) {
+ S.FunctionScopes, Var, S)) {
const unsigned FunctionScopeIndexOfCapturableLambda = Index.getValue();
MarkVarDeclODRUsed(Var, VarExpr->getExprLoc(), S,
&FunctionScopeIndexOfCapturableLambda);
@@ -7213,7 +7448,7 @@ static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(
// 'this' in that lambda (and all its enclosing lambdas).
if (const Optional<unsigned> Index =
getStackIndexOfNearestEnclosingCaptureCapableLambda(
- FunctionScopesArrayRef, /*0 is 'this'*/ nullptr, S)) {
+ S.FunctionScopes, /*0 is 'this'*/ nullptr, S)) {
const unsigned FunctionScopeIndexOfCapturableLambda = Index.getValue();
S.CheckCXXThisCapture(CurrentLSI->PotentialThisCaptureLocation,
/*Explicit*/ false, /*BuildAndDiagnose*/ true,
@@ -7306,13 +7541,12 @@ class TransformTypos : public TreeTransform<TransformTypos> {
llvm::SmallDenseMap<TypoExpr *, ExprResult, 2> TransformCache;
llvm::SmallDenseMap<OverloadExpr *, Expr *, 4> OverloadResolution;
- /// \brief Emit diagnostics for all of the TypoExprs encountered.
+ /// Emit diagnostics for all of the TypoExprs encountered.
/// If the TypoExprs were successfully corrected, then the diagnostics should
/// suggest the corrections. Otherwise the diagnostics will not suggest
/// anything (having been passed an empty TypoCorrection).
void EmitAllDiagnostics() {
- for (auto E : TypoExprs) {
- TypoExpr *TE = cast<TypoExpr>(E);
+ for (TypoExpr *TE : TypoExprs) {
auto &State = SemaRef.getTypoExprState(TE);
if (State.DiagHandler) {
TypoCorrection TC = State.Consumer->getCurrentCorrection();
@@ -7333,7 +7567,7 @@ class TransformTypos : public TreeTransform<TransformTypos> {
}
}
- /// \brief If corrections for the first TypoExpr have been exhausted for a
+ /// If corrections for the first TypoExpr have been exhausted for a
/// given combination of the other TypoExprs, retry those corrections against
/// the next combination of substitutions for the other TypoExprs by advancing
/// to the next potential correction of the second TypoExpr. For the second
@@ -7504,12 +7738,8 @@ Sema::CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl,
if (E && !ExprEvalContexts.empty() && ExprEvalContexts.back().NumTypos &&
(E->isTypeDependent() || E->isValueDependent() ||
E->isInstantiationDependent())) {
- auto TyposInContext = ExprEvalContexts.back().NumTypos;
- assert(TyposInContext < ~0U && "Recursive call of CorrectDelayedTyposInExpr");
- ExprEvalContexts.back().NumTypos = ~0U;
auto TyposResolved = DelayedTypos.size();
auto Result = TransformTypos(*this, InitDecl, Filter).Transform(E);
- ExprEvalContexts.back().NumTypos = TyposInContext;
TyposResolved -= DelayedTypos.size();
if (Result.isInvalid() || Result.get() != E) {
ExprEvalContexts.back().NumTypos -= TyposResolved;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp
index f57f79e62efe..3a8fee862c91 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp
@@ -640,6 +640,7 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
const RecordType *RTy,
SourceLocation OpLoc, bool IsArrow,
CXXScopeSpec &SS, bool HasTemplateArgs,
+ SourceLocation TemplateKWLoc,
TypoExpr *&TE) {
SourceRange BaseRange = BaseExpr ? BaseExpr->getSourceRange() : SourceRange();
RecordDecl *RDecl = RTy->getDecl();
@@ -649,13 +650,13 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
BaseRange))
return true;
- if (HasTemplateArgs) {
+ if (HasTemplateArgs || TemplateKWLoc.isValid()) {
// LookupTemplateName doesn't expect these both to exist simultaneously.
QualType ObjectType = SS.isSet() ? QualType() : QualType(RTy, 0);
bool MOUS;
- SemaRef.LookupTemplateName(R, nullptr, SS, ObjectType, false, MOUS);
- return false;
+ return SemaRef.LookupTemplateName(R, nullptr, SS, ObjectType, false, MOUS,
+ TemplateKWLoc);
}
DeclContext *DC = RDecl;
@@ -733,7 +734,8 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
ExprResult &BaseExpr, bool &IsArrow,
SourceLocation OpLoc, CXXScopeSpec &SS,
- Decl *ObjCImpDecl, bool HasTemplateArgs);
+ Decl *ObjCImpDecl, bool HasTemplateArgs,
+ SourceLocation TemplateKWLoc);
ExprResult
Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
@@ -759,9 +761,9 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
TypoExpr *TE = nullptr;
QualType RecordTy = BaseType;
if (IsArrow) RecordTy = RecordTy->getAs<PointerType>()->getPointeeType();
- if (LookupMemberExprInRecord(*this, R, nullptr,
- RecordTy->getAs<RecordType>(), OpLoc, IsArrow,
- SS, TemplateArgs != nullptr, TE))
+ if (LookupMemberExprInRecord(
+ *this, R, nullptr, RecordTy->getAs<RecordType>(), OpLoc, IsArrow,
+ SS, TemplateArgs != nullptr, TemplateKWLoc, TE))
return ExprError();
if (TE)
return TE;
@@ -769,10 +771,10 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
// Explicit member accesses.
} else {
ExprResult BaseResult = Base;
- ExprResult Result = LookupMemberExpr(
- *this, R, BaseResult, IsArrow, OpLoc, SS,
- ExtraArgs ? ExtraArgs->ObjCImpDecl : nullptr,
- TemplateArgs != nullptr);
+ ExprResult Result =
+ LookupMemberExpr(*this, R, BaseResult, IsArrow, OpLoc, SS,
+ ExtraArgs ? ExtraArgs->ObjCImpDecl : nullptr,
+ TemplateArgs != nullptr, TemplateKWLoc);
if (BaseResult.isInvalid())
return ExprError();
@@ -802,16 +804,13 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
Expr *baseObjectExpr,
SourceLocation opLoc) {
// First, build the expression that refers to the base object.
-
- bool baseObjectIsPointer = false;
- Qualifiers baseQuals;
-
+
// Case 1: the base of the indirect field is not a field.
VarDecl *baseVariable = indirectField->getVarDecl();
CXXScopeSpec EmptySS;
if (baseVariable) {
assert(baseVariable->getType()->isRecordType());
-
+
// In principle we could have a member access expression that
// accesses an anonymous struct/union that's a static member of
// the base object's class. However, under the current standard,
@@ -824,68 +823,37 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
ExprResult result
= BuildDeclarationNameExpr(EmptySS, baseNameInfo, baseVariable);
if (result.isInvalid()) return ExprError();
-
- baseObjectExpr = result.get();
- baseObjectIsPointer = false;
- baseQuals = baseObjectExpr->getType().getQualifiers();
-
- // Case 2: the base of the indirect field is a field and the user
- // wrote a member expression.
- } else if (baseObjectExpr) {
- // The caller provided the base object expression. Determine
- // whether its a pointer and whether it adds any qualifiers to the
- // anonymous struct/union fields we're looking into.
- QualType objectType = baseObjectExpr->getType();
-
- if (const PointerType *ptr = objectType->getAs<PointerType>()) {
- baseObjectIsPointer = true;
- objectType = ptr->getPointeeType();
- } else {
- baseObjectIsPointer = false;
- }
- baseQuals = objectType.getQualifiers();
-
- // Case 3: the base of the indirect field is a field and we should
- // build an implicit member access.
- } else {
- // We've found a member of an anonymous struct/union that is
- // inside a non-anonymous struct/union, so in a well-formed
- // program our base object expression is "this".
- QualType ThisTy = getCurrentThisType();
- if (ThisTy.isNull()) {
- Diag(loc, diag::err_invalid_member_use_in_static_method)
- << indirectField->getDeclName();
- return ExprError();
- }
-
- // Our base object expression is "this".
- CheckCXXThisCapture(loc);
- baseObjectExpr
- = new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/ true);
- baseObjectIsPointer = true;
- baseQuals = ThisTy->castAs<PointerType>()->getPointeeType().getQualifiers();
+
+ baseObjectExpr = result.get();
}
-
+
+ assert((baseVariable || baseObjectExpr) &&
+ "referencing anonymous struct/union without a base variable or "
+ "expression");
+
// Build the implicit member references to the field of the
// anonymous struct/union.
Expr *result = baseObjectExpr;
IndirectFieldDecl::chain_iterator
FI = indirectField->chain_begin(), FEnd = indirectField->chain_end();
-
- // Build the first member access in the chain with full information.
+
+ // Case 2: the base of the indirect field is a field and the user
+ // wrote a member expression.
if (!baseVariable) {
FieldDecl *field = cast<FieldDecl>(*FI);
-
+
+ bool baseObjectIsPointer = baseObjectExpr->getType()->isPointerType();
+
// Make a nameInfo that properly uses the anonymous name.
DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
- result = BuildFieldReferenceExpr(result, baseObjectIsPointer,
- SourceLocation(), EmptySS, field,
- foundDecl, memberNameInfo).get();
+ // Build the first member access in the chain with full information.
+ result =
+ BuildFieldReferenceExpr(result, baseObjectIsPointer, SourceLocation(),
+ SS, field, foundDecl, memberNameInfo)
+ .get();
if (!result)
return ExprError();
-
- // FIXME: check qualified member access
}
// In all cases, we should now skip the first declaration in the chain.
@@ -922,7 +890,7 @@ BuildMSPropertyRefExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
NameInfo.getLoc());
}
-/// \brief Build a MemberExpr AST node.
+/// Build a MemberExpr AST node.
static MemberExpr *BuildMemberExpr(
Sema &SemaRef, ASTContext &C, Expr *Base, bool isArrow,
SourceLocation OpLoc, const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
@@ -937,7 +905,7 @@ static MemberExpr *BuildMemberExpr(
return E;
}
-/// \brief Determine if the given scope is within a function-try-block handler.
+/// Determine if the given scope is within a function-try-block handler.
static bool IsInFnTryBlockHandler(const Scope *S) {
// Walk the scope stack until finding a FnTryCatchScope, or leave the
// function scope. If a FnTryCatchScope is found, check whether the TryScope
@@ -954,16 +922,12 @@ getVarTemplateSpecialization(Sema &S, VarTemplateDecl *VarTempl,
const TemplateArgumentListInfo *TemplateArgs,
const DeclarationNameInfo &MemberNameInfo,
SourceLocation TemplateKWLoc) {
-
if (!TemplateArgs) {
- S.Diag(MemberNameInfo.getBeginLoc(), diag::err_template_decl_ref)
- << /*Variable template*/ 1 << MemberNameInfo.getName()
- << MemberNameInfo.getSourceRange();
-
- S.Diag(VarTempl->getLocation(), diag::note_template_decl_here);
-
+ S.diagnoseMissingTemplateArguments(TemplateName(VarTempl),
+ MemberNameInfo.getBeginLoc());
return nullptr;
}
+
DeclResult VDecl = S.CheckVarTemplateId(
VarTempl, TemplateKWLoc, MemberNameInfo.getLoc(), *TemplateArgs);
if (VDecl.isInvalid())
@@ -1264,7 +1228,8 @@ Sema::PerformMemberExprBaseConversion(Expr *Base, bool IsArrow) {
static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
ExprResult &BaseExpr, bool &IsArrow,
SourceLocation OpLoc, CXXScopeSpec &SS,
- Decl *ObjCImpDecl, bool HasTemplateArgs) {
+ Decl *ObjCImpDecl, bool HasTemplateArgs,
+ SourceLocation TemplateKWLoc) {
assert(BaseExpr.get() && "no base expression");
// Perform default conversions.
@@ -1314,8 +1279,8 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
// Handle field access to simple records.
if (const RecordType *RTy = BaseType->getAs<RecordType>()) {
TypoExpr *TE = nullptr;
- if (LookupMemberExprInRecord(S, R, BaseExpr.get(), RTy,
- OpLoc, IsArrow, SS, HasTemplateArgs, TE))
+ if (LookupMemberExprInRecord(S, R, BaseExpr.get(), RTy, OpLoc, IsArrow, SS,
+ HasTemplateArgs, TemplateKWLoc, TE))
return ExprError();
// Returning valid-but-null is how we indicate to the caller that
@@ -1353,7 +1318,7 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
OpLoc, S.Context.getObjCClassType());
if (ShouldTryAgainWithRedefinitionType(S, BaseExpr))
return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
- ObjCImpDecl, HasTemplateArgs);
+ ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
goto fail;
}
@@ -1479,8 +1444,9 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
IsArrow);
if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
- if (!S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, MemberLoc))
- S.recordUseOfEvaluatedWeak(Result);
+ if (!S.isUnevaluatedContext() &&
+ !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, MemberLoc))
+ S.getCurFunction()->recordUseOfWeak(Result);
}
return Result;
@@ -1524,9 +1490,6 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
}
if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(PMDecl)) {
- // Check the use of this method.
- if (S.DiagnoseUseOfDecl(OMD, MemberLoc))
- return ExprError();
Selector SetterSel =
SelectorTable::constructSetterSelector(S.PP.getIdentifierTable(),
S.PP.getSelectorTable(),
@@ -1546,7 +1509,7 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
// use the 'id' redefinition in this case.
if (IsArrow && ShouldTryAgainWithRedefinitionType(S, BaseExpr))
return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
- ObjCImpDecl, HasTemplateArgs);
+ ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
return ExprError(S.Diag(MemberLoc, diag::err_property_not_found)
<< MemberName << BaseType);
@@ -1559,7 +1522,7 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
if (!MD) {
if (ShouldTryAgainWithRedefinitionType(S, BaseExpr))
return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
- ObjCImpDecl, HasTemplateArgs);
+ ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
goto fail;
}
@@ -1567,6 +1530,9 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
// Also must look for a getter name which uses property syntax.
Selector Sel = S.PP.getSelectorTable().getNullarySelector(Member);
ObjCInterfaceDecl *IFace = MD->getClassInterface();
+ if (!IFace)
+ goto fail;
+
ObjCMethodDecl *Getter;
if ((Getter = IFace->lookupClassMethod(Sel))) {
// Check the use of this method.
@@ -1598,7 +1564,7 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
if (ShouldTryAgainWithRedefinitionType(S, BaseExpr))
return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
- ObjCImpDecl, HasTemplateArgs);
+ ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
return ExprError(S.Diag(MemberLoc, diag::err_property_not_found)
<< MemberName << BaseType);
@@ -1623,10 +1589,14 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
else
VK = BaseExpr.get()->getValueKind();
}
+
QualType ret = CheckExtVectorComponent(S, BaseType, VK, OpLoc,
Member, MemberLoc);
if (ret.isNull())
return ExprError();
+ Qualifiers BaseQ =
+ S.Context.getCanonicalType(BaseExpr.get()->getType()).getQualifiers();
+ ret = S.Context.getQualifiedType(ret, BaseQ);
return new (S.Context)
ExtVectorElementExpr(ret, VK, BaseExpr.get(), *Member, MemberLoc);
@@ -1639,7 +1609,7 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
BaseExpr = S.ImpCastExprToType(
BaseExpr.get(), S.Context.getObjCSelRedefinitionType(), CK_BitCast);
return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
- ObjCImpDecl, HasTemplateArgs);
+ ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
}
// Failure cases.
@@ -1662,7 +1632,7 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
// Recurse as an -> access.
IsArrow = true;
return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
- ObjCImpDecl, HasTemplateArgs);
+ ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
}
}
@@ -1676,7 +1646,7 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
return ExprError();
BaseExpr = S.DefaultFunctionArrayConversion(BaseExpr.get());
return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
- ObjCImpDecl, HasTemplateArgs);
+ ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
}
S.Diag(OpLoc, diag::err_typecheck_member_reference_struct_union)
@@ -1805,7 +1775,7 @@ Sema::BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow,
if (getLangOpts().OpenMP && IsArrow &&
!CurContext->isDependentContext() &&
isa<CXXThisExpr>(Base.get()->IgnoreParenImpCasts())) {
- if (auto *PrivateCopy = IsOpenMPCapturedDecl(Field)) {
+ if (auto *PrivateCopy = isOpenMPCapturedDecl(Field)) {
return getOpenMPCapturedExpr(PrivateCopy, VK, OK,
MemberNameInfo.getLoc());
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
index cd0c2c47ae4c..bf0ffeba06b2 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
@@ -141,7 +141,7 @@ ExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){
return new (Context) ObjCStringLiteral(S, Ty, AtLoc);
}
-/// \brief Emits an error if the given method does not exist, or if the return
+/// Emits an error if the given method does not exist, or if the return
/// type is not an Objective-C object.
static bool validateBoxingMethod(Sema &S, SourceLocation Loc,
const ObjCInterfaceDecl *Class,
@@ -165,7 +165,7 @@ static bool validateBoxingMethod(Sema &S, SourceLocation Loc,
return true;
}
-/// \brief Maps ObjCLiteralKind to NSClassIdKindKind
+/// Maps ObjCLiteralKind to NSClassIdKindKind
static NSAPI::NSClassIdKindKind ClassKindFromLiteralKind(
Sema::ObjCLiteralKind LiteralKind) {
switch (LiteralKind) {
@@ -189,7 +189,7 @@ static NSAPI::NSClassIdKindKind ClassKindFromLiteralKind(
llvm_unreachable("LiteralKind can't be converted into a ClassKind");
}
-/// \brief Validates ObjCInterfaceDecl availability.
+/// Validates ObjCInterfaceDecl availability.
/// ObjCInterfaceDecl, used to create ObjC literals, should be defined
/// if clang not in a debugger mode.
static bool ValidateObjCLiteralInterfaceDecl(Sema &S, ObjCInterfaceDecl *Decl,
@@ -211,7 +211,7 @@ static bool ValidateObjCLiteralInterfaceDecl(Sema &S, ObjCInterfaceDecl *Decl,
return true;
}
-/// \brief Looks up ObjCInterfaceDecl of a given NSClassIdKindKind.
+/// Looks up ObjCInterfaceDecl of a given NSClassIdKindKind.
/// Used to create ObjC literals, such as NSDictionary (@{}),
/// NSArray (@[]) and Boxed Expressions (@())
static ObjCInterfaceDecl *LookupObjCInterfaceDeclForLiteral(Sema &S,
@@ -236,7 +236,7 @@ static ObjCInterfaceDecl *LookupObjCInterfaceDeclForLiteral(Sema &S,
return ID;
}
-/// \brief Retrieve the NSNumber factory method that should be used to create
+/// Retrieve the NSNumber factory method that should be used to create
/// an Objective-C literal for the given type.
static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
QualType NumberType,
@@ -379,7 +379,7 @@ ExprResult Sema::ActOnObjCBoolLiteral(SourceLocation AtLoc,
return BuildObjCNumericLiteral(AtLoc, Inner.get());
}
-/// \brief Check that the given expression is a valid element of an Objective-C
+/// Check that the given expression is a valid element of an Objective-C
/// collection literal.
static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,
QualType T,
@@ -1357,6 +1357,11 @@ QualType Sema::getMessageSendResultType(QualType ReceiverType,
if (isClassMessage)
return resultType;
+ // There is nothing left to do if the result type cannot have a nullability
+ // specifier.
+ if (!resultType->canHaveNullability())
+ return resultType;
+
// Map the nullability of the result into a table index.
unsigned receiverNullabilityIdx = 0;
if (auto nullability = ReceiverType->getNullability(Context))
@@ -1613,6 +1618,11 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
ParmVarDecl *param = Method->parameters()[i];
assert(argExpr && "CheckMessageArgumentTypes(): missing expression");
+ if (param->hasAttr<NoEscapeAttr>())
+ if (auto *BE = dyn_cast<BlockExpr>(
+ argExpr->IgnoreParenNoopCasts(Context)))
+ BE->getBlockDecl()->setDoesNotEscape();
+
// Strip the unbridged-cast placeholder expression off unless it's
// a consumed argument.
if (argExpr->hasPlaceholderType(BuiltinType::ARCUnbridgedCast) &&
@@ -2319,7 +2329,7 @@ static void checkFoundationAPI(Sema &S, SourceLocation Loc,
}
}
-/// \brief Diagnose use of %s directive in an NSString which is being passed
+/// Diagnose use of %s directive in an NSString which is being passed
/// as formatting string to formatting method.
static void
DiagnoseCStringFormatDirectiveInObjCAPI(Sema &S,
@@ -2358,7 +2368,7 @@ DiagnoseCStringFormatDirectiveInObjCAPI(Sema &S,
}
}
-/// \brief Build an Objective-C class message expression.
+/// Build an Objective-C class message expression.
///
/// This routine takes care of both normal class messages and
/// class messages to the superclass.
@@ -2403,11 +2413,12 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
<< FixItHint::CreateInsertion(Loc, "[");
LBracLoc = Loc;
}
- SourceLocation SelLoc;
+ ArrayRef<SourceLocation> SelectorSlotLocs;
if (!SelectorLocs.empty() && SelectorLocs.front().isValid())
- SelLoc = SelectorLocs.front();
+ SelectorSlotLocs = SelectorLocs;
else
- SelLoc = Loc;
+ SelectorSlotLocs = Loc;
+ SourceLocation SelLoc = SelectorSlotLocs.front();
if (ReceiverType->isDependentType()) {
// If the receiver type is dependent, we can't type-check anything
@@ -2432,7 +2443,7 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
assert(Class && "We don't know which class we're messaging?");
// objc++ diagnoses during typename annotation.
if (!getLangOpts().CPlusPlus)
- (void)DiagnoseUseOfDecl(Class, SelLoc);
+ (void)DiagnoseUseOfDecl(Class, SelectorSlotLocs);
// Find the method we are messaging.
if (!Method) {
SourceRange TypeRange
@@ -2457,7 +2468,7 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
if (!Method)
Method = Class->lookupPrivateClassMethod(Sel);
- if (Method && DiagnoseUseOfDecl(Method, SelLoc))
+ if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs))
return ExprError();
}
@@ -2581,7 +2592,7 @@ static bool isMethodDeclaredInRootProtocol(Sema &S, const ObjCMethodDecl *M) {
return false;
}
-/// \brief Build an Objective-C instance message expression.
+/// Build an Objective-C instance message expression.
///
/// This routine takes care of both normal instance messages and
/// instance messages to the superclass instance.
@@ -2627,11 +2638,12 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart();
SourceRange RecRange =
SuperLoc.isValid()? SuperLoc : Receiver->getSourceRange();
- SourceLocation SelLoc;
+ ArrayRef<SourceLocation> SelectorSlotLocs;
if (!SelectorLocs.empty() && SelectorLocs.front().isValid())
- SelLoc = SelectorLocs.front();
+ SelectorSlotLocs = SelectorLocs;
else
- SelLoc = Loc;
+ SelectorSlotLocs = Loc;
+ SourceLocation SelLoc = SelectorSlotLocs.front();
if (LBracLoc.isInvalid()) {
Diag(Loc, diag::err_missing_open_square_message_send)
@@ -2743,7 +2755,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
if (!AreMultipleMethodsInGlobalPool(Sel, Method,
SourceRange(LBracLoc, RBracLoc),
receiverIsIdLike, Methods))
- DiagnoseUseOfDecl(Method, SelLoc);
+ DiagnoseUseOfDecl(Method, SelectorSlotLocs);
}
} else if (ReceiverType->isObjCClassOrClassKindOfType() ||
ReceiverType->isObjCQualifiedClassType()) {
@@ -2775,7 +2787,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
if (!Method)
Method = ClassDecl->lookupPrivateClassMethod(Sel);
}
- if (Method && DiagnoseUseOfDecl(Method, SelLoc))
+ if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs))
return ExprError();
}
if (!Method) {
@@ -2792,7 +2804,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
// to select a better one.
Method = Methods[0];
- // If we find an instance method, emit waring.
+ // If we find an instance method, emit warning.
if (Method->isInstanceMethod()) {
if (const ObjCInterfaceDecl *ID =
dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
@@ -2822,7 +2834,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
Method = LookupMethodInQualifiedType(Sel, QIdTy, true);
if (!Method)
Method = LookupMethodInQualifiedType(Sel, QIdTy, false);
- if (Method && DiagnoseUseOfDecl(Method, SelLoc))
+ if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs))
return ExprError();
} else if (const ObjCObjectPointerType *OCIType
= ReceiverType->getAsObjCInterfacePointerType()) {
@@ -2897,7 +2909,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
}
}
}
- if (Method && DiagnoseUseOfDecl(Method, SelLoc, forwardClass))
+ if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs, forwardClass))
return ExprError();
} else {
// Reject other random receiver types (e.g. structs).
@@ -3491,6 +3503,7 @@ static void addFixitForObjCARCConversion(Sema &S,
// We handle C-style and implicit casts here.
switch (CCK) {
case Sema::CCK_ImplicitConversion:
+ case Sema::CCK_ForBuiltinOverloadedOp:
case Sema::CCK_CStyleCast:
case Sema::CCK_OtherCast:
break;
@@ -3644,11 +3657,13 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
SourceLocation afterLParen = S.getLocForEndOfToken(castRange.getBegin());
SourceLocation noteLoc = afterLParen.isValid() ? afterLParen : loc;
+ unsigned convKindForDiag = Sema::isCast(CCK) ? 0 : 1;
+
// Bridge from an ARC type to a CF type.
if (castACTC == ACTC_retainable && isAnyRetainable(exprACTC)) {
S.Diag(loc, diag::err_arc_cast_requires_bridge)
- << unsigned(CCK == Sema::CCK_ImplicitConversion) // cast|implicit
+ << convKindForDiag
<< 2 // of C pointer type
<< castExprType
<< unsigned(castType->isBlockPointerType()) // to ObjC|block type
@@ -3690,7 +3705,7 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC)) {
bool br = S.isKnownName("CFBridgingRetain");
S.Diag(loc, diag::err_arc_cast_requires_bridge)
- << unsigned(CCK == Sema::CCK_ImplicitConversion) // cast|implicit
+ << convKindForDiag
<< unsigned(castExprType->isBlockPointerType()) // of ObjC|block type
<< castExprType
<< 2 // to C pointer type
@@ -3727,7 +3742,7 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
}
S.Diag(loc, diag::err_arc_mismatched_cast)
- << (CCK != Sema::CCK_ImplicitConversion)
+ << !convKindForDiag
<< srcKind << castExprType << castType
<< castRange << castExpr->getSourceRange();
}
@@ -4180,7 +4195,7 @@ Sema::CheckObjCConversion(SourceRange castRange, QualType castType,
if (exprACTC == ACTC_indirectRetainable && castACTC == ACTC_voidPtr)
return ACR_okay;
if (castACTC == ACTC_indirectRetainable && exprACTC == ACTC_voidPtr &&
- CCK != CCK_ImplicitConversion)
+ isCast(CCK))
return ACR_okay;
switch (ARCCastChecker(Context, exprACTC, castACTC, false).Visit(castExpr)) {
@@ -4205,8 +4220,7 @@ Sema::CheckObjCConversion(SourceRange castRange, QualType castType,
// If this is a non-implicit cast from id or block type to a
// CoreFoundation type, delay complaining in case the cast is used
// in an acceptable context.
- if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC) &&
- CCK != CCK_ImplicitConversion)
+ if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC) && isCast(CCK))
return ACR_unbridged;
// Issue a diagnostic about a missing @-sign when implicit casting a cstring
@@ -4276,9 +4290,9 @@ Expr *Sema::stripARCUnbridgedCast(Expr *e) {
} else if (UnaryOperator *uo = dyn_cast<UnaryOperator>(e)) {
assert(uo->getOpcode() == UO_Extension);
Expr *sub = stripARCUnbridgedCast(uo->getSubExpr());
- return new (Context) UnaryOperator(sub, UO_Extension, sub->getType(),
- sub->getValueKind(), sub->getObjectKind(),
- uo->getOperatorLoc());
+ return new (Context)
+ UnaryOperator(sub, UO_Extension, sub->getType(), sub->getValueKind(),
+ sub->getObjectKind(), uo->getOperatorLoc(), false);
} else if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
assert(!gse->isResultDependent());
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
index df64a33954fa..3ee5ec4a4929 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/Designator.h"
@@ -32,7 +33,7 @@ using namespace clang;
// Sema Initialization Checking
//===----------------------------------------------------------------------===//
-/// \brief Check whether T is compatible with a wide character type (wchar_t,
+/// Check whether T is compatible with a wide character type (wchar_t,
/// char16_t or char32_t).
static bool IsWideCharCompatible(QualType T, ASTContext &Context) {
if (Context.typesAreCompatible(Context.getWideCharType(), T))
@@ -49,10 +50,12 @@ enum StringInitFailureKind {
SIF_NarrowStringIntoWideChar,
SIF_WideStringIntoChar,
SIF_IncompatWideStringIntoWideChar,
+ SIF_UTF8StringIntoPlainChar,
+ SIF_PlainStringIntoUTF8Char,
SIF_Other
};
-/// \brief Check whether the array of type AT can be initialized by the Init
+/// Check whether the array of type AT can be initialized by the Init
/// expression by means of string initialization. Returns SIF_None if so,
/// otherwise returns a StringInitFailureKind that describes why the
/// initialization would not work.
@@ -77,12 +80,21 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT,
Context.getCanonicalType(AT->getElementType()).getUnqualifiedType();
switch (SL->getKind()) {
- case StringLiteral::Ascii:
case StringLiteral::UTF8:
+ // char8_t array can be initialized with a UTF-8 string.
+ if (ElemTy->isChar8Type())
+ return SIF_None;
+ LLVM_FALLTHROUGH;
+ case StringLiteral::Ascii:
// char array can be initialized with a narrow string.
// Only allow char x[] = "foo"; not char x[] = L"foo";
if (ElemTy->isCharType())
- return SIF_None;
+ return (SL->getKind() == StringLiteral::UTF8 &&
+ Context.getLangOpts().Char8)
+ ? SIF_UTF8StringIntoPlainChar
+ : SIF_None;
+ if (ElemTy->isChar8Type())
+ return SIF_PlainStringIntoUTF8Char;
if (IsWideCharCompatible(ElemTy, Context))
return SIF_NarrowStringIntoWideChar;
return SIF_Other;
@@ -94,7 +106,7 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT,
case StringLiteral::UTF16:
if (Context.typesAreCompatible(Context.Char16Ty, ElemTy))
return SIF_None;
- if (ElemTy->isCharType())
+ if (ElemTy->isCharType() || ElemTy->isChar8Type())
return SIF_WideStringIntoChar;
if (IsWideCharCompatible(ElemTy, Context))
return SIF_IncompatWideStringIntoWideChar;
@@ -102,7 +114,7 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT,
case StringLiteral::UTF32:
if (Context.typesAreCompatible(Context.Char32Ty, ElemTy))
return SIF_None;
- if (ElemTy->isCharType())
+ if (ElemTy->isCharType() || ElemTy->isChar8Type())
return SIF_WideStringIntoChar;
if (IsWideCharCompatible(ElemTy, Context))
return SIF_IncompatWideStringIntoWideChar;
@@ -110,7 +122,7 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT,
case StringLiteral::Wide:
if (Context.typesAreCompatible(Context.getWideCharType(), ElemTy))
return SIF_None;
- if (ElemTy->isCharType())
+ if (ElemTy->isCharType() || ElemTy->isChar8Type())
return SIF_WideStringIntoChar;
if (IsWideCharCompatible(ElemTy, Context))
return SIF_IncompatWideStringIntoWideChar;
@@ -206,7 +218,7 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT,
namespace {
-/// @brief Semantic checking for initializer lists.
+/// Semantic checking for initializer lists.
///
/// The InitListChecker class contains a set of routines that each
/// handle the initialization of a certain kind of entity, e.g.,
@@ -366,7 +378,7 @@ public:
bool TreatUnavailableAsInvalid);
bool HadError() { return hadError; }
- // @brief Retrieves the fully-structured initializer list used for
+ // Retrieves the fully-structured initializer list used for
// semantic analysis and code generation.
InitListExpr *getFullyStructuredList() const { return FullyStructuredList; }
};
@@ -561,6 +573,7 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
hadError = true;
return;
}
+ SemaRef.checkInitializerLifetime(MemberEntity, DIE.get());
if (Init < NumInits)
ILE->setInit(Init, DIE.get());
else {
@@ -740,6 +753,9 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
ElementEntity.getKind() == InitializedEntity::EK_VectorElement)
ElementEntity.setElementIndex(Init);
+ if (Init >= NumInits && ILE->hasArrayFiller())
+ return;
+
Expr *InitExpr = (Init < NumInits ? ILE->getInit(Init) : nullptr);
if (!InitExpr && Init < NumInits && ILE->hasArrayFiller())
ILE->setInit(Init, ILE->getArrayFiller());
@@ -1005,6 +1021,7 @@ static void warnBracedScalarInit(Sema &S, const InitializedEntity &Entity,
case InitializedEntity::EK_BlockElement:
case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
case InitializedEntity::EK_Binding:
+ case InitializedEntity::EK_StmtExprResult:
llvm_unreachable("unexpected braced scalar init");
}
@@ -2014,7 +2031,7 @@ void InitListChecker::CheckStructUnionTypes(
StructuredList, StructuredIndex);
}
-/// \brief Expand a field designator that refers to a member of an
+/// Expand a field designator that refers to a member of an
/// anonymous struct or union into a series of field designators that
/// refers to the field within the appropriate subobject.
///
@@ -2078,7 +2095,7 @@ class FieldInitializerValidatorCCC : public CorrectionCandidateCallback {
} // end anonymous namespace
-/// @brief Check the well-formedness of a C99 designated initializer.
+/// Check the well-formedness of a C99 designated initializer.
///
/// Determines whether the designated initializer @p DIE, which
/// resides at the given @p Index within the initializer list @p
@@ -2985,6 +3002,7 @@ DeclarationName InitializedEntity::getName() const {
return DeclarationName(Capture.VarID);
case EK_Result:
+ case EK_StmtExprResult:
case EK_Exception:
case EK_New:
case EK_Temporary:
@@ -3015,6 +3033,7 @@ ValueDecl *InitializedEntity::getDecl() const {
return reinterpret_cast<ParmVarDecl*>(Parameter & ~0x1);
case EK_Result:
+ case EK_StmtExprResult:
case EK_Exception:
case EK_New:
case EK_Temporary:
@@ -3040,6 +3059,7 @@ bool InitializedEntity::allowsNRVO() const {
case EK_Exception:
return LocAndNRVO.NRVO;
+ case EK_StmtExprResult:
case EK_Variable:
case EK_Parameter:
case EK_Parameter_CF_Audited:
@@ -3075,6 +3095,7 @@ unsigned InitializedEntity::dumpImpl(raw_ostream &OS) const {
case EK_Parameter_CF_Audited: OS << "CF audited function Parameter";
break;
case EK_Result: OS << "Result"; break;
+ case EK_StmtExprResult: OS << "StmtExprResult"; break;
case EK_Exception: OS << "Exception"; break;
case EK_Member: OS << "Member"; break;
case EK_Binding: OS << "Binding"; break;
@@ -3185,6 +3206,8 @@ bool InitializationSequence::isAmbiguous() const {
case FK_NarrowStringIntoWideCharArray:
case FK_WideStringIntoCharArray:
case FK_IncompatWideStringIntoWideChar:
+ case FK_PlainStringIntoUTF8Char:
+ case FK_UTF8StringIntoPlainChar:
case FK_AddressOfOverloadFailed: // FIXME: Could do better
case FK_NonConstLValueReferenceBindingToTemporary:
case FK_NonConstLValueReferenceBindingToBitfield:
@@ -3517,7 +3540,8 @@ static void MaybeProduceObjCObject(Sema &S,
/// retainable type, then returns need to immediately retain the
/// object. If an autorelease is required, it will be done at the
/// last instant.
- } else if (Entity.getKind() == InitializedEntity::EK_Result) {
+ } else if (Entity.getKind() == InitializedEntity::EK_Result ||
+ Entity.getKind() == InitializedEntity::EK_StmtExprResult) {
if (!Entity.getType()->isObjCRetainableType())
return;
@@ -3532,7 +3556,7 @@ static void TryListInitialization(Sema &S,
InitializationSequence &Sequence,
bool TreatUnavailableAsInvalid);
-/// \brief When initializing from init list via constructor, handle
+/// When initializing from init list via constructor, handle
/// initialization of an object of type std::initializer_list<T>.
///
/// \return true if we have handled initialization of an object of type
@@ -3558,8 +3582,8 @@ static bool TryInitializerListConstruction(Sema &S,
clang::ArrayType::Normal, 0);
InitializedEntity HiddenArray =
InitializedEntity::InitializeTemporary(ArrayType);
- InitializationKind Kind =
- InitializationKind::CreateDirectList(List->getExprLoc());
+ InitializationKind Kind = InitializationKind::CreateDirectList(
+ List->getExprLoc(), List->getLocStart(), List->getLocEnd());
TryListInitialization(S, HiddenArray, Kind, List, Sequence,
TreatUnavailableAsInvalid);
if (Sequence)
@@ -3693,7 +3717,7 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
return CandidateSet.BestViableFunction(S, DeclLoc, Best);
}
-/// \brief Attempt initialization by constructor (C++ [dcl.init]), which
+/// Attempt initialization by constructor (C++ [dcl.init]), which
/// enumerates the constructors of the initialized entity and performs overload
/// resolution to select the best.
/// \param DestType The destination class type.
@@ -3910,7 +3934,7 @@ static void TryValueInitialization(Sema &S,
InitializationSequence &Sequence,
InitListExpr *InitList = nullptr);
-/// \brief Attempt list initialization of a reference.
+/// Attempt list initialization of a reference.
static void TryReferenceListInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -3984,7 +4008,7 @@ static void TryReferenceListInitialization(Sema &S,
}
}
-/// \brief Attempt list initialization (C++0x [dcl.init.list])
+/// Attempt list initialization (C++0x [dcl.init.list])
static void TryListInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -4179,7 +4203,7 @@ static void TryListInitialization(Sema &S,
Sequence.AddListInitializationStep(DestType);
}
-/// \brief Try a reference initialization that involves calling a conversion
+/// Try a reference initialization that involves calling a conversion
/// function.
static OverloadingResult TryRefInitWithConversionFunction(
Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind,
@@ -4208,9 +4232,11 @@ static OverloadingResult TryRefInitWithConversionFunction(
OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
CandidateSet.clear(OverloadCandidateSet::CSK_InitByUserDefinedConversion);
- // Determine whether we are allowed to call explicit constructors or
- // explicit conversion operators.
- bool AllowExplicit = Kind.AllowExplicit();
+ // Determine whether we are allowed to call explicit conversion operators.
+ // Note that none of [over.match.copy], [over.match.conv], nor
+ // [over.match.ref] permit an explicit constructor to be chosen when
+ // initializing a reference, not even for direct-initialization.
+ bool AllowExplicitCtors = false;
bool AllowExplicitConvs = Kind.allowExplicitConversionFunctionsInRefBinding();
const RecordType *T1RecordType = nullptr;
@@ -4226,7 +4252,7 @@ static OverloadingResult TryRefInitWithConversionFunction(
continue;
if (!Info.Constructor->isInvalidDecl() &&
- Info.Constructor->isConvertingConstructor(AllowExplicit)) {
+ Info.Constructor->isConvertingConstructor(AllowExplicitCtors)) {
if (Info.ConstructorTmpl)
S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl,
/*ExplicitArgs*/ nullptr,
@@ -4369,7 +4395,7 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S,
const InitializedEntity &Entity,
Expr *CurInitExpr);
-/// \brief Attempt reference initialization (C++0x [dcl.init.ref])
+/// Attempt reference initialization (C++0x [dcl.init.ref])
static void TryReferenceInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -4396,13 +4422,13 @@ static void TryReferenceInitialization(Sema &S,
}
/// Determine whether an expression is a non-referenceable glvalue (one to
-/// which a reference can never bind). Attemting to bind a reference to
+/// which a reference can never bind). Attempting to bind a reference to
/// such a glvalue will always create a temporary.
static bool isNonReferenceableGLValue(Expr *E) {
return E->refersToBitField() || E->refersToVectorElement();
}
-/// \brief Reference initialization without resolving overloaded functions.
+/// Reference initialization without resolving overloaded functions.
static void TryReferenceInitializationCore(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -4662,7 +4688,7 @@ static void TryReferenceInitializationCore(Sema &S,
Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true);
}
-/// \brief Attempt character array initialization from a string literal
+/// Attempt character array initialization from a string literal
/// (C++ [dcl.init.string], C99 6.7.8).
static void TryStringLiteralInitialization(Sema &S,
const InitializedEntity &Entity,
@@ -4672,7 +4698,7 @@ static void TryStringLiteralInitialization(Sema &S,
Sequence.AddStringInitStep(Entity.getType());
}
-/// \brief Attempt value initialization (C++ [dcl.init]p7).
+/// Attempt value initialization (C++ [dcl.init]p7).
static void TryValueInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -4750,7 +4776,7 @@ static void TryValueInitialization(Sema &S,
Sequence.AddZeroInitializationStep(Entity.getType());
}
-/// \brief Attempt default initialization (C++ [dcl.init]p6).
+/// Attempt default initialization (C++ [dcl.init]p6).
static void TryDefaultInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -4789,7 +4815,7 @@ static void TryDefaultInitialization(Sema &S,
}
}
-/// \brief Attempt a user-defined conversion between two types (C++ [dcl.init]),
+/// Attempt a user-defined conversion between two types (C++ [dcl.init]),
/// which enumerates all conversion functions and performs overload resolution
/// to select the best.
static void TryUserDefinedConversion(Sema &S,
@@ -5068,7 +5094,7 @@ static void checkIndirectCopyRestoreSource(Sema &S, Expr *src) {
<< src->getSourceRange();
}
-/// \brief Determine whether we have compatible array types for the
+/// Determine whether we have compatible array types for the
/// purposes of GNU by-copy array initialization.
static bool hasCompatibleArrayTypes(ASTContext &Context, const ArrayType *Dest,
const ArrayType *Source) {
@@ -5362,6 +5388,12 @@ void InitializationSequence::InitializeFrom(Sema &S,
case SIF_IncompatWideStringIntoWideChar:
SetFailed(FK_IncompatWideStringIntoWideChar);
return;
+ case SIF_PlainStringIntoUTF8Char:
+ SetFailed(FK_PlainStringIntoUTF8Char);
+ return;
+ case SIF_UTF8StringIntoPlainChar:
+ SetFailed(FK_UTF8StringIntoPlainChar);
+ return;
case SIF_Other:
break;
}
@@ -5607,6 +5639,7 @@ getAssignmentAction(const InitializedEntity &Entity, bool Diagnose = false) {
return !Diagnose ? Sema::AA_Passing : Sema::AA_Passing_CFAudited;
case InitializedEntity::EK_Result:
+ case InitializedEntity::EK_StmtExprResult: // FIXME: Not quite right.
return Sema::AA_Returning;
case InitializedEntity::EK_Temporary:
@@ -5629,13 +5662,14 @@ getAssignmentAction(const InitializedEntity &Entity, bool Diagnose = false) {
llvm_unreachable("Invalid EntityKind!");
}
-/// \brief Whether we should bind a created object as a temporary when
+/// Whether we should bind a created object as a temporary when
/// initializing the given entity.
static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
switch (Entity.getKind()) {
case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_Member:
case InitializedEntity::EK_Result:
+ case InitializedEntity::EK_StmtExprResult:
case InitializedEntity::EK_New:
case InitializedEntity::EK_Variable:
case InitializedEntity::EK_Base:
@@ -5660,11 +5694,12 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
llvm_unreachable("missed an InitializedEntity kind?");
}
-/// \brief Whether the given entity, when initialized with an object
+/// Whether the given entity, when initialized with an object
/// created for that initialization, requires destruction.
static bool shouldDestroyEntity(const InitializedEntity &Entity) {
switch (Entity.getKind()) {
case InitializedEntity::EK_Result:
+ case InitializedEntity::EK_StmtExprResult:
case InitializedEntity::EK_New:
case InitializedEntity::EK_Base:
case InitializedEntity::EK_Delegating:
@@ -5691,11 +5726,12 @@ static bool shouldDestroyEntity(const InitializedEntity &Entity) {
llvm_unreachable("missed an InitializedEntity kind?");
}
-/// \brief Get the location at which initialization diagnostics should appear.
+/// Get the location at which initialization diagnostics should appear.
static SourceLocation getInitializationLoc(const InitializedEntity &Entity,
Expr *Initializer) {
switch (Entity.getKind()) {
case InitializedEntity::EK_Result:
+ case InitializedEntity::EK_StmtExprResult:
return Entity.getReturnLoc();
case InitializedEntity::EK_Exception:
@@ -5727,7 +5763,7 @@ static SourceLocation getInitializationLoc(const InitializedEntity &Entity,
llvm_unreachable("missed an InitializedEntity kind?");
}
-/// \brief Make a (potentially elidable) temporary copy of the object
+/// Make a (potentially elidable) temporary copy of the object
/// provided by the given initializer by calling the appropriate copy
/// constructor.
///
@@ -5892,7 +5928,7 @@ static ExprResult CopyObject(Sema &S,
return CurInit;
}
-/// \brief Check whether elidable copy construction for binding a reference to
+/// Check whether elidable copy construction for binding a reference to
/// a temporary would have succeeded if we were building in C++98 mode, for
/// -Wc++98-compat.
static void CheckCXX98CompatAccessibleCopy(Sema &S,
@@ -6056,10 +6092,7 @@ PerformConstructorInitialization(Sema &S,
TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo();
if (!TSInfo)
TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc);
- SourceRange ParenOrBraceRange =
- (Kind.getKind() == InitializationKind::IK_DirectList)
- ? SourceRange(LBraceLoc, RBraceLoc)
- : Kind.getParenRange();
+ SourceRange ParenOrBraceRange = Kind.getParenOrBraceRange();
if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(
Step.Function.FoundDecl.getDecl())) {
@@ -6093,7 +6126,7 @@ PerformConstructorInitialization(Sema &S,
if (IsListInitialization)
ParenOrBraceRange = SourceRange(LBraceLoc, RBraceLoc);
else if (Kind.getKind() == InitializationKind::IK_Direct)
- ParenOrBraceRange = Kind.getParenRange();
+ ParenOrBraceRange = Kind.getParenOrBraceRange();
// If the entity allows NRVO, mark the construction as elidable
// unconditionally.
@@ -6134,90 +6167,96 @@ PerformConstructorInitialization(Sema &S,
return CurInit;
}
-/// Determine whether the specified InitializedEntity definitely has a lifetime
-/// longer than the current full-expression. Conservatively returns false if
-/// it's unclear.
-static bool
-InitializedEntityOutlivesFullExpression(const InitializedEntity &Entity) {
- const InitializedEntity *Top = &Entity;
- while (Top->getParent())
- Top = Top->getParent();
-
- switch (Top->getKind()) {
- case InitializedEntity::EK_Variable:
- case InitializedEntity::EK_Result:
- case InitializedEntity::EK_Exception:
- case InitializedEntity::EK_Member:
- case InitializedEntity::EK_Binding:
- case InitializedEntity::EK_New:
- case InitializedEntity::EK_Base:
- case InitializedEntity::EK_Delegating:
- return true;
-
- case InitializedEntity::EK_ArrayElement:
- case InitializedEntity::EK_VectorElement:
- case InitializedEntity::EK_BlockElement:
- case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
- case InitializedEntity::EK_ComplexElement:
- // Could not determine what the full initialization is. Assume it might not
- // outlive the full-expression.
- return false;
-
- case InitializedEntity::EK_Parameter:
- case InitializedEntity::EK_Parameter_CF_Audited:
- case InitializedEntity::EK_Temporary:
- case InitializedEntity::EK_LambdaCapture:
- case InitializedEntity::EK_CompoundLiteralInit:
- case InitializedEntity::EK_RelatedResult:
- // The entity being initialized might not outlive the full-expression.
- return false;
- }
-
- llvm_unreachable("unknown entity kind");
+namespace {
+enum LifetimeKind {
+ /// The lifetime of a temporary bound to this entity ends at the end of the
+ /// full-expression, and that's (probably) fine.
+ LK_FullExpression,
+
+ /// The lifetime of a temporary bound to this entity is extended to the
+ /// lifeitme of the entity itself.
+ LK_Extended,
+
+ /// The lifetime of a temporary bound to this entity probably ends too soon,
+ /// because the entity is allocated in a new-expression.
+ LK_New,
+
+ /// The lifetime of a temporary bound to this entity ends too soon, because
+ /// the entity is a return object.
+ LK_Return,
+
+ /// The lifetime of a temporary bound to this entity ends too soon, because
+ /// the entity is the result of a statement expression.
+ LK_StmtExprResult,
+
+ /// This is a mem-initializer: if it would extend a temporary (other than via
+ /// a default member initializer), the program is ill-formed.
+ LK_MemInitializer,
+};
+using LifetimeResult =
+ llvm::PointerIntPair<const InitializedEntity *, 3, LifetimeKind>;
}
/// Determine the declaration which an initialized entity ultimately refers to,
/// for the purpose of lifetime-extending a temporary bound to a reference in
/// the initialization of \p Entity.
-static const InitializedEntity *getEntityForTemporaryLifetimeExtension(
+static LifetimeResult getEntityLifetime(
const InitializedEntity *Entity,
- const InitializedEntity *FallbackDecl = nullptr) {
+ const InitializedEntity *InitField = nullptr) {
// C++11 [class.temporary]p5:
switch (Entity->getKind()) {
case InitializedEntity::EK_Variable:
// The temporary [...] persists for the lifetime of the reference
- return Entity;
+ return {Entity, LK_Extended};
case InitializedEntity::EK_Member:
// For subobjects, we look at the complete object.
if (Entity->getParent())
- return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
- Entity);
+ return getEntityLifetime(Entity->getParent(), Entity);
// except:
- // -- A temporary bound to a reference member in a constructor's
- // ctor-initializer persists until the constructor exits.
- return Entity;
+ // C++17 [class.base.init]p8:
+ // A temporary expression bound to a reference member in a
+ // mem-initializer is ill-formed.
+ // C++17 [class.base.init]p11:
+ // A temporary expression bound to a reference member from a
+ // default member initializer is ill-formed.
+ //
+ // The context of p11 and its example suggest that it's only the use of a
+ // default member initializer from a constructor that makes the program
+ // ill-formed, not its mere existence, and that it can even be used by
+ // aggregate initialization.
+ return {Entity, Entity->isDefaultMemberInitializer() ? LK_Extended
+ : LK_MemInitializer};
case InitializedEntity::EK_Binding:
// Per [dcl.decomp]p3, the binding is treated as a variable of reference
// type.
- return Entity;
+ return {Entity, LK_Extended};
case InitializedEntity::EK_Parameter:
case InitializedEntity::EK_Parameter_CF_Audited:
// -- A temporary bound to a reference parameter in a function call
// persists until the completion of the full-expression containing
// the call.
+ return {nullptr, LK_FullExpression};
+
case InitializedEntity::EK_Result:
// -- The lifetime of a temporary bound to the returned value in a
// function return statement is not extended; the temporary is
// destroyed at the end of the full-expression in the return statement.
+ return {nullptr, LK_Return};
+
+ case InitializedEntity::EK_StmtExprResult:
+ // FIXME: Should we lifetime-extend through the result of a statement
+ // expression?
+ return {nullptr, LK_StmtExprResult};
+
case InitializedEntity::EK_New:
// -- A temporary bound to a reference in a new-initializer persists
// until the completion of the full-expression containing the
// new-initializer.
- return nullptr;
+ return {nullptr, LK_New};
case InitializedEntity::EK_Temporary:
case InitializedEntity::EK_CompoundLiteralInit:
@@ -6225,56 +6264,122 @@ static const InitializedEntity *getEntityForTemporaryLifetimeExtension(
// We don't yet know the storage duration of the surrounding temporary.
// Assume it's got full-expression duration for now, it will patch up our
// storage duration if that's not correct.
- return nullptr;
+ return {nullptr, LK_FullExpression};
case InitializedEntity::EK_ArrayElement:
// For subobjects, we look at the complete object.
- return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
- FallbackDecl);
+ return getEntityLifetime(Entity->getParent(), InitField);
case InitializedEntity::EK_Base:
// For subobjects, we look at the complete object.
if (Entity->getParent())
- return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
- Entity);
- LLVM_FALLTHROUGH;
+ return getEntityLifetime(Entity->getParent(), InitField);
+ return {InitField, LK_MemInitializer};
+
case InitializedEntity::EK_Delegating:
// We can reach this case for aggregate initialization in a constructor:
// struct A { int &&r; };
// struct B : A { B() : A{0} {} };
- // In this case, use the innermost field decl as the context.
- return FallbackDecl;
+ // In this case, use the outermost field decl as the context.
+ return {InitField, LK_MemInitializer};
case InitializedEntity::EK_BlockElement:
case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
case InitializedEntity::EK_LambdaCapture:
- case InitializedEntity::EK_Exception:
case InitializedEntity::EK_VectorElement:
case InitializedEntity::EK_ComplexElement:
- return nullptr;
+ return {nullptr, LK_FullExpression};
+
+ case InitializedEntity::EK_Exception:
+ // FIXME: Can we diagnose lifetime problems with exceptions?
+ return {nullptr, LK_FullExpression};
}
llvm_unreachable("unknown entity kind");
}
-static void performLifetimeExtension(Expr *Init,
- const InitializedEntity *ExtendingEntity);
+namespace {
+enum ReferenceKind {
+ /// Lifetime would be extended by a reference binding to a temporary.
+ RK_ReferenceBinding,
+ /// Lifetime would be extended by a std::initializer_list object binding to
+ /// its backing array.
+ RK_StdInitializerList,
+};
+
+/// A temporary or local variable. This will be one of:
+/// * A MaterializeTemporaryExpr.
+/// * A DeclRefExpr whose declaration is a local.
+/// * An AddrLabelExpr.
+/// * A BlockExpr for a block with captures.
+using Local = Expr*;
+
+/// Expressions we stepped over when looking for the local state. Any steps
+/// that would inhibit lifetime extension or take us out of subexpressions of
+/// the initializer are included.
+struct IndirectLocalPathEntry {
+ enum EntryKind {
+ DefaultInit,
+ AddressOf,
+ VarInit,
+ LValToRVal,
+ } Kind;
+ Expr *E;
+ Decl *D = nullptr;
+ IndirectLocalPathEntry() {}
+ IndirectLocalPathEntry(EntryKind K, Expr *E) : Kind(K), E(E) {}
+ IndirectLocalPathEntry(EntryKind K, Expr *E, Decl *D) : Kind(K), E(E), D(D) {}
+};
+
+using IndirectLocalPath = llvm::SmallVectorImpl<IndirectLocalPathEntry>;
+
+struct RevertToOldSizeRAII {
+ IndirectLocalPath &Path;
+ unsigned OldSize = Path.size();
+ RevertToOldSizeRAII(IndirectLocalPath &Path) : Path(Path) {}
+ ~RevertToOldSizeRAII() { Path.resize(OldSize); }
+};
+
+using LocalVisitor = llvm::function_ref<bool(IndirectLocalPath &Path, Local L,
+ ReferenceKind RK)>;
+}
+
+static bool isVarOnPath(IndirectLocalPath &Path, VarDecl *VD) {
+ for (auto E : Path)
+ if (E.Kind == IndirectLocalPathEntry::VarInit && E.D == VD)
+ return true;
+ return false;
+}
+
+static bool pathContainsInit(IndirectLocalPath &Path) {
+ return std::any_of(Path.begin(), Path.end(), [=](IndirectLocalPathEntry E) {
+ return E.Kind == IndirectLocalPathEntry::DefaultInit ||
+ E.Kind == IndirectLocalPathEntry::VarInit;
+ });
+}
+
+static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
+ Expr *Init, LocalVisitor Visit,
+ bool RevisitSubinits);
+
+/// Visit the locals that would be reachable through a reference bound to the
+/// glvalue expression \c Init.
+static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
+ Expr *Init, ReferenceKind RK,
+ LocalVisitor Visit) {
+ RevertToOldSizeRAII RAII(Path);
-/// Update a glvalue expression that is used as the initializer of a reference
-/// to note that its lifetime is extended.
-/// \return \c true if any temporary had its lifetime extended.
-static bool
-performReferenceExtension(Expr *Init,
- const InitializedEntity *ExtendingEntity) {
// Walk past any constructs which we can lifetime-extend across.
Expr *Old;
do {
Old = Init;
+ if (auto *EWC = dyn_cast<ExprWithCleanups>(Init))
+ Init = EWC->getSubExpr();
+
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
- if (ILE->getNumInits() == 1 && ILE->isGLValue()) {
- // This is just redundant braces around an initializer. Step over it.
+ // If this is just redundant braces around an initializer, step over it.
+ if (ILE->isTransparent())
Init = ILE->getInit(0);
- }
}
// Step over any subobject adjustments; we may have a materialized
@@ -6288,43 +6393,134 @@ performReferenceExtension(Expr *Init,
Init = CE->getSubExpr();
// Per the current approach for DR1299, look through array element access
- // when performing lifetime extension.
- if (auto *ASE = dyn_cast<ArraySubscriptExpr>(Init))
+ // on array glvalues when performing lifetime extension.
+ if (auto *ASE = dyn_cast<ArraySubscriptExpr>(Init)) {
Init = ASE->getBase();
+ auto *ICE = dyn_cast<ImplicitCastExpr>(Init);
+ if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay)
+ Init = ICE->getSubExpr();
+ else
+ // We can't lifetime extend through this but we might still find some
+ // retained temporaries.
+ return visitLocalsRetainedByInitializer(Path, Init, Visit, true);
+ }
+
+ // Step into CXXDefaultInitExprs so we can diagnose cases where a
+ // constructor inherits one as an implicit mem-initializer.
+ if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {
+ Path.push_back(
+ {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
+ Init = DIE->getExpr();
+ }
} while (Init != Old);
- if (MaterializeTemporaryExpr *ME = dyn_cast<MaterializeTemporaryExpr>(Init)) {
- // Update the storage duration of the materialized temporary.
- // FIXME: Rebuild the expression instead of mutating it.
- ME->setExtendingDecl(ExtendingEntity->getDecl(),
- ExtendingEntity->allocateManglingNumber());
- performLifetimeExtension(ME->GetTemporaryExpr(), ExtendingEntity);
- return true;
+ if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Init)) {
+ if (Visit(Path, Local(MTE), RK))
+ visitLocalsRetainedByInitializer(Path, MTE->GetTemporaryExpr(), Visit,
+ true);
+ }
+
+ switch (Init->getStmtClass()) {
+ case Stmt::DeclRefExprClass: {
+ // If we find the name of a local non-reference parameter, we could have a
+ // lifetime problem.
+ auto *DRE = cast<DeclRefExpr>(Init);
+ auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
+ if (VD && VD->hasLocalStorage() &&
+ !DRE->refersToEnclosingVariableOrCapture()) {
+ if (!VD->getType()->isReferenceType()) {
+ Visit(Path, Local(DRE), RK);
+ } else if (isa<ParmVarDecl>(DRE->getDecl())) {
+ // The lifetime of a reference parameter is unknown; assume it's OK
+ // for now.
+ break;
+ } else if (VD->getInit() && !isVarOnPath(Path, VD)) {
+ Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
+ visitLocalsRetainedByReferenceBinding(Path, VD->getInit(),
+ RK_ReferenceBinding, Visit);
+ }
+ }
+ break;
}
- return false;
+ case Stmt::UnaryOperatorClass: {
+ // The only unary operator that make sense to handle here
+ // is Deref. All others don't resolve to a "name." This includes
+ // handling all sorts of rvalues passed to a unary operator.
+ const UnaryOperator *U = cast<UnaryOperator>(Init);
+ if (U->getOpcode() == UO_Deref)
+ visitLocalsRetainedByInitializer(Path, U->getSubExpr(), Visit, true);
+ break;
+ }
+
+ case Stmt::OMPArraySectionExprClass: {
+ visitLocalsRetainedByInitializer(
+ Path, cast<OMPArraySectionExpr>(Init)->getBase(), Visit, true);
+ break;
+ }
+
+ case Stmt::ConditionalOperatorClass:
+ case Stmt::BinaryConditionalOperatorClass: {
+ auto *C = cast<AbstractConditionalOperator>(Init);
+ if (!C->getTrueExpr()->getType()->isVoidType())
+ visitLocalsRetainedByReferenceBinding(Path, C->getTrueExpr(), RK, Visit);
+ if (!C->getFalseExpr()->getType()->isVoidType())
+ visitLocalsRetainedByReferenceBinding(Path, C->getFalseExpr(), RK, Visit);
+ break;
+ }
+
+ // FIXME: Visit the left-hand side of an -> or ->*.
+
+ default:
+ break;
+ }
}
-/// Update a prvalue expression that is going to be materialized as a
-/// lifetime-extended temporary.
-static void performLifetimeExtension(Expr *Init,
- const InitializedEntity *ExtendingEntity) {
+/// Visit the locals that would be reachable through an object initialized by
+/// the prvalue expression \c Init.
+static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
+ Expr *Init, LocalVisitor Visit,
+ bool RevisitSubinits) {
+ RevertToOldSizeRAII RAII(Path);
+
+ // Step into CXXDefaultInitExprs so we can diagnose cases where a
+ // constructor inherits one as an implicit mem-initializer.
+ if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {
+ Path.push_back({IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
+ Init = DIE->getExpr();
+ }
+
+ if (auto *EWC = dyn_cast<ExprWithCleanups>(Init))
+ Init = EWC->getSubExpr();
+
// Dig out the expression which constructs the extended temporary.
Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
if (CXXBindTemporaryExpr *BTE = dyn_cast<CXXBindTemporaryExpr>(Init))
Init = BTE->getSubExpr();
- if (CXXStdInitializerListExpr *ILE =
- dyn_cast<CXXStdInitializerListExpr>(Init)) {
- performReferenceExtension(ILE->getSubExpr(), ExtendingEntity);
- return;
- }
+ // C++17 [dcl.init.list]p6:
+ // initializing an initializer_list object from the array extends the
+ // lifetime of the array exactly like binding a reference to a temporary.
+ if (auto *ILE = dyn_cast<CXXStdInitializerListExpr>(Init))
+ return visitLocalsRetainedByReferenceBinding(Path, ILE->getSubExpr(),
+ RK_StdInitializerList, Visit);
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
+ // We already visited the elements of this initializer list while
+ // performing the initialization. Don't visit them again unless we've
+ // changed the lifetime of the initialized entity.
+ if (!RevisitSubinits)
+ return;
+
+ if (ILE->isTransparent())
+ return visitLocalsRetainedByInitializer(Path, ILE->getInit(0), Visit,
+ RevisitSubinits);
+
if (ILE->getType()->isArrayType()) {
for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
- performLifetimeExtension(ILE->getInit(I), ExtendingEntity);
+ visitLocalsRetainedByInitializer(Path, ILE->getInit(I), Visit,
+ RevisitSubinits);
return;
}
@@ -6336,7 +6532,8 @@ static void performLifetimeExtension(Expr *Init,
// bound to temporaries, those temporaries are also lifetime-extended.
if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
- performReferenceExtension(ILE->getInit(0), ExtendingEntity);
+ visitLocalsRetainedByReferenceBinding(Path, ILE->getInit(0),
+ RK_ReferenceBinding, Visit);
else {
unsigned Index = 0;
for (const auto *I : RD->fields()) {
@@ -6346,51 +6543,365 @@ static void performLifetimeExtension(Expr *Init,
continue;
Expr *SubInit = ILE->getInit(Index);
if (I->getType()->isReferenceType())
- performReferenceExtension(SubInit, ExtendingEntity);
- else if (isa<InitListExpr>(SubInit) ||
- isa<CXXStdInitializerListExpr>(SubInit))
- // This may be either aggregate-initialization of a member or
- // initialization of a std::initializer_list object. Either way,
+ visitLocalsRetainedByReferenceBinding(Path, SubInit,
+ RK_ReferenceBinding, Visit);
+ else
+ // This might be either aggregate-initialization of a member or
+ // initialization of a std::initializer_list object. Regardless,
// we should recursively lifetime-extend that initializer.
- performLifetimeExtension(SubInit, ExtendingEntity);
+ visitLocalsRetainedByInitializer(Path, SubInit, Visit,
+ RevisitSubinits);
++Index;
}
}
}
+ return;
}
-}
-static void warnOnLifetimeExtension(Sema &S, const InitializedEntity &Entity,
- const Expr *Init, bool IsInitializerList,
- const ValueDecl *ExtendingDecl) {
- // Warn if a field lifetime-extends a temporary.
- if (isa<FieldDecl>(ExtendingDecl)) {
- if (IsInitializerList) {
- S.Diag(Init->getExprLoc(), diag::warn_dangling_std_initializer_list)
- << /*at end of constructor*/true;
+ // Step over value-preserving rvalue casts.
+ while (auto *CE = dyn_cast<CastExpr>(Init)) {
+ switch (CE->getCastKind()) {
+ case CK_LValueToRValue:
+ // If we can match the lvalue to a const object, we can look at its
+ // initializer.
+ Path.push_back({IndirectLocalPathEntry::LValToRVal, CE});
+ return visitLocalsRetainedByReferenceBinding(
+ Path, Init, RK_ReferenceBinding,
+ [&](IndirectLocalPath &Path, Local L, ReferenceKind RK) -> bool {
+ if (auto *DRE = dyn_cast<DeclRefExpr>(L)) {
+ auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
+ if (VD && VD->getType().isConstQualified() && VD->getInit()) {
+ Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
+ visitLocalsRetainedByInitializer(Path, VD->getInit(), Visit, true);
+ }
+ } else if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L)) {
+ if (MTE->getType().isConstQualified())
+ visitLocalsRetainedByInitializer(Path, MTE->GetTemporaryExpr(),
+ Visit, true);
+ }
+ return false;
+ });
+
+ // We assume that objects can be retained by pointers cast to integers,
+ // but not if the integer is cast to floating-point type or to _Complex.
+ // We assume that casts to 'bool' do not preserve enough information to
+ // retain a local object.
+ case CK_NoOp:
+ case CK_BitCast:
+ case CK_BaseToDerived:
+ case CK_DerivedToBase:
+ case CK_UncheckedDerivedToBase:
+ case CK_Dynamic:
+ case CK_ToUnion:
+ case CK_IntegralToPointer:
+ case CK_PointerToIntegral:
+ case CK_VectorSplat:
+ case CK_IntegralCast:
+ case CK_CPointerToObjCPointerCast:
+ case CK_BlockPointerToObjCPointerCast:
+ case CK_AnyPointerToBlockPointerCast:
+ case CK_AddressSpaceConversion:
+ break;
+
+ case CK_ArrayToPointerDecay:
+ // Model array-to-pointer decay as taking the address of the array
+ // lvalue.
+ Path.push_back({IndirectLocalPathEntry::AddressOf, CE});
+ return visitLocalsRetainedByReferenceBinding(Path, CE->getSubExpr(),
+ RK_ReferenceBinding, Visit);
+
+ default:
return;
}
- bool IsSubobjectMember = false;
- for (const InitializedEntity *Ent = Entity.getParent(); Ent;
- Ent = Ent->getParent()) {
- if (Ent->getKind() != InitializedEntity::EK_Base) {
- IsSubobjectMember = true;
+ Init = CE->getSubExpr();
+ }
+
+ Init = Init->IgnoreParens();
+ switch (Init->getStmtClass()) {
+ case Stmt::UnaryOperatorClass: {
+ auto *UO = cast<UnaryOperator>(Init);
+ // If the initializer is the address of a local, we could have a lifetime
+ // problem.
+ if (UO->getOpcode() == UO_AddrOf) {
+ // If this is &rvalue, then it's ill-formed and we have already diagnosed
+ // it. Don't produce a redundant warning about the lifetime of the
+ // temporary.
+ if (isa<MaterializeTemporaryExpr>(UO->getSubExpr()))
+ return;
+
+ Path.push_back({IndirectLocalPathEntry::AddressOf, UO});
+ visitLocalsRetainedByReferenceBinding(Path, UO->getSubExpr(),
+ RK_ReferenceBinding, Visit);
+ }
+ break;
+ }
+
+ case Stmt::BinaryOperatorClass: {
+ // Handle pointer arithmetic.
+ auto *BO = cast<BinaryOperator>(Init);
+ BinaryOperatorKind BOK = BO->getOpcode();
+ if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub))
+ break;
+
+ if (BO->getLHS()->getType()->isPointerType())
+ visitLocalsRetainedByInitializer(Path, BO->getLHS(), Visit, true);
+ else if (BO->getRHS()->getType()->isPointerType())
+ visitLocalsRetainedByInitializer(Path, BO->getRHS(), Visit, true);
+ break;
+ }
+
+ case Stmt::ConditionalOperatorClass:
+ case Stmt::BinaryConditionalOperatorClass: {
+ auto *C = cast<AbstractConditionalOperator>(Init);
+ // In C++, we can have a throw-expression operand, which has 'void' type
+ // and isn't interesting from a lifetime perspective.
+ if (!C->getTrueExpr()->getType()->isVoidType())
+ visitLocalsRetainedByInitializer(Path, C->getTrueExpr(), Visit, true);
+ if (!C->getFalseExpr()->getType()->isVoidType())
+ visitLocalsRetainedByInitializer(Path, C->getFalseExpr(), Visit, true);
+ break;
+ }
+
+ case Stmt::BlockExprClass:
+ if (cast<BlockExpr>(Init)->getBlockDecl()->hasCaptures()) {
+ // This is a local block, whose lifetime is that of the function.
+ Visit(Path, Local(cast<BlockExpr>(Init)), RK_ReferenceBinding);
+ }
+ break;
+
+ case Stmt::AddrLabelExprClass:
+ // We want to warn if the address of a label would escape the function.
+ Visit(Path, Local(cast<AddrLabelExpr>(Init)), RK_ReferenceBinding);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/// Determine whether this is an indirect path to a temporary that we are
+/// supposed to lifetime-extend along (but don't).
+static bool shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) {
+ for (auto Elem : Path) {
+ if (Elem.Kind != IndirectLocalPathEntry::DefaultInit)
+ return false;
+ }
+ return true;
+}
+
+/// Find the range for the first interesting entry in the path at or after I.
+static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I,
+ Expr *E) {
+ for (unsigned N = Path.size(); I != N; ++I) {
+ switch (Path[I].Kind) {
+ case IndirectLocalPathEntry::AddressOf:
+ case IndirectLocalPathEntry::LValToRVal:
+ // These exist primarily to mark the path as not permitting or
+ // supporting lifetime extension.
+ break;
+
+ case IndirectLocalPathEntry::DefaultInit:
+ case IndirectLocalPathEntry::VarInit:
+ return Path[I].E->getSourceRange();
+ }
+ }
+ return E->getSourceRange();
+}
+
+void Sema::checkInitializerLifetime(const InitializedEntity &Entity,
+ Expr *Init) {
+ LifetimeResult LR = getEntityLifetime(&Entity);
+ LifetimeKind LK = LR.getInt();
+ const InitializedEntity *ExtendingEntity = LR.getPointer();
+
+ // If this entity doesn't have an interesting lifetime, don't bother looking
+ // for temporaries within its initializer.
+ if (LK == LK_FullExpression)
+ return;
+
+ auto TemporaryVisitor = [&](IndirectLocalPath &Path, Local L,
+ ReferenceKind RK) -> bool {
+ SourceRange DiagRange = nextPathEntryRange(Path, 0, L);
+ SourceLocation DiagLoc = DiagRange.getBegin();
+
+ switch (LK) {
+ case LK_FullExpression:
+ llvm_unreachable("already handled this");
+
+ case LK_Extended: {
+ auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
+ if (!MTE) {
+ // The initialized entity has lifetime beyond the full-expression,
+ // and the local entity does too, so don't warn.
+ //
+ // FIXME: We should consider warning if a static / thread storage
+ // duration variable retains an automatic storage duration local.
+ return false;
+ }
+
+ // Lifetime-extend the temporary.
+ if (Path.empty()) {
+ // Update the storage duration of the materialized temporary.
+ // FIXME: Rebuild the expression instead of mutating it.
+ MTE->setExtendingDecl(ExtendingEntity->getDecl(),
+ ExtendingEntity->allocateManglingNumber());
+ // Also visit the temporaries lifetime-extended by this initializer.
+ return true;
+ }
+
+ if (shouldLifetimeExtendThroughPath(Path)) {
+ // We're supposed to lifetime-extend the temporary along this path (per
+ // the resolution of DR1815), but we don't support that yet.
+ //
+ // FIXME: Properly handle this situation. Perhaps the easiest approach
+ // would be to clone the initializer expression on each use that would
+ // lifetime extend its temporaries.
+ Diag(DiagLoc, diag::warn_unsupported_lifetime_extension)
+ << RK << DiagRange;
+ } else {
+ // If the path goes through the initialization of a variable or field,
+ // it can't possibly reach a temporary created in this full-expression.
+ // We will have already diagnosed any problems with the initializer.
+ if (pathContainsInit(Path))
+ return false;
+
+ Diag(DiagLoc, diag::warn_dangling_variable)
+ << RK << !Entity.getParent() << ExtendingEntity->getDecl()
+ << Init->isGLValue() << DiagRange;
+ }
+ break;
+ }
+
+ case LK_MemInitializer: {
+ if (isa<MaterializeTemporaryExpr>(L)) {
+ // Under C++ DR1696, if a mem-initializer (or a default member
+ // initializer used by the absence of one) would lifetime-extend a
+ // temporary, the program is ill-formed.
+ if (auto *ExtendingDecl =
+ ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
+ bool IsSubobjectMember = ExtendingEntity != &Entity;
+ Diag(DiagLoc, shouldLifetimeExtendThroughPath(Path)
+ ? diag::err_dangling_member
+ : diag::warn_dangling_member)
+ << ExtendingDecl << IsSubobjectMember << RK << DiagRange;
+ // Don't bother adding a note pointing to the field if we're inside
+ // its default member initializer; our primary diagnostic points to
+ // the same place in that case.
+ if (Path.empty() ||
+ Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {
+ Diag(ExtendingDecl->getLocation(),
+ diag::note_lifetime_extending_member_declared_here)
+ << RK << IsSubobjectMember;
+ }
+ } else {
+ // We have a mem-initializer but no particular field within it; this
+ // is either a base class or a delegating initializer directly
+ // initializing the base-class from something that doesn't live long
+ // enough.
+ //
+ // FIXME: Warn on this.
+ return false;
+ }
+ } else {
+ // Paths via a default initializer can only occur during error recovery
+ // (there's no other way that a default initializer can refer to a
+ // local). Don't produce a bogus warning on those cases.
+ if (pathContainsInit(Path))
+ return false;
+
+ auto *DRE = dyn_cast<DeclRefExpr>(L);
+ auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) : nullptr;
+ if (!VD) {
+ // A member was initialized to a local block.
+ // FIXME: Warn on this.
+ return false;
+ }
+
+ if (auto *Member =
+ ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
+ bool IsPointer = Member->getType()->isAnyPointerType();
+ Diag(DiagLoc, IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
+ : diag::warn_bind_ref_member_to_parameter)
+ << Member << VD << isa<ParmVarDecl>(VD) << DiagRange;
+ Diag(Member->getLocation(),
+ diag::note_ref_or_ptr_member_declared_here)
+ << (unsigned)IsPointer;
+ }
+ }
+ break;
+ }
+
+ case LK_New:
+ if (isa<MaterializeTemporaryExpr>(L)) {
+ Diag(DiagLoc, RK == RK_ReferenceBinding
+ ? diag::warn_new_dangling_reference
+ : diag::warn_new_dangling_initializer_list)
+ << !Entity.getParent() << DiagRange;
+ } else {
+ // We can't determine if the allocation outlives the local declaration.
+ return false;
+ }
+ break;
+
+ case LK_Return:
+ case LK_StmtExprResult:
+ if (auto *DRE = dyn_cast<DeclRefExpr>(L)) {
+ // We can't determine if the local variable outlives the statement
+ // expression.
+ if (LK == LK_StmtExprResult)
+ return false;
+ Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
+ << Entity.getType()->isReferenceType() << DRE->getDecl()
+ << isa<ParmVarDecl>(DRE->getDecl()) << DiagRange;
+ } else if (isa<BlockExpr>(L)) {
+ Diag(DiagLoc, diag::err_ret_local_block) << DiagRange;
+ } else if (isa<AddrLabelExpr>(L)) {
+ Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange;
+ } else {
+ Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
+ << Entity.getType()->isReferenceType() << DiagRange;
+ }
+ break;
+ }
+
+ for (unsigned I = 0; I != Path.size(); ++I) {
+ auto Elem = Path[I];
+
+ switch (Elem.Kind) {
+ case IndirectLocalPathEntry::AddressOf:
+ case IndirectLocalPathEntry::LValToRVal:
+ // These exist primarily to mark the path as not permitting or
+ // supporting lifetime extension.
+ break;
+
+ case IndirectLocalPathEntry::DefaultInit: {
+ auto *FD = cast<FieldDecl>(Elem.D);
+ Diag(FD->getLocation(), diag::note_init_with_default_member_initalizer)
+ << FD << nextPathEntryRange(Path, I + 1, L);
+ break;
+ }
+
+ case IndirectLocalPathEntry::VarInit:
+ const VarDecl *VD = cast<VarDecl>(Elem.D);
+ Diag(VD->getLocation(), diag::note_local_var_initializer)
+ << VD->getType()->isReferenceType() << VD->getDeclName()
+ << nextPathEntryRange(Path, I + 1, L);
break;
}
}
- S.Diag(Init->getExprLoc(),
- diag::warn_bind_ref_member_to_temporary)
- << ExtendingDecl << Init->getSourceRange()
- << IsSubobjectMember << IsInitializerList;
- if (IsSubobjectMember)
- S.Diag(ExtendingDecl->getLocation(),
- diag::note_ref_subobject_of_member_declared_here);
- else
- S.Diag(ExtendingDecl->getLocation(),
- diag::note_ref_or_ptr_member_declared_here)
- << /*is pointer*/false;
- }
+
+ // We didn't lifetime-extend, so don't go any further; we don't need more
+ // warnings or errors on inner temporaries within this one's initializer.
+ return false;
+ };
+
+ llvm::SmallVector<IndirectLocalPathEntry, 8> Path;
+ if (Init->isGLValue())
+ visitLocalsRetainedByReferenceBinding(Path, Init, RK_ReferenceBinding,
+ TemporaryVisitor);
+ else
+ visitLocalsRetainedByInitializer(Path, Init, TemporaryVisitor, false);
}
static void DiagnoseNarrowingInInitList(Sema &S,
@@ -6427,13 +6938,7 @@ static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr,
// Find the std::move call and get the argument.
const CallExpr *CE = dyn_cast<CallExpr>(InitExpr->IgnoreParens());
- if (!CE || CE->getNumArgs() != 1)
- return;
-
- const FunctionDecl *MoveFunction = CE->getDirectCallee();
- if (!MoveFunction || !MoveFunction->isInStdNamespace() ||
- !MoveFunction->getIdentifier() ||
- !MoveFunction->getIdentifier()->isStr("move"))
+ if (!CE || !CE->isCallToStdMove())
return;
const Expr *Arg = CE->getArg(0)->IgnoreImplicit();
@@ -6490,7 +6995,7 @@ static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr,
// macro only if it is at the beginning of the macro.
while (ArgLoc.isMacroID() &&
S.getSourceManager().isAtStartOfImmediateMacroExpansion(ArgLoc)) {
- ArgLoc = S.getSourceManager().getImmediateExpansionRange(ArgLoc).first;
+ ArgLoc = S.getSourceManager().getImmediateExpansionRange(ArgLoc).getBegin();
}
if (LParen.isMacroID())
@@ -6619,7 +7124,7 @@ InitializationSequence::Perform(Sema &S,
if (Kind.getKind() == InitializationKind::IK_Direct &&
!Kind.isExplicitCast()) {
// Rebuild the ParenListExpr.
- SourceRange ParenRange = Kind.getParenRange();
+ SourceRange ParenRange = Kind.getParenOrBraceRange();
return S.ActOnParenListExpr(ParenRange.getBegin(), ParenRange.getEnd(),
Args);
}
@@ -6658,20 +7163,6 @@ InitializationSequence::Perform(Sema &S,
return ExprError();
}
- // Diagnose cases where we initialize a pointer to an array temporary, and the
- // pointer obviously outlives the temporary.
- if (Args.size() == 1 && Args[0]->getType()->isArrayType() &&
- Entity.getType()->isPointerType() &&
- InitializedEntityOutlivesFullExpression(Entity)) {
- const Expr *Init = Args[0]->skipRValueSubobjectAdjustments();
- if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Init))
- Init = MTE->GetTemporaryExpr();
- Expr::LValueClassification Kind = Init->ClassifyLValue(S.Context);
- if (Kind == Expr::LV_ClassTemporary || Kind == Expr::LV_ArrayTemporary)
- S.Diag(Init->getLocStart(), diag::warn_temporary_array_to_pointer_decay)
- << Init->getSourceRange();
- }
-
QualType DestType = Entity.getType().getNonReferenceType();
// FIXME: Ugly hack around the fact that Entity.getType() is not
// the same as Entity.getDecl()->getType() in cases involving type merging,
@@ -6822,16 +7313,6 @@ InitializationSequence::Perform(Sema &S,
}
}
- // Even though we didn't materialize a temporary, the binding may still
- // extend the lifetime of a temporary. This happens if we bind a reference
- // to the result of a cast to reference type.
- if (const InitializedEntity *ExtendingEntity =
- getEntityForTemporaryLifetimeExtension(&Entity))
- if (performReferenceExtension(CurInit.get(), ExtendingEntity))
- warnOnLifetimeExtension(S, Entity, CurInit.get(),
- /*IsInitializerList=*/false,
- ExtendingEntity->getDecl());
-
CheckForNullPointerDereference(S, CurInit.get());
break;
@@ -6846,23 +7327,13 @@ InitializationSequence::Perform(Sema &S,
// Materialize the temporary into memory.
MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr(
Step->Type, CurInit.get(), Entity.getType()->isLValueReferenceType());
-
- // Maybe lifetime-extend the temporary's subobjects to match the
- // entity's lifetime.
- if (const InitializedEntity *ExtendingEntity =
- getEntityForTemporaryLifetimeExtension(&Entity))
- if (performReferenceExtension(MTE, ExtendingEntity))
- warnOnLifetimeExtension(S, Entity, CurInit.get(),
- /*IsInitializerList=*/false,
- ExtendingEntity->getDecl());
+ CurInit = MTE;
// If we're extending this temporary to automatic storage duration -- we
// need to register its cleanup during the full-expression's cleanups.
if (MTE->getStorageDuration() == SD_Automatic &&
MTE->getType().isDestructedType())
S.Cleanup.setExprNeedsCleanups(true);
-
- CurInit = MTE;
break;
}
@@ -6935,16 +7406,6 @@ InitializationSequence::Perform(Sema &S,
if (S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation()))
return ExprError();
- // FIXME: Should we move this initialization into a separate
- // derived-to-base conversion? I believe the answer is "no", because
- // we don't want to turn off access control here for c-style casts.
- CurInit = S.PerformObjectArgumentInitialization(CurInit.get(),
- /*Qualifier=*/nullptr,
- FoundFn, Conversion);
- if (CurInit.isInvalid())
- return ExprError();
-
- // Build the actual call to the conversion function.
CurInit = S.BuildCXXMemberCallExpr(CurInit.get(), FoundFn, Conversion,
HadMultipleCandidates);
if (CurInit.isInvalid())
@@ -7139,14 +7600,17 @@ InitializationSequence::Perform(Sema &S,
bool IsStdInitListInit =
Step->Kind == SK_StdInitializerListConstructorCall;
Expr *Source = CurInit.get();
+ SourceRange Range = Kind.hasParenOrBraceRange()
+ ? Kind.getParenOrBraceRange()
+ : SourceRange();
CurInit = PerformConstructorInitialization(
S, UseTemporary ? TempEntity : Entity, Kind,
Source ? MultiExprArg(Source) : Args, *Step,
ConstructorInitRequiresZeroInit,
/*IsListInitialization*/ IsStdInitListInit,
/*IsStdInitListInitialization*/ IsStdInitListInit,
- /*LBraceLoc*/ SourceLocation(),
- /*RBraceLoc*/ SourceLocation());
+ /*LBraceLoc*/ Range.getBegin(),
+ /*RBraceLoc*/ Range.getEnd());
break;
}
@@ -7302,15 +7766,6 @@ InitializationSequence::Perform(Sema &S,
CurInit.get()->getType(), CurInit.get(),
/*BoundToLvalueReference=*/false);
- // Maybe lifetime-extend the array temporary's subobjects to match the
- // entity's lifetime.
- if (const InitializedEntity *ExtendingEntity =
- getEntityForTemporaryLifetimeExtension(&Entity))
- if (performReferenceExtension(MTE, ExtendingEntity))
- warnOnLifetimeExtension(S, Entity, CurInit.get(),
- /*IsInitializerList=*/true,
- ExtendingEntity->getDecl());
-
// Wrap it in a construction of a std::initializer_list<T>.
CurInit = new (S.Context) CXXStdInitializerListExpr(Step->Type, MTE);
@@ -7432,6 +7887,11 @@ InitializationSequence::Perform(Sema &S,
}
}
+ // Check whether the initializer has a shorter lifetime than the initialized
+ // entity, and if not, either lifetime-extend or warn as appropriate.
+ if (auto *Init = CurInit.get())
+ S.checkInitializerLifetime(Entity, Init);
+
// Diagnose non-fatal problems with the completed initialization.
if (Entity.getKind() == InitializedEntity::EK_Member &&
cast<FieldDecl>(Entity.getDecl())->isBitField())
@@ -7549,6 +8009,19 @@ bool InitializationSequence::Diagnose(Sema &S,
if (!Failed())
return false;
+ // When we want to diagnose only one element of a braced-init-list,
+ // we need to factor it out.
+ Expr *OnlyArg;
+ if (Args.size() == 1) {
+ auto *List = dyn_cast<InitListExpr>(Args[0]);
+ if (List && List->getNumInits() == 1)
+ OnlyArg = List->getInit(0);
+ else
+ OnlyArg = Args[0];
+ }
+ else
+ OnlyArg = nullptr;
+
QualType DestType = Entity.getType();
switch (Failure) {
case FK_TooManyInitsForReference:
@@ -7591,6 +8064,17 @@ bool InitializationSequence::Diagnose(Sema &S,
S.Diag(Kind.getLocation(),
diag::err_array_init_incompat_wide_string_into_wchar);
break;
+ case FK_PlainStringIntoUTF8Char:
+ S.Diag(Kind.getLocation(),
+ diag::err_array_init_plain_string_into_char8_t);
+ S.Diag(Args.front()->getLocStart(),
+ diag::note_array_init_plain_string_into_char8_t)
+ << FixItHint::CreateInsertion(Args.front()->getLocStart(), "u8");
+ break;
+ case FK_UTF8StringIntoPlainChar:
+ S.Diag(Kind.getLocation(),
+ diag::err_array_init_utf8_string_into_char);
+ break;
case FK_ArrayTypeMismatch:
case FK_NonConstantArrayInit:
S.Diag(Kind.getLocation(),
@@ -7598,7 +8082,7 @@ bool InitializationSequence::Diagnose(Sema &S,
? diag::err_array_init_different_type
: diag::err_array_init_non_constant_array))
<< DestType.getNonReferenceType()
- << Args[0]->getType()
+ << OnlyArg->getType()
<< Args[0]->getSourceRange();
break;
@@ -7609,7 +8093,7 @@ bool InitializationSequence::Diagnose(Sema &S,
case FK_AddressOfOverloadFailed: {
DeclAccessPair Found;
- S.ResolveAddressOfOverloadedFunction(Args[0],
+ S.ResolveAddressOfOverloadedFunction(OnlyArg,
DestType.getNonReferenceType(),
true,
Found);
@@ -7617,9 +8101,9 @@ bool InitializationSequence::Diagnose(Sema &S,
}
case FK_AddressOfUnaddressableFunction: {
- auto *FD = cast<FunctionDecl>(cast<DeclRefExpr>(Args[0])->getDecl());
+ auto *FD = cast<FunctionDecl>(cast<DeclRefExpr>(OnlyArg)->getDecl());
S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true,
- Args[0]->getLocStart());
+ OnlyArg->getLocStart());
break;
}
@@ -7629,11 +8113,11 @@ bool InitializationSequence::Diagnose(Sema &S,
case OR_Ambiguous:
if (Failure == FK_UserConversionOverloadFailed)
S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition)
- << Args[0]->getType() << DestType
+ << OnlyArg->getType() << DestType
<< Args[0]->getSourceRange();
else
S.Diag(Kind.getLocation(), diag::err_ref_init_ambiguous)
- << DestType << Args[0]->getType()
+ << DestType << OnlyArg->getType()
<< Args[0]->getSourceRange();
FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, Args);
@@ -7643,10 +8127,10 @@ bool InitializationSequence::Diagnose(Sema &S,
if (!S.RequireCompleteType(Kind.getLocation(),
DestType.getNonReferenceType(),
diag::err_typecheck_nonviable_condition_incomplete,
- Args[0]->getType(), Args[0]->getSourceRange()))
+ OnlyArg->getType(), Args[0]->getSourceRange()))
S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition)
<< (Entity.getKind() == InitializedEntity::EK_Result)
- << Args[0]->getType() << Args[0]->getSourceRange()
+ << OnlyArg->getType() << Args[0]->getSourceRange()
<< DestType.getNonReferenceType();
FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args);
@@ -7654,7 +8138,7 @@ bool InitializationSequence::Diagnose(Sema &S,
case OR_Deleted: {
S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function)
- << Args[0]->getType() << DestType.getNonReferenceType()
+ << OnlyArg->getType() << DestType.getNonReferenceType()
<< Args[0]->getSourceRange();
OverloadCandidateSet::iterator Best;
OverloadingResult Ovl
@@ -7690,7 +8174,7 @@ bool InitializationSequence::Diagnose(Sema &S,
: diag::err_lvalue_reference_bind_to_unrelated)
<< DestType.getNonReferenceType().isVolatileQualified()
<< DestType.getNonReferenceType()
- << Args[0]->getType()
+ << OnlyArg->getType()
<< Args[0]->getSourceRange();
break;
@@ -7715,12 +8199,12 @@ bool InitializationSequence::Diagnose(Sema &S,
case FK_RValueReferenceBindingToLValue:
S.Diag(Kind.getLocation(), diag::err_lvalue_to_rvalue_ref)
- << DestType.getNonReferenceType() << Args[0]->getType()
+ << DestType.getNonReferenceType() << OnlyArg->getType()
<< Args[0]->getSourceRange();
break;
case FK_ReferenceInitDropsQualifiers: {
- QualType SourceType = Args[0]->getType();
+ QualType SourceType = OnlyArg->getType();
QualType NonRefType = DestType.getNonReferenceType();
Qualifiers DroppedQualifiers =
SourceType.getQualifiers() - NonRefType.getQualifiers();
@@ -7736,18 +8220,18 @@ bool InitializationSequence::Diagnose(Sema &S,
case FK_ReferenceInitFailed:
S.Diag(Kind.getLocation(), diag::err_reference_bind_failed)
<< DestType.getNonReferenceType()
- << Args[0]->isLValue()
- << Args[0]->getType()
+ << OnlyArg->isLValue()
+ << OnlyArg->getType()
<< Args[0]->getSourceRange();
emitBadConversionNotes(S, Entity, Args[0]);
break;
case FK_ConversionFailed: {
- QualType FromType = Args[0]->getType();
+ QualType FromType = OnlyArg->getType();
PartialDiagnostic PDiag = S.PDiag(diag::err_init_conversion_failed)
<< (int)Entity.getKind()
<< DestType
- << Args[0]->isLValue()
+ << OnlyArg->isLValue()
<< FromType
<< Args[0]->getSourceRange();
S.HandleFunctionTypeMismatch(PDiag, FromType, DestType);
@@ -8000,6 +8484,14 @@ void InitializationSequence::dump(raw_ostream &OS) const {
OS << "incompatible wide string into wide char array";
break;
+ case FK_PlainStringIntoUTF8Char:
+ OS << "plain string literal into char8_t array";
+ break;
+
+ case FK_UTF8StringIntoPlainChar:
+ OS << "u8 string literal into char array";
+ break;
+
case FK_ArrayTypeMismatch:
OS << "array type mismatch";
break;
@@ -8290,6 +8782,11 @@ void InitializationSequence::dump() const {
dump(llvm::errs());
}
+static bool NarrowingErrs(const LangOptions &L) {
+ return L.CPlusPlus11 &&
+ (!L.MicrosoftExt || L.isCompatibleWithMSVC(LangOptions::MSVC2015));
+}
+
static void DiagnoseNarrowingInInitList(Sema &S,
const ImplicitConversionSequence &ICS,
QualType PreNarrowingType,
@@ -8323,35 +8820,34 @@ 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(),
- (S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11)
- ? diag::warn_init_list_type_narrowing
- : diag::ext_init_list_type_narrowing)
- << PostInit->getSourceRange()
- << PreNarrowingType.getLocalUnqualifiedType()
- << EntityType.getLocalUnqualifiedType();
+ S.Diag(PostInit->getLocStart(), NarrowingErrs(S.getLangOpts())
+ ? diag::ext_init_list_type_narrowing
+ : diag::warn_init_list_type_narrowing)
+ << PostInit->getSourceRange()
+ << PreNarrowingType.getLocalUnqualifiedType()
+ << EntityType.getLocalUnqualifiedType();
break;
case NK_Constant_Narrowing:
// A constant value was narrowed.
S.Diag(PostInit->getLocStart(),
- (S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11)
- ? diag::warn_init_list_constant_narrowing
- : diag::ext_init_list_constant_narrowing)
- << PostInit->getSourceRange()
- << ConstantValue.getAsString(S.getASTContext(), ConstantType)
- << EntityType.getLocalUnqualifiedType();
+ NarrowingErrs(S.getLangOpts())
+ ? diag::ext_init_list_constant_narrowing
+ : diag::warn_init_list_constant_narrowing)
+ << PostInit->getSourceRange()
+ << ConstantValue.getAsString(S.getASTContext(), ConstantType)
+ << EntityType.getLocalUnqualifiedType();
break;
case NK_Variable_Narrowing:
// A variable's value may have been narrowed.
S.Diag(PostInit->getLocStart(),
- (S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11)
- ? diag::warn_init_list_variable_narrowing
- : diag::ext_init_list_variable_narrowing)
- << PostInit->getSourceRange()
- << PreNarrowingType.getLocalUnqualifiedType()
- << EntityType.getLocalUnqualifiedType();
+ NarrowingErrs(S.getLangOpts())
+ ? diag::ext_init_list_variable_narrowing
+ : diag::warn_init_list_variable_narrowing)
+ << PostInit->getSourceRange()
+ << PreNarrowingType.getLocalUnqualifiedType()
+ << EntityType.getLocalUnqualifiedType();
break;
}
@@ -8624,6 +9120,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
Expr *E = ListInit->getInit(0);
auto *RD = E->getType()->getAsCXXRecordDecl();
if (!isa<InitListExpr>(E) && RD &&
+ isCompleteType(Kind.getLocation(), E->getType()) &&
isOrIsDerivedFromSpecializationOf(RD, Template))
TryListConstructors = false;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
index 19d2de719728..a42b2e827e9b 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
@@ -24,7 +24,7 @@
using namespace clang;
using namespace sema;
-/// \brief Examines the FunctionScopeInfo stack to determine the nearest
+/// Examines the FunctionScopeInfo stack to determine the nearest
/// enclosing lambda (to the current lambda) that is 'capture-ready' for
/// the variable referenced in the current lambda (i.e. \p VarToCapture).
/// If successful, returns the index into Sema's FunctionScopeInfo stack
@@ -135,7 +135,7 @@ getStackIndexOfNearestEnclosingCaptureReadyLambda(
return NoLambdaIsCaptureReady;
}
-/// \brief Examines the FunctionScopeInfo stack to determine the nearest
+/// Examines the FunctionScopeInfo stack to determine the nearest
/// enclosing lambda (to the current lambda) that is 'capture-capable' for
/// the variable referenced in the current lambda (i.e. \p VarToCapture).
/// If successful, returns the index into Sema's FunctionScopeInfo stack
@@ -263,7 +263,7 @@ CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange,
return Class;
}
-/// \brief Determine whether the given context is or is enclosed in an inline
+/// Determine whether the given context is or is enclosed in an inline
/// function.
static bool isInInlineFunction(const DeclContext *DC) {
while (!DC->isFileContext()) {
@@ -692,9 +692,7 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
}
// Third case: only one return statement. Don't bother doing extra work!
- SmallVectorImpl<ReturnStmt*>::iterator I = CSI.Returns.begin(),
- E = CSI.Returns.end();
- if (I+1 == E)
+ if (CSI.Returns.size() == 1)
return;
// General case: many return statements.
@@ -703,15 +701,22 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
// We require the return types to strictly match here.
// Note that we've already done the required promotions as part of
// processing the return statement.
- for (; I != E; ++I) {
- const ReturnStmt *RS = *I;
+ for (const ReturnStmt *RS : CSI.Returns) {
const Expr *RetE = RS->getRetValue();
QualType ReturnType =
(RetE ? RetE->getType() : Context.VoidTy).getUnqualifiedType();
if (Context.getCanonicalFunctionResultType(ReturnType) ==
- Context.getCanonicalFunctionResultType(CSI.ReturnType))
+ Context.getCanonicalFunctionResultType(CSI.ReturnType)) {
+ // Use the return type with the strictest possible nullability annotation.
+ auto RetTyNullability = ReturnType->getNullability(Ctx);
+ auto BlockNullability = CSI.ReturnType->getNullability(Ctx);
+ if (BlockNullability &&
+ (!RetTyNullability ||
+ hasWeakerNullability(*RetTyNullability, *BlockNullability)))
+ CSI.ReturnType = ReturnType;
continue;
+ }
// FIXME: This is a poor diagnostic for ReturnStmts without expressions.
// TODO: It's possible that the *first* return is the divergent one.
@@ -904,6 +909,14 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
ParamInfo.getDeclSpec().isConstexprSpecified());
if (ExplicitParams)
CheckCXXDefaultArguments(Method);
+
+ // This represents the function body for the lambda function, check if we
+ // have to apply optnone due to a pragma.
+ AddRangeBasedOptnone(Method);
+
+ // code_seg attribute on lambda apply to the method.
+ if (Attr *A = getImplicitCodeSegOrSectionAttrForFunction(Method, /*IsDefinition=*/true))
+ Method->addAttr(A);
// Attributes on the lambda apply to the method.
ProcessDeclAttributes(CurScope, Method, ParamInfo);
@@ -984,6 +997,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
CheckCXXThisCapture(C->Loc, /*Explicit=*/true, /*BuildAndDiagnose*/ true,
/*FunctionScopeIndexToStopAtPtr*/ nullptr,
C->Kind == LCK_StarThis);
+ if (!LSI->Captures.empty())
+ LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange;
continue;
}
@@ -1130,6 +1145,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
TryCapture_ExplicitByVal;
tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc);
}
+ if (!LSI->Captures.empty())
+ LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange;
}
finishLambdaExplicitCaptures(LSI);
@@ -1161,7 +1178,7 @@ void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope,
Class->setInvalidDecl();
SmallVector<Decl*, 4> Fields(Class->fields());
ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(),
- SourceLocation(), nullptr);
+ SourceLocation(), ParsedAttributesView());
CheckCompletedCXXClass(Class);
PopFunctionScopeInfo();
@@ -1185,7 +1202,7 @@ QualType Sema::getLambdaConversionFunctionResultType(
CallOpProto->getParamTypes(), InvokerExtInfo);
}
-/// \brief Add a lambda's conversion to function pointer, as described in
+/// Add a lambda's conversion to function pointer, as described in
/// C++11 [expr.prim.lambda]p6.
static void addFunctionPointerConversion(Sema &S,
SourceRange IntroducerRange,
@@ -1354,7 +1371,7 @@ static void addFunctionPointerConversion(Sema &S,
Class->addDecl(Invoke);
}
-/// \brief Add a lambda's conversion to block pointer.
+/// Add a lambda's conversion to block pointer.
static void addBlockPointerConversion(Sema &S,
SourceRange IntroducerRange,
CXXRecordDecl *Class,
@@ -1388,8 +1405,9 @@ static void addBlockPointerConversion(Sema &S,
Class->addDecl(Conversion);
}
-static ExprResult performLambdaVarCaptureInitialization(
- Sema &S, const LambdaScopeInfo::Capture &Capture, FieldDecl *Field) {
+static ExprResult performLambdaVarCaptureInitialization(Sema &S,
+ const Capture &Capture,
+ FieldDecl *Field) {
assert(Capture.isVariableCapture() && "not a variable capture");
auto *Var = Capture.getVariable();
@@ -1443,7 +1461,7 @@ mapImplicitCaptureStyle(CapturingScopeInfo::ImplicitCaptureStyle ICS) {
llvm_unreachable("Unknown implicit capture style");
}
-bool Sema::CaptureHasSideEffects(const LambdaScopeInfo::Capture &From) {
+bool Sema::CaptureHasSideEffects(const Capture &From) {
if (!From.isVLATypeCapture()) {
Expr *Init = From.getInitExpr();
if (Init && Init->HasSideEffects(Context))
@@ -1468,12 +1486,13 @@ bool Sema::CaptureHasSideEffects(const LambdaScopeInfo::Capture &From) {
return false;
}
-void Sema::DiagnoseUnusedLambdaCapture(const LambdaScopeInfo::Capture &From) {
+bool Sema::DiagnoseUnusedLambdaCapture(SourceRange CaptureRange,
+ const Capture &From) {
if (CaptureHasSideEffects(From))
- return;
+ return false;
if (From.isVLATypeCapture())
- return;
+ return false;
auto diag = Diag(From.getLocation(), diag::warn_unused_lambda_capture);
if (From.isThisCapture())
@@ -1481,6 +1500,8 @@ void Sema::DiagnoseUnusedLambdaCapture(const LambdaScopeInfo::Capture &From) {
else
diag << From.getVariable();
diag << From.isNonODRUsed();
+ diag << FixItHint::CreateRemoval(CaptureRange);
+ return true;
}
ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
@@ -1522,22 +1543,64 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
// Translate captures.
auto CurField = Class->field_begin();
+ // True if the current capture has a used capture or default before it.
+ bool CurHasPreviousCapture = CaptureDefault != LCD_None;
+ SourceLocation PrevCaptureLoc = CurHasPreviousCapture ?
+ CaptureDefaultLoc : IntroducerRange.getBegin();
+
for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I, ++CurField) {
- const LambdaScopeInfo::Capture &From = LSI->Captures[I];
+ const Capture &From = LSI->Captures[I];
+
assert(!From.isBlockCapture() && "Cannot capture __block variables");
bool IsImplicit = I >= LSI->NumExplicitCaptures;
+ // Use source ranges of explicit captures for fixits where available.
+ SourceRange CaptureRange = LSI->ExplicitCaptureRanges[I];
+
// Warn about unused explicit captures.
+ bool IsCaptureUsed = true;
if (!CurContext->isDependentContext() && !IsImplicit && !From.isODRUsed()) {
// Initialized captures that are non-ODR used may not be eliminated.
bool NonODRUsedInitCapture =
IsGenericLambda && From.isNonODRUsed() && From.getInitExpr();
- if (!NonODRUsedInitCapture)
- DiagnoseUnusedLambdaCapture(From);
+ if (!NonODRUsedInitCapture) {
+ bool IsLast = (I + 1) == LSI->NumExplicitCaptures;
+ SourceRange FixItRange;
+ if (CaptureRange.isValid()) {
+ if (!CurHasPreviousCapture && !IsLast) {
+ // If there are no captures preceding this capture, remove the
+ // following comma.
+ FixItRange = SourceRange(CaptureRange.getBegin(),
+ getLocForEndOfToken(CaptureRange.getEnd()));
+ } else {
+ // Otherwise, remove the comma since the last used capture.
+ FixItRange = SourceRange(getLocForEndOfToken(PrevCaptureLoc),
+ CaptureRange.getEnd());
+ }
+ }
+
+ IsCaptureUsed = !DiagnoseUnusedLambdaCapture(FixItRange, From);
+ }
+ }
+
+ if (CaptureRange.isValid()) {
+ CurHasPreviousCapture |= IsCaptureUsed;
+ PrevCaptureLoc = CaptureRange.getEnd();
}
// Handle 'this' capture.
if (From.isThisCapture()) {
+ // Capturing 'this' implicitly with a default of '[=]' is deprecated,
+ // because it results in a reference capture. Don't warn prior to
+ // C++2a; there's nothing that can be done about it before then.
+ if (getLangOpts().CPlusPlus2a && IsImplicit &&
+ CaptureDefault == LCD_ByCopy) {
+ Diag(From.getLocation(), diag::warn_deprecated_this_capture);
+ Diag(CaptureDefaultLoc, diag::note_deprecated_this_capture)
+ << FixItHint::CreateInsertion(
+ getLocForEndOfToken(CaptureDefaultLoc), ", this");
+ }
+
Captures.push_back(
LambdaCapture(From.getLocation(), IsImplicit,
From.isCopyCapture() ? LCK_StarThis : LCK_This));
@@ -1587,7 +1650,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
// Finalize the lambda class.
SmallVector<Decl*, 4> Fields(Class->fields());
ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(),
- SourceLocation(), nullptr);
+ SourceLocation(), ParsedAttributesView());
CheckCompletedCXXClass(Class);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
index a9db973851df..2732112c00b6 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
@@ -187,7 +187,7 @@ namespace {
}
void done() {
- std::sort(list.begin(), list.end(), UnqualUsingEntry::Comparator());
+ llvm::sort(list.begin(), list.end(), UnqualUsingEntry::Comparator());
}
typedef ListTy::const_iterator const_iterator;
@@ -356,7 +356,7 @@ static DeclContext *getContextForScopeMatching(Decl *D) {
return D->getDeclContext()->getRedeclContext();
}
-/// \brief Determine whether \p D is a better lookup result than \p Existing,
+/// Determine whether \p D is a better lookup result than \p Existing,
/// given that they declare the same entity.
static bool isPreferredLookupResult(Sema &S, Sema::LookupNameKind Kind,
NamedDecl *D, NamedDecl *Existing) {
@@ -669,7 +669,7 @@ LLVM_DUMP_METHOD void LookupResult::dump() {
D->dump();
}
-/// \brief Lookup a builtin function, when name lookup would otherwise
+/// Lookup a builtin function, when name lookup would otherwise
/// fail.
static bool LookupBuiltin(Sema &S, LookupResult &R) {
Sema::LookupNameKind NameKind = R.getLookupKind();
@@ -713,7 +713,7 @@ static bool LookupBuiltin(Sema &S, LookupResult &R) {
return false;
}
-/// \brief Determine whether we can declare a special member function within
+/// Determine whether we can declare a special member function within
/// the class at this point.
static bool CanDeclareSpecialMemberFunction(const CXXRecordDecl *Class) {
// We need to have a definition for the class.
@@ -755,7 +755,7 @@ void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) {
DeclareImplicitDestructor(Class);
}
-/// \brief Determine whether this is the name of an implicitly-declared
+/// Determine whether this is the name of an implicitly-declared
/// special member function.
static bool isImplicitlyDeclaredMemberFunctionName(DeclarationName Name) {
switch (Name.getNameKind()) {
@@ -773,7 +773,7 @@ static bool isImplicitlyDeclaredMemberFunctionName(DeclarationName Name) {
return false;
}
-/// \brief If there are any implicit member functions with the given name
+/// If there are any implicit member functions with the given name
/// that need to be declared in the given declaration context, do so.
static void DeclareImplicitMemberFunctionsWithName(Sema &S,
DeclarationName Name,
@@ -1354,7 +1354,7 @@ void Sema::makeMergedDefinitionVisible(NamedDecl *ND) {
makeMergedDefinitionVisible(Param);
}
-/// \brief Find the module in which the given declaration was defined.
+/// Find the module in which the given declaration was defined.
static Module *getDefiningModule(Sema &S, Decl *Entity) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Entity)) {
// If this function was instantiated from a template, the defining module is
@@ -1452,6 +1452,8 @@ template<typename Filter>
static bool hasVisibleDeclarationImpl(Sema &S, const NamedDecl *D,
llvm::SmallVectorImpl<Module *> *Modules,
Filter F) {
+ bool HasFilteredRedecls = false;
+
for (auto *Redecl : D->redecls()) {
auto *R = cast<NamedDecl>(Redecl);
if (!F(R))
@@ -1460,6 +1462,8 @@ static bool hasVisibleDeclarationImpl(Sema &S, const NamedDecl *D,
if (S.isVisible(R))
return true;
+ HasFilteredRedecls = true;
+
if (Modules) {
Modules->push_back(R->getOwningModule());
const auto &Merged = S.Context.getModulesWithMergedDefinition(R);
@@ -1467,7 +1471,11 @@ static bool hasVisibleDeclarationImpl(Sema &S, const NamedDecl *D,
}
}
- return false;
+ // Only return false if there is at least one redecl that is not filtered out.
+ if (HasFilteredRedecls)
+ return false;
+
+ return true;
}
bool Sema::hasVisibleExplicitSpecialization(
@@ -1497,11 +1505,9 @@ bool Sema::hasVisibleMemberSpecialization(
// class definition?
return D->getLexicalDeclContext()->isFileContext();
});
-
- return false;
}
-/// \brief Determine whether a declaration is visible to name lookup.
+/// Determine whether a declaration is visible to name lookup.
///
/// This routine determines whether the declaration D is visible in the current
/// lookup context, taking into account the current template instantiation
@@ -1648,7 +1654,7 @@ bool Sema::shouldLinkPossiblyHiddenDecl(LookupResult &R, const NamedDecl *New) {
return New->isExternallyDeclarable();
}
-/// \brief Retrieve the visible declaration corresponding to D, if any.
+/// Retrieve the visible declaration corresponding to D, if any.
///
/// This routine determines whether the declaration D is visible in the current
/// module, with the current imports. If not, it checks whether any
@@ -1656,7 +1662,8 @@ bool Sema::shouldLinkPossiblyHiddenDecl(LookupResult &R, const NamedDecl *New) {
///
/// \returns D, or a visible previous declaration of D, whichever is more recent
/// and visible. If no declaration of D is visible, returns null.
-static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
+static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D,
+ unsigned IDNS) {
assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
for (auto RD : D->redecls()) {
@@ -1668,7 +1675,8 @@ static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
// FIXME: This is wrong in the case where the previous declaration is not
// visible in the same scope as D. This needs to be done much more
// carefully.
- if (LookupResult::isVisible(SemaRef, ND))
+ if (ND->isInIdentifierNamespace(IDNS) &&
+ LookupResult::isVisible(SemaRef, ND))
return ND;
}
@@ -1693,17 +1701,18 @@ NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const {
auto *Key = ND->getCanonicalDecl();
if (auto *Acceptable = getSema().VisibleNamespaceCache.lookup(Key))
return Acceptable;
- auto *Acceptable =
- isVisible(getSema(), Key) ? Key : findAcceptableDecl(getSema(), Key);
+ auto *Acceptable = isVisible(getSema(), Key)
+ ? Key
+ : findAcceptableDecl(getSema(), Key, IDNS);
if (Acceptable)
getSema().VisibleNamespaceCache.insert(std::make_pair(Key, Acceptable));
return Acceptable;
}
- return findAcceptableDecl(getSema(), D);
+ return findAcceptableDecl(getSema(), D, IDNS);
}
-/// @brief Perform unqualified name lookup starting from a given
+/// Perform unqualified name lookup starting from a given
/// scope.
///
/// Unqualified name lookup (C++ [basic.lookup.unqual], C99 6.2.1) is
@@ -1841,7 +1850,7 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
return (ExternalSource && ExternalSource->LookupUnqualified(R, S));
}
-/// @brief Perform qualified name lookup in the namespaces nominated by
+/// Perform qualified name lookup in the namespaces nominated by
/// using directives by the given context.
///
/// C++98 [namespace.qual]p2:
@@ -1947,7 +1956,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
return Found;
}
-/// \brief Callback that looks for any member of a class with the given name.
+/// Callback that looks for any member of a class with the given name.
static bool LookupAnyMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path, DeclarationName Name) {
RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
@@ -1956,7 +1965,7 @@ static bool LookupAnyMember(const CXXBaseSpecifier *Specifier,
return !Path.Decls.empty();
}
-/// \brief Determine whether the given set of member declarations contains only
+/// Determine whether the given set of member declarations contains only
/// static members, nested types, and enumerators.
template<typename InputIterator>
static bool HasOnlyStaticMembers(InputIterator First, InputIterator Last) {
@@ -1988,7 +1997,7 @@ static bool HasOnlyStaticMembers(InputIterator First, InputIterator Last) {
return false;
}
-/// \brief Perform qualified name lookup into a given context.
+/// Perform qualified name lookup into a given context.
///
/// Qualified name lookup (C++ [basic.lookup.qual]) is used to find
/// names when the context of those names is explicit specified, e.g.,
@@ -2212,7 +2221,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
return true;
}
-/// \brief Performs qualified name lookup or special type of lookup for
+/// Performs qualified name lookup or special type of lookup for
/// "__super::" scope specifier.
///
/// This routine is a convenience overload meant to be called from contexts
@@ -2237,7 +2246,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
return LookupQualifiedName(R, LookupCtx);
}
-/// @brief Performs name lookup for a name that was parsed in the
+/// Performs name lookup for a name that was parsed in the
/// source code, and may contain a C++ scope specifier.
///
/// This routine is a convenience routine meant to be called from
@@ -2291,7 +2300,7 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
return LookupName(R, S, AllowBuiltinCreation);
}
-/// \brief Perform qualified name lookup into all base classes of the given
+/// Perform qualified name lookup into all base classes of the given
/// class.
///
/// \param R captures both the lookup criteria and any lookup results found.
@@ -2309,7 +2318,7 @@ bool Sema::LookupInSuper(LookupResult &R, CXXRecordDecl *Class) {
CXXRecordDecl *RD = cast<CXXRecordDecl>(
BaseSpec.getType()->castAs<RecordType>()->getDecl());
LookupResult Result(*this, R.getLookupNameInfo(), R.getLookupKind());
- Result.setBaseObjectType(Context.getRecordType(Class));
+ Result.setBaseObjectType(Context.getRecordType(Class));
LookupQualifiedName(Result, RD);
// Copy the lookup results into the target, merging the base's access into
@@ -2329,7 +2338,7 @@ bool Sema::LookupInSuper(LookupResult &R, CXXRecordDecl *Class) {
return !R.empty();
}
-/// \brief Produce a diagnostic describing the ambiguity that resulted
+/// Produce a diagnostic describing the ambiguity that resulted
/// from name lookup.
///
/// \param Result The result of the ambiguous lookup to be diagnosed.
@@ -2445,7 +2454,7 @@ static void CollectEnclosingNamespace(Sema::AssociatedNamespaceSet &Namespaces,
Namespaces.insert(Ctx->getPrimaryContext());
}
-// \brief Add the associated classes and namespaces for argument-dependent
+// Add the associated classes and namespaces for argument-dependent
// lookup that involves a template argument (C++ [basic.lookup.koenig]p2).
static void
addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
@@ -2495,7 +2504,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
}
}
-// \brief Add the associated classes and namespaces for
+// Add the associated classes and namespaces for
// argument-dependent lookup with an argument of class type
// (C++ [basic.lookup.koenig]p2).
static void
@@ -2590,7 +2599,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
}
}
-// \brief Add the associated classes and namespaces for
+// Add the associated classes and namespaces for
// argument-dependent lookup with an argument of type T
// (C++ [basic.lookup.koenig]p2).
static void
@@ -2754,7 +2763,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
}
}
-/// \brief Find the associated classes and namespaces for
+/// Find the associated classes and namespaces for
/// argument-dependent lookup for a call with the given set of
/// arguments.
///
@@ -2821,7 +2830,7 @@ NamedDecl *Sema::LookupSingleName(Scope *S, DeclarationName Name,
return R.getAsSingle<NamedDecl>();
}
-/// \brief Find the protocol with the given name, if any.
+/// Find the protocol with the given name, if any.
ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II,
SourceLocation IdLoc,
RedeclarationKind Redecl) {
@@ -3048,7 +3057,7 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD,
return *Result;
}
-/// \brief Look up the default constructor for the given class.
+/// Look up the default constructor for the given class.
CXXConstructorDecl *Sema::LookupDefaultConstructor(CXXRecordDecl *Class) {
SpecialMemberOverloadResult Result =
LookupSpecialMember(Class, CXXDefaultConstructor, false, false, false,
@@ -3057,7 +3066,7 @@ CXXConstructorDecl *Sema::LookupDefaultConstructor(CXXRecordDecl *Class) {
return cast_or_null<CXXConstructorDecl>(Result.getMethod());
}
-/// \brief Look up the copying constructor for the given class.
+/// Look up the copying constructor for the given class.
CXXConstructorDecl *Sema::LookupCopyingConstructor(CXXRecordDecl *Class,
unsigned Quals) {
assert(!(Quals & ~(Qualifiers::Const | Qualifiers::Volatile)) &&
@@ -3069,7 +3078,7 @@ CXXConstructorDecl *Sema::LookupCopyingConstructor(CXXRecordDecl *Class,
return cast_or_null<CXXConstructorDecl>(Result.getMethod());
}
-/// \brief Look up the moving constructor for the given class.
+/// Look up the moving constructor for the given class.
CXXConstructorDecl *Sema::LookupMovingConstructor(CXXRecordDecl *Class,
unsigned Quals) {
SpecialMemberOverloadResult Result =
@@ -3079,7 +3088,7 @@ CXXConstructorDecl *Sema::LookupMovingConstructor(CXXRecordDecl *Class,
return cast_or_null<CXXConstructorDecl>(Result.getMethod());
}
-/// \brief Look up the constructors for the given class.
+/// Look up the constructors for the given class.
DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) {
// If the implicit constructors have not yet been declared, do so now.
if (CanDeclareSpecialMemberFunction(Class)) {
@@ -3096,7 +3105,7 @@ DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) {
return Class->lookup(Name);
}
-/// \brief Look up the copying assignment operator for the given class.
+/// Look up the copying assignment operator for the given class.
CXXMethodDecl *Sema::LookupCopyingAssignment(CXXRecordDecl *Class,
unsigned Quals, bool RValueThis,
unsigned ThisQuals) {
@@ -3113,7 +3122,7 @@ CXXMethodDecl *Sema::LookupCopyingAssignment(CXXRecordDecl *Class,
return Result.getMethod();
}
-/// \brief Look up the moving assignment operator for the given class.
+/// Look up the moving assignment operator for the given class.
CXXMethodDecl *Sema::LookupMovingAssignment(CXXRecordDecl *Class,
unsigned Quals,
bool RValueThis,
@@ -3129,7 +3138,7 @@ CXXMethodDecl *Sema::LookupMovingAssignment(CXXRecordDecl *Class,
return Result.getMethod();
}
-/// \brief Look for the destructor of the given class.
+/// Look for the destructor of the given class.
///
/// During semantic analysis, this routine should be used in lieu of
/// CXXRecordDecl::getDestructor().
@@ -3329,6 +3338,23 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
// lookup (11.4).
DeclContext::lookup_result R = NS->lookup(Name);
for (auto *D : R) {
+ auto *Underlying = D;
+ if (auto *USD = dyn_cast<UsingShadowDecl>(D))
+ Underlying = USD->getTargetDecl();
+
+ if (!isa<FunctionDecl>(Underlying) &&
+ !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) {
@@ -3350,22 +3376,6 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
continue;
}
- auto *Underlying = D;
- if (auto *USD = dyn_cast<UsingShadowDecl>(D))
- Underlying = USD->getTargetDecl();
-
- if (!isa<FunctionDecl>(Underlying) &&
- !isa<FunctionTemplateDecl>(Underlying))
- continue;
-
- if (!isVisible(D)) {
- D = findAcceptableDecl(*this, D);
- if (!D)
- continue;
- if (auto *USD = dyn_cast<UsingShadowDecl>(D))
- Underlying = USD->getTargetDecl();
- }
-
// FIXME: Preserve D as the FoundDecl.
Result.insert(Underlying);
}
@@ -3385,26 +3395,26 @@ class ShadowContextRAII;
class VisibleDeclsRecord {
public:
- /// \brief An entry in the shadow map, which is optimized to store a
+ /// An entry in the shadow map, which is optimized to store a
/// single declaration (the common case) but can also store a list
/// of declarations.
typedef llvm::TinyPtrVector<NamedDecl*> ShadowMapEntry;
private:
- /// \brief A mapping from declaration names to the declarations that have
+ /// A mapping from declaration names to the declarations that have
/// this name within a particular scope.
typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
- /// \brief A list of shadow maps, which is used to model name hiding.
+ /// A list of shadow maps, which is used to model name hiding.
std::list<ShadowMap> ShadowMaps;
- /// \brief The declaration contexts we have already visited.
+ /// The declaration contexts we have already visited.
llvm::SmallPtrSet<DeclContext *, 8> VisitedContexts;
friend class ShadowContextRAII;
public:
- /// \brief Determine whether we have already visited this context
+ /// Determine whether we have already visited this context
/// (and, if not, note that we are going to visit that context now).
bool visitedContext(DeclContext *Ctx) {
return !VisitedContexts.insert(Ctx).second;
@@ -3414,20 +3424,20 @@ public:
return VisitedContexts.count(Ctx);
}
- /// \brief Determine whether the given declaration is hidden in the
+ /// Determine whether the given declaration is hidden in the
/// current scope.
///
/// \returns the declaration that hides the given declaration, or
/// NULL if no such declaration exists.
NamedDecl *checkHidden(NamedDecl *ND);
- /// \brief Add a declaration to the current shadow map.
+ /// Add a declaration to the current shadow map.
void add(NamedDecl *ND) {
ShadowMaps.back()[ND->getDeclName()].push_back(ND);
}
};
-/// \brief RAII object that records when we've entered a shadow context.
+/// RAII object that records when we've entered a shadow context.
class ShadowContextRAII {
VisibleDeclsRecord &Visible;
@@ -3494,7 +3504,8 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
bool InBaseClass,
VisibleDeclConsumer &Consumer,
VisibleDeclsRecord &Visited,
- bool IncludeDependentBases = false) {
+ bool IncludeDependentBases,
+ bool LoadExternal) {
if (!Ctx)
return;
@@ -3502,6 +3513,8 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
if (Visited.visitedContext(Ctx->getPrimaryContext()))
return;
+ Consumer.EnteredContext(Ctx);
+
// Outside C++, lookup results for the TU live on identifiers.
if (isa<TranslationUnitDecl>(Ctx) &&
!Result.getSema().getLangOpts().CPlusPlus) {
@@ -3509,11 +3522,12 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
auto &Idents = S.Context.Idents;
// Ensure all external identifiers are in the identifier table.
- if (IdentifierInfoLookup *External = Idents.getExternalIdentifierLookup()) {
- std::unique_ptr<IdentifierIterator> Iter(External->getIdentifiers());
- for (StringRef Name = Iter->Next(); !Name.empty(); Name = Iter->Next())
- Idents.get(Name);
- }
+ if (LoadExternal)
+ if (IdentifierInfoLookup *External = Idents.getExternalIdentifierLookup()) {
+ std::unique_ptr<IdentifierIterator> Iter(External->getIdentifiers());
+ for (StringRef Name = Iter->Next(); !Name.empty(); Name = Iter->Next())
+ Idents.get(Name);
+ }
// Walk all lookup results in the TU for each identifier.
for (const auto &Ident : Idents) {
@@ -3535,8 +3549,13 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx))
Result.getSema().ForceDeclarationOfImplicitMembers(Class);
+ // We sometimes skip loading namespace-level results (they tend to be huge).
+ bool Load = LoadExternal ||
+ !(isa<TranslationUnitDecl>(Ctx) || isa<NamespaceDecl>(Ctx));
// Enumerate all of the results in this context.
- for (DeclContextLookupResult R : Ctx->lookups()) {
+ for (DeclContextLookupResult R :
+ Load ? Ctx->lookups()
+ : Ctx->noload_lookups(/*PreserveInternalState=*/false)) {
for (auto *D : R) {
if (auto *ND = Result.getAcceptableDecl(D)) {
Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
@@ -3553,7 +3572,7 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
continue;
LookupVisibleDecls(I->getNominatedNamespace(), Result,
QualifiedNameLookup, InBaseClass, Consumer, Visited,
- IncludeDependentBases);
+ IncludeDependentBases, LoadExternal);
}
}
@@ -3610,7 +3629,7 @@ 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);
+ Visited, IncludeDependentBases, LoadExternal);
}
}
@@ -3619,22 +3638,23 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
// Traverse categories.
for (auto *Cat : IFace->visible_categories()) {
ShadowContextRAII Shadow(Visited);
- LookupVisibleDecls(Cat, Result, QualifiedNameLookup, false,
- Consumer, Visited);
+ LookupVisibleDecls(Cat, Result, QualifiedNameLookup, false, Consumer,
+ Visited, IncludeDependentBases, LoadExternal);
}
// Traverse protocols.
for (auto *I : IFace->all_referenced_protocols()) {
ShadowContextRAII Shadow(Visited);
LookupVisibleDecls(I, Result, QualifiedNameLookup, false, Consumer,
- Visited);
+ Visited, IncludeDependentBases, LoadExternal);
}
// Traverse the superclass.
if (IFace->getSuperClass()) {
ShadowContextRAII Shadow(Visited);
LookupVisibleDecls(IFace->getSuperClass(), Result, QualifiedNameLookup,
- true, Consumer, Visited);
+ true, Consumer, Visited, IncludeDependentBases,
+ LoadExternal);
}
// If there is an implementation, traverse it. We do this to find
@@ -3642,26 +3662,28 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
if (IFace->getImplementation()) {
ShadowContextRAII Shadow(Visited);
LookupVisibleDecls(IFace->getImplementation(), Result,
- QualifiedNameLookup, InBaseClass, Consumer, Visited);
+ QualifiedNameLookup, InBaseClass, Consumer, Visited,
+ IncludeDependentBases, LoadExternal);
}
} else if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Ctx)) {
for (auto *I : Protocol->protocols()) {
ShadowContextRAII Shadow(Visited);
LookupVisibleDecls(I, Result, QualifiedNameLookup, false, Consumer,
- Visited);
+ Visited, IncludeDependentBases, LoadExternal);
}
} else if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Ctx)) {
for (auto *I : Category->protocols()) {
ShadowContextRAII Shadow(Visited);
LookupVisibleDecls(I, Result, QualifiedNameLookup, false, Consumer,
- Visited);
+ Visited, IncludeDependentBases, LoadExternal);
}
// If there is an implementation, traverse it.
if (Category->getImplementation()) {
ShadowContextRAII Shadow(Visited);
LookupVisibleDecls(Category->getImplementation(), Result,
- QualifiedNameLookup, true, Consumer, Visited);
+ QualifiedNameLookup, true, Consumer, Visited,
+ IncludeDependentBases, LoadExternal);
}
}
}
@@ -3669,7 +3691,8 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
static void LookupVisibleDecls(Scope *S, LookupResult &Result,
UnqualUsingDirectiveSet &UDirs,
VisibleDeclConsumer &Consumer,
- VisibleDeclsRecord &Visited) {
+ VisibleDeclsRecord &Visited,
+ bool LoadExternal) {
if (!S)
return;
@@ -3708,7 +3731,8 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
Result.getNameLoc(), Sema::LookupMemberName);
if (ObjCInterfaceDecl *IFace = Method->getClassInterface()) {
LookupVisibleDecls(IFace, IvarResult, /*QualifiedNameLookup=*/false,
- /*InBaseClass=*/false, Consumer, Visited);
+ /*InBaseClass=*/false, Consumer, Visited,
+ /*IncludeDependentBases=*/false, LoadExternal);
}
}
@@ -3722,7 +3746,8 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
continue;
LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/false,
- /*InBaseClass=*/false, Consumer, Visited);
+ /*InBaseClass=*/false, Consumer, Visited,
+ /*IncludeDependentBases=*/false, LoadExternal);
}
} else if (!S->getParent()) {
// Look into the translation unit scope. We walk through the translation
@@ -3736,7 +3761,8 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
// in DeclContexts unless we have to" optimization), we can eliminate this.
Entity = Result.getSema().Context.getTranslationUnitDecl();
LookupVisibleDecls(Entity, Result, /*QualifiedNameLookup=*/false,
- /*InBaseClass=*/false, Consumer, Visited);
+ /*InBaseClass=*/false, Consumer, Visited,
+ /*IncludeDependentBases=*/false, LoadExternal);
}
if (Entity) {
@@ -3745,17 +3771,19 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
for (const UnqualUsingEntry &UUE : UDirs.getNamespacesFor(Entity))
LookupVisibleDecls(const_cast<DeclContext *>(UUE.getNominatedNamespace()),
Result, /*QualifiedNameLookup=*/false,
- /*InBaseClass=*/false, Consumer, Visited);
+ /*InBaseClass=*/false, Consumer, Visited,
+ /*IncludeDependentBases=*/false, LoadExternal);
}
// Lookup names in the parent scope.
ShadowContextRAII Shadow(Visited);
- LookupVisibleDecls(S->getParent(), Result, UDirs, Consumer, Visited);
+ LookupVisibleDecls(S->getParent(), Result, UDirs, Consumer, Visited,
+ LoadExternal);
}
void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind,
VisibleDeclConsumer &Consumer,
- bool IncludeGlobalScope) {
+ bool IncludeGlobalScope, bool LoadExternal) {
// Determine the set of using directives available during
// unqualified name lookup.
Scope *Initial = S;
@@ -3776,13 +3804,13 @@ void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind,
if (!IncludeGlobalScope)
Visited.visitedContext(Context.getTranslationUnitDecl());
ShadowContextRAII Shadow(Visited);
- ::LookupVisibleDecls(Initial, Result, UDirs, Consumer, Visited);
+ ::LookupVisibleDecls(Initial, Result, UDirs, Consumer, Visited, LoadExternal);
}
void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
VisibleDeclConsumer &Consumer,
bool IncludeGlobalScope,
- bool IncludeDependentBases) {
+ bool IncludeDependentBases, bool LoadExternal) {
LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind);
Result.setAllowHidden(Consumer.includeHiddenDecls());
VisibleDeclsRecord Visited;
@@ -3791,7 +3819,7 @@ void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
ShadowContextRAII Shadow(Visited);
::LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/true,
/*InBaseClass=*/false, Consumer, Visited,
- IncludeDependentBases);
+ IncludeDependentBases, LoadExternal);
}
/// LookupOrCreateLabel - Do a name lookup of a label with the specified name.
@@ -3846,7 +3874,7 @@ static void LookupPotentialTypoResult(Sema &SemaRef,
bool isObjCIvarLookup,
bool FindHidden);
-/// \brief Check whether the declarations found for a typo correction are
+/// Check whether the declarations found for a typo correction are
/// visible. Set the correction's RequiresImport flag to true if none of the
/// declarations are visible, false otherwise.
static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC) {
@@ -3865,17 +3893,13 @@ static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC) {
bool AnyVisibleDecls = !NewDecls.empty();
for (/**/; DI != DE; ++DI) {
- NamedDecl *VisibleDecl = *DI;
- if (!LookupResult::isVisible(SemaRef, *DI))
- VisibleDecl = findAcceptableDecl(SemaRef, *DI);
-
- if (VisibleDecl) {
+ if (LookupResult::isVisible(SemaRef, *DI)) {
if (!AnyVisibleDecls) {
// Found a visible decl, discard all hidden ones.
AnyVisibleDecls = true;
NewDecls.clear();
}
- NewDecls.push_back(VisibleDecl);
+ NewDecls.push_back(*DI);
} else if (!AnyVisibleDecls && !(*DI)->isModulePrivate())
NewDecls.push_back(*DI);
}
@@ -3945,8 +3969,7 @@ void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding,
// Only consider visible declarations and declarations from modules with
// names that exactly match.
- if (!LookupResult::isVisible(SemaRef, ND) && Name != Typo &&
- !findAcceptableDecl(SemaRef, ND))
+ if (!LookupResult::isVisible(SemaRef, ND) && Name != Typo)
return;
FoundName(Name->getName());
@@ -4337,7 +4360,7 @@ void TypoCorrectionConsumer::NamespaceSpecifierSet::addNameSpecifier(
DistanceMap[NumSpecifiers].push_back(SI);
}
-/// \brief Perform name lookup for a possible result for typo correction.
+/// Perform name lookup for a possible result for typo correction.
static void LookupPotentialTypoResult(Sema &SemaRef,
LookupResult &Res,
IdentifierInfo *Name,
@@ -4391,7 +4414,7 @@ static void LookupPotentialTypoResult(Sema &SemaRef,
}
}
-/// \brief Add keywords to the consumer as possible typo corrections.
+/// Add keywords to the consumer as possible typo corrections.
static void AddKeywordsToConsumer(Sema &SemaRef,
TypoCorrectionConsumer &Consumer,
Scope *S, CorrectionCandidateCallback &CCC,
@@ -4442,7 +4465,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
}
}
- if (SemaRef.getLangOpts().GNUMode)
+ if (SemaRef.getLangOpts().GNUKeywords)
Consumer.addKeywordResult("typeof");
} else if (CCC.WantFunctionLikeCasts) {
static const char *const CastableTypeSpecs[] = {
@@ -4512,7 +4535,8 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
if (S && S->getContinueParent())
Consumer.addKeywordResult("continue");
- if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
+ if (SemaRef.getCurFunction() &&
+ !SemaRef.getCurFunction()->SwitchStack.empty()) {
Consumer.addKeywordResult("case");
Consumer.addKeywordResult("default");
}
@@ -4681,7 +4705,7 @@ std::unique_ptr<TypoCorrectionConsumer> Sema::makeTypoCorrectionConsumer(
return Consumer;
}
-/// \brief Try to "correct" a typo in the source code by finding
+/// Try to "correct" a typo in the source code by finding
/// visible declarations whose names are similar to the name that was
/// present in the source code.
///
@@ -4810,7 +4834,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure && !SecondBestTC);
}
-/// \brief Try to "correct" a typo in the source code by finding
+/// Try to "correct" a typo in the source code by finding
/// visible declarations whose names are similar to the name that was
/// present in the source code.
///
@@ -4966,6 +4990,8 @@ bool FunctionCallFilterCCC::ValidateCandidate(const TypoCorrection &candidate) {
// determine if it is a pointer or reference to a function. If so,
// check against the number of arguments expected for the pointee.
QualType ValType = cast<ValueDecl>(ND)->getType();
+ if (ValType.isNull())
+ continue;
if (ValType->isAnyPointerType() || ValType->isReferenceType())
ValType = ValType->getPointeeType();
if (const FunctionProtoType *FPT = ValType->getAs<FunctionProtoType>())
@@ -5047,7 +5073,7 @@ void Sema::diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl,
Recover);
}
-/// \brief Get a "quoted.h" or <angled.h> include path to use in a diagnostic
+/// Get a "quoted.h" or <angled.h> include path to use in a diagnostic
/// suggesting the addition of a #include of the specified file.
static std::string getIncludeStringForHeader(Preprocessor &PP,
const FileEntry *E) {
@@ -5126,7 +5152,7 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, NamedDecl *Decl,
createImplicitModuleImportForErrorRecovery(UseLoc, Modules[0]);
}
-/// \brief Diagnose a successfully-corrected typo. Separated from the correction
+/// Diagnose a successfully-corrected typo. Separated from the correction
/// itself to allow external validation of the result, etc.
///
/// \param Correction The result of performing typo correction.
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
index ea5b1da46f32..2983ec51f49e 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
@@ -104,7 +104,7 @@ static void checkPropertyDeclWithOwnership(Sema &S,
<< propertyLifetime;
}
-/// \brief Check this Objective-C property against a property declared in the
+/// Check this Objective-C property against a property declared in the
/// given protocol.
static void
CheckPropertyAgainstProtocol(Sema &S, ObjCPropertyDecl *Prop,
@@ -618,7 +618,7 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
TInfo = Context.getTrivialTypeSourceInfo(T, TLoc);
}
- DeclContext *DC = cast<DeclContext>(CDecl);
+ DeclContext *DC = CDecl;
ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC,
FD.D.getIdentifierLoc(),
PropertyId, AtLoc,
@@ -897,14 +897,24 @@ SelectPropertyForSynthesisFromProtocols(Sema &S, SourceLocation AtLoc,
: HasUnexpectedAttribute;
Mismatches.push_back({Prop, Kind, AttributeName});
};
- if (isIncompatiblePropertyAttribute(OriginalAttributes, Attr,
+ // The ownership might be incompatible unless the property has no explicit
+ // ownership.
+ bool HasOwnership = (Attr & (ObjCPropertyDecl::OBJC_PR_retain |
+ ObjCPropertyDecl::OBJC_PR_strong |
+ ObjCPropertyDecl::OBJC_PR_copy |
+ ObjCPropertyDecl::OBJC_PR_assign |
+ ObjCPropertyDecl::OBJC_PR_unsafe_unretained |
+ ObjCPropertyDecl::OBJC_PR_weak)) != 0;
+ if (HasOwnership &&
+ isIncompatiblePropertyAttribute(OriginalAttributes, Attr,
ObjCPropertyDecl::OBJC_PR_copy)) {
Diag(OriginalAttributes & ObjCPropertyDecl::OBJC_PR_copy, "copy");
continue;
}
- if (areIncompatiblePropertyAttributes(
- OriginalAttributes, Attr, ObjCPropertyDecl::OBJC_PR_retain |
- ObjCPropertyDecl::OBJC_PR_strong)) {
+ if (HasOwnership && areIncompatiblePropertyAttributes(
+ OriginalAttributes, Attr,
+ ObjCPropertyDecl::OBJC_PR_retain |
+ ObjCPropertyDecl::OBJC_PR_strong)) {
Diag(OriginalAttributes & (ObjCPropertyDecl::OBJC_PR_retain |
ObjCPropertyDecl::OBJC_PR_strong),
"retain (or strong)");
@@ -1819,7 +1829,7 @@ static bool SuperClassImplementsProperty(ObjCInterfaceDecl *IDecl,
return false;
}
-/// \brief Default synthesizes all properties which must be synthesized
+/// Default synthesizes all properties which must be synthesized
/// in class's \@implementation.
void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl *IMPDecl,
ObjCInterfaceDecl *IDecl,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
index 24b58e8fd12b..e1a4c420d402 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
/// \file
-/// \brief This file implements semantic analysis for OpenMP directives and
+/// This file implements semantic analysis for OpenMP directives and
/// clauses.
///
//===----------------------------------------------------------------------===//
@@ -35,17 +35,17 @@ using namespace clang;
// Stack of data-sharing attributes for variables
//===----------------------------------------------------------------------===//
-static Expr *CheckMapClauseExpressionBase(
+static const Expr *checkMapClauseExpressionBase(
Sema &SemaRef, Expr *E,
OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
OpenMPClauseKind CKind, bool NoDiagnose);
namespace {
-/// \brief Default data sharing attributes, which can be applied to directive.
+/// Default data sharing attributes, which can be applied to directive.
enum DefaultDataSharingAttributes {
- DSA_unspecified = 0, /// \brief Data sharing attribute not specified.
- DSA_none = 1 << 0, /// \brief Default data sharing attribute 'none'.
- DSA_shared = 1 << 1, /// \brief Default data sharing attribute 'shared'.
+ DSA_unspecified = 0, /// Data sharing attribute not specified.
+ DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
+ DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
};
/// Attributes of the defaultmap clause.
@@ -54,51 +54,53 @@ enum DefaultMapAttributes {
DMA_tofrom_scalar, /// Default mapping is 'tofrom:scalar'.
};
-/// \brief Stack for tracking declarations used in OpenMP directives and
+/// Stack for tracking declarations used in OpenMP directives and
/// clauses and their data-sharing attributes.
-class DSAStackTy final {
+class DSAStackTy {
public:
- struct DSAVarData final {
+ struct DSAVarData {
OpenMPDirectiveKind DKind = OMPD_unknown;
OpenMPClauseKind CKind = OMPC_unknown;
- Expr *RefExpr = nullptr;
+ const Expr *RefExpr = nullptr;
DeclRefExpr *PrivateCopy = nullptr;
SourceLocation ImplicitDSALoc;
DSAVarData() = default;
- DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, Expr *RefExpr,
- DeclRefExpr *PrivateCopy, SourceLocation ImplicitDSALoc)
+ DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
+ const Expr *RefExpr, DeclRefExpr *PrivateCopy,
+ SourceLocation ImplicitDSALoc)
: DKind(DKind), CKind(CKind), RefExpr(RefExpr),
PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc) {}
};
- typedef llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>
- OperatorOffsetTy;
+ using OperatorOffsetTy =
+ llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
private:
- struct DSAInfo final {
+ struct DSAInfo {
OpenMPClauseKind Attributes = OMPC_unknown;
/// Pointer to a reference expression and a flag which shows that the
/// variable is marked as lastprivate(true) or not (false).
- llvm::PointerIntPair<Expr *, 1, bool> RefExpr;
+ llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
DeclRefExpr *PrivateCopy = nullptr;
};
- typedef llvm::DenseMap<ValueDecl *, DSAInfo> DeclSAMapTy;
- typedef llvm::DenseMap<ValueDecl *, Expr *> AlignedMapTy;
- typedef std::pair<unsigned, VarDecl *> LCDeclInfo;
- typedef llvm::DenseMap<ValueDecl *, LCDeclInfo> LoopControlVariablesMapTy;
+ using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
+ using AlignedMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
+ using LCDeclInfo = std::pair<unsigned, VarDecl *>;
+ using LoopControlVariablesMapTy =
+ llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
/// Struct that associates a component with the clause kind where they are
/// found.
struct MappedExprComponentTy {
OMPClauseMappableExprCommon::MappableExprComponentLists Components;
OpenMPClauseKind Kind = OMPC_unknown;
};
- typedef llvm::DenseMap<ValueDecl *, MappedExprComponentTy>
- MappedExprComponentsTy;
- typedef llvm::StringMap<std::pair<OMPCriticalDirective *, llvm::APSInt>>
- CriticalsWithHintsTy;
- typedef llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>
- DoacrossDependMapTy;
+ using MappedExprComponentsTy =
+ llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
+ using CriticalsWithHintsTy =
+ llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
+ using DoacrossDependMapTy =
+ llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>;
struct ReductionData {
- typedef llvm::PointerEmbeddedInt<BinaryOperatorKind, 16> BOKPtrType;
+ using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
SourceRange ReductionRange;
llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
ReductionData() = default;
@@ -111,9 +113,10 @@ private:
ReductionOp = RefExpr;
}
};
- typedef llvm::DenseMap<ValueDecl *, ReductionData> DeclReductionMapTy;
+ using DeclReductionMapTy =
+ llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
- struct SharingMapTy final {
+ struct SharingMapTy {
DeclSAMapTy SharingMap;
DeclReductionMapTy ReductionMap;
AlignedMapTy AlignedMap;
@@ -131,10 +134,10 @@ private:
/// get the data (loop counters etc.) about enclosing loop-based construct.
/// This data is required during codegen.
DoacrossDependMapTy DoacrossDepends;
- /// \brief first argument (Expr *) contains optional argument of the
+ /// 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<Expr *, 1, bool> OrderedRegion;
+ llvm::PointerIntPair<const Expr *, 1, bool> OrderedRegion;
bool NowaitRegion = false;
bool CancelRegion = false;
unsigned AssociatedLoops = 1;
@@ -148,25 +151,25 @@ private:
SharingMapTy() = default;
};
- typedef SmallVector<SharingMapTy, 4> StackTy;
+ using StackTy = SmallVector<SharingMapTy, 4>;
- /// \brief Stack of used declaration and their data-sharing attributes.
+ /// Stack of used declaration and their data-sharing attributes.
DeclSAMapTy Threadprivates;
const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
- /// \brief true, if check for DSA must be from parent directive, false, if
+ /// true, if check for DSA must be from parent directive, false, if
/// from current directive.
OpenMPClauseKind ClauseKindMode = OMPC_unknown;
Sema &SemaRef;
bool ForceCapturing = false;
CriticalsWithHintsTy Criticals;
- typedef SmallVector<SharingMapTy, 8>::reverse_iterator reverse_iterator;
+ using iterator = StackTy::const_reverse_iterator;
- DSAVarData getDSA(StackTy::reverse_iterator &Iter, ValueDecl *D);
+ DSAVarData getDSA(iterator &Iter, ValueDecl *D) const;
- /// \brief Checks if the variable is a local for OpenMP region.
- bool isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter);
+ /// Checks if the variable is a local for OpenMP region.
+ bool isOpenMPLocal(VarDecl *D, iterator Iter) const;
bool isStackEmpty() const {
return Stack.empty() ||
@@ -223,59 +226,61 @@ public:
}
}
- void addCriticalWithHint(OMPCriticalDirective *D, llvm::APSInt Hint) {
- Criticals[D->getDirectiveName().getAsString()] = std::make_pair(D, Hint);
+ void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
+ Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
}
- const std::pair<OMPCriticalDirective *, llvm::APSInt>
+ const std::pair<const OMPCriticalDirective *, llvm::APSInt>
getCriticalWithHint(const DeclarationNameInfo &Name) const {
auto I = Criticals.find(Name.getAsString());
if (I != Criticals.end())
return I->second;
return std::make_pair(nullptr, llvm::APSInt());
}
- /// \brief If 'aligned' declaration for given variable \a D was not seen yet,
+ /// If 'aligned' declaration for given variable \a D was not seen yet,
/// add it and return NULL; otherwise return previous occurrence's expression
/// for diagnostics.
- Expr *addUniqueAligned(ValueDecl *D, Expr *NewDE);
+ const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
- /// \brief Register specified variable as loop control variable.
- void addLoopControlVariable(ValueDecl *D, VarDecl *Capture);
- /// \brief Check if the specified variable is a loop control variable for
+ /// Register specified variable as loop control variable.
+ void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
+ /// Check if the specified variable is a loop control variable for
/// current region.
/// \return The index of the loop control variable in the list of associated
/// for-loops (from outer to inner).
- LCDeclInfo isLoopControlVariable(ValueDecl *D);
- /// \brief Check if the specified variable is a loop control variable for
+ const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
+ /// Check if the specified variable is a loop control variable for
/// parent region.
/// \return The index of the loop control variable in the list of associated
/// for-loops (from outer to inner).
- LCDeclInfo isParentLoopControlVariable(ValueDecl *D);
- /// \brief Get the loop control variable for the I-th loop (or nullptr) in
+ const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
+ /// Get the loop control variable for the I-th loop (or nullptr) in
/// parent directive.
- ValueDecl *getParentLoopControlVariable(unsigned I);
+ const ValueDecl *getParentLoopControlVariable(unsigned I) const;
- /// \brief Adds explicit data sharing attribute to the specified declaration.
- void addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A,
+ /// Adds explicit data sharing attribute to the specified declaration.
+ void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
DeclRefExpr *PrivateCopy = nullptr);
/// Adds additional information for the reduction items with the reduction id
/// represented as an operator.
- void addTaskgroupReductionData(ValueDecl *D, SourceRange SR,
+ void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
BinaryOperatorKind BOK);
/// Adds additional information for the reduction items with the reduction id
/// represented as reduction identifier.
- void addTaskgroupReductionData(ValueDecl *D, SourceRange SR,
+ void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
const Expr *ReductionRef);
/// Returns the location and reduction operation from the innermost parent
/// region for the given \p D.
- DSAVarData getTopMostTaskgroupReductionData(ValueDecl *D, SourceRange &SR,
- BinaryOperatorKind &BOK,
- Expr *&TaskgroupDescriptor);
+ const DSAVarData
+ getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
+ BinaryOperatorKind &BOK,
+ Expr *&TaskgroupDescriptor) const;
/// Returns the location and reduction operation from the innermost parent
/// region for the given \p D.
- DSAVarData getTopMostTaskgroupReductionData(ValueDecl *D, SourceRange &SR,
- const Expr *&ReductionRef,
- Expr *&TaskgroupDescriptor);
+ const DSAVarData
+ getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
+ const Expr *&ReductionRef,
+ Expr *&TaskgroupDescriptor) const;
/// Return reduction reference expression for the current taskgroup.
Expr *getTaskgroupReductionRef() const {
assert(Stack.back().first.back().Directive == OMPD_taskgroup &&
@@ -285,74 +290,75 @@ public:
}
/// Checks if the given \p VD declaration is actually a taskgroup reduction
/// descriptor variable at the \p Level of OpenMP regions.
- bool isTaskgroupReductionRef(ValueDecl *VD, unsigned Level) const {
+ bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
return Stack.back().first[Level].TaskgroupReductionRef &&
cast<DeclRefExpr>(Stack.back().first[Level].TaskgroupReductionRef)
->getDecl() == VD;
}
- /// \brief Returns data sharing attributes from top of the stack for the
+ /// Returns data sharing attributes from top of the stack for the
/// specified declaration.
- DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
- /// \brief Returns data-sharing attributes for the specified declaration.
- DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent);
- /// \brief Checks if the specified variables has data-sharing attributes which
+ const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
+ /// Returns data-sharing attributes for the specified declaration.
+ const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
+ /// Checks if the specified variables has data-sharing attributes which
/// match specified \a CPred predicate in any directive which matches \a DPred
/// predicate.
- DSAVarData hasDSA(ValueDecl *D,
- const llvm::function_ref<bool(OpenMPClauseKind)> &CPred,
- const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred,
- bool FromParent);
- /// \brief Checks if the specified variables has data-sharing attributes which
+ const DSAVarData
+ hasDSA(ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> CPred,
+ const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
+ bool FromParent) const;
+ /// Checks if the specified variables has data-sharing attributes which
/// match specified \a CPred predicate in any innermost directive which
/// matches \a DPred predicate.
- DSAVarData
+ const DSAVarData
hasInnermostDSA(ValueDecl *D,
- const llvm::function_ref<bool(OpenMPClauseKind)> &CPred,
- const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred,
- bool FromParent);
- /// \brief Checks if the specified variables has explicit data-sharing
+ const llvm::function_ref<bool(OpenMPClauseKind)> CPred,
+ const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
+ bool FromParent) const;
+ /// Checks if the specified variables has explicit data-sharing
/// attributes which match specified \a CPred predicate at the specified
/// OpenMP region.
- bool hasExplicitDSA(ValueDecl *D,
- const llvm::function_ref<bool(OpenMPClauseKind)> &CPred,
- unsigned Level, bool NotLastprivate = false);
+ bool hasExplicitDSA(const ValueDecl *D,
+ const llvm::function_ref<bool(OpenMPClauseKind)> CPred,
+ unsigned Level, bool NotLastprivate = false) const;
- /// \brief Returns true if the directive at level \Level matches in the
+ /// Returns true if the directive at level \Level matches in the
/// specified \a DPred predicate.
bool hasExplicitDirective(
- const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred,
- unsigned Level);
+ const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
+ unsigned Level) const;
- /// \brief Finds a directive which matches specified \a DPred predicate.
- bool hasDirective(const llvm::function_ref<bool(OpenMPDirectiveKind,
- const DeclarationNameInfo &,
- SourceLocation)> &DPred,
- bool FromParent);
+ /// Finds a directive which matches specified \a DPred predicate.
+ bool hasDirective(
+ const llvm::function_ref<bool(
+ OpenMPDirectiveKind, const DeclarationNameInfo &, SourceLocation)>
+ DPred,
+ bool FromParent) const;
- /// \brief Returns currently analyzed directive.
+ /// Returns currently analyzed directive.
OpenMPDirectiveKind getCurrentDirective() const {
return isStackEmpty() ? OMPD_unknown : Stack.back().first.back().Directive;
}
- /// \brief Returns directive kind at specified level.
+ /// Returns directive kind at specified level.
OpenMPDirectiveKind getDirective(unsigned Level) const {
assert(!isStackEmpty() && "No directive at specified level.");
return Stack.back().first[Level].Directive;
}
- /// \brief Returns parent directive.
+ /// Returns parent directive.
OpenMPDirectiveKind getParentDirective() const {
if (isStackEmpty() || Stack.back().first.size() == 1)
return OMPD_unknown;
return std::next(Stack.back().first.rbegin())->Directive;
}
- /// \brief Set default data sharing attribute to none.
+ /// Set default data sharing attribute to none.
void setDefaultDSANone(SourceLocation Loc) {
assert(!isStackEmpty());
Stack.back().first.back().DefaultAttr = DSA_none;
Stack.back().first.back().DefaultAttrLoc = Loc;
}
- /// \brief Set default data sharing attribute to shared.
+ /// Set default data sharing attribute to shared.
void setDefaultDSAShared(SourceLocation Loc) {
assert(!isStackEmpty());
Stack.back().first.back().DefaultAttr = DSA_shared;
@@ -385,66 +391,66 @@ public:
: Stack.back().first.back().DefaultMapAttrLoc;
}
- /// \brief Checks if the specified variable is a threadprivate.
+ /// Checks if the specified variable is a threadprivate.
bool isThreadPrivate(VarDecl *D) {
- DSAVarData DVar = getTopDSA(D, false);
+ const DSAVarData DVar = getTopDSA(D, false);
return isOpenMPThreadPrivate(DVar.CKind);
}
- /// \brief Marks current region as ordered (it has an 'ordered' clause).
- void setOrderedRegion(bool IsOrdered, Expr *Param) {
+ /// Marks current region as ordered (it has an 'ordered' clause).
+ void setOrderedRegion(bool IsOrdered, const Expr *Param) {
assert(!isStackEmpty());
Stack.back().first.back().OrderedRegion.setInt(IsOrdered);
Stack.back().first.back().OrderedRegion.setPointer(Param);
}
- /// \brief Returns true, if parent region is ordered (has associated
+ /// 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();
}
- /// \brief Returns optional parameter for the ordered region.
- Expr *getParentOrderedRegionParam() const {
+ /// 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();
}
- /// \brief Marks current region as nowait (it has a 'nowait' clause).
+ /// Marks current region as nowait (it has a 'nowait' clause).
void setNowaitRegion(bool IsNowait = true) {
assert(!isStackEmpty());
Stack.back().first.back().NowaitRegion = IsNowait;
}
- /// \brief Returns true, if parent region is nowait (has associated
+ /// Returns true, if parent region is nowait (has associated
/// 'nowait' clause), false - otherwise.
bool isParentNowaitRegion() const {
if (isStackEmpty() || Stack.back().first.size() == 1)
return false;
return std::next(Stack.back().first.rbegin())->NowaitRegion;
}
- /// \brief Marks parent region as cancel region.
+ /// Marks parent region as cancel region.
void setParentCancelRegion(bool Cancel = true) {
if (!isStackEmpty() && Stack.back().first.size() > 1) {
auto &StackElemRef = *std::next(Stack.back().first.rbegin());
StackElemRef.CancelRegion |= StackElemRef.CancelRegion || Cancel;
}
}
- /// \brief Return true if current region has inner cancel construct.
+ /// Return true if current region has inner cancel construct.
bool isCancelRegion() const {
return isStackEmpty() ? false : Stack.back().first.back().CancelRegion;
}
- /// \brief Set collapse value for the region.
+ /// Set collapse value for the region.
void setAssociatedLoops(unsigned Val) {
assert(!isStackEmpty());
Stack.back().first.back().AssociatedLoops = Val;
}
- /// \brief Return collapse value for region.
+ /// Return collapse value for region.
unsigned getAssociatedLoops() const {
return isStackEmpty() ? 0 : Stack.back().first.back().AssociatedLoops;
}
- /// \brief Marks current target region as one with closely nested teams
+ /// Marks current target region as one with closely nested teams
/// region.
void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
if (!isStackEmpty() && Stack.back().first.size() > 1) {
@@ -452,11 +458,11 @@ public:
TeamsRegionLoc;
}
}
- /// \brief Returns true, if current region has closely nested teams region.
+ /// Returns true, if current region has closely nested teams region.
bool hasInnerTeamsRegion() const {
return getInnerTeamsRegionLoc().isValid();
}
- /// \brief Returns location of the nested teams region (if any).
+ /// Returns location of the nested teams region (if any).
SourceLocation getInnerTeamsRegionLoc() const {
return isStackEmpty() ? SourceLocation()
: Stack.back().first.back().InnerTeamsRegionLoc;
@@ -465,10 +471,7 @@ public:
Scope *getCurScope() const {
return isStackEmpty() ? nullptr : Stack.back().first.back().CurScope;
}
- Scope *getCurScope() {
- return isStackEmpty() ? nullptr : Stack.back().first.back().CurScope;
- }
- SourceLocation getConstructLoc() {
+ SourceLocation getConstructLoc() const {
return isStackEmpty() ? SourceLocation()
: Stack.back().first.back().ConstructLoc;
}
@@ -476,10 +479,11 @@ public:
/// Do the check specified in \a Check to all component lists and return true
/// if any issue is found.
bool checkMappableExprComponentListsForDecl(
- ValueDecl *VD, bool CurrentRegionOnly,
+ const ValueDecl *VD, bool CurrentRegionOnly,
const llvm::function_ref<
bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
- OpenMPClauseKind)> &Check) {
+ OpenMPClauseKind)>
+ Check) const {
if (isStackEmpty())
return false;
auto SI = Stack.back().first.rbegin();
@@ -488,16 +492,16 @@ public:
if (SI == SE)
return false;
- if (CurrentRegionOnly) {
+ if (CurrentRegionOnly)
SE = std::next(SI);
- } else {
- ++SI;
- }
+ else
+ std::advance(SI, 1);
for (; SI != SE; ++SI) {
auto MI = SI->MappedExprComponents.find(VD);
if (MI != SI->MappedExprComponents.end())
- for (auto &L : MI->second.Components)
+ for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
+ MI->second.Components)
if (Check(L, MI->second.Kind))
return true;
}
@@ -507,10 +511,11 @@ public:
/// Do the check specified in \a Check to all component lists at a given level
/// and return true if any issue is found.
bool checkMappableExprComponentListsForDeclAtLevel(
- ValueDecl *VD, unsigned Level,
+ const ValueDecl *VD, unsigned Level,
const llvm::function_ref<
bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
- OpenMPClauseKind)> &Check) {
+ OpenMPClauseKind)>
+ Check) const {
if (isStackEmpty())
return false;
@@ -522,7 +527,8 @@ public:
auto MI = StartI->MappedExprComponents.find(VD);
if (MI != StartI->MappedExprComponents.end())
- for (auto &L : MI->second.Components)
+ for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
+ MI->second.Components)
if (Check(L, MI->second.Kind))
return true;
return false;
@@ -531,12 +537,13 @@ public:
/// Create a new mappable expression component list associated with a given
/// declaration and initialize it with the provided list of components.
void addMappableExpressionComponents(
- ValueDecl *VD,
+ const ValueDecl *VD,
OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
OpenMPClauseKind WhereFoundClauseKind) {
assert(!isStackEmpty() &&
"Not expecting to retrieve components from a empty stack!");
- auto &MEC = Stack.back().first.back().MappedExprComponents[VD];
+ MappedExprComponentTy &MEC =
+ Stack.back().first.back().MappedExprComponents[VD];
// Create new entry and append the new components there.
MEC.Components.resize(MEC.Components.size() + 1);
MEC.Components.back().append(Components.begin(), Components.end());
@@ -547,18 +554,19 @@ public:
assert(!isStackEmpty());
return Stack.back().first.size() - 1;
}
- void addDoacrossDependClause(OMPDependClause *C, OperatorOffsetTy &OpsOffs) {
+ void addDoacrossDependClause(OMPDependClause *C,
+ const OperatorOffsetTy &OpsOffs) {
assert(!isStackEmpty() && Stack.back().first.size() > 1);
- auto &StackElem = *std::next(Stack.back().first.rbegin());
+ SharingMapTy &StackElem = *std::next(Stack.back().first.rbegin());
assert(isOpenMPWorksharingDirective(StackElem.Directive));
- StackElem.DoacrossDepends.insert({C, OpsOffs});
+ StackElem.DoacrossDepends.try_emplace(C, OpsOffs);
}
llvm::iterator_range<DoacrossDependMapTy::const_iterator>
getDoacrossDependClauses() const {
assert(!isStackEmpty());
- auto &StackElem = Stack.back().first.back();
+ const SharingMapTy &StackElem = Stack.back().first.back();
if (isOpenMPWorksharingDirective(StackElem.Directive)) {
- auto &Ref = StackElem.DoacrossDepends;
+ const DoacrossDependMapTy &Ref = StackElem.DoacrossDepends;
return llvm::make_range(Ref.begin(), Ref.end());
}
return llvm::make_range(StackElem.DoacrossDepends.end(),
@@ -569,29 +577,34 @@ bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) {
return isOpenMPParallelDirective(DKind) || isOpenMPTaskingDirective(DKind) ||
isOpenMPTeamsDirective(DKind) || DKind == OMPD_unknown;
}
+
} // namespace
-static Expr *getExprAsWritten(Expr *E) {
- if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(E))
+static const Expr *getExprAsWritten(const Expr *E) {
+ if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(E))
E = ExprTemp->getSubExpr();
- if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
+ if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
E = MTE->GetTemporaryExpr();
- while (auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
+ while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
E = Binder->getSubExpr();
- if (auto *ICE = dyn_cast<ImplicitCastExpr>(E))
+ if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
E = ICE->getSubExprAsWritten();
return E->IgnoreParens();
}
-static ValueDecl *getCanonicalDecl(ValueDecl *D) {
- if (auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
- if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
+static Expr *getExprAsWritten(Expr *E) {
+ return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E)));
+}
+
+static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
+ if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
+ if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
D = ME->getMemberDecl();
- auto *VD = dyn_cast<VarDecl>(D);
- auto *FD = dyn_cast<FieldDecl>(D);
+ const auto *VD = dyn_cast<VarDecl>(D);
+ const auto *FD = dyn_cast<FieldDecl>(D);
if (VD != nullptr) {
VD = VD->getCanonicalDecl();
D = VD;
@@ -603,11 +616,16 @@ static ValueDecl *getCanonicalDecl(ValueDecl *D) {
return D;
}
-DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator &Iter,
- ValueDecl *D) {
+static ValueDecl *getCanonicalDecl(ValueDecl *D) {
+ return const_cast<ValueDecl *>(
+ getCanonicalDecl(const_cast<const ValueDecl *>(D)));
+}
+
+DSAStackTy::DSAVarData DSAStackTy::getDSA(iterator &Iter,
+ ValueDecl *D) const {
D = getCanonicalDecl(D);
auto *VD = dyn_cast<VarDecl>(D);
- auto *FD = dyn_cast<FieldDecl>(D);
+ const auto *FD = dyn_cast<FieldDecl>(D);
DSAVarData DVar;
if (isStackEmpty() || Iter == Stack.back().first.rend()) {
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
@@ -615,7 +633,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator &Iter,
// File-scope or namespace-scope variables referenced in called routines
// in the region are shared unless they appear in a threadprivate
// directive.
- if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(D))
+ if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
DVar.CKind = OMPC_shared;
// OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
@@ -646,9 +664,10 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator &Iter,
// Explicitly specified attributes and local variables with predetermined
// attributes.
if (Iter->SharingMap.count(D)) {
- DVar.RefExpr = Iter->SharingMap[D].RefExpr.getPointer();
- DVar.PrivateCopy = Iter->SharingMap[D].PrivateCopy;
- DVar.CKind = Iter->SharingMap[D].Attributes;
+ const DSAInfo &Data = Iter->SharingMap.lookup(D);
+ DVar.RefExpr = Data.RefExpr.getPointer();
+ DVar.PrivateCopy = Data.PrivateCopy;
+ DVar.CKind = Data.Attributes;
DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
return DVar;
}
@@ -683,7 +702,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator &Iter,
// bound to the current team is shared.
if (isOpenMPTaskingDirective(DVar.DKind)) {
DSAVarData DVarTemp;
- auto I = Iter, E = Stack.back().first.rend();
+ iterator I = Iter, E = Stack.back().first.rend();
do {
++I;
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
@@ -711,74 +730,75 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator &Iter,
return getDSA(++Iter, D);
}
-Expr *DSAStackTy::addUniqueAligned(ValueDecl *D, Expr *NewDE) {
+const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
+ const Expr *NewDE) {
assert(!isStackEmpty() && "Data sharing attributes stack is empty");
D = getCanonicalDecl(D);
- auto &StackElem = Stack.back().first.back();
+ SharingMapTy &StackElem = Stack.back().first.back();
auto It = StackElem.AlignedMap.find(D);
if (It == StackElem.AlignedMap.end()) {
assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
StackElem.AlignedMap[D] = NewDE;
return nullptr;
- } else {
- assert(It->second && "Unexpected nullptr expr in the aligned map");
- return It->second;
}
- return nullptr;
+ assert(It->second && "Unexpected nullptr expr in the aligned map");
+ return It->second;
}
-void DSAStackTy::addLoopControlVariable(ValueDecl *D, VarDecl *Capture) {
+void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
D = getCanonicalDecl(D);
- auto &StackElem = Stack.back().first.back();
- StackElem.LCVMap.insert(
- {D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture)});
+ SharingMapTy &StackElem = Stack.back().first.back();
+ StackElem.LCVMap.try_emplace(
+ D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
}
-DSAStackTy::LCDeclInfo DSAStackTy::isLoopControlVariable(ValueDecl *D) {
+const DSAStackTy::LCDeclInfo
+DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
D = getCanonicalDecl(D);
- auto &StackElem = Stack.back().first.back();
+ const SharingMapTy &StackElem = Stack.back().first.back();
auto It = StackElem.LCVMap.find(D);
if (It != StackElem.LCVMap.end())
return It->second;
return {0, nullptr};
}
-DSAStackTy::LCDeclInfo DSAStackTy::isParentLoopControlVariable(ValueDecl *D) {
+const DSAStackTy::LCDeclInfo
+DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
assert(!isStackEmpty() && Stack.back().first.size() > 1 &&
"Data-sharing attributes stack is empty");
D = getCanonicalDecl(D);
- auto &StackElem = *std::next(Stack.back().first.rbegin());
+ const SharingMapTy &StackElem = *std::next(Stack.back().first.rbegin());
auto It = StackElem.LCVMap.find(D);
if (It != StackElem.LCVMap.end())
return It->second;
return {0, nullptr};
}
-ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) {
+const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
assert(!isStackEmpty() && Stack.back().first.size() > 1 &&
"Data-sharing attributes stack is empty");
- auto &StackElem = *std::next(Stack.back().first.rbegin());
+ const SharingMapTy &StackElem = *std::next(Stack.back().first.rbegin());
if (StackElem.LCVMap.size() < I)
return nullptr;
- for (auto &Pair : StackElem.LCVMap)
+ for (const auto &Pair : StackElem.LCVMap)
if (Pair.second.first == I)
return Pair.first;
return nullptr;
}
-void DSAStackTy::addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A,
+void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
DeclRefExpr *PrivateCopy) {
D = getCanonicalDecl(D);
if (A == OMPC_threadprivate) {
- auto &Data = Threadprivates[D];
+ DSAInfo &Data = Threadprivates[D];
Data.Attributes = A;
Data.RefExpr.setPointer(E);
Data.PrivateCopy = nullptr;
} else {
assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
- auto &Data = Stack.back().first.back().SharingMap[D];
+ DSAInfo &Data = Stack.back().first.back().SharingMap[D];
assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
(A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
(A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
@@ -793,7 +813,8 @@ void DSAStackTy::addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A,
Data.RefExpr.setPointerAndInt(E, IsLastprivate);
Data.PrivateCopy = PrivateCopy;
if (PrivateCopy) {
- auto &Data = Stack.back().first.back().SharingMap[PrivateCopy->getDecl()];
+ DSAInfo &Data =
+ Stack.back().first.back().SharingMap[PrivateCopy->getDecl()];
Data.Attributes = A;
Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
Data.PrivateCopy = nullptr;
@@ -801,13 +822,14 @@ void DSAStackTy::addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A,
}
}
-/// \brief Build a variable declaration for OpenMP loop iteration variable.
+/// Build a variable declaration for OpenMP loop iteration variable.
static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
- StringRef Name, const AttrVec *Attrs = nullptr) {
+ StringRef Name, const AttrVec *Attrs = nullptr,
+ DeclRefExpr *OrigRef = nullptr) {
DeclContext *DC = SemaRef.CurContext;
IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
- VarDecl *Decl =
+ auto *Decl =
VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
if (Attrs) {
for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
@@ -815,6 +837,10 @@ static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
Decl->addAttr(*I);
}
Decl->setImplicit();
+ if (OrigRef) {
+ Decl->addAttr(
+ OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
+ }
return Decl;
}
@@ -828,14 +854,14 @@ static DeclRefExpr *buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty,
VK_LValue);
}
-void DSAStackTy::addTaskgroupReductionData(ValueDecl *D, SourceRange SR,
+void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
BinaryOperatorKind BOK) {
D = getCanonicalDecl(D);
assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
assert(
Stack.back().first.back().SharingMap[D].Attributes == OMPC_reduction &&
"Additional reduction info may be specified only for reduction items.");
- auto &ReductionData = Stack.back().first.back().ReductionMap[D];
+ ReductionData &ReductionData = Stack.back().first.back().ReductionMap[D];
assert(ReductionData.ReductionRange.isInvalid() &&
Stack.back().first.back().Directive == OMPD_taskgroup &&
"Additional reduction info may be specified only once for reduction "
@@ -844,21 +870,21 @@ void DSAStackTy::addTaskgroupReductionData(ValueDecl *D, SourceRange SR,
Expr *&TaskgroupReductionRef =
Stack.back().first.back().TaskgroupReductionRef;
if (!TaskgroupReductionRef) {
- auto *VD = buildVarDecl(SemaRef, SR.getBegin(),
- SemaRef.Context.VoidPtrTy, ".task_red.");
+ VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
+ SemaRef.Context.VoidPtrTy, ".task_red.");
TaskgroupReductionRef =
buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
}
}
-void DSAStackTy::addTaskgroupReductionData(ValueDecl *D, SourceRange SR,
+void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
const Expr *ReductionRef) {
D = getCanonicalDecl(D);
assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
assert(
Stack.back().first.back().SharingMap[D].Attributes == OMPC_reduction &&
"Additional reduction info may be specified only for reduction items.");
- auto &ReductionData = Stack.back().first.back().ReductionMap[D];
+ ReductionData &ReductionData = Stack.back().first.back().ReductionMap[D];
assert(ReductionData.ReductionRange.isInvalid() &&
Stack.back().first.back().Directive == OMPD_taskgroup &&
"Additional reduction info may be specified only once for reduction "
@@ -867,28 +893,27 @@ void DSAStackTy::addTaskgroupReductionData(ValueDecl *D, SourceRange SR,
Expr *&TaskgroupReductionRef =
Stack.back().first.back().TaskgroupReductionRef;
if (!TaskgroupReductionRef) {
- auto *VD = buildVarDecl(SemaRef, SR.getBegin(), SemaRef.Context.VoidPtrTy,
- ".task_red.");
+ VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
+ SemaRef.Context.VoidPtrTy, ".task_red.");
TaskgroupReductionRef =
buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
}
}
-DSAStackTy::DSAVarData
-DSAStackTy::getTopMostTaskgroupReductionData(ValueDecl *D, SourceRange &SR,
- BinaryOperatorKind &BOK,
- Expr *&TaskgroupDescriptor) {
+const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
+ const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
+ Expr *&TaskgroupDescriptor) const {
D = getCanonicalDecl(D);
assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
if (Stack.back().first.empty())
return DSAVarData();
- for (auto I = std::next(Stack.back().first.rbegin(), 1),
- E = Stack.back().first.rend();
+ for (iterator I = std::next(Stack.back().first.rbegin(), 1),
+ E = Stack.back().first.rend();
I != E; std::advance(I, 1)) {
- auto &Data = I->SharingMap[D];
+ const DSAInfo &Data = I->SharingMap.lookup(D);
if (Data.Attributes != OMPC_reduction || I->Directive != OMPD_taskgroup)
continue;
- auto &ReductionData = I->ReductionMap[D];
+ const ReductionData &ReductionData = I->ReductionMap.lookup(D);
if (!ReductionData.ReductionOp ||
ReductionData.ReductionOp.is<const Expr *>())
return DSAVarData();
@@ -904,21 +929,20 @@ DSAStackTy::getTopMostTaskgroupReductionData(ValueDecl *D, SourceRange &SR,
return DSAVarData();
}
-DSAStackTy::DSAVarData
-DSAStackTy::getTopMostTaskgroupReductionData(ValueDecl *D, SourceRange &SR,
- const Expr *&ReductionRef,
- Expr *&TaskgroupDescriptor) {
+const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
+ const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
+ Expr *&TaskgroupDescriptor) const {
D = getCanonicalDecl(D);
assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
if (Stack.back().first.empty())
return DSAVarData();
- for (auto I = std::next(Stack.back().first.rbegin(), 1),
- E = Stack.back().first.rend();
+ for (iterator I = std::next(Stack.back().first.rbegin(), 1),
+ E = Stack.back().first.rend();
I != E; std::advance(I, 1)) {
- auto &Data = I->SharingMap[D];
+ const DSAInfo &Data = I->SharingMap.lookup(D);
if (Data.Attributes != OMPC_reduction || I->Directive != OMPD_taskgroup)
continue;
- auto &ReductionData = I->ReductionMap[D];
+ const ReductionData &ReductionData = I->ReductionMap.lookup(D);
if (!ReductionData.ReductionOp ||
!ReductionData.ReductionOp.is<const Expr *>())
return DSAVarData();
@@ -934,12 +958,13 @@ DSAStackTy::getTopMostTaskgroupReductionData(ValueDecl *D, SourceRange &SR,
return DSAVarData();
}
-bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
+bool DSAStackTy::isOpenMPLocal(VarDecl *D, iterator Iter) const {
D = D->getCanonicalDecl();
- if (!isStackEmpty() && Stack.back().first.size() > 1) {
- reverse_iterator I = Iter, E = Stack.back().first.rend();
+ if (!isStackEmpty()) {
+ iterator I = Iter, E = Stack.back().first.rend();
Scope *TopScope = nullptr;
- while (I != E && !isParallelOrTaskRegion(I->Directive))
+ while (I != E && !isParallelOrTaskRegion(I->Directive) &&
+ !isOpenMPTargetExecutionDirective(I->Directive))
++I;
if (I == E)
return false;
@@ -952,35 +977,80 @@ bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
return false;
}
-DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) {
+const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
+ bool FromParent) {
D = getCanonicalDecl(D);
DSAVarData DVar;
+ auto *VD = dyn_cast<VarDecl>(D);
+ auto TI = Threadprivates.find(D);
+ if (TI != Threadprivates.end()) {
+ DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
+ DVar.CKind = OMPC_threadprivate;
+ return DVar;
+ }
+ if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
+ DVar.RefExpr = buildDeclRefExpr(
+ SemaRef, VD, D->getType().getNonReferenceType(),
+ VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
+ DVar.CKind = OMPC_threadprivate;
+ addDSA(D, DVar.RefExpr, OMPC_threadprivate);
+ return DVar;
+ }
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
// in a Construct, C/C++, predetermined, p.1]
// Variables appearing in threadprivate directives are threadprivate.
- auto *VD = dyn_cast<VarDecl>(D);
if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
!(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
SemaRef.getLangOpts().OpenMPUseTLS &&
SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
(VD && VD->getStorageClass() == SC_Register &&
VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
- addDSA(D, buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
- D->getLocation()),
- OMPC_threadprivate);
- }
- auto TI = Threadprivates.find(D);
- if (TI != Threadprivates.end()) {
- DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
- DVar.CKind = OMPC_threadprivate;
- return DVar;
- } else if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
DVar.RefExpr = buildDeclRefExpr(
- SemaRef, VD, D->getType().getNonReferenceType(),
- VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
+ SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
DVar.CKind = OMPC_threadprivate;
addDSA(D, DVar.RefExpr, OMPC_threadprivate);
+ return DVar;
+ }
+ if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
+ VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
+ !isLoopControlVariable(D).first) {
+ iterator IterTarget =
+ std::find_if(Stack.back().first.rbegin(), Stack.back().first.rend(),
+ [](const SharingMapTy &Data) {
+ return isOpenMPTargetExecutionDirective(Data.Directive);
+ });
+ if (IterTarget != Stack.back().first.rend()) {
+ iterator ParentIterTarget = std::next(IterTarget, 1);
+ for (iterator Iter = Stack.back().first.rbegin();
+ Iter != ParentIterTarget; std::advance(Iter, 1)) {
+ if (isOpenMPLocal(VD, Iter)) {
+ DVar.RefExpr =
+ buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
+ D->getLocation());
+ DVar.CKind = OMPC_threadprivate;
+ return DVar;
+ }
+ }
+ if (!isClauseParsingMode() || IterTarget != Stack.back().first.rbegin()) {
+ auto DSAIter = IterTarget->SharingMap.find(D);
+ if (DSAIter != IterTarget->SharingMap.end() &&
+ isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
+ DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
+ DVar.CKind = OMPC_threadprivate;
+ return DVar;
+ }
+ iterator End = Stack.back().first.rend();
+ if (!SemaRef.isOpenMPCapturedByRef(
+ D, std::distance(ParentIterTarget, End))) {
+ DVar.RefExpr =
+ buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
+ IterTarget->ConstructLoc);
+ DVar.CKind = OMPC_threadprivate;
+ return DVar;
+ }
+ }
+ }
}
if (isStackEmpty())
@@ -994,7 +1064,7 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) {
// in a Construct, C/C++, predetermined, p.7]
// Variables with static storage duration that are declared in a scope
// inside the construct are shared.
- auto &&MatchesAlways = [](OpenMPDirectiveKind) -> bool { return true; };
+ auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
if (VD && VD->isStaticDataMember()) {
DSAVarData DVarTemp = hasDSA(D, isOpenMPPrivate, MatchesAlways, FromParent);
if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
@@ -1011,21 +1081,21 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) {
// in a Construct, C/C++, predetermined, p.6]
// Variables with const qualified type having no mutable member are
// shared.
- CXXRecordDecl *RD =
+ const CXXRecordDecl *RD =
SemaRef.getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr;
- if (auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
- if (auto *CTD = CTSD->getSpecializedTemplate())
+ 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) -> bool { return C == OMPC_firstprivate; },
- MatchesAlways, FromParent);
+ DSAVarData DVarTemp =
+ hasDSA(D, [](OpenMPClauseKind C) { return C == OMPC_firstprivate; },
+ MatchesAlways, FromParent);
if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr)
- return DVar;
+ return DVarTemp;
DVar.CKind = OMPC_shared;
return DVar;
@@ -1033,14 +1103,16 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) {
// Explicitly specified attributes and local variables with predetermined
// attributes.
- auto I = Stack.back().first.rbegin();
- auto EndI = Stack.back().first.rend();
+ iterator I = Stack.back().first.rbegin();
+ iterator EndI = Stack.back().first.rend();
if (FromParent && I != EndI)
std::advance(I, 1);
- if (I->SharingMap.count(D)) {
- DVar.RefExpr = I->SharingMap[D].RefExpr.getPointer();
- DVar.PrivateCopy = I->SharingMap[D].PrivateCopy;
- DVar.CKind = I->SharingMap[D].Attributes;
+ auto It = I->SharingMap.find(D);
+ if (It != I->SharingMap.end()) {
+ const DSAInfo &Data = It->getSecond();
+ DVar.RefExpr = Data.RefExpr.getPointer();
+ DVar.PrivateCopy = Data.PrivateCopy;
+ DVar.CKind = Data.Attributes;
DVar.ImplicitDSALoc = I->DefaultAttrLoc;
DVar.DKind = I->Directive;
}
@@ -1048,36 +1120,36 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) {
return DVar;
}
-DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
- bool FromParent) {
+const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
+ bool FromParent) const {
if (isStackEmpty()) {
- StackTy::reverse_iterator I;
+ iterator I;
return getDSA(I, D);
}
D = getCanonicalDecl(D);
- auto StartI = Stack.back().first.rbegin();
- auto EndI = Stack.back().first.rend();
+ iterator StartI = Stack.back().first.rbegin();
+ iterator EndI = Stack.back().first.rend();
if (FromParent && StartI != EndI)
std::advance(StartI, 1);
return getDSA(StartI, D);
}
-DSAStackTy::DSAVarData
+const DSAStackTy::DSAVarData
DSAStackTy::hasDSA(ValueDecl *D,
- const llvm::function_ref<bool(OpenMPClauseKind)> &CPred,
- const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred,
- bool FromParent) {
+ const llvm::function_ref<bool(OpenMPClauseKind)> CPred,
+ const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
+ bool FromParent) const {
if (isStackEmpty())
return {};
D = getCanonicalDecl(D);
- auto I = Stack.back().first.rbegin();
- auto EndI = Stack.back().first.rend();
+ iterator I = Stack.back().first.rbegin();
+ iterator EndI = Stack.back().first.rend();
if (FromParent && I != EndI)
std::advance(I, 1);
for (; I != EndI; std::advance(I, 1)) {
if (!DPred(I->Directive) && !isParallelOrTaskRegion(I->Directive))
continue;
- auto NewI = I;
+ iterator NewI = I;
DSAVarData DVar = getDSA(NewI, D);
if (I == NewI && CPred(DVar.CKind))
return DVar;
@@ -1085,27 +1157,27 @@ DSAStackTy::hasDSA(ValueDecl *D,
return {};
}
-DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
- ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> &CPred,
- const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred,
- bool FromParent) {
+const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
+ ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> CPred,
+ const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
+ bool FromParent) const {
if (isStackEmpty())
return {};
D = getCanonicalDecl(D);
- auto StartI = Stack.back().first.rbegin();
- auto EndI = Stack.back().first.rend();
+ iterator StartI = Stack.back().first.rbegin();
+ iterator EndI = Stack.back().first.rend();
if (FromParent && StartI != EndI)
std::advance(StartI, 1);
if (StartI == EndI || !DPred(StartI->Directive))
return {};
- auto NewI = StartI;
+ iterator NewI = StartI;
DSAVarData DVar = getDSA(NewI, D);
return (NewI == StartI && CPred(DVar.CKind)) ? DVar : DSAVarData();
}
bool DSAStackTy::hasExplicitDSA(
- ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> &CPred,
- unsigned Level, bool NotLastprivate) {
+ const ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> CPred,
+ unsigned Level, bool NotLastprivate) const {
if (isStackEmpty())
return false;
D = getCanonicalDecl(D);
@@ -1114,15 +1186,16 @@ bool DSAStackTy::hasExplicitDSA(
if (std::distance(StartI, EndI) <= (int)Level)
return false;
std::advance(StartI, Level);
- return (StartI->SharingMap.count(D) > 0) &&
- StartI->SharingMap[D].RefExpr.getPointer() &&
- CPred(StartI->SharingMap[D].Attributes) &&
- (!NotLastprivate || !StartI->SharingMap[D].RefExpr.getInt());
+ auto I = StartI->SharingMap.find(D);
+ return (I != StartI->SharingMap.end()) &&
+ I->getSecond().RefExpr.getPointer() &&
+ CPred(I->getSecond().Attributes) &&
+ (!NotLastprivate || !I->getSecond().RefExpr.getInt());
}
bool DSAStackTy::hasExplicitDirective(
- const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred,
- unsigned Level) {
+ const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
+ unsigned Level) const {
if (isStackEmpty())
return false;
auto StartI = Stack.back().first.begin();
@@ -1136,8 +1209,8 @@ bool DSAStackTy::hasExplicitDirective(
bool DSAStackTy::hasDirective(
const llvm::function_ref<bool(OpenMPDirectiveKind,
const DeclarationNameInfo &, SourceLocation)>
- &DPred,
- bool FromParent) {
+ DPred,
+ bool FromParent) const {
// We look only in the enclosing region.
if (isStackEmpty())
return false;
@@ -1166,15 +1239,26 @@ void Sema::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
DSAStack->popFunction(OldFSI);
}
-bool Sema::IsOpenMPCapturedByRef(ValueDecl *D, unsigned Level) {
+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");
- auto &Ctx = getASTContext();
+ ASTContext &Ctx = getASTContext();
bool IsByRef = true;
// Find the directive that is associated with the provided scope.
D = cast<ValueDecl>(D->getCanonicalDecl());
- auto Ty = D->getType();
+ QualType Ty = D->getType();
if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
// This table summarizes how a given variable should be passed to the device
@@ -1241,7 +1325,9 @@ bool Sema::IsOpenMPCapturedByRef(ValueDecl *D, unsigned Level) {
bool IsVariableAssociatedWithSection = false;
DSAStack->checkMappableExprComponentListsForDeclAtLevel(
- D, Level, [&](OMPClauseMappableExprCommon::MappableExprComponentListRef
+ D, Level,
+ [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection, D](
+ OMPClauseMappableExprCommon::MappableExprComponentListRef
MapExprComponents,
OpenMPClauseKind WhereFoundClauseKind) {
// Only the map clause information influences how a variable is
@@ -1331,20 +1417,22 @@ bool Sema::isInOpenMPTargetExecutionDirective() const {
false);
}
-VarDecl *Sema::IsOpenMPCapturedDecl(ValueDecl *D) {
+VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D) const {
assert(LangOpts.OpenMP && "OpenMP is not allowed");
D = getCanonicalDecl(D);
// If we are attempting to capture a global variable in a directive with
// 'target' we return true so that this global is also mapped to the device.
//
- // FIXME: If the declaration is enclosed in a 'declare target' directive,
- // then it should not be captured. Therefore, an extra check has to be
- // inserted here once support for 'declare target' is added.
- //
auto *VD = dyn_cast<VarDecl>(D);
- if (VD && !VD->hasLocalStorage() && isInOpenMPTargetExecutionDirective())
+ if (VD && !VD->hasLocalStorage() && isInOpenMPTargetExecutionDirective()) {
+ // If the declaration is enclosed in a 'declare target' directive,
+ // then it should not be captured.
+ //
+ if (isDeclareTargetDeclaration(VD))
+ return nullptr;
return VD;
+ }
if (DSAStack->getCurrentDirective() != OMPD_unknown &&
(!DSAStack->isClauseParsingMode() ||
@@ -1355,12 +1443,13 @@ VarDecl *Sema::IsOpenMPCapturedDecl(ValueDecl *D) {
isParallelOrTaskRegion(DSAStack->getCurrentDirective())) ||
(VD && DSAStack->isForceVarCapturing()))
return VD ? VD : Info.second;
- auto DVarPrivate = DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
+ DSAStackTy::DSAVarData DVarPrivate =
+ DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
if (DVarPrivate.CKind != OMPC_unknown && isOpenMPPrivate(DVarPrivate.CKind))
return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
- DVarPrivate = DSAStack->hasDSA(
- D, isOpenMPPrivate, [](OpenMPDirectiveKind) -> bool { return true; },
- DSAStack->isClauseParsingMode());
+ DVarPrivate = DSAStack->hasDSA(D, isOpenMPPrivate,
+ [](OpenMPDirectiveKind) { return true; },
+ DSAStack->isClauseParsingMode());
if (DVarPrivate.CKind != OMPC_unknown)
return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
}
@@ -1374,11 +1463,10 @@ void Sema::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
FunctionScopesIndex -= Regions.size();
}
-bool Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level) {
+bool Sema::isOpenMPPrivateDecl(const ValueDecl *D, unsigned Level) const {
assert(LangOpts.OpenMP && "OpenMP is not allowed");
return DSAStack->hasExplicitDSA(
- D, [](OpenMPClauseKind K) -> bool { return K == OMPC_private; },
- Level) ||
+ D, [](OpenMPClauseKind K) { return K == OMPC_private; }, Level) ||
(DSAStack->isClauseParsingMode() &&
DSAStack->getClauseParsingMode() == OMPC_private) ||
// Consider taskgroup reduction descriptor variable a private to avoid
@@ -1389,7 +1477,8 @@ bool Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level) {
DSAStack->isTaskgroupReductionRef(D, Level));
}
-void Sema::setOpenMPCaptureKind(FieldDecl *FD, ValueDecl *D, unsigned Level) {
+void Sema::setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D,
+ unsigned Level) {
assert(LangOpts.OpenMP && "OpenMP is not allowed");
D = getCanonicalDecl(D);
OpenMPClauseKind OMPC = OMPC_unknown;
@@ -1414,7 +1503,11 @@ void Sema::setOpenMPCaptureKind(FieldDecl *FD, ValueDecl *D, unsigned Level) {
}
if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
NewLevel)) {
- OMPC = OMPC_firstprivate;
+ OMPC = OMPC_map;
+ if (D->getType()->isScalarType() &&
+ DSAStack->getDefaultDMAAtLevel(NewLevel) !=
+ DefaultMapAttributes::DMA_tofrom_scalar)
+ OMPC = OMPC_firstprivate;
break;
}
}
@@ -1422,11 +1515,12 @@ void Sema::setOpenMPCaptureKind(FieldDecl *FD, ValueDecl *D, unsigned Level) {
FD->addAttr(OMPCaptureKindAttr::CreateImplicit(Context, OMPC));
}
-bool Sema::isOpenMPTargetCapturedDecl(ValueDecl *D, unsigned Level) {
+bool Sema::isOpenMPTargetCapturedDecl(const ValueDecl *D,
+ unsigned Level) const {
assert(LangOpts.OpenMP && "OpenMP is not allowed");
// Return true if the current level is no longer enclosed in a target region.
- auto *VD = dyn_cast<VarDecl>(D);
+ const auto *VD = dyn_cast<VarDecl>(D);
return VD && !VD->hasLocalStorage() &&
DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
Level);
@@ -1456,28 +1550,29 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
// clause requires an accessible, unambiguous default constructor for the
// class type, unless the list item is also specified in a firstprivate
// clause.
- if (auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
- for (auto *C : D->clauses()) {
+ if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
+ for (OMPClause *C : D->clauses()) {
if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
SmallVector<Expr *, 8> PrivateCopies;
- for (auto *DE : Clause->varlists()) {
+ for (Expr *DE : Clause->varlists()) {
if (DE->isValueDependent() || DE->isTypeDependent()) {
PrivateCopies.push_back(nullptr);
continue;
}
auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
- VarDecl *VD = cast<VarDecl>(DRE->getDecl());
+ auto *VD = cast<VarDecl>(DRE->getDecl());
QualType Type = VD->getType().getNonReferenceType();
- auto DVar = DSAStack->getTopDSA(VD, false);
+ const DSAStackTy::DSAVarData DVar =
+ DSAStack->getTopDSA(VD, /*FromParent=*/false);
if (DVar.CKind == OMPC_lastprivate) {
// Generate helper private variable and initialize it with the
// default value. The address of the original variable is replaced
// by the address of the new private variable in CodeGen. This new
// variable is not added to IdResolver, so the code in the OpenMP
// region uses original variable for proper diagnostics.
- auto *VDPrivate = buildVarDecl(
+ VarDecl *VDPrivate = buildVarDecl(
*this, DE->getExprLoc(), Type.getUnqualifiedType(),
- VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr);
+ VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
ActOnUninitializedDecl(VDPrivate);
if (VDPrivate->isInvalidDecl())
continue;
@@ -1507,7 +1602,7 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
namespace {
-class VarDeclFilterCCC : public CorrectionCandidateCallback {
+class VarDeclFilterCCC final : public CorrectionCandidateCallback {
private:
Sema &SemaRef;
@@ -1515,7 +1610,7 @@ public:
explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
bool ValidateCandidate(const TypoCorrection &Candidate) override {
NamedDecl *ND = Candidate.getCorrectionDecl();
- if (auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
+ if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
return VD->hasGlobalStorage() &&
SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
SemaRef.getCurScope());
@@ -1524,7 +1619,7 @@ public:
}
};
-class VarOrFuncDeclFilterCCC : public CorrectionCandidateCallback {
+class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
private:
Sema &SemaRef;
@@ -1568,12 +1663,10 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
<< Id.getName();
return ExprError();
}
- } else {
- if (!(VD = Lookup.getAsSingle<VarDecl>())) {
- Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
- Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
- return ExprError();
- }
+ } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
+ Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
+ Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
+ return ExprError();
}
Lookup.suppressDiagnostics();
@@ -1591,7 +1684,7 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
}
VarDecl *CanonicalVD = VD->getCanonicalDecl();
- NamedDecl *ND = cast<NamedDecl>(CanonicalVD);
+ NamedDecl *ND = CanonicalVD;
// OpenMP [2.9.2, Restrictions, C/C++, p.2]
// A threadprivate directive for file-scope variables must appear outside
// any definition or declaration.
@@ -1679,12 +1772,13 @@ Sema::ActOnOpenMPThreadprivateDirective(SourceLocation Loc,
}
namespace {
-class LocalVarRefChecker : public ConstStmtVisitor<LocalVarRefChecker, bool> {
+class LocalVarRefChecker final
+ : public ConstStmtVisitor<LocalVarRefChecker, bool> {
Sema &SemaRef;
public:
bool VisitDeclRefExpr(const DeclRefExpr *E) {
- if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
+ if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
if (VD->hasLocalStorage()) {
SemaRef.Diag(E->getLocStart(),
diag::err_omp_local_var_in_threadprivate_init)
@@ -1697,7 +1791,7 @@ public:
return false;
}
bool VisitStmt(const Stmt *S) {
- for (auto Child : S->children()) {
+ for (const Stmt *Child : S->children()) {
if (Child && Visit(Child))
return true;
}
@@ -1710,9 +1804,9 @@ public:
OMPThreadPrivateDecl *
Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
SmallVector<Expr *, 8> Vars;
- for (auto &RefExpr : VarList) {
- DeclRefExpr *DE = cast<DeclRefExpr>(RefExpr);
- VarDecl *VD = cast<VarDecl>(DE->getDecl());
+ for (Expr *RefExpr : VarList) {
+ auto *DE = cast<DeclRefExpr>(RefExpr);
+ auto *VD = cast<VarDecl>(DE->getDecl());
SourceLocation ILoc = DE->getExprLoc();
// Mark variable as used.
@@ -1766,7 +1860,7 @@ Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
// Check if initial value of threadprivate variable reference variable with
// local storage (it is not supported by runtime).
- if (auto Init = VD->getAnyInitializer()) {
+ if (const Expr *Init = VD->getAnyInitializer()) {
LocalVarRefChecker Checker(*this);
if (Checker.Visit(Init))
continue;
@@ -1776,7 +1870,7 @@ Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
DSAStack->addDSA(VD, DE, OMPC_threadprivate);
VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
Context, SourceRange(Loc, Loc)));
- if (auto *ML = Context.getASTMutationListener())
+ if (ASTMutationListener *ML = Context.getASTMutationListener())
ML->DeclarationMarkedOpenMPThreadPrivate(VD);
}
OMPThreadPrivateDecl *D = nullptr;
@@ -1788,8 +1882,9 @@ Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
return D;
}
-static void ReportOriginalDSA(Sema &SemaRef, DSAStackTy *Stack,
- const ValueDecl *D, DSAStackTy::DSAVarData DVar,
+static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
+ const ValueDecl *D,
+ const DSAStackTy::DSAVarData &DVar,
bool IsLoopIterVar = false) {
if (DVar.RefExpr) {
SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
@@ -1845,15 +1940,15 @@ static void ReportOriginalDSA(Sema &SemaRef, DSAStackTy *Stack,
}
namespace {
-class DSAAttrChecker : public StmtVisitor<DSAAttrChecker, void> {
+class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
DSAStackTy *Stack;
Sema &SemaRef;
- bool ErrorFound;
- CapturedStmt *CS;
- llvm::SmallVector<Expr *, 8> ImplicitFirstprivate;
- llvm::SmallVector<Expr *, 8> ImplicitMap;
- llvm::DenseMap<ValueDecl *, Expr *> VarsWithInheritedDSA;
- llvm::DenseSet<ValueDecl *> ImplicitDeclarations;
+ bool ErrorFound = false;
+ CapturedStmt *CS = nullptr;
+ llvm::SmallVector<Expr *, 4> ImplicitFirstprivate;
+ llvm::SmallVector<Expr *, 4> ImplicitMap;
+ Sema::VarsWithInheritedDSAType VarsWithInheritedDSA;
+ llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
public:
void VisitDeclRefExpr(DeclRefExpr *E) {
@@ -1866,17 +1961,20 @@ public:
if (VD->hasLocalStorage() && !CS->capturesVariable(VD))
return;
- auto DVar = Stack->getTopDSA(VD, false);
+ DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
// Check if the variable has explicit DSA set and stop analysis if it so.
if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
return;
// Skip internally declared static variables.
- if (VD->hasGlobalStorage() && !CS->capturesVariable(VD))
+ llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
+ isDeclareTargetDeclaration(VD);
+ if (VD->hasGlobalStorage() && !CS->capturesVariable(VD) &&
+ (!Res || *Res != OMPDeclareTargetDeclAttr::MT_Link))
return;
- auto ELoc = E->getExprLoc();
- auto DKind = Stack->getCurrentDirective();
+ SourceLocation ELoc = E->getExprLoc();
+ OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
// The default(none) clause requires that each variable that is referenced
// in the construct, and does not have a predetermined data-sharing
// attribute, must have its data-sharing attribute explicitly determined
@@ -1919,7 +2017,7 @@ public:
IsFirstprivate =
IsFirstprivate ||
(VD->getType().getNonReferenceType()->isScalarType() &&
- Stack->getDefaultDMA() != DMA_tofrom_scalar);
+ Stack->getDefaultDMA() != DMA_tofrom_scalar && !Res);
if (IsFirstprivate)
ImplicitFirstprivate.emplace_back(E);
else
@@ -1933,8 +2031,8 @@ public:
// enclosing worksharing or parallel construct may not be accessed in an
// explicit task.
DVar = Stack->hasInnermostDSA(
- VD, [](OpenMPClauseKind C) -> bool { return C == OMPC_reduction; },
- [](OpenMPDirectiveKind K) -> bool {
+ VD, [](OpenMPClauseKind C) { return C == OMPC_reduction; },
+ [](OpenMPDirectiveKind K) {
return isOpenMPParallelDirective(K) ||
isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
},
@@ -1942,12 +2040,12 @@ public:
if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
ErrorFound = true;
SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
- ReportOriginalDSA(SemaRef, Stack, VD, DVar);
+ reportOriginalDsa(SemaRef, Stack, VD, DVar);
return;
}
// Define implicit data-sharing attributes for task.
- DVar = Stack->getImplicitDSA(VD, false);
+ DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
!Stack->isLoopControlVariable(VD).first)
ImplicitFirstprivate.push_back(E);
@@ -1962,7 +2060,7 @@ public:
if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
if (!FD)
return;
- auto DVar = Stack->getTopDSA(FD, false);
+ DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
// Check if the variable has explicit DSA set and stop analysis if it
// so.
if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
@@ -1990,14 +2088,14 @@ public:
return;
}
- auto ELoc = E->getExprLoc();
+ SourceLocation ELoc = E->getExprLoc();
// OpenMP [2.9.3.6, Restrictions, p.2]
// A list item that appears in a reduction clause of the innermost
// enclosing worksharing or parallel construct may not be accessed in
// an explicit task.
DVar = Stack->hasInnermostDSA(
- FD, [](OpenMPClauseKind C) -> bool { return C == OMPC_reduction; },
- [](OpenMPDirectiveKind K) -> bool {
+ FD, [](OpenMPClauseKind C) { return C == OMPC_reduction; },
+ [](OpenMPDirectiveKind K) {
return isOpenMPParallelDirective(K) ||
isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
},
@@ -2005,12 +2103,12 @@ public:
if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
ErrorFound = true;
SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
- ReportOriginalDSA(SemaRef, Stack, FD, DVar);
+ reportOriginalDsa(SemaRef, Stack, FD, DVar);
return;
}
// Define implicit data-sharing attributes for task.
- DVar = Stack->getImplicitDSA(FD, false);
+ DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
!Stack->isLoopControlVariable(FD).first)
ImplicitFirstprivate.push_back(E);
@@ -2018,10 +2116,10 @@ public:
}
if (isOpenMPTargetExecutionDirective(DKind)) {
OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
- if (!CheckMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
+ if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
/*NoDiagnose=*/true))
return;
- auto *VD = cast<ValueDecl>(
+ const auto *VD = cast<ValueDecl>(
CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
if (!Stack->checkMappableExprComponentListsForDecl(
VD, /*CurrentRegionOnly=*/true,
@@ -2041,8 +2139,8 @@ public:
CCI->getAssociatedExpression())))
return false;
- Decl *CCD = CCI->getAssociatedDeclaration();
- Decl *SCD = SC.getAssociatedDeclaration();
+ const Decl *CCD = CCI->getAssociatedDeclaration();
+ const Decl *SCD = SC.getAssociatedDeclaration();
CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
if (SCD != CCD)
@@ -2055,18 +2153,19 @@ public:
})) {
Visit(E->getBase());
}
- } else
+ } else {
Visit(E->getBase());
+ }
}
void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
- for (auto *C : S->clauses()) {
+ for (OMPClause *C : S->clauses()) {
// Skip analysis of arguments of implicitly defined firstprivate clause
// for task|target directives.
// Skip analysis of arguments of implicitly defined map clause for target
// directives.
if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) &&
C->isImplicit())) {
- for (auto *CC : C->children()) {
+ for (Stmt *CC : C->children()) {
if (CC)
Visit(CC);
}
@@ -2074,18 +2173,18 @@ public:
}
}
void VisitStmt(Stmt *S) {
- for (auto *C : S->children()) {
+ for (Stmt *C : S->children()) {
if (C && !isa<OMPExecutableDirective>(C))
Visit(C);
}
}
- bool isErrorFound() { return ErrorFound; }
+ bool isErrorFound() const { return ErrorFound; }
ArrayRef<Expr *> getImplicitFirstprivate() const {
return ImplicitFirstprivate;
}
ArrayRef<Expr *> getImplicitMap() const { return ImplicitMap; }
- llvm::DenseMap<ValueDecl *, Expr *> &getVarsWithInheritedDSA() {
+ const Sema::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
return VarsWithInheritedDSA;
}
@@ -2103,7 +2202,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
case OMPD_teams:
case OMPD_teams_distribute:
case OMPD_teams_distribute_simd: {
- QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
QualType KmpInt32PtrTy =
Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
Sema::CapturedParamNameType Params[] = {
@@ -2121,15 +2220,37 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
case OMPD_target_parallel_for_simd:
case OMPD_target_teams_distribute:
case OMPD_target_teams_distribute_simd: {
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
+ QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
+ QualType KmpInt32PtrTy =
+ Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
+ QualType Args[] = {VoidPtrTy};
+ FunctionProtoType::ExtProtoInfo EPI;
+ EPI.Variadic = true;
+ QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(".global_tid.", KmpInt32Ty),
+ std::make_pair(".part_id.", KmpInt32PtrTy),
+ std::make_pair(".privates.", VoidPtrTy),
+ std::make_pair(
+ ".copy_fn.",
+ Context.getPointerType(CopyFnType).withConst().withRestrict()),
+ std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ // Mark this captured region as inlined, because we don't use outlined
+ // function directly.
+ getCurCapturedRegion()->TheCapturedDecl->addAttr(
+ AlwaysInlineAttr::CreateImplicit(
+ Context, AlwaysInlineAttr::Keyword_forceinline));
Sema::CapturedParamNameType ParamsTarget[] = {
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
// Start a captured region for 'target' with no implicit parameters.
ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
ParamsTarget);
- QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
- QualType KmpInt32PtrTy =
- Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
Sema::CapturedParamNameType ParamsTeamsOrParallel[] = {
std::make_pair(".global_tid.", KmpInt32PtrTy),
std::make_pair(".bound_tid.", KmpInt32PtrTy),
@@ -2141,6 +2262,37 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
ParamsTeamsOrParallel);
break;
}
+ case OMPD_target:
+ case OMPD_target_simd: {
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
+ QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
+ QualType KmpInt32PtrTy =
+ Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
+ QualType Args[] = {VoidPtrTy};
+ FunctionProtoType::ExtProtoInfo EPI;
+ EPI.Variadic = true;
+ QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(".global_tid.", KmpInt32Ty),
+ std::make_pair(".part_id.", KmpInt32PtrTy),
+ std::make_pair(".privates.", VoidPtrTy),
+ std::make_pair(
+ ".copy_fn.",
+ Context.getPointerType(CopyFnType).withConst().withRestrict()),
+ std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ // Mark this captured region as inlined, because we don't use outlined
+ // function directly.
+ getCurCapturedRegion()->TheCapturedDecl->addAttr(
+ AlwaysInlineAttr::CreateImplicit(
+ Context, AlwaysInlineAttr::Keyword_forceinline));
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ std::make_pair(StringRef(), QualType()));
+ break;
+ }
case OMPD_simd:
case OMPD_for:
case OMPD_for_simd:
@@ -2154,9 +2306,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
case OMPD_distribute_simd:
case OMPD_ordered:
case OMPD_atomic:
- case OMPD_target_data:
- case OMPD_target:
- case OMPD_target_simd: {
+ case OMPD_target_data: {
Sema::CapturedParamNameType Params[] = {
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
@@ -2165,17 +2315,21 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
break;
}
case OMPD_task: {
- QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
- QualType Args[] = {Context.VoidPtrTy.withConst().withRestrict()};
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
+ QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
+ QualType KmpInt32PtrTy =
+ Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
+ QualType Args[] = {VoidPtrTy};
FunctionProtoType::ExtProtoInfo EPI;
EPI.Variadic = true;
QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
Sema::CapturedParamNameType Params[] = {
std::make_pair(".global_tid.", KmpInt32Ty),
- std::make_pair(".part_id.", Context.getPointerType(KmpInt32Ty)),
- std::make_pair(".privates.", Context.VoidPtrTy.withConst()),
- std::make_pair(".copy_fn.",
- Context.getPointerType(CopyFnType).withConst()),
+ std::make_pair(".part_id.", KmpInt32PtrTy),
+ std::make_pair(".privates.", VoidPtrTy),
+ std::make_pair(
+ ".copy_fn.",
+ Context.getPointerType(CopyFnType).withConst().withRestrict()),
std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
@@ -2185,35 +2339,40 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
// function directly.
getCurCapturedRegion()->TheCapturedDecl->addAttr(
AlwaysInlineAttr::CreateImplicit(
- Context, AlwaysInlineAttr::Keyword_forceinline, SourceRange()));
+ Context, AlwaysInlineAttr::Keyword_forceinline));
break;
}
case OMPD_taskloop:
case OMPD_taskloop_simd: {
QualType KmpInt32Ty =
- Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
+ Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
+ .withConst();
QualType KmpUInt64Ty =
- Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
+ Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
+ .withConst();
QualType KmpInt64Ty =
- Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
- QualType Args[] = {Context.VoidPtrTy.withConst().withRestrict()};
+ Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
+ .withConst();
+ QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
+ QualType KmpInt32PtrTy =
+ Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
+ QualType Args[] = {VoidPtrTy};
FunctionProtoType::ExtProtoInfo EPI;
EPI.Variadic = true;
QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
Sema::CapturedParamNameType Params[] = {
std::make_pair(".global_tid.", KmpInt32Ty),
- std::make_pair(".part_id.", Context.getPointerType(KmpInt32Ty)),
- std::make_pair(".privates.",
- Context.VoidPtrTy.withConst().withRestrict()),
+ std::make_pair(".part_id.", KmpInt32PtrTy),
+ std::make_pair(".privates.", VoidPtrTy),
std::make_pair(
".copy_fn.",
Context.getPointerType(CopyFnType).withConst().withRestrict()),
std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
std::make_pair(".lb.", KmpUInt64Ty),
- std::make_pair(".ub.", KmpUInt64Ty), std::make_pair(".st.", KmpInt64Ty),
+ std::make_pair(".ub.", KmpUInt64Ty),
+ std::make_pair(".st.", KmpInt64Ty),
std::make_pair(".liter.", KmpInt32Ty),
- std::make_pair(".reductions.",
- Context.VoidPtrTy.withConst().withRestrict()),
+ std::make_pair(".reductions.", VoidPtrTy),
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
@@ -2222,30 +2381,86 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
// function directly.
getCurCapturedRegion()->TheCapturedDecl->addAttr(
AlwaysInlineAttr::CreateImplicit(
- Context, AlwaysInlineAttr::Keyword_forceinline, SourceRange()));
+ Context, AlwaysInlineAttr::Keyword_forceinline));
break;
}
case OMPD_distribute_parallel_for_simd:
- case OMPD_distribute_parallel_for:
+ case OMPD_distribute_parallel_for: {
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
+ QualType KmpInt32PtrTy =
+ Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(".global_tid.", KmpInt32PtrTy),
+ std::make_pair(".bound_tid.", KmpInt32PtrTy),
+ std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
+ std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
case OMPD_target_teams_distribute_parallel_for:
case OMPD_target_teams_distribute_parallel_for_simd: {
- QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
QualType KmpInt32PtrTy =
Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
+ QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
+
+ QualType Args[] = {VoidPtrTy};
+ FunctionProtoType::ExtProtoInfo EPI;
+ EPI.Variadic = true;
+ QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
Sema::CapturedParamNameType Params[] = {
+ std::make_pair(".global_tid.", KmpInt32Ty),
+ std::make_pair(".part_id.", KmpInt32PtrTy),
+ std::make_pair(".privates.", VoidPtrTy),
+ std::make_pair(
+ ".copy_fn.",
+ Context.getPointerType(CopyFnType).withConst().withRestrict()),
+ std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ // Mark this captured region as inlined, because we don't use outlined
+ // function directly.
+ getCurCapturedRegion()->TheCapturedDecl->addAttr(
+ AlwaysInlineAttr::CreateImplicit(
+ Context, AlwaysInlineAttr::Keyword_forceinline));
+ Sema::CapturedParamNameType ParamsTarget[] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ // Start a captured region for 'target' with no implicit parameters.
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ ParamsTarget);
+
+ Sema::CapturedParamNameType ParamsTeams[] = {
std::make_pair(".global_tid.", KmpInt32PtrTy),
std::make_pair(".bound_tid.", KmpInt32PtrTy),
- std::make_pair(".previous.lb.", Context.getSizeType()),
- std::make_pair(".previous.ub.", Context.getSizeType()),
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
+ // Start a captured region for 'target' with no implicit parameters.
ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
- Params);
+ ParamsTeams);
+
+ Sema::CapturedParamNameType ParamsParallel[] = {
+ std::make_pair(".global_tid.", KmpInt32PtrTy),
+ std::make_pair(".bound_tid.", KmpInt32PtrTy),
+ std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
+ std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ // Start a captured region for 'teams' or 'parallel'. Both regions have
+ // the same implicit parameters.
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ ParamsParallel);
break;
}
+
case OMPD_teams_distribute_parallel_for:
case OMPD_teams_distribute_parallel_for_simd: {
- QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
QualType KmpInt32PtrTy =
Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
@@ -2261,8 +2476,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
Sema::CapturedParamNameType ParamsParallel[] = {
std::make_pair(".global_tid.", KmpInt32PtrTy),
std::make_pair(".bound_tid.", KmpInt32PtrTy),
- std::make_pair(".previous.lb.", Context.getSizeType()),
- std::make_pair(".previous.ub.", Context.getSizeType()),
+ std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
+ std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
// Start a captured region for 'teams' or 'parallel'. Both regions have
@@ -2274,17 +2489,21 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
case OMPD_target_update:
case OMPD_target_enter_data:
case OMPD_target_exit_data: {
- QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
- QualType Args[] = {Context.VoidPtrTy.withConst().withRestrict()};
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
+ QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
+ QualType KmpInt32PtrTy =
+ Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
+ QualType Args[] = {VoidPtrTy};
FunctionProtoType::ExtProtoInfo EPI;
EPI.Variadic = true;
QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
Sema::CapturedParamNameType Params[] = {
std::make_pair(".global_tid.", KmpInt32Ty),
- std::make_pair(".part_id.", Context.getPointerType(KmpInt32Ty)),
- std::make_pair(".privates.", Context.VoidPtrTy.withConst()),
- std::make_pair(".copy_fn.",
- Context.getPointerType(CopyFnType).withConst()),
+ std::make_pair(".part_id.", KmpInt32PtrTy),
+ std::make_pair(".privates.", VoidPtrTy),
+ std::make_pair(
+ ".copy_fn.",
+ Context.getPointerType(CopyFnType).withConst().withRestrict()),
std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
@@ -2294,7 +2513,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
// function directly.
getCurCapturedRegion()->TheCapturedDecl->addAttr(
AlwaysInlineAttr::CreateImplicit(
- Context, AlwaysInlineAttr::Keyword_forceinline, SourceRange()));
+ Context, AlwaysInlineAttr::Keyword_forceinline));
break;
}
case OMPD_threadprivate:
@@ -2343,7 +2562,7 @@ static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
auto *CED = OMPCapturedExprDecl::Create(C, S.CurContext, Id, Ty,
CaptureExpr->getLocStart());
if (!WithInit)
- CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C, SourceRange()));
+ CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
S.CurContext->addHiddenDecl(CED);
S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
return CED;
@@ -2352,12 +2571,11 @@ static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
bool WithInit) {
OMPCapturedExprDecl *CD;
- if (auto *VD = S.IsOpenMPCapturedDecl(D)) {
+ if (VarDecl *VD = S.isOpenMPCapturedDecl(D))
CD = cast<OMPCapturedExprDecl>(VD);
- } else {
+ else
CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
/*AsExpression=*/false);
- }
return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
CaptureExpr->getExprLoc());
}
@@ -2395,7 +2613,7 @@ class CaptureRegionUnwinderRAII {
private:
Sema &S;
bool &ErrorFound;
- OpenMPDirectiveKind DKind;
+ OpenMPDirectiveKind DKind = OMPD_unknown;
public:
CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
@@ -2425,16 +2643,16 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
OMPOrderedClause *OC = nullptr;
OMPScheduleClause *SC = nullptr;
- SmallVector<OMPLinearClause *, 4> LCs;
- SmallVector<OMPClauseWithPreInit *, 8> PICs;
+ SmallVector<const OMPLinearClause *, 4> LCs;
+ SmallVector<const OMPClauseWithPreInit *, 4> PICs;
// This is required for proper codegen.
- for (auto *Clause : Clauses) {
+ for (OMPClause *Clause : Clauses) {
if (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
Clause->getClauseKind() == OMPC_in_reduction) {
// Capture taskgroup task_reduction descriptors inside the tasking regions
// with the corresponding in_reduction items.
auto *IRC = cast<OMPInReductionClause>(Clause);
- for (auto *E : IRC->taskgroup_descriptors())
+ for (Expr *E : IRC->taskgroup_descriptors())
if (E)
MarkDeclarationsReferencedInExpr(E);
}
@@ -2445,7 +2663,7 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
Clause->getClauseKind() == OMPC_copyin)) {
DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
// Mark all variables in private list clauses as used in inner region.
- for (auto *VarRef : Clause->children()) {
+ for (Stmt *VarRef : Clause->children()) {
if (auto *E = cast_or_null<Expr>(VarRef)) {
MarkDeclarationsReferencedInExpr(E);
}
@@ -2456,7 +2674,7 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
if (auto *C = OMPClauseWithPreInit::get(Clause))
PICs.push_back(C);
if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
- if (auto *E = C->getPostUpdateExpr())
+ if (Expr *E = C->getPostUpdateExpr())
MarkDeclarationsReferencedInExpr(E);
}
}
@@ -2483,7 +2701,7 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
ErrorFound = true;
}
if (!LCs.empty() && OC && OC->getNumForLoops()) {
- for (auto *C : LCs) {
+ for (const OMPLinearClause *C : LCs) {
Diag(C->getLocStart(), diag::err_omp_linear_ordered)
<< SourceRange(OC->getLocStart(), OC->getLocEnd());
}
@@ -2505,7 +2723,7 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
// Required for proper codegen of combined directives.
// TODO: add processing for other clauses.
if (ThisCaptureRegion != OMPD_unknown) {
- for (auto *C : PICs) {
+ for (const clang::OMPClauseWithPreInit *C : PICs) {
OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
// Find the particular capture region for the clause if the
// directive is a combined one with multiple capture regions.
@@ -2515,7 +2733,7 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
if (CaptureRegion == ThisCaptureRegion ||
CaptureRegion == OMPD_unknown) {
if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
- for (auto *D : DS->decls())
+ for (Decl *D : DS->decls())
MarkVariableReferenced(D->getLocation(), cast<VarDecl>(D));
}
}
@@ -2542,14 +2760,14 @@ static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
return true;
}
-static bool checkNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
+static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
OpenMPDirectiveKind CurrentRegion,
const DeclarationNameInfo &CurrentName,
OpenMPDirectiveKind CancelRegion,
SourceLocation StartLoc) {
if (Stack->getCurScope()) {
- auto ParentRegion = Stack->getParentDirective();
- auto OffendingRegion = ParentRegion;
+ OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
+ OpenMPDirectiveKind OffendingRegion = ParentRegion;
bool NestingProhibited = false;
bool CloseNesting = true;
bool OrphanSeen = false;
@@ -2642,12 +2860,12 @@ static bool checkNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
bool DeadLock = Stack->hasDirective(
[CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
const DeclarationNameInfo &DNI,
- SourceLocation Loc) -> bool {
+ SourceLocation Loc) {
if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
PreviousCriticalLoc = Loc;
return true;
- } else
- return false;
+ }
+ return false;
},
false /* skip top directive */);
if (DeadLock) {
@@ -2732,12 +2950,12 @@ static bool checkNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// target region, the behavior is unspecified.
NestingProhibited = Stack->hasDirective(
[&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
- SourceLocation) -> bool {
+ SourceLocation) {
if (isOpenMPTargetExecutionDirective(K)) {
OffendingRegion = K;
return true;
- } else
- return false;
+ }
+ return false;
},
false /* don't skip top directive */);
CloseNesting = false;
@@ -2765,7 +2983,7 @@ static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
SmallVector<const OMPIfClause *, OMPC_unknown + 1> FoundNameModifiers(
OMPD_unknown + 1);
SmallVector<SourceLocation, 4> NameModifierLoc;
- for (const auto *C : Clauses) {
+ for (const OMPClause *C : Clauses) {
if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
// At most one if clause without a directive-name-modifier can appear on
// the directive.
@@ -2831,7 +3049,7 @@ static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
diag::err_omp_unnamed_if_clause)
<< (TotalAllowedNum > 1) << Values;
}
- for (auto Loc : NameModifierLoc) {
+ for (SourceLocation Loc : NameModifierLoc) {
S.Diag(Loc, diag::note_omp_previous_named_if_clause);
}
ErrorFound = true;
@@ -2851,7 +3069,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
return StmtError();
llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
- llvm::DenseMap<ValueDecl *, Expr *> VarsWithInheritedDSA;
+ VarsWithInheritedDSAType VarsWithInheritedDSA;
bool ErrorFound = false;
ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
if (AStmt && !CurContext->isDependentContext()) {
@@ -2875,9 +3093,9 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
SmallVector<Expr *, 4> ImplicitMaps(DSAChecker.getImplicitMap().begin(),
DSAChecker.getImplicitMap().end());
// Mark taskgroup task_reduction descriptors as implicitly firstprivate.
- for (auto *C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
- for (auto *E : IRC->taskgroup_descriptors())
+ for (Expr *E : IRC->taskgroup_descriptors())
if (E)
ImplicitFirstprivates.emplace_back(E);
}
@@ -2889,8 +3107,9 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
ClausesWithImplicit.push_back(Implicit);
ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
ImplicitFirstprivates.size();
- } else
+ } else {
ErrorFound = true;
+ }
}
if (!ImplicitMaps.empty()) {
if (OMPClause *Implicit = ActOnOpenMPMapClause(
@@ -2900,8 +3119,9 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
ClausesWithImplicit.emplace_back(Implicit);
ErrorFound |=
cast<OMPMapClause>(Implicit)->varlist_size() != ImplicitMaps.size();
- } else
+ } else {
ErrorFound = true;
+ }
}
}
@@ -3153,7 +3373,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
llvm_unreachable("Unknown OpenMP directive");
}
- for (auto P : VarsWithInheritedDSA) {
+ for (const auto &P : VarsWithInheritedDSA) {
Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
<< P.first << P.second->getSourceRange();
}
@@ -3183,7 +3403,7 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective(
Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd);
return DG;
}
- auto *ADecl = DG.get().getSingleDecl();
+ Decl *ADecl = DG.get().getSingleDecl();
if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
ADecl = FTD->getTemplatedDecl();
@@ -3205,16 +3425,16 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective(
// The uniform clause declares one or more arguments to have an invariant
// value for all concurrent invocations of the function in the execution of a
// single SIMD loop.
- llvm::DenseMap<Decl *, Expr *> UniformedArgs;
- Expr *UniformedLinearThis = nullptr;
- for (auto *E : Uniforms) {
+ llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
+ const Expr *UniformedLinearThis = nullptr;
+ for (const Expr *E : Uniforms) {
E = E->IgnoreParenImpCasts();
- if (auto *DRE = dyn_cast<DeclRefExpr>(E))
- if (auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
+ if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
FD->getParamDecl(PVD->getFunctionScopeIndex())
->getCanonicalDecl() == PVD->getCanonicalDecl()) {
- UniformedArgs.insert(std::make_pair(PVD->getCanonicalDecl(), E));
+ UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
continue;
}
if (isa<CXXThisExpr>(E)) {
@@ -3232,13 +3452,13 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective(
// function in any of the linear, aligned, or uniform clauses.
// The type of list items appearing in the aligned clause must be array,
// pointer, reference to array, or reference to pointer.
- llvm::DenseMap<Decl *, Expr *> AlignedArgs;
- Expr *AlignedThis = nullptr;
- for (auto *E : Aligneds) {
+ llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
+ const Expr *AlignedThis = nullptr;
+ for (const Expr *E : Aligneds) {
E = E->IgnoreParenImpCasts();
- if (auto *DRE = dyn_cast<DeclRefExpr>(E))
- if (auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
- auto *CanonPVD = PVD->getCanonicalDecl();
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
+ if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
+ const VarDecl *CanonPVD = PVD->getCanonicalDecl();
if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
FD->getParamDecl(PVD->getFunctionScopeIndex())
->getCanonicalDecl() == CanonPVD) {
@@ -3283,8 +3503,8 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective(
// positive integer expression. If no optional parameter is specified,
// implementation-defined default alignments for SIMD instructions on the
// target platforms are assumed.
- SmallVector<Expr *, 4> NewAligns;
- for (auto *E : Alignments) {
+ SmallVector<const Expr *, 4> NewAligns;
+ for (Expr *E : Alignments) {
ExprResult Align;
if (E)
Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
@@ -3299,16 +3519,16 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective(
// When a linear-step expression is specified in a linear clause it must be
// either a constant integer expression or an integer-typed parameter that is
// specified in a uniform clause on the directive.
- llvm::DenseMap<Decl *, Expr *> LinearArgs;
+ llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
const bool IsUniformedThis = UniformedLinearThis != nullptr;
auto MI = LinModifiers.begin();
- for (auto *E : Linears) {
+ for (const Expr *E : Linears) {
auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
++MI;
E = E->IgnoreParenImpCasts();
- if (auto *DRE = dyn_cast<DeclRefExpr>(E))
- if (auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
- auto *CanonPVD = PVD->getCanonicalDecl();
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
+ if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
+ const VarDecl *CanonPVD = PVD->getCanonicalDecl();
if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
FD->getParamDecl(PVD->getFunctionScopeIndex())
->getCanonicalDecl() == CanonPVD) {
@@ -3368,25 +3588,25 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective(
Expr *Step = nullptr;
Expr *NewStep = nullptr;
SmallVector<Expr *, 4> NewSteps;
- for (auto *E : Steps) {
+ for (Expr *E : Steps) {
// Skip the same step expression, it was checked already.
if (Step == E || !E) {
NewSteps.push_back(E ? NewStep : nullptr);
continue;
}
Step = E;
- if (auto *DRE = dyn_cast<DeclRefExpr>(Step))
- if (auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
- auto *CanonPVD = PVD->getCanonicalDecl();
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
+ if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
+ const VarDecl *CanonPVD = PVD->getCanonicalDecl();
if (UniformedArgs.count(CanonPVD) == 0) {
Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
<< Step->getSourceRange();
} else if (E->isValueDependent() || E->isTypeDependent() ||
E->isInstantiationDependent() ||
E->containsUnexpandedParameterPack() ||
- CanonPVD->getType()->hasIntegerRepresentation())
+ CanonPVD->getType()->hasIntegerRepresentation()) {
NewSteps.push_back(Step);
- else {
+ } else {
Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
<< Step->getSourceRange();
}
@@ -3421,7 +3641,7 @@ StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
// top and a single exit at the bottom.
@@ -3429,108 +3649,110 @@ StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPParallelDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
DSAStack->isCancelRegion());
}
namespace {
-/// \brief Helper class for checking canonical form of the OpenMP loops and
+/// Helper class for checking canonical form of the OpenMP loops and
/// extracting iteration space of each loop in the loop nest, that will be used
/// for IR generation.
class OpenMPIterationSpaceChecker {
- /// \brief Reference to Sema.
+ /// Reference to Sema.
Sema &SemaRef;
- /// \brief A location for diagnostics (when there is no some better location).
+ /// A location for diagnostics (when there is no some better location).
SourceLocation DefaultLoc;
- /// \brief A location for diagnostics (when increment is not compatible).
+ /// A location for diagnostics (when increment is not compatible).
SourceLocation ConditionLoc;
- /// \brief A source location for referring to loop init later.
+ /// A source location for referring to loop init later.
SourceRange InitSrcRange;
- /// \brief A source location for referring to condition later.
+ /// A source location for referring to condition later.
SourceRange ConditionSrcRange;
- /// \brief A source location for referring to increment later.
+ /// A source location for referring to increment later.
SourceRange IncrementSrcRange;
- /// \brief Loop variable.
+ /// Loop variable.
ValueDecl *LCDecl = nullptr;
- /// \brief Reference to loop variable.
+ /// Reference to loop variable.
Expr *LCRef = nullptr;
- /// \brief Lower bound (initializer for the var).
+ /// Lower bound (initializer for the var).
Expr *LB = nullptr;
- /// \brief Upper bound.
+ /// Upper bound.
Expr *UB = nullptr;
- /// \brief Loop step (increment).
+ /// Loop step (increment).
Expr *Step = nullptr;
- /// \brief This flag is true when condition is one of:
+ /// This flag is true when condition is one of:
/// Var < UB
/// Var <= UB
/// UB > Var
/// UB >= Var
bool TestIsLessOp = false;
- /// \brief This flag is true when condition is strict ( < or > ).
+ /// This flag is true when condition is strict ( < or > ).
bool TestIsStrictOp = false;
- /// \brief This flag is true when step is subtracted on each iteration.
+ /// This flag is true when step is subtracted on each iteration.
bool SubtractStep = false;
public:
OpenMPIterationSpaceChecker(Sema &SemaRef, SourceLocation DefaultLoc)
: SemaRef(SemaRef), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc) {}
- /// \brief Check init-expr for canonical loop form and save loop counter
+ /// Check init-expr for canonical loop form and save loop counter
/// variable - #Var and its initialization value - #LB.
- bool CheckInit(Stmt *S, bool EmitDiags = true);
- /// \brief Check test-expr for canonical form, save upper-bound (#UB), flags
+ bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
+ /// Check test-expr for canonical form, save upper-bound (#UB), flags
/// for less/greater and for strict/non-strict comparison.
- bool CheckCond(Expr *S);
- /// \brief Check incr-expr for canonical loop form and return true if it
+ bool checkAndSetCond(Expr *S);
+ /// Check incr-expr for canonical loop form and return true if it
/// does not conform, otherwise save loop step (#Step).
- bool CheckInc(Expr *S);
- /// \brief Return the loop counter variable.
- ValueDecl *GetLoopDecl() const { return LCDecl; }
- /// \brief Return the reference expression to loop counter variable.
- Expr *GetLoopDeclRefExpr() const { return LCRef; }
- /// \brief Source range of the loop init.
- SourceRange GetInitSrcRange() const { return InitSrcRange; }
- /// \brief Source range of the loop condition.
- SourceRange GetConditionSrcRange() const { return ConditionSrcRange; }
- /// \brief Source range of the loop increment.
- SourceRange GetIncrementSrcRange() const { return IncrementSrcRange; }
- /// \brief True if the step should be subtracted.
- bool ShouldSubtractStep() const { return SubtractStep; }
- /// \brief Build the expression to calculate the number of iterations.
+ bool checkAndSetInc(Expr *S);
+ /// Return the loop counter variable.
+ ValueDecl *getLoopDecl() const { return LCDecl; }
+ /// Return the reference expression to loop counter variable.
+ Expr *getLoopDeclRefExpr() const { return LCRef; }
+ /// Source range of the loop init.
+ SourceRange getInitSrcRange() const { return InitSrcRange; }
+ /// Source range of the loop condition.
+ SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
+ /// Source range of the loop increment.
+ SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
+ /// True if the step should be subtracted.
+ bool shouldSubtractStep() const { return SubtractStep; }
+ /// Build the expression to calculate the number of iterations.
+ Expr *buildNumIterations(
+ Scope *S, const bool LimitedType,
+ llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
+ /// Build the precondition expression for the loops.
Expr *
- BuildNumIterations(Scope *S, const bool LimitedType,
- llvm::MapVector<Expr *, DeclRefExpr *> &Captures) const;
- /// \brief Build the precondition expression for the loops.
- Expr *BuildPreCond(Scope *S, Expr *Cond,
- llvm::MapVector<Expr *, DeclRefExpr *> &Captures) const;
- /// \brief Build reference expression to the counter be used for codegen.
- DeclRefExpr *BuildCounterVar(llvm::MapVector<Expr *, DeclRefExpr *> &Captures,
- DSAStackTy &DSA) const;
- /// \brief Build reference expression to the private counter be used for
+ buildPreCond(Scope *S, Expr *Cond,
+ llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
+ /// Build reference expression to the counter be used for codegen.
+ DeclRefExpr *
+ buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
+ DSAStackTy &DSA) const;
+ /// Build reference expression to the private counter be used for
/// codegen.
- Expr *BuildPrivateCounterVar() const;
- /// \brief Build initialization of the counter be used for codegen.
- Expr *BuildCounterInit() const;
- /// \brief Build step of the counter be used for codegen.
- Expr *BuildCounterStep() const;
- /// \brief Return true if any expression is dependent.
- bool Dependent() const;
+ Expr *buildPrivateCounterVar() const;
+ /// Build initialization of the counter be used for codegen.
+ Expr *buildCounterInit() const;
+ /// Build step of the counter be used for codegen.
+ Expr *buildCounterStep() const;
+ /// Return true if any expression is dependent.
+ bool dependent() const;
private:
- /// \brief Check the right-hand side of an assignment in the increment
+ /// Check the right-hand side of an assignment in the increment
/// expression.
- bool CheckIncRHS(Expr *RHS);
- /// \brief Helper to set loop counter variable and its initializer.
- bool SetLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB);
- /// \brief Helper to set upper bound.
- bool SetUB(Expr *NewUB, bool LessOp, bool StrictOp, SourceRange SR,
+ bool checkAndSetIncRHS(Expr *RHS);
+ /// 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);
- /// \brief Helper to set loop increment.
- bool SetStep(Expr *NewStep, bool Subtract);
+ /// Helper to set loop increment.
+ bool setStep(Expr *NewStep, bool Subtract);
};
-bool OpenMPIterationSpaceChecker::Dependent() const {
+bool OpenMPIterationSpaceChecker::dependent() const {
if (!LCDecl) {
assert(!LB && !UB && !Step);
return false;
@@ -3540,7 +3762,7 @@ bool OpenMPIterationSpaceChecker::Dependent() const {
(Step && Step->isValueDependent());
}
-bool OpenMPIterationSpaceChecker::SetLCDeclAndLB(ValueDecl *NewLCDecl,
+bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
Expr *NewLCRefExpr,
Expr *NewLB) {
// State consistency checking to ensure correct usage.
@@ -3560,7 +3782,7 @@ bool OpenMPIterationSpaceChecker::SetLCDeclAndLB(ValueDecl *NewLCDecl,
return false;
}
-bool OpenMPIterationSpaceChecker::SetUB(Expr *NewUB, bool LessOp, bool StrictOp,
+bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, bool LessOp, bool StrictOp,
SourceRange SR, SourceLocation SL) {
// State consistency checking to ensure correct usage.
assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
@@ -3575,7 +3797,7 @@ bool OpenMPIterationSpaceChecker::SetUB(Expr *NewUB, bool LessOp, bool StrictOp,
return false;
}
-bool OpenMPIterationSpaceChecker::SetStep(Expr *NewStep, bool Subtract) {
+bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
// State consistency checking to ensure correct usage.
assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
if (!NewStep)
@@ -3632,7 +3854,7 @@ bool OpenMPIterationSpaceChecker::SetStep(Expr *NewStep, bool Subtract) {
return false;
}
-bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S, bool EmitDiags) {
+bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
// Check init-expr for canonical loop form and save loop counter
// variable - #Var and its initialization value - #LB.
// OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
@@ -3656,17 +3878,17 @@ bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S, bool EmitDiags) {
S = E->IgnoreParens();
if (auto *BO = dyn_cast<BinaryOperator>(S)) {
if (BO->getOpcode() == BO_Assign) {
- auto *LHS = BO->getLHS()->IgnoreParens();
+ Expr *LHS = BO->getLHS()->IgnoreParens();
if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
- return SetLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
- return SetLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS());
+ return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
+ return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS());
}
if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
if (ME->isArrow() &&
isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
- return SetLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
+ return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
}
}
} else if (auto *DS = dyn_cast<DeclStmt>(S)) {
@@ -3678,28 +3900,28 @@ bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S, bool EmitDiags) {
SemaRef.Diag(S->getLocStart(),
diag::ext_omp_loop_not_canonical_init)
<< S->getSourceRange();
- return SetLCDeclAndLB(Var, nullptr, Var->getInit());
+ return setLCDeclAndLB(Var, nullptr, Var->getInit());
}
}
}
} else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
if (CE->getOperator() == OO_Equal) {
- auto *LHS = CE->getArg(0);
+ Expr *LHS = CE->getArg(0);
if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
- return SetLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
- return SetLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1));
+ return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
+ return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1));
}
if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
if (ME->isArrow() &&
isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
- return SetLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
+ return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
}
}
}
- if (Dependent() || SemaRef.CurContext->isDependentContext())
+ if (dependent() || SemaRef.CurContext->isDependentContext())
return false;
if (EmitDiags) {
SemaRef.Diag(S->getLocStart(), diag::err_omp_loop_not_canonical_init)
@@ -3708,29 +3930,29 @@ bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S, bool EmitDiags) {
return true;
}
-/// \brief Ignore parenthesizes, implicit casts, copy constructor and return the
+/// Ignore parenthesizes, implicit casts, copy constructor and return the
/// variable (which may be the loop variable) if possible.
-static const ValueDecl *GetInitLCDecl(Expr *E) {
+static const ValueDecl *getInitLCDecl(const Expr *E) {
if (!E)
return nullptr;
E = getExprAsWritten(E);
- if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
+ if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
if (const CXXConstructorDecl *Ctor = CE->getConstructor())
if ((Ctor->isCopyOrMoveConstructor() ||
Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
E = CE->getArg(0)->IgnoreParenImpCasts();
- if (auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
- if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
+ if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
+ if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
return getCanonicalDecl(VD);
}
- if (auto *ME = dyn_cast_or_null<MemberExpr>(E))
+ if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
return getCanonicalDecl(ME->getMemberDecl());
return nullptr;
}
-bool OpenMPIterationSpaceChecker::CheckCond(Expr *S) {
+bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
// Check test-expr for canonical form, save upper-bound UB, flags for
// less/greater and for strict/non-strict comparison.
// OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
@@ -3745,13 +3967,13 @@ bool OpenMPIterationSpaceChecker::CheckCond(Expr *S) {
SourceLocation CondLoc = S->getLocStart();
if (auto *BO = dyn_cast<BinaryOperator>(S)) {
if (BO->isRelationalOp()) {
- if (GetInitLCDecl(BO->getLHS()) == LCDecl)
- return SetUB(BO->getRHS(),
+ if (getInitLCDecl(BO->getLHS()) == LCDecl)
+ return setUB(BO->getRHS(),
(BO->getOpcode() == BO_LT || BO->getOpcode() == BO_LE),
(BO->getOpcode() == BO_LT || BO->getOpcode() == BO_GT),
BO->getSourceRange(), BO->getOperatorLoc());
- if (GetInitLCDecl(BO->getRHS()) == LCDecl)
- return SetUB(BO->getLHS(),
+ if (getInitLCDecl(BO->getRHS()) == LCDecl)
+ return setUB(BO->getLHS(),
(BO->getOpcode() == BO_GT || BO->getOpcode() == BO_GE),
(BO->getOpcode() == BO_LT || BO->getOpcode() == BO_GT),
BO->getSourceRange(), BO->getOperatorLoc());
@@ -3764,12 +3986,12 @@ bool OpenMPIterationSpaceChecker::CheckCond(Expr *S) {
case OO_GreaterEqual:
case OO_Less:
case OO_LessEqual:
- if (GetInitLCDecl(CE->getArg(0)) == LCDecl)
- return SetUB(CE->getArg(1), Op == OO_Less || Op == OO_LessEqual,
+ if (getInitLCDecl(CE->getArg(0)) == LCDecl)
+ return setUB(CE->getArg(1), Op == OO_Less || Op == OO_LessEqual,
Op == OO_Less || Op == OO_Greater, CE->getSourceRange(),
CE->getOperatorLoc());
- if (GetInitLCDecl(CE->getArg(1)) == LCDecl)
- return SetUB(CE->getArg(0), Op == OO_Greater || Op == OO_GreaterEqual,
+ if (getInitLCDecl(CE->getArg(1)) == LCDecl)
+ return setUB(CE->getArg(0), Op == OO_Greater || Op == OO_GreaterEqual,
Op == OO_Less || Op == OO_Greater, CE->getSourceRange(),
CE->getOperatorLoc());
break;
@@ -3778,14 +4000,14 @@ bool OpenMPIterationSpaceChecker::CheckCond(Expr *S) {
}
}
}
- if (Dependent() || SemaRef.CurContext->isDependentContext())
+ if (dependent() || SemaRef.CurContext->isDependentContext())
return false;
SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
<< S->getSourceRange() << LCDecl;
return true;
}
-bool OpenMPIterationSpaceChecker::CheckIncRHS(Expr *RHS) {
+bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
// RHS of canonical loop form increment can be:
// var + incr
// incr + var
@@ -3795,28 +4017,28 @@ bool OpenMPIterationSpaceChecker::CheckIncRHS(Expr *RHS) {
if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
if (BO->isAdditiveOp()) {
bool IsAdd = BO->getOpcode() == BO_Add;
- if (GetInitLCDecl(BO->getLHS()) == LCDecl)
- return SetStep(BO->getRHS(), !IsAdd);
- if (IsAdd && GetInitLCDecl(BO->getRHS()) == LCDecl)
- return SetStep(BO->getLHS(), false);
+ if (getInitLCDecl(BO->getLHS()) == LCDecl)
+ return setStep(BO->getRHS(), !IsAdd);
+ if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
+ return setStep(BO->getLHS(), /*Subtract=*/false);
}
} else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
bool IsAdd = CE->getOperator() == OO_Plus;
if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
- if (GetInitLCDecl(CE->getArg(0)) == LCDecl)
- return SetStep(CE->getArg(1), !IsAdd);
- if (IsAdd && GetInitLCDecl(CE->getArg(1)) == LCDecl)
- return SetStep(CE->getArg(0), false);
+ if (getInitLCDecl(CE->getArg(0)) == LCDecl)
+ return setStep(CE->getArg(1), !IsAdd);
+ if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
+ return setStep(CE->getArg(0), /*Subtract=*/false);
}
}
- if (Dependent() || SemaRef.CurContext->isDependentContext())
+ if (dependent() || SemaRef.CurContext->isDependentContext())
return false;
SemaRef.Diag(RHS->getLocStart(), diag::err_omp_loop_not_canonical_incr)
<< RHS->getSourceRange() << LCDecl;
return true;
}
-bool OpenMPIterationSpaceChecker::CheckInc(Expr *S) {
+bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
// Check incr-expr for canonical loop form and return true if it
// does not conform.
// OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
@@ -3842,22 +4064,22 @@ bool OpenMPIterationSpaceChecker::CheckInc(Expr *S) {
S = S->IgnoreParens();
if (auto *UO = dyn_cast<UnaryOperator>(S)) {
if (UO->isIncrementDecrementOp() &&
- GetInitLCDecl(UO->getSubExpr()) == LCDecl)
- return SetStep(SemaRef
+ getInitLCDecl(UO->getSubExpr()) == LCDecl)
+ return setStep(SemaRef
.ActOnIntegerConstant(UO->getLocStart(),
(UO->isDecrementOp() ? -1 : 1))
.get(),
- false);
+ /*Subtract=*/false);
} else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
switch (BO->getOpcode()) {
case BO_AddAssign:
case BO_SubAssign:
- if (GetInitLCDecl(BO->getLHS()) == LCDecl)
- return SetStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
+ if (getInitLCDecl(BO->getLHS()) == LCDecl)
+ return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
break;
case BO_Assign:
- if (GetInitLCDecl(BO->getLHS()) == LCDecl)
- return CheckIncRHS(BO->getRHS());
+ if (getInitLCDecl(BO->getLHS()) == LCDecl)
+ return checkAndSetIncRHS(BO->getRHS());
break;
default:
break;
@@ -3866,28 +4088,28 @@ bool OpenMPIterationSpaceChecker::CheckInc(Expr *S) {
switch (CE->getOperator()) {
case OO_PlusPlus:
case OO_MinusMinus:
- if (GetInitLCDecl(CE->getArg(0)) == LCDecl)
- return SetStep(SemaRef
+ if (getInitLCDecl(CE->getArg(0)) == LCDecl)
+ return setStep(SemaRef
.ActOnIntegerConstant(
CE->getLocStart(),
((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
.get(),
- false);
+ /*Subtract=*/false);
break;
case OO_PlusEqual:
case OO_MinusEqual:
- if (GetInitLCDecl(CE->getArg(0)) == LCDecl)
- return SetStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
+ if (getInitLCDecl(CE->getArg(0)) == LCDecl)
+ return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
break;
case OO_Equal:
- if (GetInitLCDecl(CE->getArg(0)) == LCDecl)
- return CheckIncRHS(CE->getArg(1));
+ if (getInitLCDecl(CE->getArg(0)) == LCDecl)
+ return checkAndSetIncRHS(CE->getArg(1));
break;
default:
break;
}
}
- if (Dependent() || SemaRef.CurContext->isDependentContext())
+ if (dependent() || SemaRef.CurContext->isDependentContext())
return false;
SemaRef.Diag(S->getLocStart(), diag::err_omp_loop_not_canonical_incr)
<< S->getSourceRange() << LCDecl;
@@ -3896,7 +4118,7 @@ bool OpenMPIterationSpaceChecker::CheckInc(Expr *S) {
static ExprResult
tryBuildCapture(Sema &SemaRef, Expr *Capture,
- llvm::MapVector<Expr *, DeclRefExpr *> &Captures) {
+ llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
if (SemaRef.CurContext->isDependentContext())
return ExprResult(Capture);
if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
@@ -3912,17 +4134,17 @@ tryBuildCapture(Sema &SemaRef, Expr *Capture,
return Res;
}
-/// \brief Build the expression to calculate the number of iterations.
-Expr *OpenMPIterationSpaceChecker::BuildNumIterations(
+/// Build the expression to calculate the number of iterations.
+Expr *OpenMPIterationSpaceChecker::buildNumIterations(
Scope *S, const bool LimitedType,
- llvm::MapVector<Expr *, DeclRefExpr *> &Captures) const {
+ llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
ExprResult Diff;
- auto VarType = LCDecl->getType().getNonReferenceType();
+ QualType VarType = LCDecl->getType().getNonReferenceType();
if (VarType->isIntegerType() || VarType->isPointerType() ||
SemaRef.getLangOpts().CPlusPlus) {
// Upper - Lower
- auto *UBExpr = TestIsLessOp ? UB : LB;
- auto *LBExpr = TestIsLessOp ? LB : UB;
+ Expr *UBExpr = TestIsLessOp ? UB : LB;
+ Expr *LBExpr = TestIsLessOp ? LB : UB;
Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures).get();
Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures).get();
if (!Upper || !Lower)
@@ -3951,7 +4173,7 @@ Expr *OpenMPIterationSpaceChecker::BuildNumIterations(
return nullptr;
// Upper - Lower [- 1] + Step
- auto NewStep = tryBuildCapture(SemaRef, Step, Captures);
+ ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures);
if (!NewStep.isUsable())
return nullptr;
Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
@@ -3970,7 +4192,7 @@ Expr *OpenMPIterationSpaceChecker::BuildNumIterations(
// OpenMP runtime requires 32-bit or 64-bit loop variables.
QualType Type = Diff.get()->getType();
- auto &C = SemaRef.Context;
+ ASTContext &C = SemaRef.Context;
bool UseVarType = VarType->hasIntegerRepresentation() &&
C.getTypeSize(Type) > C.getTypeSize(VarType);
if (!Type->isIntegerType() || UseVarType) {
@@ -4009,22 +4231,23 @@ Expr *OpenMPIterationSpaceChecker::BuildNumIterations(
return Diff.get();
}
-Expr *OpenMPIterationSpaceChecker::BuildPreCond(
+Expr *OpenMPIterationSpaceChecker::buildPreCond(
Scope *S, Expr *Cond,
- llvm::MapVector<Expr *, DeclRefExpr *> &Captures) const {
+ llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
// Try to build LB <op> UB, where <op> is <, >, <=, or >=.
bool Suppress = SemaRef.getDiagnostics().getSuppressAllDiagnostics();
SemaRef.getDiagnostics().setSuppressAllDiagnostics(/*Val=*/true);
- auto NewLB = tryBuildCapture(SemaRef, LB, Captures);
- auto NewUB = tryBuildCapture(SemaRef, UB, Captures);
+ ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
+ ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
if (!NewLB.isUsable() || !NewUB.isUsable())
return nullptr;
- auto CondExpr = SemaRef.BuildBinOp(
- S, DefaultLoc, TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
- : (TestIsStrictOp ? BO_GT : BO_GE),
- NewLB.get(), NewUB.get());
+ ExprResult CondExpr =
+ SemaRef.BuildBinOp(S, DefaultLoc,
+ TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
+ : (TestIsStrictOp ? BO_GT : BO_GE),
+ NewLB.get(), NewUB.get());
if (CondExpr.isUsable()) {
if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
SemaRef.Context.BoolTy))
@@ -4037,15 +4260,16 @@ Expr *OpenMPIterationSpaceChecker::BuildPreCond(
return CondExpr.isUsable() ? CondExpr.get() : Cond;
}
-/// \brief Build reference expression to the counter be used for codegen.
-DeclRefExpr *OpenMPIterationSpaceChecker::BuildCounterVar(
- llvm::MapVector<Expr *, DeclRefExpr *> &Captures, DSAStackTy &DSA) const {
+/// Build reference expression to the counter be used for codegen.
+DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
+ llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, DSAStackTy &DSA) const {
auto *VD = dyn_cast<VarDecl>(LCDecl);
if (!VD) {
- VD = SemaRef.IsOpenMPCapturedDecl(LCDecl);
- auto *Ref = buildDeclRefExpr(
+ VD = SemaRef.isOpenMPCapturedDecl(LCDecl);
+ DeclRefExpr *Ref = buildDeclRefExpr(
SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
- DSAStackTy::DSAVarData Data = DSA.getTopDSA(LCDecl, /*FromParent=*/false);
+ const DSAStackTy::DSAVarData Data =
+ DSA.getTopDSA(LCDecl, /*FromParent=*/false);
// If the loop control decl is explicitly marked as private, do not mark it
// as captured again.
if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
@@ -4056,12 +4280,15 @@ DeclRefExpr *OpenMPIterationSpaceChecker::BuildCounterVar(
DefaultLoc);
}
-Expr *OpenMPIterationSpaceChecker::BuildPrivateCounterVar() const {
+Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
if (LCDecl && !LCDecl->isInvalidDecl()) {
- auto Type = LCDecl->getType().getNonReferenceType();
- auto *PrivateVar =
- buildVarDecl(SemaRef, DefaultLoc, Type, LCDecl->getName(),
- LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr);
+ QualType Type = LCDecl->getType().getNonReferenceType();
+ VarDecl *PrivateVar = buildVarDecl(
+ SemaRef, DefaultLoc, Type, LCDecl->getName(),
+ LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
+ isa<VarDecl>(LCDecl)
+ ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
+ : nullptr);
if (PrivateVar->isInvalidDecl())
return nullptr;
return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
@@ -4069,35 +4296,35 @@ Expr *OpenMPIterationSpaceChecker::BuildPrivateCounterVar() const {
return nullptr;
}
-/// \brief Build initialization of the counter to be used for codegen.
-Expr *OpenMPIterationSpaceChecker::BuildCounterInit() const { return LB; }
+/// Build initialization of the counter to be used for codegen.
+Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
-/// \brief Build step of the counter be used for codegen.
-Expr *OpenMPIterationSpaceChecker::BuildCounterStep() const { return Step; }
+/// Build step of the counter be used for codegen.
+Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
-/// \brief Iteration space of a single for loop.
+/// Iteration space of a single for loop.
struct LoopIterationSpace final {
- /// \brief Condition of the loop.
+ /// Condition of the loop.
Expr *PreCond = nullptr;
- /// \brief This expression calculates the number of iterations in the loop.
+ /// This expression calculates the number of iterations in the loop.
/// It is always possible to calculate it before starting the loop.
Expr *NumIterations = nullptr;
- /// \brief The loop counter variable.
+ /// The loop counter variable.
Expr *CounterVar = nullptr;
- /// \brief Private loop counter variable.
+ /// Private loop counter variable.
Expr *PrivateCounterVar = nullptr;
- /// \brief This is initializer for the initial value of #CounterVar.
+ /// This is initializer for the initial value of #CounterVar.
Expr *CounterInit = nullptr;
- /// \brief This is step for the #CounterVar used to generate its update:
+ /// This is step for the #CounterVar used to generate its update:
/// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
Expr *CounterStep = nullptr;
- /// \brief Should step be subtracted?
+ /// Should step be subtracted?
bool Subtract = false;
- /// \brief Source range of the loop init.
+ /// Source range of the loop init.
SourceRange InitSrcRange;
- /// \brief Source range of the loop condition.
+ /// Source range of the loop condition.
SourceRange CondSrcRange;
- /// \brief Source range of the loop increment.
+ /// Source range of the loop increment.
SourceRange IncSrcRange;
};
@@ -4110,15 +4337,15 @@ void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) {
if (AssociatedLoops > 0 &&
isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
OpenMPIterationSpaceChecker ISC(*this, ForLoc);
- if (!ISC.CheckInit(Init, /*EmitDiags=*/false)) {
- if (auto *D = ISC.GetLoopDecl()) {
+ if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
+ if (ValueDecl *D = ISC.getLoopDecl()) {
auto *VD = dyn_cast<VarDecl>(D);
if (!VD) {
- if (auto *Private = IsOpenMPCapturedDecl(D))
+ if (VarDecl *Private = isOpenMPCapturedDecl(D)) {
VD = Private;
- else {
- auto *Ref = buildCapture(*this, D, ISC.GetLoopDeclRefExpr(),
- /*WithInit=*/false);
+ } else {
+ DeclRefExpr *Ref = buildCapture(*this, D, ISC.getLoopDeclRefExpr(),
+ /*WithInit=*/false);
VD = cast<VarDecl>(Ref->getDecl());
}
}
@@ -4129,15 +4356,15 @@ void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) {
}
}
-/// \brief Called on a for stmt to check and extract its iteration space
+/// Called on a for stmt to check and extract its iteration space
/// for further processing (such as collapsing).
-static bool CheckOpenMPIterationSpace(
+static bool checkOpenMPIterationSpace(
OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA,
+ Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
LoopIterationSpace &ResultIterSpace,
- llvm::MapVector<Expr *, DeclRefExpr *> &Captures) {
+ llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
// OpenMP [2.6, Canonical Loop Form]
// for (init-expr; test-expr; incr-expr) structured-block
auto *For = dyn_cast_or_null<ForStmt>(S);
@@ -4168,22 +4395,22 @@ static bool CheckOpenMPIterationSpace(
OpenMPIterationSpaceChecker ISC(SemaRef, For->getForLoc());
// Check init.
- auto Init = For->getInit();
- if (ISC.CheckInit(Init))
+ Stmt *Init = For->getInit();
+ if (ISC.checkAndSetInit(Init))
return true;
bool HasErrors = false;
// Check loop variable's type.
- if (auto *LCDecl = ISC.GetLoopDecl()) {
- auto *LoopDeclRefExpr = ISC.GetLoopDeclRefExpr();
+ if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
+ Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
// OpenMP [2.6, Canonical Loop Form]
// Var is one of the following:
// A variable of signed or unsigned integer type.
// For C++, a variable of a random access iterator type.
// For C, a variable of a pointer type.
- auto VarType = LCDecl->getType().getNonReferenceType();
+ QualType VarType = LCDecl->getType().getNonReferenceType();
if (!VarType->isDependentType() && !VarType->isIntegerType() &&
!VarType->isPointerType() &&
!(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
@@ -4214,7 +4441,7 @@ static bool CheckOpenMPIterationSpace(
DSAStackTy::DSAVarData DVar = DSA.getTopDSA(LCDecl, false);
// If LoopVarRefExpr is nullptr it means the corresponding loop variable is
// declared in the loop and it is predetermined as a private.
- auto PredeterminedCKind =
+ OpenMPClauseKind PredeterminedCKind =
isOpenMPSimdDirective(DKind)
? ((NestedLoopCount == 1) ? OMPC_linear : OMPC_lastprivate)
: OMPC_private;
@@ -4230,7 +4457,7 @@ static bool CheckOpenMPIterationSpace(
<< getOpenMPClauseName(PredeterminedCKind);
if (DVar.RefExpr == nullptr)
DVar.CKind = PredeterminedCKind;
- ReportOriginalDSA(SemaRef, &DSA, LCDecl, DVar, /*IsLoopIterVar=*/true);
+ reportOriginalDsa(SemaRef, &DSA, LCDecl, DVar, /*IsLoopIterVar=*/true);
HasErrors = true;
} else if (LoopDeclRefExpr != nullptr) {
// Make the loop iteration variable private (for worksharing constructs),
@@ -4247,31 +4474,31 @@ static bool CheckOpenMPIterationSpace(
assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
// Check test-expr.
- HasErrors |= ISC.CheckCond(For->getCond());
+ HasErrors |= ISC.checkAndSetCond(For->getCond());
// Check incr-expr.
- HasErrors |= ISC.CheckInc(For->getInc());
+ HasErrors |= ISC.checkAndSetInc(For->getInc());
}
- if (ISC.Dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
+ if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
return HasErrors;
// Build the loop's iteration space representation.
ResultIterSpace.PreCond =
- ISC.BuildPreCond(DSA.getCurScope(), For->getCond(), Captures);
- ResultIterSpace.NumIterations = ISC.BuildNumIterations(
+ ISC.buildPreCond(DSA.getCurScope(), For->getCond(), Captures);
+ ResultIterSpace.NumIterations = ISC.buildNumIterations(
DSA.getCurScope(),
(isOpenMPWorksharingDirective(DKind) ||
isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind)),
Captures);
- ResultIterSpace.CounterVar = ISC.BuildCounterVar(Captures, DSA);
- ResultIterSpace.PrivateCounterVar = ISC.BuildPrivateCounterVar();
- ResultIterSpace.CounterInit = ISC.BuildCounterInit();
- ResultIterSpace.CounterStep = ISC.BuildCounterStep();
- ResultIterSpace.InitSrcRange = ISC.GetInitSrcRange();
- ResultIterSpace.CondSrcRange = ISC.GetConditionSrcRange();
- ResultIterSpace.IncSrcRange = ISC.GetIncrementSrcRange();
- ResultIterSpace.Subtract = ISC.ShouldSubtractStep();
+ ResultIterSpace.CounterVar = ISC.buildCounterVar(Captures, DSA);
+ ResultIterSpace.PrivateCounterVar = ISC.buildPrivateCounterVar();
+ ResultIterSpace.CounterInit = ISC.buildCounterInit();
+ ResultIterSpace.CounterStep = ISC.buildCounterStep();
+ ResultIterSpace.InitSrcRange = ISC.getInitSrcRange();
+ ResultIterSpace.CondSrcRange = ISC.getConditionSrcRange();
+ ResultIterSpace.IncSrcRange = ISC.getIncrementSrcRange();
+ ResultIterSpace.Subtract = ISC.shouldSubtractStep();
HasErrors |= (ResultIterSpace.PreCond == nullptr ||
ResultIterSpace.NumIterations == nullptr ||
@@ -4283,13 +4510,13 @@ static bool CheckOpenMPIterationSpace(
return HasErrors;
}
-/// \brief Build 'VarRef = Start.
+/// Build 'VarRef = Start.
static ExprResult
-BuildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
+buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
ExprResult Start,
- llvm::MapVector<Expr *, DeclRefExpr *> &Captures) {
+ llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
// Build 'VarRef = Start.
- auto NewStart = tryBuildCapture(SemaRef, Start.get(), Captures);
+ ExprResult NewStart = tryBuildCapture(SemaRef, Start.get(), Captures);
if (!NewStart.isUsable())
return ExprError();
if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
@@ -4301,17 +4528,16 @@ BuildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
return ExprError();
}
- auto Init =
+ ExprResult Init =
SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
return Init;
}
-/// \brief Build 'VarRef = Start + Iter * Step'.
-static ExprResult
-BuildCounterUpdate(Sema &SemaRef, Scope *S, SourceLocation Loc,
- ExprResult VarRef, ExprResult Start, ExprResult Iter,
- ExprResult Step, bool Subtract,
- llvm::MapVector<Expr *, DeclRefExpr *> *Captures = nullptr) {
+/// Build 'VarRef = Start + Iter * Step'.
+static ExprResult buildCounterUpdate(
+ Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
+ ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
+ llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
// Add parentheses (for debugging purposes only).
Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
@@ -4378,12 +4604,12 @@ BuildCounterUpdate(Sema &SemaRef, Scope *S, SourceLocation Loc,
return Update;
}
-/// \brief Convert integer expression \a E to make it have at least \a Bits
+/// Convert integer expression \a E to make it have at least \a Bits
/// bits.
-static ExprResult WidenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
+static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
if (E == nullptr)
return ExprError();
- auto &C = SemaRef.Context;
+ ASTContext &C = SemaRef.Context;
QualType OldType = E->getType();
unsigned HasBits = C.getTypeSize(OldType);
if (HasBits >= Bits)
@@ -4394,9 +4620,9 @@ static ExprResult WidenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
true);
}
-/// \brief Check if the given expression \a E is a constant integer that fits
+/// Check if the given expression \a E is a constant integer that fits
/// into \a Bits bits.
-static bool FitsInto(unsigned Bits, bool Signed, Expr *E, Sema &SemaRef) {
+static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
if (E == nullptr)
return false;
llvm::APSInt Result;
@@ -4419,10 +4645,10 @@ static Stmt *buildPreInits(ASTContext &Context,
/// Build preinits statement for the given declarations.
static Stmt *
buildPreInits(ASTContext &Context,
- const llvm::MapVector<Expr *, DeclRefExpr *> &Captures) {
+ const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
if (!Captures.empty()) {
SmallVector<Decl *, 16> PreInits;
- for (auto &Pair : Captures)
+ for (const auto &Pair : Captures)
PreInits.push_back(Pair.second->getDecl());
return buildPreInits(Context, PreInits);
}
@@ -4433,7 +4659,7 @@ buildPreInits(ASTContext &Context,
static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
Expr *PostUpdate = nullptr;
if (!PostUpdates.empty()) {
- for (auto *E : PostUpdates) {
+ for (Expr *E : PostUpdates) {
Expr *ConvE = S.BuildCStyleCastExpr(
E->getExprLoc(),
S.Context.getTrivialTypeSourceInfo(S.Context.VoidTy),
@@ -4449,14 +4675,14 @@ static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
return PostUpdate;
}
-/// \brief Called on a for stmt to check itself and nested loops (if any).
+/// Called on a for stmt to check itself and nested loops (if any).
/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
/// number of collapsed loops otherwise.
static unsigned
-CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
+checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
DSAStackTy &DSA,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA,
+ Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
OMPLoopDirective::HelperExprs &Built) {
unsigned NestedLoopCount = 1;
if (CollapseLoopCountExpr) {
@@ -4482,12 +4708,12 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
}
// This is helper routine for loop directives (e.g., 'for', 'simd',
// 'for simd', etc.).
- llvm::MapVector<Expr *, DeclRefExpr *> Captures;
+ llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
SmallVector<LoopIterationSpace, 4> IterSpaces;
IterSpaces.resize(NestedLoopCount);
Stmt *CurStmt = AStmt->IgnoreContainers(/* IgnoreCaptured */ true);
for (unsigned Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
- if (CheckOpenMPIterationSpace(DKind, CurStmt, SemaRef, DSA, Cnt,
+ if (checkOpenMPIterationSpace(DKind, CurStmt, SemaRef, DSA, Cnt,
NestedLoopCount, CollapseLoopCountExpr,
OrderedLoopCountExpr, VarsWithImplicitDSA,
IterSpaces[Cnt], Captures))
@@ -4537,26 +4763,28 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// Precondition tests if there is at least one iteration (all conditions are
// true).
auto PreCond = ExprResult(IterSpaces[0].PreCond);
- auto N0 = IterSpaces[0].NumIterations;
- ExprResult LastIteration32 = WidenIterationCount(
- 32 /* Bits */, SemaRef
- .PerformImplicitConversion(
- N0->IgnoreImpCasts(), N0->getType(),
- Sema::AA_Converting, /*AllowExplicit=*/true)
- .get(),
- SemaRef);
- ExprResult LastIteration64 = WidenIterationCount(
- 64 /* Bits */, SemaRef
- .PerformImplicitConversion(
- N0->IgnoreImpCasts(), N0->getType(),
- Sema::AA_Converting, /*AllowExplicit=*/true)
- .get(),
+ Expr *N0 = IterSpaces[0].NumIterations;
+ ExprResult LastIteration32 =
+ widenIterationCount(/*Bits=*/32,
+ SemaRef
+ .PerformImplicitConversion(
+ N0->IgnoreImpCasts(), N0->getType(),
+ Sema::AA_Converting, /*AllowExplicit=*/true)
+ .get(),
+ SemaRef);
+ ExprResult LastIteration64 = widenIterationCount(
+ /*Bits=*/64,
+ SemaRef
+ .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
+ Sema::AA_Converting,
+ /*AllowExplicit=*/true)
+ .get(),
SemaRef);
if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
return NestedLoopCount;
- auto &C = SemaRef.Context;
+ ASTContext &C = SemaRef.Context;
bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
Scope *CurScope = DSA.getCurScope();
@@ -4566,7 +4794,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
PreCond.get(), IterSpaces[Cnt].PreCond);
}
- auto N = IterSpaces[Cnt].NumIterations;
+ Expr *N = IterSpaces[Cnt].NumIterations;
SourceLocation Loc = N->getExprLoc();
AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
if (LastIteration32.isUsable())
@@ -4592,8 +4820,8 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
if (LastIteration32.isUsable() &&
C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
(AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
- FitsInto(
- 32 /* Bits */,
+ fitsInto(
+ /*Bits=*/32,
LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
LastIteration64.get(), SemaRef)))
LastIteration = LastIteration32;
@@ -4681,7 +4909,8 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
UB.get(), LastIteration.get());
ExprResult CondOp = SemaRef.ActOnConditionalOp(
- InitLoc, InitLoc, IsUBGreater.get(), LastIteration.get(), UB.get());
+ LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
+ LastIteration.get(), UB.get());
EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
CondOp.get());
EUB = SemaRef.ActOnFinishFullExpr(EUB.get());
@@ -4691,7 +4920,6 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// enclosing region. E.g. in 'distribute parallel for' the bounds obtained
// by scheduling 'distribute' have to be passed to the schedule of 'for'.
if (isOpenMPLoopBoundSharingDirective(DKind)) {
-
// Lower bound variable, initialized with zero.
VarDecl *CombLBDecl =
buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
@@ -4716,7 +4944,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
CombCondOp.get());
CombEUB = SemaRef.ActOnFinishFullExpr(CombEUB.get());
- auto *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
+ const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
// We expect to have at least 2 more parameters than the 'parallel'
// directive does - the lower and upper bounds of the previous schedule.
assert(CD->getNumParams() >= 4 &&
@@ -4724,8 +4952,8 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// Set the proper type for the bounds given what we learned from the
// enclosed loops.
- auto *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
- auto *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
+ ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
+ ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
// Previous lower and upper bounds are obtained from the region
// parameters.
@@ -4764,7 +4992,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
}
// Loop condition (IV < NumIterations) or (IV <= UB) for worksharing loops.
- SourceLocation CondLoc;
+ SourceLocation CondLoc = AStmt->getLocStart();
ExprResult Cond =
(isOpenMPWorksharingDirective(DKind) ||
isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind))
@@ -4777,7 +5005,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), CombUB.get());
}
// Loop increment (IV = IV + 1)
- SourceLocation IncLoc;
+ SourceLocation IncLoc = AStmt->getLocStart();
ExprResult Inc =
SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
@@ -4844,7 +5072,7 @@ 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;
+ SourceLocation DistIncLoc = AStmt->getLocStart();
ExprResult DistCond, DistInc, PrevEUB;
if (isOpenMPLoopBoundSharingDirective(DKind)) {
DistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), UB.get());
@@ -4860,7 +5088,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// Build expression: UB = min(UB, prevUB) for #for in composite or combined
// construct
- SourceLocation DistEUBLoc;
+ SourceLocation DistEUBLoc = AStmt->getLocStart();
ExprResult IsUBGreater =
SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT, UB.get(), PrevUB.get());
ExprResult CondOp = SemaRef.ActOnConditionalOp(
@@ -4905,16 +5133,16 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
- auto *CounterVar = buildDeclRefExpr(SemaRef, VD, IS.CounterVar->getType(),
- IS.CounterVar->getExprLoc(),
- /*RefersToCapture=*/true);
- ExprResult Init = BuildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
+ DeclRefExpr *CounterVar = buildDeclRefExpr(
+ SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
+ /*RefersToCapture=*/true);
+ ExprResult Init = buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
IS.CounterInit, Captures);
if (!Init.isUsable()) {
HasErrors = true;
break;
}
- ExprResult Update = BuildCounterUpdate(
+ ExprResult Update = buildCounterUpdate(
SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
IS.CounterStep, IS.Subtract, &Captures);
if (!Update.isUsable()) {
@@ -4923,7 +5151,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
}
// Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
- ExprResult Final = BuildCounterUpdate(
+ ExprResult Final = buildCounterUpdate(
SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit,
IS.NumIterations, IS.CounterStep, IS.Subtract, &Captures);
if (!Final.isUsable()) {
@@ -4996,10 +5224,10 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
Expr *CounterVal = SemaRef.DefaultLvalueConversion(IV.get()).get();
// Fill data for doacross depend clauses.
- for (auto Pair : DSA.getDoacrossDependClauses()) {
- if (Pair.first->getDependencyKind() == OMPC_DEPEND_source)
+ for (const auto &Pair : DSA.getDoacrossDependClauses()) {
+ if (Pair.first->getDependencyKind() == OMPC_DEPEND_source) {
Pair.first->setCounterValue(CounterVal);
- else {
+ } else {
if (NestedLoopCount != Pair.second.size() ||
NestedLoopCount != LoopMultipliers.size() + 1) {
// Erroneous case - clause has some problems.
@@ -5064,10 +5292,10 @@ static Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) {
static bool checkSimdlenSafelenSpecified(Sema &S,
const ArrayRef<OMPClause *> Clauses) {
- OMPSafelenClause *Safelen = nullptr;
- OMPSimdlenClause *Simdlen = nullptr;
+ const OMPSafelenClause *Safelen = nullptr;
+ const OMPSimdlenClause *Simdlen = nullptr;
- for (auto *Clause : Clauses) {
+ for (const OMPClause *Clause : Clauses) {
if (Clause->getClauseKind() == OMPC_safelen)
Safelen = cast<OMPSafelenClause>(Clause);
else if (Clause->getClauseKind() == OMPC_simdlen)
@@ -5078,8 +5306,8 @@ static bool checkSimdlenSafelenSpecified(Sema &S,
if (Simdlen && Safelen) {
llvm::APSInt SimdlenRes, SafelenRes;
- auto SimdlenLength = Simdlen->getSimdlen();
- auto SafelenLength = Safelen->getSafelen();
+ const Expr *SimdlenLength = Simdlen->getSimdlen();
+ const Expr *SafelenLength = Safelen->getSafelen();
if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
SimdlenLength->isInstantiationDependent() ||
SimdlenLength->containsUnexpandedParameterPack())
@@ -5104,10 +5332,10 @@ static bool checkSimdlenSafelenSpecified(Sema &S,
return false;
}
-StmtResult Sema::ActOnOpenMPSimdDirective(
- ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+StmtResult
+Sema::ActOnOpenMPSimdDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt,
+ SourceLocation StartLoc, SourceLocation EndLoc,
+ VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
@@ -5115,7 +5343,7 @@ StmtResult Sema::ActOnOpenMPSimdDirective(
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
- unsigned NestedLoopCount = CheckOpenMPLoop(
+ unsigned NestedLoopCount = checkOpenMPLoop(
OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -5126,7 +5354,7 @@ StmtResult Sema::ActOnOpenMPSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -5138,15 +5366,15 @@ StmtResult Sema::ActOnOpenMPSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
Clauses, AStmt, B);
}
-StmtResult Sema::ActOnOpenMPForDirective(
- ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+StmtResult
+Sema::ActOnOpenMPForDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt,
+ SourceLocation StartLoc, SourceLocation EndLoc,
+ VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
@@ -5154,7 +5382,7 @@ StmtResult Sema::ActOnOpenMPForDirective(
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
- unsigned NestedLoopCount = CheckOpenMPLoop(
+ unsigned NestedLoopCount = checkOpenMPLoop(
OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -5165,7 +5393,7 @@ StmtResult Sema::ActOnOpenMPForDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -5174,15 +5402,14 @@ StmtResult Sema::ActOnOpenMPForDirective(
}
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPForDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
Clauses, AStmt, B, DSAStack->isCancelRegion());
}
StmtResult Sema::ActOnOpenMPForSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
@@ -5191,7 +5418,7 @@ StmtResult Sema::ActOnOpenMPForSimdDirective(
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
+ checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -5202,7 +5429,7 @@ StmtResult Sema::ActOnOpenMPForSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -5214,7 +5441,7 @@ StmtResult Sema::ActOnOpenMPForSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPForSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
Clauses, AStmt, B);
}
@@ -5251,7 +5478,7 @@ StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
return StmtError();
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPSectionsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
DSAStack->isCancelRegion());
@@ -5265,7 +5492,7 @@ StmtResult Sema::ActOnOpenMPSectionDirective(Stmt *AStmt,
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
return OMPSectionDirective::Create(Context, StartLoc, EndLoc, AStmt,
@@ -5281,13 +5508,13 @@ StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
// OpenMP [2.7.3, single Construct, Restrictions]
// The copyprivate clause must not be used with the nowait clause.
- OMPClause *Nowait = nullptr;
- OMPClause *Copyprivate = nullptr;
- for (auto *Clause : Clauses) {
+ const OMPClause *Nowait = nullptr;
+ const OMPClause *Copyprivate = nullptr;
+ for (const OMPClause *Clause : Clauses) {
if (Clause->getClauseKind() == OMPC_nowait)
Nowait = Clause;
else if (Clause->getClauseKind() == OMPC_copyprivate)
@@ -5311,7 +5538,7 @@ StmtResult Sema::ActOnOpenMPMasterDirective(Stmt *AStmt,
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt);
}
@@ -5328,7 +5555,7 @@ StmtResult Sema::ActOnOpenMPCriticalDirective(
llvm::APSInt Hint;
SourceLocation HintLoc;
bool DependentHint = false;
- for (auto *C : Clauses) {
+ for (const OMPClause *C : Clauses) {
if (C->getClauseKind() == OMPC_hint) {
if (!DirName.getName()) {
Diag(C->getLocStart(), diag::err_omp_hint_clause_no_name);
@@ -5336,9 +5563,9 @@ StmtResult Sema::ActOnOpenMPCriticalDirective(
}
Expr *E = cast<OMPHintClause>(C)->getHint();
if (E->isTypeDependent() || E->isValueDependent() ||
- E->isInstantiationDependent())
+ E->isInstantiationDependent()) {
DependentHint = true;
- else {
+ } else {
Hint = E->EvaluateKnownConstInt(Context);
HintLoc = C->getLocStart();
}
@@ -5346,26 +5573,27 @@ StmtResult Sema::ActOnOpenMPCriticalDirective(
}
if (ErrorFound)
return StmtError();
- auto Pair = DSAStack->getCriticalWithHint(DirName);
+ const auto Pair = DSAStack->getCriticalWithHint(DirName);
if (Pair.first && DirName.getName() && !DependentHint) {
if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
Diag(StartLoc, diag::err_omp_critical_with_hint);
- if (HintLoc.isValid()) {
+ if (HintLoc.isValid())
Diag(HintLoc, diag::note_omp_critical_hint_here)
<< 0 << Hint.toString(/*Radix=*/10, /*Signed=*/false);
- } else
+ else
Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
- if (auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
+ if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
Diag(C->getLocStart(), diag::note_omp_critical_hint_here)
<< 1
<< C->getHint()->EvaluateKnownConstInt(Context).toString(
/*Radix=*/10, /*Signed=*/false);
- } else
+ } else {
Diag(Pair.first->getLocStart(), diag::note_omp_critical_no_hint) << 1;
+ }
}
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
auto *Dir = OMPCriticalDirective::Create(Context, DirName, StartLoc, EndLoc,
Clauses, AStmt);
@@ -5376,12 +5604,11 @@ StmtResult Sema::ActOnOpenMPCriticalDirective(
StmtResult Sema::ActOnOpenMPParallelForDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
// top and a single exit at the bottom.
@@ -5393,7 +5620,7 @@ StmtResult Sema::ActOnOpenMPParallelForDirective(
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
+ checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -5404,7 +5631,7 @@ StmtResult Sema::ActOnOpenMPParallelForDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -5413,7 +5640,7 @@ StmtResult Sema::ActOnOpenMPParallelForDirective(
}
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPParallelForDirective::Create(Context, StartLoc, EndLoc,
NestedLoopCount, Clauses, AStmt, B,
DSAStack->isCancelRegion());
@@ -5421,12 +5648,11 @@ StmtResult Sema::ActOnOpenMPParallelForDirective(
StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
// top and a single exit at the bottom.
@@ -5438,7 +5664,7 @@ StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
+ checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -5446,7 +5672,7 @@ StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -5458,7 +5684,7 @@ StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPParallelForSimdDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
@@ -5496,7 +5722,7 @@ Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
return StmtError();
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPParallelSectionsDirective::Create(
Context, StartLoc, EndLoc, Clauses, AStmt, DSAStack->isCancelRegion());
@@ -5516,7 +5742,7 @@ StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
DSAStack->isCancelRegion());
@@ -5546,7 +5772,7 @@ StmtResult Sema::ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses,
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTaskgroupDirective::Create(Context, StartLoc, EndLoc, Clauses,
AStmt,
@@ -5564,13 +5790,13 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- OMPClause *DependFound = nullptr;
- OMPClause *DependSourceClause = nullptr;
- OMPClause *DependSinkClause = nullptr;
+ const OMPClause *DependFound = nullptr;
+ const OMPClause *DependSourceClause = nullptr;
+ const OMPClause *DependSinkClause = nullptr;
bool ErrorFound = false;
- OMPThreadsClause *TC = nullptr;
- OMPSIMDClause *SC = nullptr;
- for (auto *C : Clauses) {
+ const OMPThreadsClause *TC = nullptr;
+ const OMPSIMDClause *SC = nullptr;
+ for (const OMPClause *C : Clauses) {
if (auto *DC = dyn_cast<OMPDependClause>(C)) {
DependFound = C;
if (DC->getDependencyKind() == OMPC_DEPEND_source) {
@@ -5579,8 +5805,9 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
<< getOpenMPDirectiveName(OMPD_ordered)
<< getOpenMPClauseName(OMPC_depend) << 2;
ErrorFound = true;
- } else
+ } else {
DependSourceClause = C;
+ }
if (DependSinkClause) {
Diag(C->getLocStart(), diag::err_omp_depend_sink_source_not_allowed)
<< 0;
@@ -5594,10 +5821,11 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
}
DependSinkClause = C;
}
- } else if (C->getClauseKind() == OMPC_threads)
+ } else if (C->getClauseKind() == OMPC_threads) {
TC = cast<OMPThreadsClause>(C);
- else if (C->getClauseKind() == OMPC_simd)
+ } else if (C->getClauseKind() == OMPC_simd) {
SC = cast<OMPSIMDClause>(C);
+ }
}
if (!ErrorFound && !SC &&
isOpenMPSimdDirective(DSAStack->getParentDirective())) {
@@ -5615,7 +5843,7 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
diag::err_omp_ordered_directive_without_param);
ErrorFound = true;
} else if (TC || Clauses.empty()) {
- if (auto *Param = DSAStack->getParentOrderedRegionParam()) {
+ if (const Expr *Param = DSAStack->getParentOrderedRegionParam()) {
SourceLocation ErrLoc = TC ? TC->getLocStart() : StartLoc;
Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
<< (TC != nullptr);
@@ -5629,57 +5857,57 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
if (AStmt) {
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
}
return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
}
namespace {
-/// \brief Helper class for checking expression in 'omp atomic [update]'
+/// Helper class for checking expression in 'omp atomic [update]'
/// construct.
class OpenMPAtomicUpdateChecker {
- /// \brief Error results for atomic update expressions.
+ /// Error results for atomic update expressions.
enum ExprAnalysisErrorCode {
- /// \brief A statement is not an expression statement.
+ /// A statement is not an expression statement.
NotAnExpression,
- /// \brief Expression is not builtin binary or unary operation.
+ /// Expression is not builtin binary or unary operation.
NotABinaryOrUnaryExpression,
- /// \brief Unary operation is not post-/pre- increment/decrement operation.
+ /// Unary operation is not post-/pre- increment/decrement operation.
NotAnUnaryIncDecExpression,
- /// \brief An expression is not of scalar type.
+ /// An expression is not of scalar type.
NotAScalarType,
- /// \brief A binary operation is not an assignment operation.
+ /// A binary operation is not an assignment operation.
NotAnAssignmentOp,
- /// \brief RHS part of the binary operation is not a binary expression.
+ /// RHS part of the binary operation is not a binary expression.
NotABinaryExpression,
- /// \brief RHS part is not additive/multiplicative/shift/biwise binary
+ /// RHS part is not additive/multiplicative/shift/biwise binary
/// expression.
NotABinaryOperator,
- /// \brief RHS binary operation does not have reference to the updated LHS
+ /// RHS binary operation does not have reference to the updated LHS
/// part.
NotAnUpdateExpression,
- /// \brief No errors is found.
+ /// No errors is found.
NoError
};
- /// \brief Reference to Sema.
+ /// Reference to Sema.
Sema &SemaRef;
- /// \brief A location for note diagnostics (when error is found).
+ /// A location for note diagnostics (when error is found).
SourceLocation NoteLoc;
- /// \brief 'x' lvalue part of the source atomic expression.
+ /// 'x' lvalue part of the source atomic expression.
Expr *X;
- /// \brief 'expr' rvalue part of the source atomic expression.
+ /// 'expr' rvalue part of the source atomic expression.
Expr *E;
- /// \brief Helper expression of the form
+ /// Helper expression of the form
/// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
/// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
Expr *UpdateExpr;
- /// \brief Is 'x' a LHS in a RHS part of full update expression. It is
+ /// Is 'x' a LHS in a RHS part of full update expression. It is
/// important for non-associative operations.
bool IsXLHSInRHSPart;
BinaryOperatorKind Op;
SourceLocation OpLoc;
- /// \brief true if the source expression is a postfix unary operation, false
+ /// true if the source expression is a postfix unary operation, false
/// if it is a prefix unary operation.
bool IsPostfixUpdate;
@@ -5687,7 +5915,7 @@ public:
OpenMPAtomicUpdateChecker(Sema &SemaRef)
: SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
- /// \brief Check specified statement that it is suitable for 'atomic update'
+ /// Check specified statement that it is suitable for 'atomic update'
/// constructs and extract 'x', 'expr' and Operation from the original
/// expression. If DiagId and NoteId == 0, then only check is performed
/// without error notification.
@@ -5695,19 +5923,19 @@ public:
/// \param NoteId Diagnostic note for the main error message.
/// \return true if statement is not an update expression, false otherwise.
bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
- /// \brief Return the 'x' lvalue part of the source atomic expression.
+ /// Return the 'x' lvalue part of the source atomic expression.
Expr *getX() const { return X; }
- /// \brief Return the 'expr' rvalue part of the source atomic expression.
+ /// Return the 'expr' rvalue part of the source atomic expression.
Expr *getExpr() const { return E; }
- /// \brief Return the update expression used in calculation of the updated
+ /// Return the update expression used in calculation of the updated
/// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
/// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
Expr *getUpdateExpr() const { return UpdateExpr; }
- /// \brief Return true if 'x' is LHS in RHS part of full update expression,
+ /// Return true if 'x' is LHS in RHS part of full update expression,
/// false otherwise.
bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
- /// \brief true if the source expression is a postfix unary operation, false
+ /// true if the source expression is a postfix unary operation, false
/// if it is a prefix unary operation.
bool isPostfixUpdate() const { return IsPostfixUpdate; }
@@ -5727,15 +5955,15 @@ bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
// x = expr binop x;
if (AtomicBinOp->getOpcode() == BO_Assign) {
X = AtomicBinOp->getLHS();
- if (auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
+ if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
if (AtomicInnerBinOp->isMultiplicativeOp() ||
AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
AtomicInnerBinOp->isBitwiseOp()) {
Op = AtomicInnerBinOp->getOpcode();
OpLoc = AtomicInnerBinOp->getOperatorLoc();
- auto *LHS = AtomicInnerBinOp->getLHS();
- auto *RHS = AtomicInnerBinOp->getRHS();
+ Expr *LHS = AtomicInnerBinOp->getLHS();
+ Expr *RHS = AtomicInnerBinOp->getRHS();
llvm::FoldingSetNodeID XId, LHSId, RHSId;
X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
/*Canonical=*/true);
@@ -5779,7 +6007,8 @@ bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
return true;
- } else if (SemaRef.CurContext->isDependentContext())
+ }
+ if (SemaRef.CurContext->isDependentContext())
E = X = UpdateExpr = nullptr;
return ErrorFound != NoError;
}
@@ -5801,7 +6030,7 @@ bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
AtomicBody = AtomicBody->IgnoreParenImpCasts();
if (AtomicBody->getType()->isScalarType() ||
AtomicBody->isInstantiationDependent()) {
- if (auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
+ if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
AtomicBody->IgnoreParenImpCasts())) {
// Check for Compound Assignment Operation
Op = BinaryOperator::getOpForCompoundAssignment(
@@ -5815,7 +6044,7 @@ bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
// Check for Binary Operation
if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
return true;
- } else if (auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
+ } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
AtomicBody->IgnoreParenImpCasts())) {
// Check for Unary Operation
if (AtomicUnaryOp->isIncrementDecrementOp()) {
@@ -5851,7 +6080,8 @@ bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
return true;
- } else if (SemaRef.CurContext->isDependentContext())
+ }
+ if (SemaRef.CurContext->isDependentContext())
E = X = UpdateExpr = nullptr;
if (ErrorFound == NoError && E && X) {
// Build an update expression of form 'OpaqueValueExpr(x) binop
@@ -5861,7 +6091,7 @@ bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_RValue);
auto *OVEExpr = new (SemaRef.getASTContext())
OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_RValue);
- auto Update =
+ ExprResult Update =
SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
IsXLHSInRHSPart ? OVEExpr : OVEX);
if (Update.isInvalid())
@@ -5890,7 +6120,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
// longjmp() and throw() must not violate the entry/exit criteria.
OpenMPClauseKind AtomicKind = OMPC_unknown;
SourceLocation AtomicKindLoc;
- for (auto *C : Clauses) {
+ for (const OMPClause *C : Clauses) {
if (C->getClauseKind() == OMPC_read || C->getClauseKind() == OMPC_write ||
C->getClauseKind() == OMPC_update ||
C->getClauseKind() == OMPC_capture) {
@@ -5906,7 +6136,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
}
}
- auto Body = CS->getCapturedStmt();
+ Stmt *Body = CS->getCapturedStmt();
if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
Body = EWC->getSubExpr();
@@ -5950,8 +6180,8 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
SourceRange ErrorRange, NoteRange;
// If clause is read:
// v = x;
- if (auto *AtomicBody = dyn_cast<Expr>(Body)) {
- auto *AtomicBinOp =
+ if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
+ const auto *AtomicBinOp =
dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
@@ -5959,7 +6189,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
(V->isInstantiationDependent() || V->getType()->isScalarType())) {
if (!X->isLValue() || !V->isLValue()) {
- auto NotLValueExpr = X->isLValue() ? V : X;
+ const Expr *NotLValueExpr = X->isLValue() ? V : X;
ErrorFound = NotAnLValue;
ErrorLoc = AtomicBinOp->getExprLoc();
ErrorRange = AtomicBinOp->getSourceRange();
@@ -5968,7 +6198,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
}
} else if (!X->isInstantiationDependent() ||
!V->isInstantiationDependent()) {
- auto NotScalarExpr =
+ const Expr *NotScalarExpr =
(X->isInstantiationDependent() || X->getType()->isScalarType())
? V
: X;
@@ -5998,7 +6228,8 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
Diag(NoteLoc, diag::note_omp_atomic_read_write) << ErrorFound
<< NoteRange;
return StmtError();
- } else if (CurContext->isDependentContext())
+ }
+ if (CurContext->isDependentContext())
V = X = nullptr;
} else if (AtomicKind == OMPC_write) {
enum {
@@ -6012,8 +6243,8 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
SourceRange ErrorRange, NoteRange;
// If clause is write:
// x = expr;
- if (auto *AtomicBody = dyn_cast<Expr>(Body)) {
- auto *AtomicBinOp =
+ if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
+ const auto *AtomicBinOp =
dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
X = AtomicBinOp->getLHS();
@@ -6029,7 +6260,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
}
} else if (!X->isInstantiationDependent() ||
!E->isInstantiationDependent()) {
- auto NotScalarExpr =
+ const Expr *NotScalarExpr =
(X->isInstantiationDependent() || X->getType()->isScalarType())
? E
: X;
@@ -6059,7 +6290,8 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
Diag(NoteLoc, diag::note_omp_atomic_read_write) << ErrorFound
<< NoteRange;
return StmtError();
- } else if (CurContext->isDependentContext())
+ }
+ if (CurContext->isDependentContext())
E = X = nullptr;
} else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
// If clause is update:
@@ -6093,7 +6325,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
} ErrorFound = NoError;
SourceLocation ErrorLoc, NoteLoc;
SourceRange ErrorRange, NoteRange;
- if (auto *AtomicBody = dyn_cast<Expr>(Body)) {
+ if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
// If clause is a capture:
// v = x++;
// v = x--;
@@ -6102,7 +6334,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
// v = x binop= expr;
// v = x = x binop expr;
// v = x = expr binop x;
- auto *AtomicBinOp =
+ const auto *AtomicBinOp =
dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
V = AtomicBinOp->getLHS();
@@ -6131,9 +6363,9 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
<< ErrorRange;
Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
return StmtError();
- } else if (CurContext->isDependentContext()) {
- UE = V = E = X = nullptr;
}
+ if (CurContext->isDependentContext())
+ UE = V = E = X = nullptr;
} else {
// If clause is a capture:
// { v = x; x = expr; }
@@ -6154,8 +6386,8 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
// Check that this is { expr1; expr2; }
if (CS->size() == 2) {
- auto *First = CS->body_front();
- auto *Second = CS->body_back();
+ Stmt *First = CS->body_front();
+ Stmt *Second = CS->body_back();
if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
First = EWC->getSubExpr()->IgnoreParenImpCasts();
if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
@@ -6177,7 +6409,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
// { v = x; x = x binop expr; }
// { v = x; x = expr binop x; }
// Check that the first expression has form v = x.
- auto *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
+ Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
llvm::FoldingSetNodeID XId, PossibleXId;
Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
@@ -6207,7 +6439,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
// { x = x binop expr; v = x; }
// { x = expr binop x; v = x; }
// Check that the second expression has form v = x.
- auto *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
+ Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
llvm::FoldingSetNodeID XId, PossibleXId;
Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
@@ -6248,9 +6480,9 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
SecondBinOp ? SecondBinOp->getSourceRange()
: SourceRange(ErrorLoc, ErrorLoc);
} else {
- auto *PossibleXRHSInFirst =
+ Expr *PossibleXRHSInFirst =
FirstBinOp->getRHS()->IgnoreParenImpCasts();
- auto *PossibleXLHSInSecond =
+ Expr *PossibleXLHSInSecond =
SecondBinOp->getLHS()->IgnoreParenImpCasts();
llvm::FoldingSetNodeID X1Id, X2Id;
PossibleXRHSInFirst->Profile(X1Id, Context,
@@ -6293,13 +6525,13 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
<< ErrorRange;
Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
return StmtError();
- } else if (CurContext->isDependentContext()) {
- UE = V = E = X = nullptr;
}
+ if (CurContext->isDependentContext())
+ UE = V = E = X = nullptr;
}
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPAtomicDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
X, V, E, UE, IsXLHSInRHSPart,
@@ -6313,25 +6545,35 @@ StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
// top and a single exit at the bottom.
// The point of exit cannot be a branch out of the structured block.
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
+ for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target);
+ ThisCaptureLevel > 1; --ThisCaptureLevel) {
+ CS = cast<CapturedStmt>(CS->getCapturedStmt());
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+ }
// OpenMP [2.16, Nesting of Regions]
// If specified, a teams construct must be contained within a target
// construct. That target construct must contain no statements or directives
// outside of the teams construct.
if (DSAStack->hasInnerTeamsRegion()) {
- auto S = AStmt->IgnoreContainers(/*IgnoreCaptured*/ true);
+ const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
bool OMPTeamsFound = true;
- if (auto *CS = dyn_cast<CompoundStmt>(S)) {
+ if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
auto I = CS->body_begin();
while (I != CS->body_end()) {
- auto *OED = dyn_cast<OMPExecutableDirective>(*I);
+ const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
if (!OED || !isOpenMPTeamsDirective(OED->getDirectiveKind())) {
OMPTeamsFound = false;
break;
@@ -6341,7 +6583,7 @@ StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
assert(I != CS->body_end() && "Not found statement");
S = *I;
} else {
- auto *OED = dyn_cast<OMPExecutableDirective>(S);
+ const auto *OED = dyn_cast<OMPExecutableDirective>(S);
OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
}
if (!OMPTeamsFound) {
@@ -6354,7 +6596,7 @@ StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
}
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
}
@@ -6366,15 +6608,25 @@ Sema::ActOnOpenMPTargetParallelDirective(ArrayRef<OMPClause *> Clauses,
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
// top and a single exit at the bottom.
// The point of exit cannot be a branch out of the structured block.
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
+ for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel);
+ ThisCaptureLevel > 1; --ThisCaptureLevel) {
+ CS = cast<CapturedStmt>(CS->getCapturedStmt());
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+ }
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetParallelDirective::Create(Context, StartLoc, EndLoc, Clauses,
AStmt);
@@ -6382,12 +6634,11 @@ Sema::ActOnOpenMPTargetParallelDirective(ArrayRef<OMPClause *> Clauses,
StmtResult Sema::ActOnOpenMPTargetParallelForDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
// top and a single exit at the bottom.
@@ -6409,7 +6660,7 @@ StmtResult Sema::ActOnOpenMPTargetParallelForDirective(
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
+ checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -6420,7 +6671,7 @@ StmtResult Sema::ActOnOpenMPTargetParallelForDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -6429,7 +6680,7 @@ StmtResult Sema::ActOnOpenMPTargetParallelForDirective(
}
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetParallelForDirective::Create(Context, StartLoc, EndLoc,
NestedLoopCount, Clauses, AStmt,
B, DSAStack->isCancelRegion());
@@ -6466,7 +6717,7 @@ StmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
return StmtError();
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
AStmt);
@@ -6479,7 +6730,7 @@ Sema::ActOnOpenMPTargetEnterDataDirective(ArrayRef<OMPClause *> Clauses,
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
// top and a single exit at the bottom.
@@ -6516,7 +6767,7 @@ Sema::ActOnOpenMPTargetExitDataDirective(ArrayRef<OMPClause *> Clauses,
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
// top and a single exit at the bottom.
@@ -6553,7 +6804,7 @@ StmtResult Sema::ActOnOpenMPTargetUpdateDirective(ArrayRef<OMPClause *> Clauses,
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
// top and a single exit at the bottom.
@@ -6585,7 +6836,7 @@ StmtResult Sema::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
// top and a single exit at the bottom.
@@ -6593,7 +6844,7 @@ StmtResult Sema::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
DSAStack->setParentTeamsRegionLoc(StartLoc);
@@ -6635,9 +6886,9 @@ StmtResult Sema::ActOnOpenMPCancelDirective(ArrayRef<OMPClause *> Clauses,
static bool checkGrainsizeNumTasksClauses(Sema &S,
ArrayRef<OMPClause *> Clauses) {
- OMPClause *PrevClause = nullptr;
+ const OMPClause *PrevClause = nullptr;
bool ErrorFound = false;
- for (auto *C : Clauses) {
+ for (const OMPClause *C : Clauses) {
if (C->getClauseKind() == OMPC_grainsize ||
C->getClauseKind() == OMPC_num_tasks) {
if (!PrevClause)
@@ -6659,9 +6910,9 @@ static bool checkGrainsizeNumTasksClauses(Sema &S,
static bool checkReductionClauseWithNogroup(Sema &S,
ArrayRef<OMPClause *> Clauses) {
- OMPClause *ReductionClause = nullptr;
- OMPClause *NogroupClause = nullptr;
- for (auto *C : Clauses) {
+ const OMPClause *ReductionClause = nullptr;
+ const OMPClause *NogroupClause = nullptr;
+ for (const OMPClause *C : Clauses) {
if (C->getClauseKind() == OMPC_reduction) {
ReductionClause = C;
if (NogroupClause)
@@ -6686,8 +6937,7 @@ static bool checkReductionClauseWithNogroup(Sema &S,
StmtResult Sema::ActOnOpenMPTaskLoopDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
@@ -6696,7 +6946,7 @@ StmtResult Sema::ActOnOpenMPTaskLoopDirective(
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
+ checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
/*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -6716,15 +6966,14 @@ StmtResult Sema::ActOnOpenMPTaskLoopDirective(
if (checkReductionClauseWithNogroup(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTaskLoopDirective::Create(Context, StartLoc, EndLoc,
NestedLoopCount, Clauses, AStmt, B);
}
StmtResult Sema::ActOnOpenMPTaskLoopSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
@@ -6733,7 +6982,7 @@ StmtResult Sema::ActOnOpenMPTaskLoopSimdDirective(
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
+ checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
/*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -6744,7 +6993,7 @@ StmtResult Sema::ActOnOpenMPTaskLoopSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -6766,15 +7015,14 @@ StmtResult Sema::ActOnOpenMPTaskLoopSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTaskLoopSimdDirective::Create(Context, StartLoc, EndLoc,
NestedLoopCount, Clauses, AStmt, B);
}
StmtResult Sema::ActOnOpenMPDistributeDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
@@ -6783,7 +7031,7 @@ StmtResult Sema::ActOnOpenMPDistributeDirective(
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
+ checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
nullptr /*ordered not a clause on distribute*/, AStmt,
*this, *DSAStack, VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -6792,19 +7040,18 @@ StmtResult Sema::ActOnOpenMPDistributeDirective(
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp for loop exprs were not built");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPDistributeDirective::Create(Context, StartLoc, EndLoc,
NestedLoopCount, Clauses, AStmt, B);
}
StmtResult Sema::ActOnOpenMPDistributeParallelForDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
// top and a single exit at the bottom.
@@ -6826,7 +7073,7 @@ StmtResult Sema::ActOnOpenMPDistributeParallelForDirective(
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
- unsigned NestedLoopCount = CheckOpenMPLoop(
+ unsigned NestedLoopCount = checkOpenMPLoop(
OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
@@ -6836,7 +7083,7 @@ StmtResult Sema::ActOnOpenMPDistributeParallelForDirective(
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp for loop exprs were not built");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPDistributeParallelForDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
DSAStack->isCancelRegion());
@@ -6844,12 +7091,11 @@ StmtResult Sema::ActOnOpenMPDistributeParallelForDirective(
StmtResult Sema::ActOnOpenMPDistributeParallelForSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
// top and a single exit at the bottom.
@@ -6871,7 +7117,7 @@ StmtResult Sema::ActOnOpenMPDistributeParallelForSimdDirective(
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
- unsigned NestedLoopCount = CheckOpenMPLoop(
+ unsigned NestedLoopCount = checkOpenMPLoop(
OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
@@ -6883,7 +7129,7 @@ StmtResult Sema::ActOnOpenMPDistributeParallelForSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -6895,19 +7141,18 @@ StmtResult Sema::ActOnOpenMPDistributeParallelForSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPDistributeParallelForSimdDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
StmtResult Sema::ActOnOpenMPDistributeSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
// top and a single exit at the bottom.
@@ -6929,7 +7174,7 @@ StmtResult Sema::ActOnOpenMPDistributeSimdDirective(
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
+ checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
nullptr /*ordered not a clause on distribute*/, CS, *this,
*DSAStack, VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -6940,7 +7185,7 @@ StmtResult Sema::ActOnOpenMPDistributeSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -6952,19 +7197,18 @@ StmtResult Sema::ActOnOpenMPDistributeSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPDistributeSimdDirective::Create(Context, StartLoc, EndLoc,
NestedLoopCount, Clauses, AStmt, B);
}
StmtResult Sema::ActOnOpenMPTargetParallelForSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
// top and a single exit at the bottom.
@@ -6985,7 +7229,7 @@ StmtResult Sema::ActOnOpenMPTargetParallelForSimdDirective(
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
- unsigned NestedLoopCount = CheckOpenMPLoop(
+ unsigned NestedLoopCount = checkOpenMPLoop(
OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
@@ -6997,7 +7241,7 @@ StmtResult Sema::ActOnOpenMPTargetParallelForSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -7008,19 +7252,18 @@ StmtResult Sema::ActOnOpenMPTargetParallelForSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetParallelForSimdDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
StmtResult Sema::ActOnOpenMPTargetSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
// top and a single exit at the bottom.
@@ -7042,7 +7285,7 @@ StmtResult Sema::ActOnOpenMPTargetSimdDirective(
// In presence of clause 'collapse' with number of loops, it will define the
// nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
+ checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -7053,7 +7296,7 @@ StmtResult Sema::ActOnOpenMPTargetSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -7065,19 +7308,18 @@ StmtResult Sema::ActOnOpenMPTargetSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetSimdDirective::Create(Context, StartLoc, EndLoc,
NestedLoopCount, Clauses, AStmt, B);
}
StmtResult Sema::ActOnOpenMPTeamsDistributeDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
// top and a single exit at the bottom.
@@ -7099,7 +7341,7 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeDirective(
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
+ checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
nullptr /*ordered not a clause on distribute*/, CS, *this,
*DSAStack, VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
@@ -7108,7 +7350,7 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeDirective(
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp teams distribute loop exprs were not built");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
DSAStack->setParentTeamsRegionLoc(StartLoc);
@@ -7118,12 +7360,11 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeDirective(
StmtResult Sema::ActOnOpenMPTeamsDistributeSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
// top and a single exit at the bottom.
@@ -7146,7 +7387,7 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeSimdDirective(
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
- unsigned NestedLoopCount = CheckOpenMPLoop(
+ unsigned NestedLoopCount = checkOpenMPLoop(
OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
@@ -7159,7 +7400,7 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -7171,7 +7412,7 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
DSAStack->setParentTeamsRegionLoc(StartLoc);
@@ -7181,12 +7422,11 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeSimdDirective(
StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
// top and a single exit at the bottom.
@@ -7209,7 +7449,7 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
- auto NestedLoopCount = CheckOpenMPLoop(
+ unsigned NestedLoopCount = checkOpenMPLoop(
OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
@@ -7222,7 +7462,7 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -7234,7 +7474,7 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
DSAStack->setParentTeamsRegionLoc(StartLoc);
@@ -7244,12 +7484,11 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
// top and a single exit at the bottom.
@@ -7272,7 +7511,7 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForDirective(
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
- unsigned NestedLoopCount = CheckOpenMPLoop(
+ unsigned NestedLoopCount = checkOpenMPLoop(
OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
@@ -7283,7 +7522,7 @@ StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForDirective(
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp for loop exprs were not built");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
DSAStack->setParentTeamsRegionLoc(StartLoc);
@@ -7299,7 +7538,7 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDirective(ArrayRef<OMPClause *> Clauses,
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
// top and a single exit at the bottom.
@@ -7317,7 +7556,7 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDirective(ArrayRef<OMPClause *> Clauses,
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses,
AStmt);
@@ -7325,12 +7564,11 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDirective(ArrayRef<OMPClause *> Clauses,
StmtResult Sema::ActOnOpenMPTargetTeamsDistributeDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
// top and a single exit at the bottom.
@@ -7352,7 +7590,7 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeDirective(
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
- auto NestedLoopCount = CheckOpenMPLoop(
+ unsigned NestedLoopCount = checkOpenMPLoop(
OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
@@ -7362,33 +7600,42 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeDirective(
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp target teams distribute loop exprs were not built");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetTeamsDistributeDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
// top and a single exit at the bottom.
// The point of exit cannot be a branch out of the structured block.
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
+ for (int ThisCaptureLevel =
+ getOpenMPCaptureLevels(OMPD_target_teams_distribute_parallel_for);
+ ThisCaptureLevel > 1; --ThisCaptureLevel) {
+ CS = cast<CapturedStmt>(CS->getCapturedStmt());
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+ }
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
- auto NestedLoopCount = CheckOpenMPLoop(
- OMPD_target_teams_distribute_parallel_for,
- getCollapseNumberExpr(Clauses),
- nullptr /*ordered not a clause on distribute*/, AStmt, *this, *DSAStack,
+ unsigned NestedLoopCount = checkOpenMPLoop(
+ OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
+ nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
@@ -7396,7 +7643,18 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp target teams distribute parallel for loop exprs were not built");
- getCurFunction()->setHasBranchProtectedScope();
+ if (!CurContext->isDependentContext()) {
+ // Finalize the clauses that need pre-built expressions for CodeGen.
+ for (OMPClause *C : Clauses) {
+ if (auto *LC = dyn_cast<OMPLinearClause>(C))
+ if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
+ B.NumIterations, *this, CurScope,
+ DSAStack))
+ return StmtError();
+ }
+ }
+
+ setFunctionHasBranchProtectedScope();
return OMPTargetTeamsDistributeParallelForDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
DSAStack->isCancelRegion());
@@ -7404,27 +7662,37 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
- CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ auto *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
// top and a single exit at the bottom.
// The point of exit cannot be a branch out of the structured block.
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
+ for (int ThisCaptureLevel = getOpenMPCaptureLevels(
+ OMPD_target_teams_distribute_parallel_for_simd);
+ ThisCaptureLevel > 1; --ThisCaptureLevel) {
+ CS = cast<CapturedStmt>(CS->getCapturedStmt());
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+ }
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
- auto NestedLoopCount = CheckOpenMPLoop(
- OMPD_target_teams_distribute_parallel_for_simd,
- getCollapseNumberExpr(Clauses),
- nullptr /*ordered not a clause on distribute*/, AStmt, *this, *DSAStack,
- VarsWithImplicitDSA, B);
+ unsigned NestedLoopCount =
+ checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
+ getCollapseNumberExpr(Clauses),
+ nullptr /*ordered not a clause on distribute*/, CS, *this,
+ *DSAStack, VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
@@ -7434,7 +7702,7 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -7446,15 +7714,14 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetTeamsDistributeParallelForSimdDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
StmtResult Sema::ActOnOpenMPTargetTeamsDistributeSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc,
- llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
@@ -7480,7 +7747,7 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeSimdDirective(
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
- auto NestedLoopCount = CheckOpenMPLoop(
+ unsigned NestedLoopCount = checkOpenMPLoop(
OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
VarsWithImplicitDSA, B);
@@ -7492,7 +7759,7 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
- for (auto C : Clauses) {
+ for (OMPClause *C : Clauses) {
if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
@@ -7504,7 +7771,7 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeSimdDirective(
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetTeamsDistributeSimdDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
@@ -7612,13 +7879,18 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_target_parallel:
case OMPD_target_parallel_for:
case OMPD_target_parallel_for_simd:
- case OMPD_target_teams_distribute_parallel_for:
- case OMPD_target_teams_distribute_parallel_for_simd:
// If this clause applies to the nested 'parallel' region, capture within
// the 'target' region, otherwise do not capture.
if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
CaptureRegion = OMPD_target;
break;
+ case OMPD_target_teams_distribute_parallel_for:
+ case OMPD_target_teams_distribute_parallel_for_simd:
+ // If this clause applies to the nested 'parallel' region, capture within
+ // the 'teams' region, otherwise do not capture.
+ if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
+ CaptureRegion = OMPD_teams;
+ break;
case OMPD_teams_distribute_parallel_for:
case OMPD_teams_distribute_parallel_for_simd:
CaptureRegion = OMPD_teams;
@@ -7682,12 +7954,12 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_target_parallel:
case OMPD_target_parallel_for:
case OMPD_target_parallel_for_simd:
- case OMPD_target_teams_distribute_parallel_for:
- case OMPD_target_teams_distribute_parallel_for_simd:
CaptureRegion = OMPD_target;
break;
case OMPD_teams_distribute_parallel_for:
case OMPD_teams_distribute_parallel_for_simd:
+ case OMPD_target_teams_distribute_parallel_for:
+ case OMPD_target_teams_distribute_parallel_for_simd:
CaptureRegion = OMPD_teams;
break;
case OMPD_parallel:
@@ -7870,20 +8142,16 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
break;
case OMPC_schedule:
switch (DKind) {
- case OMPD_target_parallel_for:
- case OMPD_target_parallel_for_simd:
- case OMPD_target_teams_distribute_parallel_for:
- case OMPD_target_teams_distribute_parallel_for_simd:
- CaptureRegion = OMPD_target;
- break;
- case OMPD_teams_distribute_parallel_for:
- case OMPD_teams_distribute_parallel_for_simd:
- CaptureRegion = OMPD_teams;
- break;
case OMPD_parallel_for:
case OMPD_parallel_for_simd:
case OMPD_distribute_parallel_for:
case OMPD_distribute_parallel_for_simd:
+ case OMPD_teams_distribute_parallel_for:
+ case OMPD_teams_distribute_parallel_for_simd:
+ case OMPD_target_parallel_for:
+ case OMPD_target_parallel_for_simd:
+ case OMPD_target_teams_distribute_parallel_for:
+ case OMPD_target_teams_distribute_parallel_for_simd:
CaptureRegion = OMPD_parallel;
break;
case OMPD_for:
@@ -7941,18 +8209,14 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_teams_distribute_parallel_for_simd:
case OMPD_teams_distribute:
case OMPD_teams_distribute_simd:
- CaptureRegion = OMPD_teams;
- break;
case OMPD_target_teams_distribute_parallel_for:
case OMPD_target_teams_distribute_parallel_for_simd:
case OMPD_target_teams_distribute:
case OMPD_target_teams_distribute_simd:
- CaptureRegion = OMPD_target;
+ CaptureRegion = OMPD_teams;
break;
case OMPD_distribute_parallel_for:
case OMPD_distribute_parallel_for_simd:
- CaptureRegion = OMPD_parallel;
- break;
case OMPD_distribute:
case OMPD_distribute_simd:
// Do not capture thread_limit-clause expressions.
@@ -8007,19 +8271,19 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_target_update:
case OMPD_target_enter_data:
case OMPD_target_exit_data:
- CaptureRegion = OMPD_task;
- break;
+ case OMPD_target:
+ case OMPD_target_simd:
case OMPD_target_teams:
+ case OMPD_target_parallel:
case OMPD_target_teams_distribute:
case OMPD_target_teams_distribute_simd:
+ case OMPD_target_parallel_for:
+ case OMPD_target_parallel_for_simd:
case OMPD_target_teams_distribute_parallel_for:
case OMPD_target_teams_distribute_parallel_for_simd:
+ CaptureRegion = OMPD_task;
+ break;
case OMPD_target_data:
- case OMPD_target:
- case OMPD_target_simd:
- case OMPD_target_parallel:
- case OMPD_target_parallel_for:
- case OMPD_target_parallel_for_simd:
// Do not capture device-clause expressions.
break;
case OMPD_teams_distribute_parallel_for:
@@ -8137,7 +8401,7 @@ OMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier,
getOpenMPCaptureRegionForClause(DKind, OMPC_if, NameModifier);
if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
ValExpr = MakeFullExpr(ValExpr).get();
- llvm::MapVector<Expr *, DeclRefExpr *> Captures;
+ llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
}
@@ -8209,7 +8473,7 @@ ExprResult Sema::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,
return PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
}
-static bool IsNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef,
+static bool isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef,
OpenMPClauseKind CKind,
bool StrictlyPositive) {
if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
@@ -8245,7 +8509,7 @@ OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
// OpenMP [2.5, Restrictions]
// The num_threads expression must evaluate to a positive integer value.
- if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_num_threads,
+ if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_num_threads,
/*StrictlyPositive=*/true))
return nullptr;
@@ -8254,7 +8518,7 @@ OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
getOpenMPCaptureRegionForClause(DKind, OMPC_num_threads);
if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
ValExpr = MakeFullExpr(ValExpr).get();
- llvm::MapVector<Expr *, DeclRefExpr *> Captures;
+ llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
}
@@ -8352,8 +8616,9 @@ OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
if (NumForLoopsResult.isInvalid())
return nullptr;
NumForLoops = NumForLoopsResult.get();
- } else
+ } else {
NumForLoops = nullptr;
+ }
DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops);
return new (Context)
OMPOrderedClause(NumForLoops, StartLoc, LParenLoc, EndLoc);
@@ -8431,24 +8696,23 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
static std::string
getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last,
ArrayRef<unsigned> Exclude = llvm::None) {
- std::string Values;
+ SmallString<256> Buffer;
+ llvm::raw_svector_ostream Out(Buffer);
unsigned Bound = Last >= 2 ? Last - 2 : 0;
unsigned Skipped = Exclude.size();
auto S = Exclude.begin(), E = Exclude.end();
- for (unsigned i = First; i < Last; ++i) {
- if (std::find(S, E, i) != E) {
+ for (unsigned I = First; I < Last; ++I) {
+ if (std::find(S, E, I) != E) {
--Skipped;
continue;
}
- Values += "'";
- Values += getOpenMPSimpleClauseTypeName(K, i);
- Values += "'";
- if (i == Bound - Skipped)
- Values += " or ";
- else if (i != Bound + 1 - Skipped)
- Values += ", ";
+ Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
+ if (I == Bound - Skipped)
+ Out << " or ";
+ else if (I != Bound + 1 - Skipped)
+ Out << ", ";
}
- return Values;
+ return Out.str();
}
OMPClause *Sema::ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind,
@@ -8682,7 +8946,7 @@ OMPClause *Sema::ActOnOpenMPScheduleClause(
OMPD_unknown &&
!CurContext->isDependentContext()) {
ValExpr = MakeFullExpr(ValExpr).get();
- llvm::MapVector<Expr *, DeclRefExpr *> Captures;
+ llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
}
@@ -8986,13 +9250,13 @@ getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
} IsArrayExpr = NoArrayExpr;
if (AllowArraySection) {
if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
- auto *Base = ASE->getBase()->IgnoreParenImpCasts();
+ Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
Base = TempASE->getBase()->IgnoreParenImpCasts();
RefExpr = Base;
IsArrayExpr = ArraySubscript;
} else if (auto *OASE = dyn_cast_or_null<OMPArraySectionExpr>(RefExpr)) {
- auto *Base = OASE->getBase()->IgnoreParenImpCasts();
+ Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
Base = TempOASE->getBase()->IgnoreParenImpCasts();
while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
@@ -9010,10 +9274,10 @@ getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
(S.getCurrentThisType().isNull() || !ME ||
!isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
!isa<FieldDecl>(ME->getMemberDecl()))) {
- if (IsArrayExpr != NoArrayExpr)
+ if (IsArrayExpr != NoArrayExpr) {
S.Diag(ELoc, diag::err_omp_expected_base_var_name) << IsArrayExpr
<< ERange;
- else {
+ } else {
S.Diag(ELoc,
AllowArraySection
? diag::err_omp_expected_var_name_member_expr_or_array_item
@@ -9032,7 +9296,7 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
SmallVector<Expr *, 8> PrivateCopies;
- for (auto &RefExpr : VarList) {
+ for (Expr *RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP private clause.");
SourceLocation ELoc;
SourceRange ERange;
@@ -9064,15 +9328,15 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
// 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.
- DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, false);
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_private);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
- auto CurrDir = DSAStack->getCurrentDirective();
+ OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
// Variably modified types are not supported for tasks.
if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
isOpenMPTaskingDirective(CurrDir)) {
@@ -9091,14 +9355,7 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
// OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
// A list item cannot appear in both a map clause and a data-sharing
// attribute clause on the same construct
- if (CurrDir == OMPD_target || CurrDir == OMPD_target_parallel ||
- CurrDir == OMPD_target_teams ||
- CurrDir == OMPD_target_teams_distribute ||
- CurrDir == OMPD_target_teams_distribute_parallel_for ||
- CurrDir == OMPD_target_teams_distribute_parallel_for_simd ||
- CurrDir == OMPD_target_teams_distribute_simd ||
- CurrDir == OMPD_target_parallel_for_simd ||
- CurrDir == OMPD_target_parallel_for) {
+ if (isOpenMPTargetExecutionDirective(CurrDir)) {
OpenMPClauseKind ConflictKind;
if (DSAStack->checkMappableExprComponentListsForDecl(
VD, /*CurrentRegionOnly=*/true,
@@ -9111,7 +9368,7 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
<< getOpenMPClauseName(OMPC_private)
<< getOpenMPClauseName(ConflictKind)
<< getOpenMPDirectiveName(CurrDir);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
}
@@ -9126,12 +9383,14 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
// IdResolver, so the code in the OpenMP region uses original variable for
// proper diagnostics.
Type = Type.getUnqualifiedType();
- auto VDPrivate = buildVarDecl(*this, ELoc, Type, D->getName(),
- D->hasAttrs() ? &D->getAttrs() : nullptr);
+ VarDecl *VDPrivate =
+ buildVarDecl(*this, ELoc, Type, D->getName(),
+ D->hasAttrs() ? &D->getAttrs() : nullptr,
+ VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
ActOnUninitializedDecl(VDPrivate);
if (VDPrivate->isInvalidDecl())
continue;
- auto VDPrivateRefExpr = buildDeclRefExpr(
+ DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
*this, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
DeclRefExpr *Ref = nullptr;
@@ -9156,7 +9415,7 @@ class DiagsUninitializedSeveretyRAII {
private:
DiagnosticsEngine &Diags;
SourceLocation SavedLoc;
- bool IsIgnored;
+ bool IsIgnored = false;
public:
DiagsUninitializedSeveretyRAII(DiagnosticsEngine &Diags, SourceLocation Loc,
@@ -9184,9 +9443,9 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
SmallVector<Decl *, 4> ExprCaptures;
bool IsImplicitClause =
StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
- auto ImplicitClauseLoc = DSAStack->getConstructLoc();
+ SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
- for (auto &RefExpr : VarList) {
+ for (Expr *RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
SourceLocation ELoc;
SourceRange ERange;
@@ -9218,12 +9477,13 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
// A variable of class type (or array thereof) that appears in a private
// clause requires an accessible, unambiguous copy constructor for the
// class type.
- auto ElemType = Context.getBaseElementType(Type).getNonReferenceType();
+ QualType ElemType = Context.getBaseElementType(Type).getNonReferenceType();
// If an implicit firstprivate variable found it was checked already.
DSAStackTy::DSAVarData TopDVar;
if (!IsImplicitClause) {
- DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, false);
+ DSAStackTy::DSAVarData DVar =
+ DSAStack->getTopDSA(D, /*FromParent=*/false);
TopDVar = DVar;
OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
bool IsConstant = ElemType.isConstant(Context);
@@ -9241,7 +9501,7 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
Diag(ELoc, diag::err_omp_wrong_dsa)
<< getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_firstprivate);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
@@ -9261,7 +9521,7 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
Diag(ELoc, diag::err_omp_wrong_dsa)
<< getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_firstprivate);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
@@ -9292,7 +9552,7 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
Diag(ELoc, diag::err_omp_required_access)
<< getOpenMPClauseName(OMPC_firstprivate)
<< getOpenMPClauseName(OMPC_shared);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
}
@@ -9309,8 +9569,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
// from the worksharing construct.
if (isOpenMPTaskingDirective(CurrDir)) {
DVar = DSAStack->hasInnermostDSA(
- D, [](OpenMPClauseKind C) -> bool { return C == OMPC_reduction; },
- [](OpenMPDirectiveKind K) -> bool {
+ D, [](OpenMPClauseKind C) { return C == OMPC_reduction; },
+ [](OpenMPDirectiveKind K) {
return isOpenMPParallelDirective(K) ||
isOpenMPWorksharingDirective(K) ||
isOpenMPTeamsDirective(K);
@@ -9322,7 +9582,7 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
isOpenMPTeamsDirective(DVar.DKind))) {
Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
<< getOpenMPDirectiveName(DVar.DKind);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
}
@@ -9334,8 +9594,9 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
OpenMPClauseKind ConflictKind;
if (DSAStack->checkMappableExprComponentListsForDecl(
VD, /*CurrentRegionOnly=*/true,
- [&](OMPClauseMappableExprCommon::MappableExprComponentListRef,
- OpenMPClauseKind WhereFoundClauseKind) -> bool {
+ [&ConflictKind](
+ OMPClauseMappableExprCommon::MappableExprComponentListRef,
+ OpenMPClauseKind WhereFoundClauseKind) {
ConflictKind = WhereFoundClauseKind;
return true;
})) {
@@ -9343,7 +9604,7 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
<< getOpenMPClauseName(OMPC_firstprivate)
<< getOpenMPClauseName(ConflictKind)
<< getOpenMPDirectiveName(DSAStack->getCurrentDirective());
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
}
@@ -9365,8 +9626,10 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
}
Type = Type.getUnqualifiedType();
- auto VDPrivate = buildVarDecl(*this, ELoc, Type, D->getName(),
- D->hasAttrs() ? &D->getAttrs() : nullptr);
+ VarDecl *VDPrivate =
+ buildVarDecl(*this, ELoc, Type, D->getName(),
+ D->hasAttrs() ? &D->getAttrs() : nullptr,
+ VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
// Generate helper private variable and initialize it with the value of the
// original variable. The address of the original variable is replaced by
// the address of the new private variable in the CodeGen. This new variable
@@ -9376,13 +9639,13 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
// For arrays generate initializer for single element and replace it by the
// original array element in CodeGen.
if (Type->isArrayType()) {
- auto VDInit =
+ VarDecl *VDInit =
buildVarDecl(*this, RefExpr->getExprLoc(), ElemType, D->getName());
VDInitRefExpr = buildDeclRefExpr(*this, VDInit, ElemType, ELoc);
- auto Init = DefaultLvalueConversion(VDInitRefExpr).get();
+ Expr *Init = DefaultLvalueConversion(VDInitRefExpr).get();
ElemType = ElemType.getUnqualifiedType();
- auto *VDInitTemp = buildVarDecl(*this, RefExpr->getExprLoc(), ElemType,
- ".firstprivate.temp");
+ VarDecl *VDInitTemp = buildVarDecl(*this, RefExpr->getExprLoc(), ElemType,
+ ".firstprivate.temp");
InitializedEntity Entity =
InitializedEntity::InitializeVariable(VDInitTemp);
InitializationKind Kind = InitializationKind::CreateCopy(ELoc, ELoc);
@@ -9396,8 +9659,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
// Remove temp variable declaration.
Context.Deallocate(VDInitTemp);
} else {
- auto *VDInit = buildVarDecl(*this, RefExpr->getExprLoc(), Type,
- ".firstprivate.temp");
+ VarDecl *VDInit = buildVarDecl(*this, RefExpr->getExprLoc(), Type,
+ ".firstprivate.temp");
VDInitRefExpr = buildDeclRefExpr(*this, VDInit, RefExpr->getType(),
RefExpr->getExprLoc());
AddInitializerToDecl(VDPrivate,
@@ -9412,16 +9675,16 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
continue;
}
CurContext->addDecl(VDPrivate);
- auto VDPrivateRefExpr = buildDeclRefExpr(
+ DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
*this, VDPrivate, RefExpr->getType().getUnqualifiedType(),
RefExpr->getExprLoc());
DeclRefExpr *Ref = nullptr;
if (!VD && !CurContext->isDependentContext()) {
- if (TopDVar.CKind == OMPC_lastprivate)
+ if (TopDVar.CKind == OMPC_lastprivate) {
Ref = TopDVar.PrivateCopy;
- else {
+ } else {
Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
- if (!IsOpenMPCapturedDecl(D))
+ if (!isOpenMPCapturedDecl(D))
ExprCaptures.push_back(Ref->getDecl());
}
}
@@ -9451,7 +9714,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
SmallVector<Expr *, 8> AssignmentOps;
SmallVector<Decl *, 4> ExprCaptures;
SmallVector<Expr *, 4> ExprPostUpdates;
- for (auto &RefExpr : VarList) {
+ for (Expr *RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
SourceLocation ELoc;
SourceRange ERange;
@@ -9488,7 +9751,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
// OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
// A list item may appear in a firstprivate or lastprivate clause but not
// both.
- DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, false);
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
(isOpenMPDistributeDirective(CurrDir) ||
DVar.CKind != OMPC_firstprivate) &&
@@ -9496,7 +9759,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
Diag(ELoc, diag::err_omp_wrong_dsa)
<< getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_lastprivate);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
@@ -9515,7 +9778,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
Diag(ELoc, diag::err_omp_required_access)
<< getOpenMPClauseName(OMPC_lastprivate)
<< getOpenMPClauseName(OMPC_shared);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
}
@@ -9529,19 +9792,19 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
// lastprivate clause requires an accessible, unambiguous copy assignment
// operator for the class type.
Type = Context.getBaseElementType(Type).getNonReferenceType();
- auto *SrcVD = buildVarDecl(*this, ERange.getBegin(),
- Type.getUnqualifiedType(), ".lastprivate.src",
- D->hasAttrs() ? &D->getAttrs() : nullptr);
- auto *PseudoSrcExpr =
+ VarDecl *SrcVD = buildVarDecl(*this, ERange.getBegin(),
+ Type.getUnqualifiedType(), ".lastprivate.src",
+ D->hasAttrs() ? &D->getAttrs() : nullptr);
+ DeclRefExpr *PseudoSrcExpr =
buildDeclRefExpr(*this, SrcVD, Type.getUnqualifiedType(), ELoc);
- auto *DstVD =
+ VarDecl *DstVD =
buildVarDecl(*this, ERange.getBegin(), Type, ".lastprivate.dst",
D->hasAttrs() ? &D->getAttrs() : nullptr);
- auto *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
+ DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
// For arrays generate assignment operation for single element and replace
// it by the original array element in CodeGen.
- auto AssignmentOp = BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
- PseudoDstExpr, PseudoSrcExpr);
+ ExprResult AssignmentOp = BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
+ PseudoDstExpr, PseudoSrcExpr);
if (AssignmentOp.isInvalid())
continue;
AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
@@ -9551,15 +9814,15 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
DeclRefExpr *Ref = nullptr;
if (!VD && !CurContext->isDependentContext()) {
- if (TopDVar.CKind == OMPC_firstprivate)
+ if (TopDVar.CKind == OMPC_firstprivate) {
Ref = TopDVar.PrivateCopy;
- else {
+ } else {
Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
- if (!IsOpenMPCapturedDecl(D))
+ if (!isOpenMPCapturedDecl(D))
ExprCaptures.push_back(Ref->getDecl());
}
if (TopDVar.CKind == OMPC_firstprivate ||
- (!IsOpenMPCapturedDecl(D) &&
+ (!isOpenMPCapturedDecl(D) &&
Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
ExprResult RefRes = DefaultLvalueConversion(Ref);
if (!RefRes.isUsable())
@@ -9596,7 +9859,7 @@ OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
- for (auto &RefExpr : VarList) {
+ for (Expr *RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
SourceLocation ELoc;
SourceRange ERange;
@@ -9618,17 +9881,17 @@ OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
// 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.
- DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, false);
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
DVar.RefExpr) {
Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_shared);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
DeclRefExpr *Ref = nullptr;
- if (!VD && IsOpenMPCapturedDecl(D) && !CurContext->isDependentContext())
+ if (!VD && isOpenMPCapturedDecl(D) && !CurContext->isDependentContext())
Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
Vars.push_back((VD || !Ref || CurContext->isDependentContext())
@@ -9648,23 +9911,21 @@ class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
public:
bool VisitDeclRefExpr(DeclRefExpr *E) {
- if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) {
- DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, false);
+ if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
+ DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
return false;
if (DVar.CKind != OMPC_unknown)
return true;
DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
- VD, isOpenMPPrivate, [](OpenMPDirectiveKind) -> bool { return true; },
+ VD, isOpenMPPrivate, [](OpenMPDirectiveKind) { return true; },
/*FromParent=*/true);
- if (DVarPrivate.CKind != OMPC_unknown)
- return true;
- return false;
+ return DVarPrivate.CKind != OMPC_unknown;
}
return false;
}
bool VisitStmt(Stmt *S) {
- for (auto Child : S->children()) {
+ for (Stmt *Child : S->children()) {
if (Child && Visit(Child))
return true;
}
@@ -9679,8 +9940,8 @@ namespace {
// DeclRefExpr to specified OMPCapturedExprDecl.
class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
typedef TreeTransform<TransformExprToCaptures> BaseTransform;
- ValueDecl *Field;
- DeclRefExpr *CapturedExpr;
+ ValueDecl *Field = nullptr;
+ DeclRefExpr *CapturedExpr = nullptr;
public:
TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
@@ -9698,12 +9959,12 @@ public:
};
} // namespace
-template <typename T>
-static T filterLookupForUDR(SmallVectorImpl<UnresolvedSet<8>> &Lookups,
- const llvm::function_ref<T(ValueDecl *)> &Gen) {
- for (auto &Set : Lookups) {
+template <typename T, typename U>
+static T filterLookupForUDR(SmallVectorImpl<U> &Lookups,
+ const llvm::function_ref<T(ValueDecl *)> Gen) {
+ for (U &Set : Lookups) {
for (auto *D : Set) {
- if (auto Res = Gen(cast<ValueDecl>(D)))
+ if (T Res = Gen(cast<ValueDecl>(D)))
return Res;
}
}
@@ -9722,7 +9983,7 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
Lookup.suppressDiagnostics();
while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec)) {
- auto *D = Lookup.getRepresentativeDecl();
+ NamedDecl *D = Lookup.getRepresentativeDecl();
do {
S = S->getParent();
} while (S && !S->isDeclScope(D));
@@ -9736,7 +9997,7 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
Lookups.push_back(UnresolvedSet<8>());
Decl *PrevD = nullptr;
- for (auto *D : ULE->decls()) {
+ for (NamedDecl *D : ULE->decls()) {
if (D == PrevD)
Lookups.push_back(UnresolvedSet<8>());
else if (auto *DRD = cast<OMPDeclareReductionDecl>(D))
@@ -9747,14 +10008,14 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
Ty->isInstantiationDependentType() ||
Ty->containsUnexpandedParameterPack() ||
- filterLookupForUDR<bool>(Lookups, [](ValueDecl *D) -> bool {
+ filterLookupForUDR<bool>(Lookups, [](ValueDecl *D) {
return !D->isInvalidDecl() &&
(D->getType()->isDependentType() ||
D->getType()->isInstantiationDependentType() ||
D->getType()->containsUnexpandedParameterPack());
})) {
UnresolvedSet<8> ResSet;
- for (auto &Set : Lookups) {
+ for (const UnresolvedSet<8> &Set : Lookups) {
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]);
@@ -9856,7 +10117,7 @@ struct ReductionData {
};
} // namespace
-static bool CheckOMPArraySectionConstantForReduction(
+static bool checkOMPArraySectionConstantForReduction(
ASTContext &Context, const OMPArraySectionExpr *OASE, bool &SingleElement,
SmallVectorImpl<llvm::APSInt> &ArraySizes) {
const Expr *Length = OASE->getLength();
@@ -9918,14 +10179,14 @@ static bool CheckOMPArraySectionConstantForReduction(
return true;
}
-static bool ActOnOMPReductionKindClause(
+static bool actOnOMPReductionKindClause(
Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation ColonLoc, SourceLocation EndLoc,
CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
- auto DN = ReductionId.getName();
- auto OOK = DN.getCXXOverloadedOperator();
+ DeclarationName DN = ReductionId.getName();
+ OverloadedOperatorKind OOK = DN.getCXXOverloadedOperator();
BinaryOperatorKind BOK = BO_Comma;
ASTContext &Context = S.Context;
@@ -9999,7 +10260,7 @@ static bool ActOnOMPReductionKindClause(
case NUM_OVERLOADED_OPERATORS:
llvm_unreachable("Unexpected reduction identifier");
case OO_None:
- if (auto *II = DN.getAsIdentifierInfo()) {
+ if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
if (II->isStr("max"))
BOK = BO_GT;
else if (II->isStr("min"))
@@ -10016,7 +10277,7 @@ static bool ActOnOMPReductionKindClause(
auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
bool FirstIter = true;
- for (auto RefExpr : VarList) {
+ for (Expr *RefExpr : VarList) {
assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
// OpenMP [2.1, C/C++]
// A list item is a variable or array section, subject to the restrictions
@@ -10057,23 +10318,25 @@ static bool ActOnOMPReductionKindClause(
QualType Type;
auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
auto *OASE = dyn_cast<OMPArraySectionExpr>(RefExpr->IgnoreParens());
- if (ASE)
+ if (ASE) {
Type = ASE->getType().getNonReferenceType();
- else if (OASE) {
- auto BaseType = OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
- if (auto *ATy = BaseType->getAsArrayTypeUnsafe())
+ } else if (OASE) {
+ QualType BaseType =
+ OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
+ if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
Type = ATy->getElementType();
else
Type = BaseType->getPointeeType();
Type = Type.getNonReferenceType();
- } else
+ } else {
Type = Context.getBaseElementType(D->getType().getNonReferenceType());
+ }
auto *VD = dyn_cast<VarDecl>(D);
// OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
// A variable that appears in a private clause must not have an incomplete
// type or a reference type.
- if (S.RequireCompleteType(ELoc, Type,
+ if (S.RequireCompleteType(ELoc, D->getType(),
diag::err_omp_reduction_incomplete_type))
continue;
// OpenMP [2.14.3.6, reduction clause, Restrictions]
@@ -10117,19 +10380,19 @@ static bool ActOnOMPReductionKindClause(
// 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;
- DVar = Stack->getTopDSA(D, false);
+ 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;
- } else if (DVar.CKind != OMPC_unknown) {
+ }
+ if (DVar.CKind != OMPC_unknown) {
S.Diag(ELoc, diag::err_omp_wrong_dsa)
<< getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_reduction);
- ReportOriginalDSA(S, Stack, D, DVar);
+ reportOriginalDsa(S, Stack, D, DVar);
continue;
}
@@ -10146,7 +10409,7 @@ static bool ActOnOMPReductionKindClause(
S.Diag(ELoc, diag::err_omp_required_access)
<< getOpenMPClauseName(OMPC_reduction)
<< getOpenMPClauseName(OMPC_shared);
- ReportOriginalDSA(S, Stack, D, DVar);
+ reportOriginalDsa(S, Stack, D, DVar);
continue;
}
}
@@ -10212,11 +10475,11 @@ static bool ActOnOMPReductionKindClause(
}
Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
- auto *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
- D->hasAttrs() ? &D->getAttrs() : nullptr);
- auto *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
- D->hasAttrs() ? &D->getAttrs() : nullptr);
- auto PrivateTy = Type;
+ VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
+ D->hasAttrs() ? &D->getAttrs() : nullptr);
+ VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
+ D->hasAttrs() ? &D->getAttrs() : nullptr);
+ QualType PrivateTy = Type;
// Try if we can determine constant lengths for all array sections and avoid
// the VLA.
@@ -10224,15 +10487,14 @@ static bool ActOnOMPReductionKindClause(
if (OASE) {
bool SingleElement;
llvm::SmallVector<llvm::APSInt, 4> ArraySizes;
- ConstantLengthOASE = CheckOMPArraySectionConstantForReduction(
+ ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
Context, OASE, SingleElement, ArraySizes);
// If we don't have a single element, we must emit a constant array type.
if (ConstantLengthOASE && !SingleElement) {
- for (auto &Size : ArraySizes) {
+ for (llvm::APSInt &Size : ArraySizes)
PrivateTy = Context.getConstantArrayType(
PrivateTy, Size, ArrayType::Normal, /*IndexTypeQuals=*/0);
- }
}
}
@@ -10255,15 +10517,18 @@ static bool ActOnOMPReductionKindClause(
new (Context) OpaqueValueExpr(ELoc, Context.getSizeType(), VK_RValue),
ArrayType::Normal, /*IndexTypeQuals=*/0, SourceRange());
} else if (!ASE && !OASE &&
- Context.getAsArrayType(D->getType().getNonReferenceType()))
+ Context.getAsArrayType(D->getType().getNonReferenceType())) {
PrivateTy = D->getType().getNonReferenceType();
+ }
// Private copy.
- auto *PrivateVD = buildVarDecl(S, ELoc, PrivateTy, D->getName(),
- D->hasAttrs() ? &D->getAttrs() : nullptr);
+ VarDecl *PrivateVD =
+ buildVarDecl(S, ELoc, PrivateTy, D->getName(),
+ D->hasAttrs() ? &D->getAttrs() : nullptr,
+ VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
// Add initializer for private variable.
Expr *Init = nullptr;
- auto *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
- auto *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
+ DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
+ DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
if (DeclareReductionRef.isUsable()) {
auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
@@ -10301,7 +10566,7 @@ static bool ActOnOMPReductionKindClause(
Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
Type, ELoc);
} else if (Type->isScalarType()) {
- auto Size = Context.getTypeSize(Type);
+ uint64_t Size = Context.getTypeSize(Type);
QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
llvm::APInt InitValue = llvm::APInt::getAllOnesValue(Size);
Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
@@ -10322,7 +10587,7 @@ static bool ActOnOMPReductionKindClause(
// the reduction list item type'.
if (Type->isIntegerType() || Type->isPointerType()) {
bool IsSigned = Type->hasSignedIntegerRepresentation();
- auto Size = Context.getTypeSize(Type);
+ uint64_t Size = Context.getTypeSize(Type);
QualType IntTy =
Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
llvm::APInt InitValue =
@@ -10333,7 +10598,7 @@ static bool ActOnOMPReductionKindClause(
Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
if (Type->isPointerType()) {
// Cast to pointer type.
- auto CastExpr = S.BuildCStyleCastExpr(
+ ExprResult CastExpr = S.BuildCStyleCastExpr(
ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
if (CastExpr.isInvalid())
continue;
@@ -10394,7 +10659,7 @@ static bool ActOnOMPReductionKindClause(
// codegen.
PrivateVD->setInit(RHSVD->getInit());
PrivateVD->setInitStyle(RHSVD->getInitStyle());
- auto *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
+ DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
ExprResult ReductionOp;
if (DeclareReductionRef.isUsable()) {
QualType RedTy = DeclareReductionRef.get()->getType();
@@ -10506,7 +10771,7 @@ static bool ActOnOMPReductionKindClause(
} else {
VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
}
- if (!S.IsOpenMPCapturedDecl(D)) {
+ if (!S.isOpenMPCapturedDecl(D)) {
RD.ExprCaptures.emplace_back(Ref->getDecl());
if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
ExprResult RefRes = S.DefaultLvalueConversion(Ref);
@@ -10551,8 +10816,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
ArrayRef<Expr *> UnresolvedReductions) {
ReductionData RD(VarList.size());
-
- if (ActOnOMPReductionKindClause(*this, DSAStack, OMPC_reduction, VarList,
+ if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_reduction, VarList,
StartLoc, LParenLoc, ColonLoc, EndLoc,
ReductionIdScopeSpec, ReductionId,
UnresolvedReductions, RD))
@@ -10572,10 +10836,9 @@ OMPClause *Sema::ActOnOpenMPTaskReductionClause(
CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
ArrayRef<Expr *> UnresolvedReductions) {
ReductionData RD(VarList.size());
-
- if (ActOnOMPReductionKindClause(*this, DSAStack, OMPC_task_reduction,
- VarList, StartLoc, LParenLoc, ColonLoc,
- EndLoc, ReductionIdScopeSpec, ReductionId,
+ if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_task_reduction, VarList,
+ StartLoc, LParenLoc, ColonLoc, EndLoc,
+ ReductionIdScopeSpec, ReductionId,
UnresolvedReductions, RD))
return nullptr;
@@ -10593,8 +10856,7 @@ OMPClause *Sema::ActOnOpenMPInReductionClause(
CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
ArrayRef<Expr *> UnresolvedReductions) {
ReductionData RD(VarList.size());
-
- if (ActOnOMPReductionKindClause(*this, DSAStack, OMPC_in_reduction, VarList,
+ if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_in_reduction, VarList,
StartLoc, LParenLoc, ColonLoc, EndLoc,
ReductionIdScopeSpec, ReductionId,
UnresolvedReductions, RD))
@@ -10618,10 +10880,10 @@ bool Sema::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
return false;
}
-bool Sema::CheckOpenMPLinearDecl(ValueDecl *D, SourceLocation ELoc,
+bool Sema::CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc,
OpenMPLinearClauseKind LinKind,
QualType Type) {
- auto *VD = dyn_cast_or_null<VarDecl>(D);
+ const auto *VD = dyn_cast_or_null<VarDecl>(D);
// A variable must not have an incomplete type or a reference type.
if (RequireCompleteType(ELoc, Type, diag::err_omp_linear_incomplete_type))
return true;
@@ -10678,7 +10940,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause(
SmallVector<Expr *, 4> ExprPostUpdates;
if (CheckOpenMPLinearModifier(LinKind, LinLoc))
LinKind = OMPC_LINEAR_val;
- for (auto &RefExpr : VarList) {
+ for (Expr *RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP linear clause.");
SourceLocation ELoc;
SourceRange ERange;
@@ -10702,11 +10964,11 @@ OMPClause *Sema::ActOnOpenMPLinearClause(
// A list-item cannot appear in more than one linear clause.
// A list-item that appears in a linear clause cannot appear in any
// other data-sharing attribute clause.
- DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, false);
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
if (DVar.RefExpr) {
Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_linear);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
@@ -10715,16 +10977,18 @@ OMPClause *Sema::ActOnOpenMPLinearClause(
Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
// Build private copy of original var.
- auto *Private = buildVarDecl(*this, ELoc, Type, D->getName(),
- D->hasAttrs() ? &D->getAttrs() : nullptr);
- auto *PrivateRef = buildDeclRefExpr(*this, Private, Type, ELoc);
+ VarDecl *Private =
+ buildVarDecl(*this, ELoc, Type, D->getName(),
+ D->hasAttrs() ? &D->getAttrs() : nullptr,
+ VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
+ DeclRefExpr *PrivateRef = buildDeclRefExpr(*this, Private, Type, ELoc);
// Build var to save initial value.
VarDecl *Init = buildVarDecl(*this, ELoc, Type, ".linear.start");
Expr *InitExpr;
DeclRefExpr *Ref = nullptr;
if (!VD && !CurContext->isDependentContext()) {
Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
- if (!IsOpenMPCapturedDecl(D)) {
+ if (!isOpenMPCapturedDecl(D)) {
ExprCaptures.push_back(Ref->getDecl());
if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
ExprResult RefRes = DefaultLvalueConversion(Ref);
@@ -10746,7 +11010,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause(
InitExpr = VD ? SimpleRefExpr : Ref;
AddInitializerToDecl(Init, DefaultLvalueConversion(InitExpr).get(),
/*DirectInit=*/false);
- auto InitRef = buildDeclRefExpr(*this, Init, Type, ELoc);
+ DeclRefExpr *InitRef = buildDeclRefExpr(*this, Init, Type, ELoc);
DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
Vars.push_back((VD || CurContext->isDependentContext())
@@ -10810,16 +11074,15 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
Expr *CalcStep = Clause.getCalcStep();
// OpenMP [2.14.3.7, linear clause]
// If linear-step is not specified it is assumed to be 1.
- if (Step == nullptr)
+ if (!Step)
Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
- else if (CalcStep) {
+ else if (CalcStep)
Step = cast<BinaryOperator>(CalcStep)->getLHS();
- }
bool HasErrors = false;
auto CurInit = Clause.inits().begin();
auto CurPrivate = Clause.privates().begin();
- auto LinKind = Clause.getModifier();
- for (auto &RefExpr : Clause.varlists()) {
+ OpenMPLinearClauseKind LinKind = Clause.getModifier();
+ for (Expr *RefExpr : Clause.varlists()) {
SourceLocation ELoc;
SourceRange ERange;
Expr *SimpleRefExpr = RefExpr;
@@ -10860,22 +11123,22 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
// Build update: Var = InitExpr + IV * Step
ExprResult Update;
- if (!Info.first) {
+ if (!Info.first)
Update =
- BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), *CurPrivate,
+ buildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), *CurPrivate,
InitExpr, IV, Step, /* Subtract */ false);
- } else
+ else
Update = *CurPrivate;
Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getLocStart(),
/*DiscardedValue=*/true);
// Build final: Var = InitExpr + NumIterations * Step
ExprResult Final;
- if (!Info.first) {
- Final = BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), CapturedRef,
- InitExpr, NumIterations, Step,
- /* Subtract */ false);
- } else
+ if (!Info.first)
+ Final =
+ buildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), CapturedRef,
+ InitExpr, NumIterations, Step, /*Subtract=*/false);
+ else
Final = *CurPrivate;
Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getLocStart(),
/*DiscardedValue=*/true);
@@ -10899,9 +11162,8 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
OMPClause *Sema::ActOnOpenMPAlignedClause(
ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
-
SmallVector<Expr *, 8> Vars;
- for (auto &RefExpr : VarList) {
+ for (Expr *RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP linear clause.");
SourceLocation ELoc;
SourceRange ERange;
@@ -10938,7 +11200,7 @@ OMPClause *Sema::ActOnOpenMPAlignedClause(
// OpenMP [2.8.1, simd construct, Restrictions]
// A list-item cannot appear in more than one aligned clause.
- if (Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
+ if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
Diag(ELoc, diag::err_omp_aligned_twice) << 0 << ERange;
Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
<< getOpenMPClauseName(OMPC_aligned);
@@ -10946,7 +11208,7 @@ OMPClause *Sema::ActOnOpenMPAlignedClause(
}
DeclRefExpr *Ref = nullptr;
- if (!VD && IsOpenMPCapturedDecl(D))
+ if (!VD && isOpenMPCapturedDecl(D))
Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
Vars.push_back(DefaultFunctionArrayConversion(
(VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
@@ -10980,7 +11242,7 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
SmallVector<Expr *, 8> SrcExprs;
SmallVector<Expr *, 8> DstExprs;
SmallVector<Expr *, 8> AssignmentOps;
- for (auto &RefExpr : VarList) {
+ for (Expr *RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP copyin clause.");
if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
@@ -10996,7 +11258,7 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
// A list item is a variable name.
// OpenMP [2.14.4.1, Restrictions, p.1]
// A list item that appears in a copyin clause must be threadprivate.
- DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr);
+ auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
if (!DE || !isa<VarDecl>(DE->getDecl())) {
Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
<< 0 << RefExpr->getSourceRange();
@@ -11004,7 +11266,7 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
}
Decl *D = DE->getDecl();
- VarDecl *VD = cast<VarDecl>(D);
+ auto *VD = cast<VarDecl>(D);
QualType Type = VD->getType();
if (Type->isDependentType() || Type->isInstantiationDependentType()) {
@@ -11029,21 +11291,22 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
// A variable of class type (or array thereof) that appears in a
// copyin clause requires an accessible, unambiguous copy assignment
// operator for the class type.
- auto ElemType = Context.getBaseElementType(Type).getNonReferenceType();
- auto *SrcVD =
+ QualType ElemType = Context.getBaseElementType(Type).getNonReferenceType();
+ VarDecl *SrcVD =
buildVarDecl(*this, DE->getLocStart(), ElemType.getUnqualifiedType(),
".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
- auto *PseudoSrcExpr = buildDeclRefExpr(
+ DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
*this, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
- auto *DstVD =
+ VarDecl *DstVD =
buildVarDecl(*this, DE->getLocStart(), ElemType, ".copyin.dst",
VD->hasAttrs() ? &VD->getAttrs() : nullptr);
- auto *PseudoDstExpr =
+ DeclRefExpr *PseudoDstExpr =
buildDeclRefExpr(*this, DstVD, ElemType, DE->getExprLoc());
// For arrays generate assignment operation for single element and replace
// it by the original array element in CodeGen.
- auto AssignmentOp = BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
- PseudoDstExpr, PseudoSrcExpr);
+ ExprResult AssignmentOp =
+ BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign, PseudoDstExpr,
+ PseudoSrcExpr);
if (AssignmentOp.isInvalid())
continue;
AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
@@ -11073,7 +11336,7 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
SmallVector<Expr *, 8> SrcExprs;
SmallVector<Expr *, 8> DstExprs;
SmallVector<Expr *, 8> AssignmentOps;
- for (auto &RefExpr : VarList) {
+ for (Expr *RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP linear clause.");
SourceLocation ELoc;
SourceRange ERange;
@@ -11098,13 +11361,14 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
// A list item that appears in a copyprivate clause may not appear in a
// private or firstprivate clause on the single construct.
if (!VD || !DSAStack->isThreadPrivate(VD)) {
- auto DVar = DSAStack->getTopDSA(D, false);
+ DSAStackTy::DSAVarData DVar =
+ DSAStack->getTopDSA(D, /*FromParent=*/false);
if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
DVar.RefExpr) {
Diag(ELoc, diag::err_omp_wrong_dsa)
<< getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_copyprivate);
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
@@ -11117,7 +11381,7 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
Diag(ELoc, diag::err_omp_required_access)
<< getOpenMPClauseName(OMPC_copyprivate)
<< "threadprivate or private in the enclosing context";
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
}
@@ -11143,16 +11407,16 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
// operator for the class type.
Type = Context.getBaseElementType(Type.getNonReferenceType())
.getUnqualifiedType();
- auto *SrcVD =
+ VarDecl *SrcVD =
buildVarDecl(*this, RefExpr->getLocStart(), Type, ".copyprivate.src",
D->hasAttrs() ? &D->getAttrs() : nullptr);
- auto *PseudoSrcExpr = buildDeclRefExpr(*this, SrcVD, Type, ELoc);
- auto *DstVD =
+ DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(*this, SrcVD, Type, ELoc);
+ VarDecl *DstVD =
buildVarDecl(*this, RefExpr->getLocStart(), Type, ".copyprivate.dst",
D->hasAttrs() ? &D->getAttrs() : nullptr);
- auto *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
- auto AssignmentOp = BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
- PseudoDstExpr, PseudoSrcExpr);
+ 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,
@@ -11162,7 +11426,7 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
// No need to mark vars as copyprivate, they are already threadprivate or
// implicitly private.
- assert(VD || IsOpenMPCapturedDecl(D));
+ assert(VD || isOpenMPCapturedDecl(D));
Vars.push_back(
VD ? RefExpr->IgnoreParens()
: buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false));
@@ -11214,143 +11478,139 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
llvm::APSInt DepCounter(/*BitWidth=*/32);
llvm::APSInt TotalDepCount(/*BitWidth=*/32);
if (DepKind == OMPC_DEPEND_sink) {
- if (auto *OrderedCountExpr = DSAStack->getParentOrderedRegionParam()) {
+ if (const Expr *OrderedCountExpr = DSAStack->getParentOrderedRegionParam()) {
TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Context);
TotalDepCount.setIsUnsigned(/*Val=*/true);
}
}
- if ((DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) ||
- DSAStack->getParentOrderedRegionParam()) {
- for (auto &RefExpr : VarList) {
- assert(RefExpr && "NULL expr in OpenMP shared clause.");
- if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
+ for (Expr *RefExpr : VarList) {
+ assert(RefExpr && "NULL expr in OpenMP shared clause.");
+ if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
+ // It will be analyzed later.
+ Vars.push_back(RefExpr);
+ continue;
+ }
+
+ SourceLocation ELoc = RefExpr->getExprLoc();
+ Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
+ if (DepKind == OMPC_DEPEND_sink) {
+ if (DSAStack->getParentOrderedRegionParam() &&
+ DepCounter >= TotalDepCount) {
+ Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
+ continue;
+ }
+ ++DepCounter;
+ // OpenMP [2.13.9, Summary]
+ // depend(dependence-type : vec), where dependence-type is:
+ // 'sink' and where vec is the iteration vector, which has the form:
+ // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
+ // where n is the value specified by the ordered clause in the loop
+ // directive, xi denotes the loop iteration variable of the i-th nested
+ // loop associated with the loop directive, and di is a constant
+ // non-negative integer.
+ if (CurContext->isDependentContext()) {
// It will be analyzed later.
Vars.push_back(RefExpr);
continue;
}
+ SimpleExpr = SimpleExpr->IgnoreImplicit();
+ OverloadedOperatorKind OOK = OO_None;
+ SourceLocation OOLoc;
+ Expr *LHS = SimpleExpr;
+ Expr *RHS = nullptr;
+ if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
+ OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
+ OOLoc = BO->getOperatorLoc();
+ LHS = BO->getLHS()->IgnoreParenImpCasts();
+ RHS = BO->getRHS()->IgnoreParenImpCasts();
+ } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
+ OOK = OCE->getOperator();
+ OOLoc = OCE->getOperatorLoc();
+ LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
+ RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
+ } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
+ OOK = MCE->getMethodDecl()
+ ->getNameInfo()
+ .getName()
+ .getCXXOverloadedOperator();
+ OOLoc = MCE->getCallee()->getExprLoc();
+ LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
+ RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
+ }
+ SourceLocation ELoc;
+ SourceRange ERange;
+ auto Res = getPrivateItem(*this, LHS, ELoc, ERange,
+ /*AllowArraySection=*/false);
+ if (Res.second) {
+ // It will be analyzed later.
+ Vars.push_back(RefExpr);
+ }
+ ValueDecl *D = Res.first;
+ if (!D)
+ continue;
- SourceLocation ELoc = RefExpr->getExprLoc();
- auto *SimpleExpr = RefExpr->IgnoreParenCasts();
- if (DepKind == OMPC_DEPEND_sink) {
- if (DepCounter >= TotalDepCount) {
- Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
- continue;
- }
- ++DepCounter;
- // OpenMP [2.13.9, Summary]
- // depend(dependence-type : vec), where dependence-type is:
- // 'sink' and where vec is the iteration vector, which has the form:
- // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
- // where n is the value specified by the ordered clause in the loop
- // directive, xi denotes the loop iteration variable of the i-th nested
- // loop associated with the loop directive, and di is a constant
- // non-negative integer.
- if (CurContext->isDependentContext()) {
- // It will be analyzed later.
- Vars.push_back(RefExpr);
- continue;
- }
- SimpleExpr = SimpleExpr->IgnoreImplicit();
- OverloadedOperatorKind OOK = OO_None;
- SourceLocation OOLoc;
- Expr *LHS = SimpleExpr;
- Expr *RHS = nullptr;
- if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
- OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
- OOLoc = BO->getOperatorLoc();
- LHS = BO->getLHS()->IgnoreParenImpCasts();
- RHS = BO->getRHS()->IgnoreParenImpCasts();
- } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
- OOK = OCE->getOperator();
- OOLoc = OCE->getOperatorLoc();
- LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
- RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
- } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
- OOK = MCE->getMethodDecl()
- ->getNameInfo()
- .getName()
- .getCXXOverloadedOperator();
- OOLoc = MCE->getCallee()->getExprLoc();
- LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
- RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
- }
- SourceLocation ELoc;
- SourceRange ERange;
- auto Res = getPrivateItem(*this, LHS, ELoc, ERange,
- /*AllowArraySection=*/false);
- if (Res.second) {
- // It will be analyzed later.
- Vars.push_back(RefExpr);
- }
- ValueDecl *D = Res.first;
- if (!D)
- continue;
-
- if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
- Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
- continue;
- }
- if (RHS) {
- ExprResult RHSRes = VerifyPositiveIntegerConstantInClause(
- RHS, OMPC_depend, /*StrictlyPositive=*/false);
- if (RHSRes.isInvalid())
- continue;
- }
- if (!CurContext->isDependentContext() &&
- DSAStack->getParentOrderedRegionParam() &&
- DepCounter != DSAStack->isParentLoopControlVariable(D).first) {
- ValueDecl* VD = DSAStack->getParentLoopControlVariable(
- DepCounter.getZExtValue());
- if (VD) {
- Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
- << 1 << VD;
- } else {
- Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration) << 0;
- }
- continue;
- }
- OpsOffs.push_back({RHS, OOK});
- } else {
- auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
- if (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
- (ASE &&
- !ASE->getBase()
- ->getType()
- .getNonReferenceType()
- ->isPointerType() &&
- !ASE->getBase()->getType().getNonReferenceType()->isArrayType())) {
- Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
- << RefExpr->getSourceRange();
- continue;
- }
- bool Suppress = getDiagnostics().getSuppressAllDiagnostics();
- getDiagnostics().setSuppressAllDiagnostics(/*Val=*/true);
- ExprResult Res = CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
- RefExpr->IgnoreParenImpCasts());
- getDiagnostics().setSuppressAllDiagnostics(Suppress);
- if (!Res.isUsable() && !isa<OMPArraySectionExpr>(SimpleExpr)) {
- Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
- << RefExpr->getSourceRange();
+ if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
+ Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
+ continue;
+ }
+ if (RHS) {
+ ExprResult RHSRes = VerifyPositiveIntegerConstantInClause(
+ RHS, OMPC_depend, /*StrictlyPositive=*/false);
+ if (RHSRes.isInvalid())
continue;
- }
}
- Vars.push_back(RefExpr->IgnoreParenImpCasts());
+ if (!CurContext->isDependentContext() &&
+ DSAStack->getParentOrderedRegionParam() &&
+ DepCounter != DSAStack->isParentLoopControlVariable(D).first) {
+ const ValueDecl *VD =
+ DSAStack->getParentLoopControlVariable(DepCounter.getZExtValue());
+ if (VD)
+ Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
+ << 1 << VD;
+ else
+ Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration) << 0;
+ continue;
+ }
+ OpsOffs.emplace_back(RHS, OOK);
+ } else {
+ auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
+ if (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
+ (ASE &&
+ !ASE->getBase()->getType().getNonReferenceType()->isPointerType() &&
+ !ASE->getBase()->getType().getNonReferenceType()->isArrayType())) {
+ Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
+ << RefExpr->getSourceRange();
+ continue;
+ }
+ bool Suppress = getDiagnostics().getSuppressAllDiagnostics();
+ getDiagnostics().setSuppressAllDiagnostics(/*Val=*/true);
+ ExprResult Res =
+ CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RefExpr->IgnoreParenImpCasts());
+ getDiagnostics().setSuppressAllDiagnostics(Suppress);
+ if (!Res.isUsable() && !isa<OMPArraySectionExpr>(SimpleExpr)) {
+ Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
+ << RefExpr->getSourceRange();
+ continue;
+ }
}
+ Vars.push_back(RefExpr->IgnoreParenImpCasts());
+ }
- if (!CurContext->isDependentContext() && DepKind == OMPC_DEPEND_sink &&
- TotalDepCount > VarList.size() &&
- DSAStack->getParentOrderedRegionParam() &&
- DSAStack->getParentLoopControlVariable(VarList.size() + 1)) {
- Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration) << 1
- << DSAStack->getParentLoopControlVariable(VarList.size() + 1);
- }
- if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
- Vars.empty())
- return nullptr;
+ if (!CurContext->isDependentContext() && DepKind == OMPC_DEPEND_sink &&
+ TotalDepCount > VarList.size() &&
+ DSAStack->getParentOrderedRegionParam() &&
+ DSAStack->getParentLoopControlVariable(VarList.size() + 1)) {
+ Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
+ << 1 << DSAStack->getParentLoopControlVariable(VarList.size() + 1);
}
+ if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
+ Vars.empty())
+ return nullptr;
+
auto *C = OMPDependClause::Create(Context, StartLoc, LParenLoc, EndLoc,
DepKind, DepLoc, ColonLoc, Vars);
- if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source)
+ if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
+ DSAStack->isParentOrderedRegion())
DSAStack->addDoacrossDependClause(C, OpsOffs);
return C;
}
@@ -11363,7 +11623,7 @@ OMPClause *Sema::ActOnOpenMPDeviceClause(Expr *Device, SourceLocation StartLoc,
// OpenMP [2.9.1, Restrictions]
// The device expression must evaluate to a non-negative integer value.
- if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_device,
+ if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_device,
/*StrictlyPositive=*/false))
return nullptr;
@@ -11372,46 +11632,50 @@ OMPClause *Sema::ActOnOpenMPDeviceClause(Expr *Device, SourceLocation StartLoc,
getOpenMPCaptureRegionForClause(DKind, OMPC_device);
if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
ValExpr = MakeFullExpr(ValExpr).get();
- llvm::MapVector<Expr *, DeclRefExpr *> Captures;
+ llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
}
- return new (Context)
- OMPDeviceClause(ValExpr, HelperValStmt, StartLoc, LParenLoc, EndLoc);
+ return new (Context) OMPDeviceClause(ValExpr, HelperValStmt, CaptureRegion,
+ StartLoc, LParenLoc, EndLoc);
}
-static bool CheckTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
- DSAStackTy *Stack, QualType QTy) {
+static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
+ DSAStackTy *Stack, QualType QTy,
+ bool FullCheck = true) {
NamedDecl *ND;
if (QTy->isIncompleteType(&ND)) {
SemaRef.Diag(SL, diag::err_incomplete_type) << QTy << SR;
return false;
}
+ if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
+ !QTy.isTrivialType(SemaRef.Context))
+ SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
return true;
}
-/// \brief Return true if it can be proven that the provided array expression
+/// Return true if it can be proven that the provided array expression
/// (array section or array subscript) does NOT specify the whole size of the
/// array whose base type is \a BaseQTy.
-static bool CheckArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
+static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
const Expr *E,
QualType BaseQTy) {
- auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
+ const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
// If this is an array subscript, it refers to the whole size if the size of
// the dimension is constant and equals 1. Also, an array section assumes the
// format of an array subscript if no colon is used.
if (isa<ArraySubscriptExpr>(E) || (OASE && OASE->getColonLoc().isInvalid())) {
- if (auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
+ if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
return ATy->getSize().getSExtValue() != 1;
// Size can't be evaluated statically.
return false;
}
assert(OASE && "Expecting array section if not an array subscript.");
- auto *LowerBound = OASE->getLowerBound();
- auto *Length = OASE->getLength();
+ const Expr *LowerBound = OASE->getLowerBound();
+ const Expr *Length = OASE->getLength();
// If there is a lower bound that does not evaluates to zero, we are not
// covering the whole dimension.
@@ -11434,7 +11698,7 @@ static bool CheckArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
// We can only check if the length is the same as the size of the dimension
// if we have a constant array.
- auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
+ const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
if (!CATy)
return false;
@@ -11448,10 +11712,10 @@ static bool CheckArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
// Return true if it can be proven that the provided array expression (array
// section or array subscript) does NOT specify a single element of the array
// whose base type is \a BaseQTy.
-static bool CheckArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
+static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
const Expr *E,
QualType BaseQTy) {
- auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
+ const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
// An array subscript always refer to a single element. Also, an array section
// assumes the format of an array subscript if no colon is used.
@@ -11459,13 +11723,13 @@ static bool CheckArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
return false;
assert(OASE && "Expecting array section if not an array subscript.");
- auto *Length = OASE->getLength();
+ const Expr *Length = OASE->getLength();
// If we don't have a length we have to check if the array has unitary size
// for this dimension. Also, we should always expect a length if the base type
// is pointer.
if (!Length) {
- if (auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
+ if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
return ATy->getSize().getSExtValue() != 1;
// We cannot assume anything.
return false;
@@ -11483,7 +11747,7 @@ static bool CheckArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
// cannot be determined and do all the necessary checks to see if the expression
// is valid as a standalone mappable expression. In the process, record all the
// components of the expression.
-static Expr *CheckMapClauseExpressionBase(
+static const Expr *checkMapClauseExpressionBase(
Sema &SemaRef, Expr *E,
OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
OpenMPClauseKind CKind, bool NoDiagnose) {
@@ -11509,7 +11773,7 @@ static Expr *CheckMapClauseExpressionBase(
//
// We want to retrieve the member expression 'this->S';
- Expr *RelevantExpr = nullptr;
+ const Expr *RelevantExpr = nullptr;
// OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.2]
// If a list item is an array section, it must specify contiguous storage.
@@ -11548,7 +11812,7 @@ static Expr *CheckMapClauseExpressionBase(
// Record the component.
CurComponents.emplace_back(CurE, CurE->getDecl());
} else if (auto *CurE = dyn_cast<MemberExpr>(E)) {
- auto *BaseE = CurE->getBase()->IgnoreParenImpCasts();
+ Expr *BaseE = CurE->getBase()->IgnoreParenImpCasts();
if (isa<CXXThisExpr>(BaseE))
// We found a base expression: this->Val.
@@ -11592,15 +11856,13 @@ static Expr *CheckMapClauseExpressionBase(
// A list item cannot be a variable that is a member of a structure with
// a union type.
//
- if (auto *RT = CurType->getAs<RecordType>()) {
- if (RT->isUnionType()) {
- if (!NoDiagnose) {
- SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
- << CurE->getSourceRange();
- return nullptr;
- }
- continue;
+ if (CurType->isUnionType()) {
+ if (!NoDiagnose) {
+ SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
+ << CurE->getSourceRange();
+ return nullptr;
}
+ continue;
}
// If we got a member expression, we should not expect any array section
@@ -11630,7 +11892,7 @@ static Expr *CheckMapClauseExpressionBase(
// If we got an array subscript that express the whole dimension we
// can have any array expressions before. If it only expressing part of
// the dimension, we can only have unitary-size array expressions.
- if (CheckArrayExpressionDoesNotReferToWholeSize(SemaRef, CurE,
+ if (checkArrayExpressionDoesNotReferToWholeSize(SemaRef, CurE,
E->getType()))
AllowWholeSizeArraySection = false;
@@ -11658,9 +11920,9 @@ static Expr *CheckMapClauseExpressionBase(
}
bool NotWhole =
- CheckArrayExpressionDoesNotReferToWholeSize(SemaRef, CurE, CurType);
+ checkArrayExpressionDoesNotReferToWholeSize(SemaRef, CurE, CurType);
bool NotUnity =
- CheckArrayExpressionDoesNotReferToUnitySize(SemaRef, CurE, CurType);
+ checkArrayExpressionDoesNotReferToUnitySize(SemaRef, CurE, CurType);
if (AllowWholeSizeArraySection) {
// Any array section is currently allowed. Allowing a whole size array
@@ -11698,8 +11960,8 @@ static Expr *CheckMapClauseExpressionBase(
// Return true if expression E associated with value VD has conflicts with other
// map information.
-static bool CheckMapConflicts(
- Sema &SemaRef, DSAStackTy *DSAS, ValueDecl *VD, Expr *E,
+static bool checkMapConflicts(
+ Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
bool CurrentRegionOnly,
OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents,
OpenMPClauseKind CKind) {
@@ -11721,17 +11983,19 @@ static bool CheckMapConflicts(
bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
VD, CurrentRegionOnly,
- [&](OMPClauseMappableExprCommon::MappableExprComponentListRef
- StackComponents,
- OpenMPClauseKind) -> bool {
-
+ [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
+ ERange, CKind, &EnclosingExpr,
+ CurComponents](OMPClauseMappableExprCommon::MappableExprComponentListRef
+ StackComponents,
+ OpenMPClauseKind) {
assert(!StackComponents.empty() &&
"Map clause expression with no components!");
assert(StackComponents.back().getAssociatedDeclaration() == VD &&
"Map clause expression with unexpected base!");
+ (void)VD;
// The whole expression in the stack.
- auto *RE = StackComponents.front().getAssociatedExpression();
+ const Expr *RE = StackComponents.front().getAssociatedExpression();
// Expressions must start from the same base. Here we detect at which
// point both expressions diverge from each other and see if we can
@@ -11774,17 +12038,17 @@ static bool CheckMapConflicts(
// If they are, the maps completely overlap, which is legal.
for (; SI != SE; ++SI) {
QualType Type;
- if (auto *ASE =
+ if (const auto *ASE =
dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
- } else if (auto *OASE = dyn_cast<OMPArraySectionExpr>(
+ } else if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(
SI->getAssociatedExpression())) {
- auto *E = OASE->getBase()->IgnoreParenImpCasts();
+ const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
Type =
OMPArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
}
if (Type.isNull() || Type->isAnyPointerType() ||
- CheckArrayExpressionDoesNotReferToWholeSize(
+ checkArrayExpressionDoesNotReferToWholeSize(
SemaRef, SI->getAssociatedExpression(), Type))
break;
}
@@ -11797,9 +12061,9 @@ static bool CheckMapConflicts(
// other, it means they are sharing storage.
if (CI == CE && SI == SE) {
if (CurrentRegionOnly) {
- if (CKind == OMPC_map)
+ if (CKind == OMPC_map) {
SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
- else {
+ } else {
assert(CKind == OMPC_to || CKind == OMPC_from);
SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
<< ERange;
@@ -11807,12 +12071,11 @@ static bool CheckMapConflicts(
SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
<< RE->getSourceRange();
return true;
- } else {
- // If we find the same expression in the enclosing data environment,
- // that is legal.
- IsEnclosedByDataEnvironmentExpr = true;
- return false;
}
+ // If we find the same expression in the enclosing data environment,
+ // that is legal.
+ IsEnclosedByDataEnvironmentExpr = true;
+ return false;
}
QualType DerivedType =
@@ -11842,14 +12105,21 @@ static bool CheckMapConflicts(
DerivedLoc,
diag::err_omp_pointer_mapped_along_with_derived_section)
<< DerivedLoc;
- } else {
+ SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
+ << RE->getSourceRange();
+ return true;
+ }
+ if (CI->getAssociatedExpression()->getStmtClass() !=
+ SI->getAssociatedExpression()->getStmtClass() ||
+ CI->getAssociatedDeclaration()->getCanonicalDecl() ==
+ SI->getAssociatedDeclaration()->getCanonicalDecl()) {
assert(CI != CE && SI != SE);
- SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_derreferenced)
+ SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
<< DerivedLoc;
+ SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
+ << RE->getSourceRange();
+ return true;
}
- SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
- << RE->getSourceRange();
- return true;
}
// OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
@@ -11858,9 +12128,9 @@ static bool CheckMapConflicts(
//
// An expression is a subset of the other.
if (CurrentRegionOnly && (CI == CE || SI == SE)) {
- if (CKind == OMPC_map)
+ if (CKind == OMPC_map) {
SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
- else {
+ } else {
assert(CKind == OMPC_to || CKind == OMPC_from);
SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
<< ERange;
@@ -11912,7 +12182,7 @@ static bool CheckMapConflicts(
namespace {
// Utility struct that gathers all the related lists associated with a mappable
// expression.
-struct MappableVarListInfo final {
+struct MappableVarListInfo {
// The list of expressions.
ArrayRef<Expr *> VarList;
// The list of processed expressions.
@@ -11952,11 +12222,11 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS,
// In the end we should have the same amount of declarations and component
// lists.
- for (auto &RE : MVLI.VarList) {
+ for (Expr *RE : MVLI.VarList) {
assert(RE && "Null expr in omp to/from/map clause");
SourceLocation ELoc = RE->getExprLoc();
- auto *VE = RE->IgnoreParenLValueCasts();
+ const Expr *VE = RE->IgnoreParenLValueCasts();
if (VE->isValueDependent() || VE->isTypeDependent() ||
VE->isInstantiationDependent() ||
@@ -11967,7 +12237,7 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS,
continue;
}
- auto *SimpleExpr = RE->IgnoreParenCasts();
+ Expr *SimpleExpr = RE->IgnoreParenCasts();
if (!RE->IgnoreParenImpCasts()->isLValue()) {
SemaRef.Diag(ELoc,
@@ -11981,8 +12251,8 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS,
// Obtain the array or member expression bases if required. Also, fill the
// components array with all the components identified in the process.
- auto *BE = CheckMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents,
- CKind, /*NoDiagnose=*/false);
+ const Expr *BE = checkMapClauseExpressionBase(
+ SemaRef, SimpleExpr, CurComponents, CKind, /*NoDiagnose=*/false);
if (!BE)
continue;
@@ -11999,7 +12269,7 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS,
"Expecting components to have associated only canonical declarations.");
auto *VD = dyn_cast<VarDecl>(CurDeclaration);
- auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
+ const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
assert((VD || FD) && "Only variables or fields are expected here!");
(void)FD;
@@ -12009,10 +12279,10 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS,
// OpenMP 4.5 [2.10.5, target update Construct]
// threadprivate variables cannot appear in a from clause.
if (VD && DSAS->isThreadPrivate(VD)) {
- auto DVar = DSAS->getTopDSA(VD, false);
+ DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
<< getOpenMPClauseName(CKind);
- ReportOriginalDSA(SemaRef, DSAS, VD, DVar);
+ reportOriginalDsa(SemaRef, DSAS, VD, DVar);
continue;
}
@@ -12024,11 +12294,11 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS,
// with the current construct separately from the enclosing data
// environment, because the restrictions are different. We only have to
// check conflicts across regions for the map clauses.
- if (CheckMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
+ if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
/*CurrentRegionOnly=*/true, CurComponents, CKind))
break;
if (CKind == OMPC_map &&
- CheckMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
+ checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
/*CurrentRegionOnly=*/false, CurComponents, CKind))
break;
@@ -12036,13 +12306,20 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS,
// OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
// If the type of a list item is a reference to a type T then the type will
// be considered to be T for all purposes of this clause.
- QualType Type = CurDeclaration->getType().getNonReferenceType();
+ auto I = llvm::find_if(
+ CurComponents,
+ [](const OMPClauseMappableExprCommon::MappableComponent &MC) {
+ return MC.getAssociatedDeclaration();
+ });
+ assert(I != CurComponents.end() && "Null decl on map clause.");
+ QualType Type =
+ I->getAssociatedDeclaration()->getType().getNonReferenceType();
// OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
// A list item in a to or from clause must have a mappable type.
// OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
// A list item must have a mappable type.
- if (!CheckTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
+ if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
DSAS, Type))
continue;
@@ -12078,18 +12355,14 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS,
// OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
// A list item cannot appear in both a map clause and a data-sharing
// attribute clause on the same construct
- if ((DKind == OMPD_target || DKind == OMPD_target_teams ||
- DKind == OMPD_target_teams_distribute ||
- DKind == OMPD_target_teams_distribute_parallel_for ||
- DKind == OMPD_target_teams_distribute_parallel_for_simd ||
- DKind == OMPD_target_teams_distribute_simd) && VD) {
- auto DVar = DSAS->getTopDSA(VD, false);
+ if (VD && isOpenMPTargetExecutionDirective(DKind)) {
+ DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
if (isOpenMPPrivate(DVar.CKind)) {
SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
<< getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_map)
<< getOpenMPDirectiveName(DSAS->getCurrentDirective());
- ReportOriginalDSA(SemaRef, DSAS, CurDeclaration, DVar);
+ reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
continue;
}
}
@@ -12190,14 +12463,14 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveStart(
FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
/*AllowInlineNamespace=*/false);
llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
- auto Filter = Lookup.makeFilter();
+ LookupResult::Filter Filter = Lookup.makeFilter();
while (Filter.hasNext()) {
auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
if (InCompoundScope) {
auto I = UsedAsPrevious.find(PrevDecl);
if (I == UsedAsPrevious.end())
UsedAsPrevious[PrevDecl] = false;
- if (auto *D = PrevDecl->getPrevDeclInScope())
+ if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
UsedAsPrevious[D] = true;
}
PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
@@ -12205,7 +12478,7 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveStart(
}
Filter.done();
if (InCompoundScope) {
- for (auto &PrevData : UsedAsPrevious) {
+ for (const auto &PrevData : UsedAsPrevious) {
if (!PrevData.second) {
PrevDRD = PrevData.first;
break;
@@ -12221,8 +12494,8 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveStart(
PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
} while (PrevDRDInScope != nullptr);
}
- for (auto &TyData : ReductionTypes) {
- auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
+ for (const auto &TyData : ReductionTypes) {
+ const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
bool Invalid = false;
if (I != PreviousRedeclTypes.end()) {
Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
@@ -12251,7 +12524,7 @@ void Sema::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) {
// Enter new function scope.
PushFunctionScope();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
getCurFunction()->setHasOMPDeclareReductionCombiner();
if (S != nullptr)
@@ -12269,7 +12542,7 @@ void Sema::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) {
// reference. C lang does not support references, so pass all parameters as
// pointers.
// Create 'T omp_in;' variable.
- auto *OmpInParm =
+ VarDecl *OmpInParm =
buildVarDecl(*this, D->getLocation(), ReductionType, "omp_in");
// Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
// be replaced by '*omp_parm' during codegen. This required because 'omp_out'
@@ -12277,7 +12550,7 @@ void Sema::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) {
// reference. C lang does not support references, so pass all parameters as
// pointers.
// Create 'T omp_out;' variable.
- auto *OmpOutParm =
+ VarDecl *OmpOutParm =
buildVarDecl(*this, D->getLocation(), ReductionType, "omp_out");
if (S != nullptr) {
PushOnScopeChains(OmpInParm, S);
@@ -12307,7 +12580,7 @@ VarDecl *Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) {
// Enter new function scope.
PushFunctionScope();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
if (S != nullptr)
PushDeclContext(S, DRD);
@@ -12324,7 +12597,7 @@ VarDecl *Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) {
// reference. C lang does not support references, so pass all parameters as
// pointers.
// Create 'T omp_priv;' variable.
- auto *OmpPrivParm =
+ VarDecl *OmpPrivParm =
buildVarDecl(*this, D->getLocation(), ReductionType, "omp_priv");
// Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
// be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
@@ -12332,7 +12605,7 @@ VarDecl *Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) {
// reference. C lang does not support references, so pass all parameters as
// pointers.
// Create 'T omp_orig;' variable.
- auto *OmpOrigParm =
+ VarDecl *OmpOrigParm =
buildVarDecl(*this, D->getLocation(), ReductionType, "omp_orig");
if (S != nullptr) {
PushOnScopeChains(OmpPrivParm, S);
@@ -12367,13 +12640,14 @@ void Sema::ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer,
Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveEnd(
Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
- for (auto *D : DeclReductions.get()) {
+ for (Decl *D : DeclReductions.get()) {
if (IsValid) {
- auto *DRD = cast<OMPDeclareReductionDecl>(D);
- if (S != nullptr)
- PushOnScopeChains(DRD, S, /*AddToContext=*/false);
- } else
+ if (S)
+ PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
+ /*AddToContext=*/false);
+ } else {
D->setInvalidDecl();
+ }
}
return DeclReductions;
}
@@ -12387,7 +12661,7 @@ OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams,
// OpenMP [teams Constrcut, Restrictions]
// The num_teams expression must evaluate to a positive integer value.
- if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_num_teams,
+ if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_num_teams,
/*StrictlyPositive=*/true))
return nullptr;
@@ -12396,7 +12670,7 @@ OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams,
getOpenMPCaptureRegionForClause(DKind, OMPC_num_teams);
if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
ValExpr = MakeFullExpr(ValExpr).get();
- llvm::MapVector<Expr *, DeclRefExpr *> Captures;
+ llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
}
@@ -12414,7 +12688,7 @@ OMPClause *Sema::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit,
// OpenMP [teams Constrcut, Restrictions]
// The thread_limit expression must evaluate to a positive integer value.
- if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_thread_limit,
+ if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_thread_limit,
/*StrictlyPositive=*/true))
return nullptr;
@@ -12423,7 +12697,7 @@ OMPClause *Sema::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit,
getOpenMPCaptureRegionForClause(DKind, OMPC_thread_limit);
if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
ValExpr = MakeFullExpr(ValExpr).get();
- llvm::MapVector<Expr *, DeclRefExpr *> Captures;
+ llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
}
@@ -12440,7 +12714,7 @@ OMPClause *Sema::ActOnOpenMPPriorityClause(Expr *Priority,
// OpenMP [2.9.1, task Constrcut]
// The priority-value is a non-negative numerical scalar expression.
- if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_priority,
+ if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_priority,
/*StrictlyPositive=*/false))
return nullptr;
@@ -12456,7 +12730,7 @@ OMPClause *Sema::ActOnOpenMPGrainsizeClause(Expr *Grainsize,
// OpenMP [2.9.2, taskloop Constrcut]
// The parameter of the grainsize clause must be a positive integer
// expression.
- if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_grainsize,
+ if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_grainsize,
/*StrictlyPositive=*/true))
return nullptr;
@@ -12472,7 +12746,7 @@ OMPClause *Sema::ActOnOpenMPNumTasksClause(Expr *NumTasks,
// OpenMP [2.9.2, taskloop Constrcut]
// The parameter of the num_tasks clause must be a positive integer
// expression.
- if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_num_tasks,
+ if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_num_tasks,
/*StrictlyPositive=*/true))
return nullptr;
@@ -12534,7 +12808,7 @@ OMPClause *Sema::ActOnOpenMPDistScheduleClause(
OMPD_unknown &&
!CurContext->isDependentContext()) {
ValExpr = MakeFullExpr(ValExpr).get();
- llvm::MapVector<Expr *, DeclRefExpr *> Captures;
+ llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
}
@@ -12599,7 +12873,6 @@ bool Sema::ActOnStartOpenMPDeclareTargetDirective(SourceLocation Loc) {
void Sema::ActOnFinishOpenMPDeclareTargetDirective() {
assert(IsInOpenMPDeclareTargetContext &&
"Unexpected ActOnFinishOpenMPDeclareTargetDirective");
-
IsInOpenMPDeclareTargetContext = false;
}
@@ -12634,9 +12907,8 @@ void Sema::ActOnOpenMPDeclareTargetName(Scope *CurScope,
if (isa<VarDecl>(ND) || isa<FunctionDecl>(ND)) {
if (!SameDirectiveDecls.insert(cast<NamedDecl>(ND->getCanonicalDecl())))
Diag(Id.getLoc(), diag::err_omp_declare_target_multiple) << Id.getName();
-
if (!ND->hasAttr<OMPDeclareTargetDeclAttr>()) {
- Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(Context, MT);
+ auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(Context, MT);
ND->addAttr(A);
if (ASTMutationListener *ML = Context.getASTMutationListener())
ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
@@ -12645,15 +12917,16 @@ void Sema::ActOnOpenMPDeclareTargetName(Scope *CurScope,
Diag(Id.getLoc(), diag::err_omp_declare_target_to_and_link)
<< Id.getName();
}
- } else
+ } else {
Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
+ }
}
static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
Sema &SemaRef, Decl *D) {
if (!D)
return;
- Decl *LD = nullptr;
+ const Decl *LD = nullptr;
if (isa<TagDecl>(D)) {
LD = cast<TagDecl>(D)->getDefinition();
} else if (isa<VarDecl>(D)) {
@@ -12662,56 +12935,63 @@ static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
// If this is an implicit variable that is legal and we do not need to do
// anything.
if (cast<VarDecl>(D)->isImplicit()) {
- Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(
+ 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 (isa<FunctionDecl>(D)) {
+ } else if (const auto *F = dyn_cast<FunctionDecl>(D)) {
const FunctionDecl *FD = nullptr;
- if (cast<FunctionDecl>(D)->hasBody(FD))
- LD = const_cast<FunctionDecl *>(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) {
- Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(
- SemaRef.Context, OMPDeclareTargetDeclAttr::MT_To);
- D->addAttr(A);
- if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener())
- ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
- return;
+ 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<FunctionDecl>(LD))) {
+ ((isa<VarDecl>(LD) && !isa<ParmVarDecl>(LD)) || isa<FunctionDecl>(LD))) {
// Outlined declaration is not declared target.
- if (LD->isOutOfLine()) {
- SemaRef.Diag(LD->getLocation(), diag::warn_omp_not_in_target_context);
- SemaRef.Diag(SL, diag::note_used_here) << SR;
- } else {
- DeclContext *DC = LD->getDeclContext();
- while (DC) {
- if (isa<FunctionDecl>(DC) &&
- cast<FunctionDecl>(DC)->hasAttr<OMPDeclareTargetDeclAttr>())
- break;
- DC = DC->getParent();
- }
- if (DC)
- return;
+ 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;
+ // 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.
- Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(
+ auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
SemaRef.Context, OMPDeclareTargetDeclAttr::MT_To);
D->addAttr(A);
if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener())
@@ -12722,11 +13002,9 @@ static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR,
Sema &SemaRef, DSAStackTy *Stack,
ValueDecl *VD) {
- if (VD->hasAttr<OMPDeclareTargetDeclAttr>())
- return true;
- if (!CheckTypeMappable(SL, SR, SemaRef, Stack, VD->getType()))
- return false;
- return true;
+ return VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
+ checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
+ /*FullCheck=*/false);
}
void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
@@ -12735,22 +13013,27 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
return;
SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
SourceLocation SL = E ? E->getLocStart() : D->getLocation();
- // 2.10.6: threadprivate variable cannot appear in a declare target directive.
- if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (auto *VD = dyn_cast<VarDecl>(D)) {
+ // Only global variables can be marked as declare target.
+ if (VD->isLocalVarDeclOrParm())
+ return;
+ // 2.10.6: threadprivate variable cannot appear in a declare target
+ // directive.
if (DSAStack->isThreadPrivate(VD)) {
Diag(SL, diag::err_omp_threadprivate_in_target);
- ReportOriginalDSA(*this, DSAStack, VD, DSAStack->getTopDSA(VD, false));
+ reportOriginalDsa(*this, DSAStack, VD, DSAStack->getTopDSA(VD, false));
return;
}
}
- if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
+ 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)) {
- Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(
+ if (isa<VarDecl>(VD) || isa<FunctionDecl>(VD) ||
+ isa<FunctionTemplateDecl>(VD)) {
+ auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
Context, OMPDeclareTargetDeclAttr::MT_To);
VD->addAttr(A);
if (ASTMutationListener *ML = Context.getASTMutationListener())
@@ -12759,7 +13042,7 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
return;
}
}
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->hasAttr<OMPDeclareTargetDeclAttr>() &&
(FD->getAttr<OMPDeclareTargetDeclAttr>()->getMapType() ==
OMPDeclareTargetDeclAttr::MT_Link)) {
@@ -12769,11 +13052,22 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
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))) {
- Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(
+ (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())
@@ -12820,7 +13114,7 @@ OMPClause *Sema::ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList,
SmallVector<Expr *, 8> PrivateCopies;
SmallVector<Expr *, 8> Inits;
- for (auto &RefExpr : VarList) {
+ for (Expr *RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
SourceLocation ELoc;
SourceRange ERange;
@@ -12849,20 +13143,22 @@ OMPClause *Sema::ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList,
}
// Build the private variable and the expression that refers to it.
- auto VDPrivate = buildVarDecl(*this, ELoc, Type, D->getName(),
- D->hasAttrs() ? &D->getAttrs() : nullptr);
+ auto VDPrivate =
+ buildVarDecl(*this, ELoc, Type, D->getName(),
+ D->hasAttrs() ? &D->getAttrs() : nullptr,
+ VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
if (VDPrivate->isInvalidDecl())
continue;
CurContext->addDecl(VDPrivate);
- auto VDPrivateRefExpr = buildDeclRefExpr(
+ DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
*this, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
// Add temporary variable to initialize the private copy of the pointer.
- auto *VDInit =
+ VarDecl *VDInit =
buildVarDecl(*this, RefExpr->getExprLoc(), Type, ".devptr.temp");
- auto *VDInitRefExpr = buildDeclRefExpr(*this, VDInit, RefExpr->getType(),
- RefExpr->getExprLoc());
+ DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
+ *this, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
AddInitializerToDecl(VDPrivate,
DefaultLvalueConversion(VDInitRefExpr).get(),
/*DirectInit=*/false);
@@ -12902,7 +13198,7 @@ OMPClause *Sema::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
MappableVarListInfo MVLI(VarList);
- for (auto &RefExpr : VarList) {
+ for (Expr *RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
SourceLocation ELoc;
SourceRange ERange;
@@ -12927,17 +13223,17 @@ OMPClause *Sema::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
// Check if the declaration in the clause does not show up in any data
// sharing attribute.
- auto DVar = DSAStack->getTopDSA(D, false);
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
if (isOpenMPPrivate(DVar.CKind)) {
Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
<< getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_is_device_ptr)
<< getOpenMPDirectiveName(DSAStack->getCurrentDirective());
- ReportOriginalDSA(*this, DSAStack, D, DVar);
+ reportOriginalDsa(*this, DSAStack, D, DVar);
continue;
}
- Expr *ConflictExpr;
+ const Expr *ConflictExpr;
if (DSAStack->checkMappableExprComponentListsForDecl(
D, /*CurrentRegionOnly=*/true,
[&ConflictExpr](
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
index f2b1963df1ed..08af485ef4c7 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
@@ -223,6 +223,7 @@ bool StandardConversionSequence::isPointerConversionToBool() const {
// a pointer.
if (getToType(1)->isBooleanType() &&
(getFromType()->isPointerType() ||
+ getFromType()->isMemberPointerType() ||
getFromType()->isObjCObjectPointerType() ||
getFromType()->isBlockPointerType() ||
getFromType()->isNullPtrType() ||
@@ -288,11 +289,11 @@ static const Expr *IgnoreNarrowingConversion(const Expr *Converted) {
/// value of the expression prior to the narrowing conversion.
/// \param ConstantType If this is an NK_Constant_Narrowing conversion, the
/// type of the expression prior to the narrowing conversion.
-NarrowingKind
-StandardConversionSequence::getNarrowingKind(ASTContext &Ctx,
- const Expr *Converted,
- APValue &ConstantValue,
- QualType &ConstantType) const {
+/// \param IgnoreFloatToIntegralConversion If true type-narrowing conversions
+/// from floating point types to integral types should be ignored.
+NarrowingKind StandardConversionSequence::getNarrowingKind(
+ ASTContext &Ctx, const Expr *Converted, APValue &ConstantValue,
+ QualType &ConstantType, bool IgnoreFloatToIntegralConversion) const {
assert(Ctx.getLangOpts().CPlusPlus && "narrowing check outside C++");
// C++11 [dcl.init.list]p7:
@@ -327,7 +328,10 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx,
FloatingIntegralConversion:
if (FromType->isRealFloatingType() && ToType->isIntegralType(Ctx)) {
return NK_Type_Narrowing;
- } else if (FromType->isIntegralType(Ctx) && ToType->isRealFloatingType()) {
+ } else if (FromType->isIntegralOrUnscopedEnumerationType() &&
+ ToType->isRealFloatingType()) {
+ if (IgnoreFloatToIntegralConversion)
+ return NK_Not_Narrowing;
llvm::APSInt IntConstantValue;
const Expr *Initializer = IgnoreNarrowingConversion(Converted);
assert(Initializer && "Unknown conversion expression");
@@ -580,7 +584,7 @@ namespace {
};
}
-/// \brief Convert from Sema's representation of template deduction information
+/// Convert from Sema's representation of template deduction information
/// to the form used in overload-candidate information.
DeductionFailureInfo
clang::MakeDeductionFailureInfo(ASTContext &Context,
@@ -625,6 +629,8 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
break;
}
+ case Sema::TDK_IncompletePack:
+ // FIXME: It's slightly wasteful to allocate two TemplateArguments for this.
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified: {
// FIXME: Should allocate from normal heap so that we can free this later.
@@ -667,6 +673,7 @@ void DeductionFailureInfo::Destroy() {
case Sema::TDK_NonDependentConversionFailure:
break;
+ case Sema::TDK_IncompletePack:
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
case Sema::TDK_DeducedMismatch:
@@ -716,6 +723,7 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() {
case Sema::TDK_InvalidExplicitArguments:
return TemplateParameter::getFromOpaqueValue(Data);
+ case Sema::TDK_IncompletePack:
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
return static_cast<DFIParamWithArguments*>(Data)->Param;
@@ -736,6 +744,7 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() {
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
case Sema::TDK_Incomplete:
+ case Sema::TDK_IncompletePack:
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
@@ -773,6 +782,7 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() {
case Sema::TDK_NonDependentConversionFailure:
return nullptr;
+ case Sema::TDK_IncompletePack:
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
case Sema::TDK_DeducedMismatch:
@@ -794,6 +804,7 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() {
case Sema::TDK_Invalid:
case Sema::TDK_InstantiationDepth:
case Sema::TDK_Incomplete:
+ case Sema::TDK_IncompletePack:
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
case Sema::TDK_InvalidExplicitArguments:
@@ -997,6 +1008,13 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
Match = *I;
return Ovl_Match;
}
+
+ // Builtins that have custom typechecking or have a reference should
+ // not be overloadable or redeclarable.
+ if (!getASTContext().canBuiltinBeRedeclared(OldF)) {
+ Match = *I;
+ return Ovl_NonFunction;
+ }
} else if (isa<UsingDecl>(OldD) || isa<UsingPackDecl>(OldD)) {
// We can overload with these, which can show up when doing
// redeclaration checks for UsingDecls.
@@ -1182,7 +1200,7 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
return false;
}
-/// \brief Checks availability of the function depending on the current
+/// Checks availability of the function depending on the current
/// function context. Inside an unavailable function, unavailability is ignored.
///
/// \returns true if \arg FD is unavailable and current context is inside
@@ -1200,7 +1218,7 @@ bool Sema::isFunctionConsideredUnavailable(FunctionDecl *FD) {
return true;
}
-/// \brief Tries a user-defined conversion from From to ToType.
+/// Tries a user-defined conversion from From to ToType.
///
/// Produces an implicit conversion sequence for when a standard conversion
/// is not an option. See TryImplicitConversion for more information.
@@ -1412,7 +1430,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
return PerformImplicitConversion(From, ToType, ICS, Action);
}
-/// \brief Determine whether the conversion from FromType to ToType is a valid
+/// Determine whether the conversion from FromType to ToType is a valid
/// conversion that strips "noexcept" or "noreturn" off the nested function
/// type.
bool Sema::IsFunctionConversion(QualType FromType, QualType ToType,
@@ -1473,12 +1491,10 @@ bool Sema::IsFunctionConversion(QualType FromType, QualType ToType,
// Drop 'noexcept' if not present in target type.
if (const auto *FromFPT = dyn_cast<FunctionProtoType>(FromFn)) {
const auto *ToFPT = cast<FunctionProtoType>(ToFn);
- if (FromFPT->isNothrow(Context) && !ToFPT->isNothrow(Context)) {
+ if (FromFPT->isNothrow() && !ToFPT->isNothrow()) {
FromFn = cast<FunctionType>(
- Context.getFunctionType(FromFPT->getReturnType(),
- FromFPT->getParamTypes(),
- FromFPT->getExtProtoInfo().withExceptionSpec(
- FunctionProtoType::ExceptionSpecInfo()))
+ Context.getFunctionTypeWithExceptionSpec(QualType(FromFPT, 0),
+ EST_None)
.getTypePtr());
Changed = true;
}
@@ -1511,7 +1527,7 @@ bool Sema::IsFunctionConversion(QualType FromType, QualType ToType,
return true;
}
-/// \brief Determine whether the conversion from FromType to ToType is a valid
+/// Determine whether the conversion from FromType to ToType is a valid
/// vector conversion.
///
/// \param ICK Will be set to the vector conversion kind, if this is a vector
@@ -1766,8 +1782,8 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
(FromType == S.Context.LongDoubleTy &&
ToType == S.Context.Float128Ty));
if (Float128AndLongDouble &&
- (&S.Context.getFloatTypeSemantics(S.Context.LongDoubleTy) !=
- &llvm::APFloat::IEEEdouble()))
+ (&S.Context.getFloatTypeSemantics(S.Context.LongDoubleTy) ==
+ &llvm::APFloat::PPCDoubleDouble()))
return false;
}
// Floating point conversions (C++ 4.8).
@@ -1998,6 +2014,14 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
isCompleteType(From->getLocStart(), FromType))
return Context.hasSameUnqualifiedType(
ToType, FromEnumType->getDecl()->getPromotionType());
+
+ // C++ [conv.prom]p5:
+ // If the bit-field has an enumerated type, it is treated as any other
+ // value of that type for promotion purposes.
+ //
+ // ... so do not fall through into the bit-field checks below in C++.
+ if (getLangOpts().CPlusPlus)
+ return false;
}
// C++0x [conv.prom]p2:
@@ -2045,6 +2069,11 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
// other value of that type for promotion purposes (C++ 4.5p3).
// FIXME: We should delay checking of bit-fields until we actually perform the
// conversion.
+ //
+ // FIXME: In C, only bit-fields of types _Bool, int, or unsigned int may be
+ // promoted, per C11 6.3.1.1/2. We promote all bit-fields (including enum
+ // bit-fields and those whose underlying type is larger than int) for GCC
+ // compatibility.
if (From) {
if (FieldDecl *MemberDecl = From->getSourceBitField()) {
llvm::APSInt BitWidth;
@@ -2111,7 +2140,7 @@ bool Sema::IsFloatingPointPromotion(QualType FromType, QualType ToType) {
return false;
}
-/// \brief Determine if a conversion is a complex promotion.
+/// Determine if a conversion is a complex promotion.
///
/// A complex promotion is defined as a complex -> complex conversion
/// where the conversion between the underlying real types is a
@@ -2345,7 +2374,7 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
return false;
}
-/// \brief Adopt the given qualifiers for the given type.
+/// Adopt the given qualifiers for the given type.
static QualType AdoptQualifiers(ASTContext &Context, QualType T, Qualifiers Qs){
Qualifiers TQs = T.getQualifiers();
@@ -2533,7 +2562,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
return false;
}
-/// \brief Determine whether this is an Objective-C writeback conversion,
+/// Determine whether this is an Objective-C writeback conversion,
/// used for parameter passing when performing automatic reference counting.
///
/// \param FromType The type we're converting form.
@@ -2593,7 +2622,7 @@ bool Sema::isObjCWritebackConversion(QualType FromType, QualType ToType,
IncompatibleObjC))
return false;
- /// \brief Construct the type we're converting to, which is a pointer to
+ /// Construct the type we're converting to, which is a pointer to
/// __autoreleasing pointee.
FromPointee = Context.getQualifiedType(FromPointee, FromQuals);
ConvertedType = Context.getPointerType(FromPointee);
@@ -2803,9 +2832,9 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
// Handle exception specification differences on canonical type (in C++17
// onwards).
if (cast<FunctionProtoType>(FromFunction->getCanonicalTypeUnqualified())
- ->isNothrow(Context) !=
+ ->isNothrow() !=
cast<FunctionProtoType>(ToFunction->getCanonicalTypeUnqualified())
- ->isNothrow(Context)) {
+ ->isNothrow()) {
PDiag << ft_noexcept;
return;
}
@@ -3065,7 +3094,7 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType,
// in multi-level pointers, subject to the following rules: [...]
bool PreviousToQualsIncludeConst = true;
bool UnwrappedAnyPointer = false;
- while (Context.UnwrapSimilarPointerTypes(FromType, ToType)) {
+ while (Context.UnwrapSimilarTypes(FromType, ToType)) {
// Within each iteration of the loop, we check the qualifiers to
// determine if this still looks like a qualification
// conversion. Then, if all is well, we unwrap one more level of
@@ -3121,6 +3150,15 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType,
= PreviousToQualsIncludeConst && ToQuals.hasConst();
}
+ // Allows address space promotion by language rules implemented in
+ // Type::Qualifiers::isAddressSpaceSupersetOf.
+ Qualifiers FromQuals = FromType.getQualifiers();
+ Qualifiers ToQuals = ToType.getQualifiers();
+ if (!ToQuals.isAddressSpaceSupersetOf(FromQuals) &&
+ !FromQuals.isAddressSpaceSupersetOf(ToQuals)) {
+ return false;
+ }
+
// We are left with FromType and ToType being the pointee types
// after unwrapping the original FromType and ToType the same number
// of types. If we unwrapped any pointers, and if FromType and
@@ -3129,7 +3167,7 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType,
return UnwrappedAnyPointer && Context.hasSameUnqualifiedType(FromType,ToType);
}
-/// \brief - Determine whether this is a conversion from a scalar type to an
+/// - Determine whether this is a conversion from a scalar type to an
/// atomic type.
///
/// If successful, updates \c SCS's second and third steps in the conversion
@@ -3472,7 +3510,7 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
return true;
}
-/// \brief Compare the user-defined conversion functions or constructors
+/// Compare the user-defined conversion functions or constructors
/// of two user-defined conversion sequences to determine whether any ordering
/// is possible.
static ImplicitConversionSequence::CompareKind
@@ -3620,16 +3658,6 @@ CompareImplicitConversionSequences(Sema &S, SourceLocation Loc,
return Result;
}
-static bool hasSimilarType(ASTContext &Context, QualType T1, QualType T2) {
- while (Context.UnwrapSimilarPointerTypes(T1, T2)) {
- Qualifiers Quals;
- T1 = Context.getUnqualifiedArrayType(T1, Quals);
- T2 = Context.getUnqualifiedArrayType(T2, Quals);
- }
-
- return Context.hasSameUnqualifiedType(T1, T2);
-}
-
// Per 13.3.3.2p3, compare the given standard conversion sequences to
// determine if one is a proper subset of the other.
static ImplicitConversionSequence::CompareKind
@@ -3653,7 +3681,7 @@ compareStandardConversionSubsets(ASTContext &Context,
Result = ImplicitConversionSequence::Worse;
else
return ImplicitConversionSequence::Indistinguishable;
- } else if (!hasSimilarType(Context, SCS1.getToType(1), SCS2.getToType(1)))
+ } else if (!Context.hasSimilarType(SCS1.getToType(1), SCS2.getToType(1)))
return ImplicitConversionSequence::Indistinguishable;
if (SCS1.Third == SCS2.Third) {
@@ -3674,7 +3702,7 @@ compareStandardConversionSubsets(ASTContext &Context,
return ImplicitConversionSequence::Indistinguishable;
}
-/// \brief Determine whether one of the given reference bindings is better
+/// Determine whether one of the given reference bindings is better
/// than the other based on what kind of bindings they are.
static bool
isBetterReferenceBindingKind(const StandardConversionSequence &SCS1,
@@ -3927,7 +3955,7 @@ CompareQualificationConversions(Sema &S,
: ImplicitConversionSequence::Better;
}
- while (S.Context.UnwrapSimilarPointerTypes(T1, T2)) {
+ while (S.Context.UnwrapSimilarTypes(T1, T2)) {
// Within each iteration of the loop, we check the qualifiers to
// determine if this still looks like a qualification
// conversion. Then, if all is well, we unwrap one more level of
@@ -4199,7 +4227,7 @@ CompareDerivedToBaseConversions(Sema &S, SourceLocation Loc,
return ImplicitConversionSequence::Indistinguishable;
}
-/// \brief Determine whether the given type is valid, e.g., it is not an invalid
+/// Determine whether the given type is valid, e.g., it is not an invalid
/// C++ class.
static bool isTypeValid(QualType T) {
if (CXXRecordDecl *Record = T->getAsCXXRecordDecl())
@@ -4302,7 +4330,7 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
return Ref_Related;
}
-/// \brief Look for a user-defined conversion to a value reference-compatible
+/// Look for a user-defined conversion to a value reference-compatible
/// with DeclType. Return true if something definite is found.
static bool
FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
@@ -4429,7 +4457,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
llvm_unreachable("Invalid OverloadResult!");
}
-/// \brief Compute an implicit conversion sequence for reference
+/// Compute an implicit conversion sequence for reference
/// initialization.
static ImplicitConversionSequence
TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
@@ -5137,6 +5165,13 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
FromRecordType = From->getType();
DestType = ImplicitParamRecordType;
FromClassification = From->Classify(Context);
+
+ // When performing member access on an rvalue, materialize a temporary.
+ if (From->isRValue()) {
+ From = CreateMaterializeTemporaryExpr(FromRecordType, From,
+ Method->getRefQualifier() !=
+ RefQualifierKind::RQ_RValue);
+ }
}
// Note that we always use the true parent context when performing
@@ -5399,10 +5434,11 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
SmallVector<PartialDiagnosticAt, 8> Notes;
Expr::EvalResult Eval;
Eval.Diag = &Notes;
+ Expr::ConstExprUsage Usage = CCE == Sema::CCEK_TemplateArg
+ ? Expr::EvaluateForMangling
+ : Expr::EvaluateForCodeGen;
- if ((T->isReferenceType()
- ? !Result.get()->EvaluateAsLValue(Eval, S.Context)
- : !Result.get()->EvaluateAsRValue(Eval, S.Context)) ||
+ if (!Result.get()->EvaluateAsConstantExpr(Eval, Usage, S.Context) ||
(RequireInt && !Eval.Val.isInt())) {
// The expression can't be folded, so we can't keep it at this position in
// the AST.
@@ -5641,7 +5677,7 @@ collectViableConversionCandidates(Sema &SemaRef, Expr *From, QualType ToType,
}
}
-/// \brief Attempt to convert the given expression to a type which is accepted
+/// Attempt to convert the given expression to a type which is accepted
/// by the given converter.
///
/// This routine will attempt to convert an expression of class type to a
@@ -5959,6 +5995,13 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
Candidate.IgnoreObjectArgument = false;
Candidate.ExplicitCallArguments = Args.size();
+ if (Function->isMultiVersion() && Function->hasAttr<TargetAttr>() &&
+ !Function->getAttr<TargetAttr>()->isDefaultVersion()) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_non_default_multiversion_function;
+ return;
+ }
+
if (Constructor) {
// C++ [class.copy]p3:
// A member function template is never instantiated to perform the copy
@@ -6239,12 +6282,17 @@ convertArgsForAvailabilityChecks(Sema &S, FunctionDecl *Function, Expr *ThisArg,
if (!Function->isVariadic() && Args.size() < Function->getNumParams()) {
for (unsigned i = Args.size(), e = Function->getNumParams(); i != e; ++i) {
ParmVarDecl *P = Function->getParamDecl(i);
- ExprResult R = S.PerformCopyInitialization(
- InitializedEntity::InitializeParameter(S.Context,
- Function->getParamDecl(i)),
- SourceLocation(),
- P->hasUninstantiatedDefaultArg() ? P->getUninstantiatedDefaultArg()
- : P->getDefaultArg());
+ Expr *DefArg = P->hasUninstantiatedDefaultArg()
+ ? P->getUninstantiatedDefaultArg()
+ : P->getDefaultArg();
+ // This can only happen in code completion, i.e. when PartialOverloading
+ // is true.
+ if (!DefArg)
+ return false;
+ ExprResult R =
+ S.PerformCopyInitialization(InitializedEntity::InitializeParameter(
+ S.Context, Function->getParamDecl(i)),
+ SourceLocation(), DefArg);
if (R.isInvalid())
return false;
ConvertedArgs.push_back(R.get());
@@ -6355,67 +6403,65 @@ bool Sema::diagnoseArgIndependentDiagnoseIfAttrs(const NamedDecl *ND,
});
}
-/// \brief Add all of the function declarations in the given function set to
+/// Add all of the function declarations in the given function set to
/// the overload candidate set.
void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
ArrayRef<Expr *> Args,
- OverloadCandidateSet& CandidateSet,
+ OverloadCandidateSet &CandidateSet,
TemplateArgumentListInfo *ExplicitTemplateArgs,
bool SuppressUserConversions,
bool PartialOverloading,
bool FirstArgumentIsBase) {
for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) {
NamedDecl *D = F.getDecl()->getUnderlyingDecl();
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- ArrayRef<Expr *> FunctionArgs = Args;
- if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) {
- QualType ObjectType;
- Expr::Classification ObjectClassification;
- if (Args.size() > 0) {
- if (Expr *E = Args[0]) {
- // Use the explit base to restrict the lookup:
- ObjectType = E->getType();
- ObjectClassification = E->Classify(Context);
- } // .. else there is an implit base.
- FunctionArgs = Args.slice(1);
- }
- AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(),
- cast<CXXMethodDecl>(FD)->getParent(), ObjectType,
- ObjectClassification, FunctionArgs, CandidateSet,
- SuppressUserConversions, PartialOverloading);
- } else {
- // Slice the first argument (which is the base) when we access
- // static method as non-static
- if (Args.size() > 0 && (!Args[0] || (FirstArgumentIsBase && isa<CXXMethodDecl>(FD) &&
- !isa<CXXConstructorDecl>(FD)))) {
- assert(cast<CXXMethodDecl>(FD)->isStatic());
- FunctionArgs = Args.slice(1);
- }
- AddOverloadCandidate(FD, F.getPair(), FunctionArgs, CandidateSet,
- SuppressUserConversions, PartialOverloading);
- }
- } else {
- FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(D);
- if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) &&
- !cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic()) {
- QualType ObjectType;
- Expr::Classification ObjectClassification;
+ ArrayRef<Expr *> FunctionArgs = Args;
+
+ FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D);
+ FunctionDecl *FD =
+ FunTmpl ? FunTmpl->getTemplatedDecl() : cast<FunctionDecl>(D);
+
+ if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) {
+ QualType ObjectType;
+ Expr::Classification ObjectClassification;
+ if (Args.size() > 0) {
if (Expr *E = Args[0]) {
- // Use the explit base to restrict the lookup:
+ // Use the explicit base to restrict the lookup:
ObjectType = E->getType();
ObjectClassification = E->Classify(Context);
- } // .. else there is an implit base.
+ } // .. else there is an implicit base.
+ FunctionArgs = Args.slice(1);
+ }
+ if (FunTmpl) {
AddMethodTemplateCandidate(
FunTmpl, F.getPair(),
cast<CXXRecordDecl>(FunTmpl->getDeclContext()),
ExplicitTemplateArgs, ObjectType, ObjectClassification,
- Args.slice(1), CandidateSet, SuppressUserConversions,
+ FunctionArgs, CandidateSet, SuppressUserConversions,
PartialOverloading);
} else {
- AddTemplateOverloadCandidate(FunTmpl, F.getPair(),
- ExplicitTemplateArgs, Args,
- CandidateSet, SuppressUserConversions,
- PartialOverloading);
+ AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(),
+ cast<CXXMethodDecl>(FD)->getParent(), ObjectType,
+ ObjectClassification, FunctionArgs, CandidateSet,
+ SuppressUserConversions, PartialOverloading);
+ }
+ } else {
+ // This branch handles both standalone functions and static methods.
+
+ // Slice the first argument (which is the base) when we access
+ // static method as non-static.
+ if (Args.size() > 0 &&
+ (!Args[0] || (FirstArgumentIsBase && isa<CXXMethodDecl>(FD) &&
+ !isa<CXXConstructorDecl>(FD)))) {
+ assert(cast<CXXMethodDecl>(FD)->isStatic());
+ FunctionArgs = Args.slice(1);
+ }
+ if (FunTmpl) {
+ AddTemplateOverloadCandidate(
+ FunTmpl, F.getPair(), ExplicitTemplateArgs, FunctionArgs,
+ CandidateSet, SuppressUserConversions, PartialOverloading);
+ } else {
+ AddOverloadCandidate(FD, F.getPair(), FunctionArgs, CandidateSet,
+ SuppressUserConversions, PartialOverloading);
}
}
}
@@ -6583,9 +6629,15 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
Candidate.DeductionFailure.Data = FailedAttr;
return;
}
+
+ if (Method->isMultiVersion() && Method->hasAttr<TargetAttr>() &&
+ !Method->getAttr<TargetAttr>()->isDefaultVersion()) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_non_default_multiversion_function;
+ }
}
-/// \brief Add a C++ member function template as a candidate to the candidate
+/// Add a C++ member function template as a candidate to the candidate
/// set, using template argument deduction to produce an appropriate member
/// function template specialization.
void
@@ -6653,7 +6705,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
Conversions);
}
-/// \brief Add a C++ function template specialization as a candidate
+/// 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
@@ -6986,9 +7038,15 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
Candidate.DeductionFailure.Data = FailedAttr;
return;
}
+
+ if (Conversion->isMultiVersion() && Conversion->hasAttr<TargetAttr>() &&
+ !Conversion->getAttr<TargetAttr>()->isDefaultVersion()) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_non_default_multiversion_function;
+ }
}
-/// \brief Adds a conversion function template specialization
+/// Adds a conversion function template specialization
/// candidate to the overload set, using template argument deduction
/// to deduce the template arguments of the conversion function
/// template from the type that we are converting to (C++
@@ -7143,7 +7201,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
}
}
-/// \brief Add overload candidates for overloaded operators that are
+/// Add overload candidates for overloaded operators that are
/// member functions.
///
/// Add the overloaded operator candidates that are member functions
@@ -7279,18 +7337,18 @@ class BuiltinCandidateTypeSet {
/// used in the built-in candidates.
TypeSet EnumerationTypes;
- /// \brief The set of vector types that will be used in the built-in
+ /// The set of vector types that will be used in the built-in
/// candidates.
TypeSet VectorTypes;
- /// \brief A flag indicating non-record types are viable candidates
+ /// A flag indicating non-record types are viable candidates
bool HasNonRecordTypes;
- /// \brief A flag indicating whether either arithmetic or enumeration types
+ /// A flag indicating whether either arithmetic or enumeration types
/// were present in the candidate set.
bool HasArithmeticOrEnumeralTypes;
- /// \brief A flag indicating whether the nullptr type was present in the
+ /// A flag indicating whether the nullptr type was present in the
/// candidate set.
bool HasNullPtrType;
@@ -7543,7 +7601,7 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
}
}
-/// \brief Helper function for AddBuiltinOperatorCandidates() that adds
+/// Helper function for AddBuiltinOperatorCandidates() that adds
/// the volatile- and non-volatile-qualified assignment operators for the
/// given type to the candidate set.
static void AddBuiltinAssignmentOperatorCandidates(Sema &S,
@@ -7621,7 +7679,7 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) {
namespace {
-/// \brief Helper class to manage the addition of builtin operator overload
+/// Helper class to manage the addition of builtin operator overload
/// candidates. It provides shared state and utility methods used throughout
/// the process, as well as a helper method to add each group of builtin
/// operator overloads from the standard to a candidate set.
@@ -7677,6 +7735,8 @@ class BuiltinOperatorOverloadBuilder {
ArithmeticTypes.push_back(S.Context.BoolTy);
ArithmeticTypes.push_back(S.Context.CharTy);
ArithmeticTypes.push_back(S.Context.WCharTy);
+ if (S.Context.getLangOpts().Char8)
+ ArithmeticTypes.push_back(S.Context.Char8Ty);
ArithmeticTypes.push_back(S.Context.Char16Ty);
ArithmeticTypes.push_back(S.Context.Char32Ty);
ArithmeticTypes.push_back(S.Context.SignedCharTy);
@@ -7692,7 +7752,7 @@ class BuiltinOperatorOverloadBuilder {
"Enough inline storage for all arithmetic types.");
}
- /// \brief Helper method to factor out the common pattern of adding overloads
+ /// Helper method to factor out the common pattern of adding overloads
/// for '++' and '--' builtin operators.
void addPlusPlusMinusMinusStyleOverloads(QualType CandidateTy,
bool HasVolatile,
@@ -7752,11 +7812,13 @@ public:
InitArithmeticTypes();
}
+ // Increment is deprecated for bool since C++17.
+ //
// C++ [over.built]p3:
//
- // For every pair (T, VQ), where T is an arithmetic type, and VQ
- // is either volatile or empty, there exist candidate operator
- // functions of the form
+ // For every pair (T, VQ), where T is an arithmetic type other
+ // than bool, and VQ is either volatile or empty, there exist
+ // candidate operator functions of the form
//
// VQ T& operator++(VQ T&);
// T operator++(VQ T&, int);
@@ -7773,10 +7835,16 @@ public:
if (!HasArithmeticOrEnumeralCandidateType)
return;
- for (unsigned Arith = (Op == OO_PlusPlus? 0 : 1);
- Arith < NumArithmeticTypes; ++Arith) {
+ for (unsigned Arith = 0; Arith < NumArithmeticTypes; ++Arith) {
+ const auto TypeOfT = ArithmeticTypes[Arith];
+ if (TypeOfT == S.Context.BoolTy) {
+ if (Op == OO_MinusMinus)
+ continue;
+ if (Op == OO_PlusPlus && S.getLangOpts().CPlusPlus17)
+ continue;
+ }
addPlusPlusMinusMinusStyleOverloads(
- ArithmeticTypes[Arith],
+ TypeOfT,
VisibleTypeConversionsQuals.hasVolatile(),
VisibleTypeConversionsQuals.hasRestrict());
}
@@ -7948,7 +8016,8 @@ public:
// bool operator>=(T, T);
// bool operator==(T, T);
// bool operator!=(T, T);
- void addRelationalPointerOrEnumeralOverloads() {
+ // R operator<=>(T, T)
+ void addGenericBinaryPointerOrEnumeralOverloads() {
// C++ [over.match.oper]p3:
// [...]the built-in candidates include all of the candidate operator
// functions defined in 13.6 that, compared to the given operator, [...]
@@ -8021,7 +8090,6 @@ public:
UserDefinedBinaryOperators.count(std::make_pair(CanonType,
CanonType)))
continue;
-
QualType ParamTypes[2] = { *Enum, *Enum };
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
@@ -8139,6 +8207,41 @@ public:
}
}
+ // C++2a [over.built]p14:
+ //
+ // For every integral type T there exists a candidate operator function
+ // of the form
+ //
+ // std::strong_ordering operator<=>(T, T)
+ //
+ // C++2a [over.built]p15:
+ //
+ // For every pair of floating-point types L and R, there exists a candidate
+ // operator function of the form
+ //
+ // std::partial_ordering operator<=>(L, R);
+ //
+ // FIXME: The current specification for integral types doesn't play nice with
+ // the direction of p0946r0, which allows mixed integral and unscoped-enum
+ // comparisons. Under the current spec this can lead to ambiguity during
+ // overload resolution. For example:
+ //
+ // enum A : int {a};
+ // auto x = (a <=> (long)42);
+ //
+ // error: call is ambiguous for arguments 'A' and 'long'.
+ // note: candidate operator<=>(int, int)
+ // note: candidate operator<=>(long, long)
+ //
+ // To avoid this error, this function deviates from the specification and adds
+ // the mixed overloads `operator<=>(L, R)` where L and R are promoted
+ // arithmetic types (the same as the generic relational overloads).
+ //
+ // For now this function acts as a placeholder.
+ void addThreeWayArithmeticOverloads() {
+ addGenericBinaryArithmeticOverloads();
+ }
+
// C++ [over.built]p17:
//
// For every pair of promoted integral types L and R, there
@@ -8707,12 +8810,14 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
case OO_Greater:
case OO_LessEqual:
case OO_GreaterEqual:
- OpBuilder.addRelationalPointerOrEnumeralOverloads();
+ OpBuilder.addGenericBinaryPointerOrEnumeralOverloads();
OpBuilder.addGenericBinaryArithmeticOverloads();
break;
case OO_Spaceship:
- llvm_unreachable("<=> expressions not supported yet");
+ OpBuilder.addGenericBinaryPointerOrEnumeralOverloads();
+ OpBuilder.addThreeWayArithmeticOverloads();
+ break;
case OO_Percent:
case OO_Caret:
@@ -8783,7 +8888,7 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
}
}
-/// \brief Add function candidates found via argument-dependent lookup
+/// Add function candidates found via argument-dependent lookup
/// to the set of overloading candidates.
///
/// This routine performs argument-dependent name lookup based on the
@@ -8889,6 +8994,47 @@ static Comparison compareEnableIfAttrs(const Sema &S, const FunctionDecl *Cand1,
return Cand1I == Cand1Attrs.end() ? Comparison::Equal : Comparison::Better;
}
+static bool isBetterMultiversionCandidate(const OverloadCandidate &Cand1,
+ const OverloadCandidate &Cand2) {
+ if (!Cand1.Function || !Cand1.Function->isMultiVersion() || !Cand2.Function ||
+ !Cand2.Function->isMultiVersion())
+ return false;
+
+ // 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>();
+ bool Cand2CPUDisp = Cand2.Function->hasAttr<CPUDispatchAttr>();
+ const auto *Cand1CPUSpec = Cand1.Function->getAttr<CPUSpecificAttr>();
+ const auto *Cand2CPUSpec = Cand2.Function->getAttr<CPUSpecificAttr>();
+
+ if (!Cand1CPUDisp && !Cand2CPUDisp && !Cand1CPUSpec && !Cand2CPUSpec)
+ return false;
+
+ if (Cand1CPUDisp && !Cand2CPUDisp)
+ return true;
+ if (Cand2CPUDisp && !Cand1CPUDisp)
+ return false;
+
+ if (Cand1CPUSpec && Cand2CPUSpec) {
+ if (Cand1CPUSpec->cpus_size() != Cand2CPUSpec->cpus_size())
+ return Cand1CPUSpec->cpus_size() < Cand2CPUSpec->cpus_size();
+
+ std::pair<CPUSpecificAttr::cpus_iterator, CPUSpecificAttr::cpus_iterator>
+ FirstDiff = std::mismatch(
+ Cand1CPUSpec->cpus_begin(), Cand1CPUSpec->cpus_end(),
+ Cand2CPUSpec->cpus_begin(),
+ [](const IdentifierInfo *LHS, const IdentifierInfo *RHS) {
+ return LHS->getName() == RHS->getName();
+ });
+
+ assert(FirstDiff.first != Cand1CPUSpec->cpus_end() &&
+ "Two different cpu-specific versions should not have the same "
+ "identifier list, otherwise they'd be the same decl!");
+ return (*FirstDiff.first)->getName() < (*FirstDiff.second)->getName();
+ }
+ llvm_unreachable("No way to get here unless both had cpu_dispatch");
+}
+
/// isBetterOverloadCandidate - Determines whether the first overload
/// candidate is a better candidate than the second (C++ 13.3.3p1).
bool clang::isBetterOverloadCandidate(
@@ -9086,7 +9232,10 @@ bool clang::isBetterOverloadCandidate(
functionHasPassObjectSizeParams(Cand1.Function);
bool HasPS2 = Cand2.Function != nullptr &&
functionHasPassObjectSizeParams(Cand2.Function);
- return HasPS1 != HasPS2 && HasPS1;
+ if (HasPS1 != HasPS2 && HasPS1)
+ return true;
+
+ return isBetterMultiversionCandidate(Cand1, Cand2);
}
/// Determine whether two declarations are "equivalent" for the purposes of
@@ -9156,7 +9305,7 @@ void Sema::diagnoseEquivalentInternalLinkageDeclarations(
}
}
-/// \brief Computes the best viable function (C++ 13.3.3)
+/// Computes the best viable function (C++ 13.3.3)
/// within an overload candidate set.
///
/// \param Loc The location of the function name (or operator symbol) for
@@ -9247,66 +9396,77 @@ enum OverloadCandidateKind {
oc_function,
oc_method,
oc_constructor,
- oc_function_template,
- oc_method_template,
- oc_constructor_template,
oc_implicit_default_constructor,
oc_implicit_copy_constructor,
oc_implicit_move_constructor,
oc_implicit_copy_assignment,
oc_implicit_move_assignment,
- oc_inherited_constructor,
- oc_inherited_constructor_template
+ oc_inherited_constructor
+};
+
+enum OverloadCandidateSelect {
+ ocs_non_template,
+ ocs_template,
+ ocs_described_template,
};
-static OverloadCandidateKind
+static std::pair<OverloadCandidateKind, OverloadCandidateSelect>
ClassifyOverloadCandidate(Sema &S, NamedDecl *Found, FunctionDecl *Fn,
std::string &Description) {
- bool isTemplate = false;
+ bool isTemplate = Fn->isTemplateDecl() || Found->isTemplateDecl();
if (FunctionTemplateDecl *FunTmpl = Fn->getPrimaryTemplate()) {
isTemplate = true;
Description = S.getTemplateArgumentBindingsText(
- FunTmpl->getTemplateParameters(), *Fn->getTemplateSpecializationArgs());
+ FunTmpl->getTemplateParameters(), *Fn->getTemplateSpecializationArgs());
}
- if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn)) {
- if (!Ctor->isImplicit()) {
- if (isa<ConstructorUsingShadowDecl>(Found))
- return isTemplate ? oc_inherited_constructor_template
- : oc_inherited_constructor;
- else
- return isTemplate ? oc_constructor_template : oc_constructor;
- }
+ OverloadCandidateSelect Select = [&]() {
+ if (!Description.empty())
+ return ocs_described_template;
+ return isTemplate ? ocs_template : ocs_non_template;
+ }();
- if (Ctor->isDefaultConstructor())
- return oc_implicit_default_constructor;
+ OverloadCandidateKind Kind = [&]() {
+ if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn)) {
+ if (!Ctor->isImplicit()) {
+ if (isa<ConstructorUsingShadowDecl>(Found))
+ return oc_inherited_constructor;
+ else
+ return oc_constructor;
+ }
- if (Ctor->isMoveConstructor())
- return oc_implicit_move_constructor;
+ if (Ctor->isDefaultConstructor())
+ return oc_implicit_default_constructor;
- assert(Ctor->isCopyConstructor() &&
- "unexpected sort of implicit constructor");
- return oc_implicit_copy_constructor;
- }
+ if (Ctor->isMoveConstructor())
+ return oc_implicit_move_constructor;
- if (CXXMethodDecl *Meth = dyn_cast<CXXMethodDecl>(Fn)) {
- // This actually gets spelled 'candidate function' for now, but
- // it doesn't hurt to split it out.
- if (!Meth->isImplicit())
- return isTemplate ? oc_method_template : oc_method;
+ assert(Ctor->isCopyConstructor() &&
+ "unexpected sort of implicit constructor");
+ return oc_implicit_copy_constructor;
+ }
- if (Meth->isMoveAssignmentOperator())
- return oc_implicit_move_assignment;
+ if (CXXMethodDecl *Meth = dyn_cast<CXXMethodDecl>(Fn)) {
+ // This actually gets spelled 'candidate function' for now, but
+ // it doesn't hurt to split it out.
+ if (!Meth->isImplicit())
+ return oc_method;
- if (Meth->isCopyAssignmentOperator())
- return oc_implicit_copy_assignment;
+ if (Meth->isMoveAssignmentOperator())
+ return oc_implicit_move_assignment;
- assert(isa<CXXConversionDecl>(Meth) && "expected conversion");
- return oc_method;
- }
+ if (Meth->isCopyAssignmentOperator())
+ return oc_implicit_copy_assignment;
- return isTemplate ? oc_function_template : oc_function;
+ assert(isa<CXXConversionDecl>(Meth) && "expected conversion");
+ return oc_method;
+ }
+
+ return oc_function;
+ }();
+
+ return std::make_pair(Kind, Select);
}
void MaybeEmitInheritedConstructorNote(Sema &S, Decl *FoundDecl) {
@@ -9332,7 +9492,7 @@ static bool isFunctionAlwaysEnabled(const ASTContext &Ctx,
return true;
}
-/// \brief Returns true if we can take the address of the function.
+/// Returns true if we can take the address of the function.
///
/// \param Complain - If true, we'll emit a diagnostic
/// \param InOverloadResolution - For the purposes of emitting a diagnostic, are
@@ -9394,11 +9554,16 @@ void Sema::NoteOverloadCandidate(NamedDecl *Found, FunctionDecl *Fn,
QualType DestType, bool TakingAddress) {
if (TakingAddress && !checkAddressOfCandidateIsAvailable(*this, Fn))
return;
+ if (Fn->isMultiVersion() && Fn->hasAttr<TargetAttr>() &&
+ !Fn->getAttr<TargetAttr>()->isDefaultVersion())
+ return;
std::string FnDesc;
- OverloadCandidateKind K = ClassifyOverloadCandidate(*this, Found, Fn, FnDesc);
+ std::pair<OverloadCandidateKind, OverloadCandidateSelect> KSPair =
+ ClassifyOverloadCandidate(*this, Found, Fn, FnDesc);
PartialDiagnostic PD = PDiag(diag::note_ovl_candidate)
- << (unsigned) K << Fn << FnDesc;
+ << (unsigned)KSPair.first << (unsigned)KSPair.second
+ << Fn << FnDesc;
HandleFunctionTypeMismatch(PD, Fn->getType(), DestType);
Diag(Fn->getLocation(), PD);
@@ -9472,7 +9637,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
}
std::string FnDesc;
- OverloadCandidateKind FnKind =
+ std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair =
ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, FnDesc);
Expr *FromExpr = Conv.Bad.FromExpr;
@@ -9487,9 +9652,9 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
DeclarationName Name = cast<OverloadExpr>(E)->getName();
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_overload)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << ToTy << Name << I+1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << ToTy
+ << Name << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -9516,43 +9681,38 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
if (FromQs.getAddressSpace() != ToQs.getAddressSpace()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_addrspace)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy
- << FromQs.getAddressSpaceAttributePrintValue()
- << ToQs.getAddressSpaceAttributePrintValue()
- << (unsigned) isObjectArgument << I+1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << ToTy << (unsigned)isObjectArgument << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
if (FromQs.getObjCLifetime() != ToQs.getObjCLifetime()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_ownership)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy
- << FromQs.getObjCLifetime() << ToQs.getObjCLifetime()
- << (unsigned) isObjectArgument << I+1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << FromQs.getObjCLifetime() << ToQs.getObjCLifetime()
+ << (unsigned)isObjectArgument << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
if (FromQs.getObjCGCAttr() != ToQs.getObjCGCAttr()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_gc)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy
- << FromQs.getObjCGCAttr() << ToQs.getObjCGCAttr()
- << (unsigned) isObjectArgument << I+1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << FromQs.getObjCGCAttr() << ToQs.getObjCGCAttr()
+ << (unsigned)isObjectArgument << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
if (FromQs.hasUnaligned() != ToQs.hasUnaligned()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_unaligned)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy << FromQs.hasUnaligned() << I+1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << FromQs.hasUnaligned() << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -9562,14 +9722,14 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
if (isObjectArgument) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr_this)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy << (CVR - 1);
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << (CVR - 1);
} else {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy << (CVR - 1) << I+1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << (CVR - 1) << I + 1;
}
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
@@ -9579,9 +9739,9 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
// telling the user that it has type void is not useful.
if (FromExpr && isa<InitListExpr>(FromExpr)) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_list_argument)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy << ToTy << (unsigned) isObjectArgument << I+1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << ToTy << (unsigned)isObjectArgument << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -9595,10 +9755,10 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
if (TempFromTy->isIncompleteType()) {
// Emit the generic diagnostic and, optionally, add the hints to it.
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv_incomplete)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy << ToTy << (unsigned) isObjectArgument << I+1
- << (unsigned) (Cand->Fix.Kind);
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << ToTy << (unsigned)isObjectArgument << I + 1
+ << (unsigned)(Cand->Fix.Kind);
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
@@ -9636,21 +9796,19 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
ToTy.getNonReferenceType().getCanonicalType() ==
FromTy.getNonReferenceType().getCanonicalType()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_lvalue)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << (unsigned) isObjectArgument << I + 1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (unsigned)isObjectArgument << I + 1
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange());
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
}
if (BaseToDerivedConversion) {
- S.Diag(Fn->getLocation(),
- diag::note_ovl_candidate_bad_base_to_derived_conv)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << (BaseToDerivedConversion - 1)
- << FromTy << ToTy << I+1;
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_base_to_derived_conv)
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+ << (BaseToDerivedConversion - 1) << FromTy << ToTy << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -9661,9 +9819,9 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
Qualifiers ToQs = CToTy.getQualifiers();
if (FromQs.getObjCLifetime() != ToQs.getObjCLifetime()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_arc_conv)
- << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy << ToTy << (unsigned) isObjectArgument << I+1;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second
+ << FnDesc << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+ << FromTy << ToTy << (unsigned)isObjectArgument << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -9675,10 +9833,10 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
// Emit the generic diagnostic and, optionally, add the hints to it.
PartialDiagnostic FDiag = S.PDiag(diag::note_ovl_candidate_bad_conv);
- FDiag << (unsigned) FnKind << FnDesc
- << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
- << FromTy << ToTy << (unsigned) isObjectArgument << I + 1
- << (unsigned) (Cand->Fix.Kind);
+ FDiag << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
+ << ToTy << (unsigned)isObjectArgument << I + 1
+ << (unsigned)(Cand->Fix.Kind);
// If we can fix the conversion, suggest the FixIts.
for (std::vector<FixItHint>::iterator HI = Cand->Fix.Hints.begin(),
@@ -9751,17 +9909,18 @@ static void DiagnoseArityMismatch(Sema &S, NamedDecl *Found, Decl *D,
}
std::string Description;
- OverloadCandidateKind FnKind =
+ std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair =
ClassifyOverloadCandidate(S, Found, Fn, Description);
if (modeCount == 1 && Fn->getParamDecl(0)->getDeclName())
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity_one)
- << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != nullptr)
- << mode << Fn->getParamDecl(0) << NumFormalArgs;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second
+ << Description << mode << Fn->getParamDecl(0) << NumFormalArgs;
else
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity)
- << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != nullptr)
- << mode << modeCount << NumFormalArgs;
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second
+ << Description << mode << modeCount << NumFormalArgs;
+
MaybeEmitInheritedConstructorNote(S, Found);
}
@@ -9802,6 +9961,17 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
return;
}
+ case Sema::TDK_IncompletePack: {
+ assert(ParamD && "no parameter found for incomplete deduction result");
+ S.Diag(Templated->getLocation(),
+ diag::note_ovl_candidate_incomplete_deduction_pack)
+ << ParamD->getDeclName()
+ << (DeductionFailure.getFirstArg()->pack_size() + 1)
+ << *DeductionFailure.getFirstArg();
+ MaybeEmitInheritedConstructorNote(S, Found);
+ return;
+ }
+
case Sema::TDK_Underqualified: {
assert(ParamD && "no parameter found for bad qualifiers deduction result");
TemplateTypeParmDecl *TParam = cast<TemplateTypeParmDecl>(ParamD);
@@ -10036,11 +10206,13 @@ static void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) {
CalleeTarget = S.IdentifyCUDATarget(Callee);
std::string FnDesc;
- OverloadCandidateKind FnKind =
+ std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair =
ClassifyOverloadCandidate(S, Cand->FoundDecl, Callee, FnDesc);
S.Diag(Callee->getLocation(), diag::note_ovl_candidate_bad_target)
- << (unsigned)FnKind << CalleeTarget << CallerTarget;
+ << (unsigned)FnKindPair.first << (unsigned)ocs_non_template
+ << FnDesc /* Ignored */
+ << CalleeTarget << CallerTarget;
// This could be an implicit constructor for which we could not infer the
// target due to a collsion. Diagnose that case.
@@ -10049,7 +10221,7 @@ static void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) {
CXXRecordDecl *ParentClass = Meth->getParent();
Sema::CXXSpecialMember CSM;
- switch (FnKind) {
+ switch (FnKindPair.first) {
default:
return;
case oc_implicit_default_constructor:
@@ -10121,12 +10293,12 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
if (Cand->Viable) {
if (Fn->isDeleted() || S.isFunctionConsideredUnavailable(Fn)) {
std::string FnDesc;
- OverloadCandidateKind FnKind =
- ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, FnDesc);
+ std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair =
+ ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, FnDesc);
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted)
- << FnKind << FnDesc
- << (Fn->isDeleted() ? (Fn->isDeletedAsWritten() ? 1 : 2) : 0);
+ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
+ << (Fn->isDeleted() ? (Fn->isDeletedAsWritten() ? 1 : 2) : 0);
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
@@ -10195,6 +10367,9 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
assert(!Available);
break;
}
+ case ovl_non_default_multiversion_function:
+ // Do nothing, these should simply be ignored.
+ break;
}
}
@@ -10276,6 +10451,7 @@ static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) {
case Sema::TDK_Invalid:
case Sema::TDK_Incomplete:
+ case Sema::TDK_IncompletePack:
return 1;
case Sema::TDK_Underqualified:
@@ -10512,9 +10688,8 @@ static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
}
}
-/// PrintOverloadCandidates - When overload resolution fails, prints
-/// diagnostic messages containing the candidates in the candidate
-/// set.
+/// When overload resolution fails, prints diagnostic messages containing the
+/// candidates in the candidate set.
void OverloadCandidateSet::NoteCandidates(
Sema &S, OverloadCandidateDisplayKind OCD, ArrayRef<Expr *> Args,
StringRef Opc, SourceLocation OpLoc,
@@ -10661,8 +10836,8 @@ void TemplateSpecCandidateSet::NoteCandidates(Sema &S, SourceLocation Loc) {
// in general, want to list every possible builtin candidate.
}
- std::sort(Cands.begin(), Cands.end(),
- CompareTemplateSpecCandidatesForDisplay(S));
+ llvm::sort(Cands.begin(), Cands.end(),
+ CompareTemplateSpecCandidatesForDisplay(S));
// FIXME: Perhaps rename OverloadsShown and getShowOverloads()
// for generalization purposes (?).
@@ -10931,6 +11106,11 @@ private:
if (FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext))
if (!Caller->isImplicit() && !S.IsAllowedCUDACall(Caller, FunDecl))
return false;
+ if (FunDecl->isMultiVersion()) {
+ const auto *TA = FunDecl->getAttr<TargetAttr>();
+ if (TA && !TA->isDefaultVersion())
+ return false;
+ }
// If any candidate has a placeholder return type, trigger its deduction
// now.
@@ -11012,9 +11192,9 @@ private:
MatchesCopy.begin(), MatchesCopy.end(), FailedCandidates,
SourceExpr->getLocStart(), S.PDiag(),
S.PDiag(diag::err_addr_ovl_ambiguous)
- << Matches[0].second->getDeclName(),
+ << Matches[0].second->getDeclName(),
S.PDiag(diag::note_ovl_candidate)
- << (unsigned)oc_function_template,
+ << (unsigned)oc_function << (unsigned)ocs_described_template,
Complain, TargetFunctionType);
if (Result != MatchesCopy.end()) {
@@ -11176,7 +11356,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr,
return Fn;
}
-/// \brief Given an expression that refers to an overloaded function, try to
+/// Given an expression that refers to an overloaded function, try to
/// resolve that function to a single function that can have its address taken.
/// This will modify `Pair` iff it returns non-null.
///
@@ -11212,7 +11392,7 @@ Sema::resolveAddressOfOnlyViableOverloadCandidate(Expr *E,
return Result;
}
-/// \brief Given an overloaded function, tries to turn it into a non-overloaded
+/// Given an overloaded function, tries to turn it into a non-overloaded
/// function reference using resolveAddressOfOnlyViableOverloadCandidate. This
/// will perform access checks, diagnose the use of the resultant decl, and, if
/// requested, potentially perform a function-to-pointer decay.
@@ -11226,7 +11406,8 @@ bool Sema::resolveAndFixAddressOfOnlyViableOverloadCandidate(
DeclAccessPair DAP;
FunctionDecl *Found = resolveAddressOfOnlyViableOverloadCandidate(E, DAP);
- if (!Found)
+ if (!Found || Found->isCPUDispatchMultiVersion() ||
+ Found->isCPUSpecificMultiVersion())
return false;
// Emitting multiple diagnostics for a function that is both inaccessible and
@@ -11242,7 +11423,7 @@ bool Sema::resolveAndFixAddressOfOnlyViableOverloadCandidate(
return true;
}
-/// \brief Given an expression that refers to an overloaded function, try to
+/// Given an expression that refers to an overloaded function, try to
/// resolve that overloaded function expression down to a single function.
///
/// This routine can only resolve template-ids that refer to a single function
@@ -11411,7 +11592,7 @@ bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization(
return true;
}
-/// \brief Add a single candidate to the overload set.
+/// Add a single candidate to the overload set.
static void AddOverloadedCallCandidate(Sema &S,
DeclAccessPair FoundDecl,
TemplateArgumentListInfo *ExplicitTemplateArgs,
@@ -11450,7 +11631,7 @@ static void AddOverloadedCallCandidate(Sema &S,
assert(!KnownValid && "unhandled case in overloaded call candidate");
}
-/// \brief Add the overload candidates named by callee and/or found by argument
+/// Add the overload candidates named by callee and/or found by argument
/// dependent lookup to the given overload set.
void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
ArrayRef<Expr *> Args,
@@ -11742,7 +11923,7 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
RParenLoc);
}
-/// \brief Constructs and populates an OverloadedCandidateSet from
+/// Constructs and populates an OverloadedCandidateSet from
/// the given function.
/// \returns true when an the ExprResult output parameter has been set.
bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn,
@@ -11882,7 +12063,7 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
<< Fn->getSourceRange();
CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, Args);
- // We emitted an error for the unvailable/deleted function call but keep
+ // We emitted an error for the unavailable/deleted function call but keep
// the call in the AST.
FunctionDecl *FDecl = (*Best)->Function;
Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl);
@@ -11948,7 +12129,7 @@ static bool IsOverloaded(const UnresolvedSetImpl &Functions) {
(Functions.size() == 1 && isa<FunctionTemplateDecl>(*Functions.begin()));
}
-/// \brief Create a unary operation that may resolve to an overloaded
+/// Create a unary operation that may resolve to an overloaded
/// operator.
///
/// \param OpLoc The location of the operator itself (e.g., '*').
@@ -11994,7 +12175,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
if (Input->isTypeDependent()) {
if (Fns.empty())
return new (Context) UnaryOperator(Input, Opc, Context.DependentTy,
- VK_RValue, OK_Ordinary, OpLoc);
+ VK_RValue, OK_Ordinary, OpLoc, false);
CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
UnresolvedLookupExpr *Fn
@@ -12093,7 +12274,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
// break out so that we will build the appropriate built-in
// operator node.
ExprResult InputRes = PerformImplicitConversion(
- Input, Best->BuiltinParamTypes[0], Best->Conversions[0], AA_Passing);
+ Input, Best->BuiltinParamTypes[0], Best->Conversions[0], AA_Passing,
+ CCK_ForBuiltinOverloadedOp);
if (InputRes.isInvalid())
return ExprError();
Input = InputRes.get();
@@ -12139,7 +12321,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
return CreateBuiltinUnaryOp(OpLoc, Opc, Input);
}
-/// \brief Create a binary operation that may resolve to an overloaded
+/// Create a binary operation that may resolve to an overloaded
/// operator.
///
/// \param OpLoc The location of the operator itself (e.g., '+').
@@ -12337,16 +12519,16 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// We matched a built-in operator. Convert the arguments, then
// break out so that we will build the appropriate built-in
// operator node.
- ExprResult ArgsRes0 =
- PerformImplicitConversion(Args[0], Best->BuiltinParamTypes[0],
- Best->Conversions[0], AA_Passing);
+ ExprResult ArgsRes0 = PerformImplicitConversion(
+ Args[0], Best->BuiltinParamTypes[0], Best->Conversions[0],
+ AA_Passing, CCK_ForBuiltinOverloadedOp);
if (ArgsRes0.isInvalid())
return ExprError();
Args[0] = ArgsRes0.get();
- ExprResult ArgsRes1 =
- PerformImplicitConversion(Args[1], Best->BuiltinParamTypes[1],
- Best->Conversions[1], AA_Passing);
+ ExprResult ArgsRes1 = PerformImplicitConversion(
+ Args[1], Best->BuiltinParamTypes[1], Best->Conversions[1],
+ AA_Passing, CCK_ForBuiltinOverloadedOp);
if (ArgsRes1.isInvalid())
return ExprError();
Args[1] = ArgsRes1.get();
@@ -12362,7 +12544,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
if (Opc == BO_Comma)
break;
- // For class as left operand for assignment or compound assigment
+ // For class as left operand for assignment or compound assignment
// operator do not fall through to handling in built-in, but report that
// no overloaded assignment operator found
ExprResult Result = ExprError();
@@ -12549,16 +12731,16 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
// We matched a built-in operator. Convert the arguments, then
// break out so that we will build the appropriate built-in
// operator node.
- ExprResult ArgsRes0 =
- PerformImplicitConversion(Args[0], Best->BuiltinParamTypes[0],
- Best->Conversions[0], AA_Passing);
+ ExprResult ArgsRes0 = PerformImplicitConversion(
+ Args[0], Best->BuiltinParamTypes[0], Best->Conversions[0],
+ AA_Passing, CCK_ForBuiltinOverloadedOp);
if (ArgsRes0.isInvalid())
return ExprError();
Args[0] = ArgsRes0.get();
- ExprResult ArgsRes1 =
- PerformImplicitConversion(Args[1], Best->BuiltinParamTypes[1],
- Best->Conversions[1], AA_Passing);
+ ExprResult ArgsRes1 = PerformImplicitConversion(
+ Args[1], Best->BuiltinParamTypes[1], Best->Conversions[1],
+ AA_Passing, CCK_ForBuiltinOverloadedOp);
if (ArgsRes1.isInvalid())
return ExprError();
Args[1] = ArgsRes1.get();
@@ -13524,7 +13706,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
return new (Context) UnaryOperator(SubExpr, UO_AddrOf, MemPtrType,
VK_RValue, OK_Ordinary,
- UnOp->getOperatorLoc());
+ UnOp->getOperatorLoc(), false);
}
}
Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
@@ -13535,7 +13717,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
return new (Context) UnaryOperator(SubExpr, UO_AddrOf,
Context.getPointerType(SubExpr->getType()),
VK_RValue, OK_Ordinary,
- UnOp->getOperatorLoc());
+ UnOp->getOperatorLoc(), false);
}
// C++ [except.spec]p17:
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp
index 58980be64a30..4484e9b3513b 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp
@@ -132,7 +132,8 @@ namespace {
uop->getType(),
uop->getValueKind(),
uop->getObjectKind(),
- uop->getOperatorLoc());
+ uop->getOperatorLoc(),
+ uop->canOverflow());
}
if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
@@ -189,11 +190,12 @@ namespace {
Sema &S;
unsigned ResultIndex;
SourceLocation GenericLoc;
+ bool IsUnique;
SmallVector<Expr *, 4> Semantics;
- PseudoOpBuilder(Sema &S, SourceLocation genericLoc)
+ PseudoOpBuilder(Sema &S, SourceLocation genericLoc, bool IsUnique)
: S(S), ResultIndex(PseudoObjectExpr::NoResult),
- GenericLoc(genericLoc) {}
+ GenericLoc(genericLoc), IsUnique(IsUnique) {}
virtual ~PseudoOpBuilder() {}
@@ -207,6 +209,9 @@ namespace {
assert(ResultIndex == PseudoObjectExpr::NoResult);
ResultIndex = Semantics.size();
Semantics.push_back(resultExpr);
+ // An OVE is not unique if it is used as the result expression.
+ if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantics.back()))
+ OVE->setIsUnique(false);
}
ExprResult buildRValueOperation(Expr *op);
@@ -226,6 +231,9 @@ namespace {
void setResultToLastSemantic() {
assert(ResultIndex == PseudoObjectExpr::NoResult);
ResultIndex = Semantics.size() - 1;
+ // An OVE is not unique if it is used as the result expression.
+ if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantics.back()))
+ OVE->setIsUnique(false);
}
/// Return true if assignments have a non-void result.
@@ -245,7 +253,7 @@ namespace {
virtual ExprResult buildGet() = 0;
virtual ExprResult buildSet(Expr *, SourceLocation,
bool captureSetValueAsResult) = 0;
- /// \brief Should the result of an assignment be the formal result of the
+ /// Should the result of an assignment be the formal result of the
/// setter call or the value that was passed to the setter?
///
/// Different pseudo-object language features use different language rules
@@ -273,10 +281,10 @@ namespace {
Selector GetterSelector;
public:
- ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) :
- PseudoOpBuilder(S, refExpr->getLocation()), RefExpr(refExpr),
- SyntacticRefExpr(nullptr), InstanceReceiver(nullptr), Getter(nullptr),
- Setter(nullptr) {
+ ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr, bool IsUnique)
+ : PseudoOpBuilder(S, refExpr->getLocation(), IsUnique),
+ RefExpr(refExpr), SyntacticRefExpr(nullptr),
+ InstanceReceiver(nullptr), Getter(nullptr), Setter(nullptr) {
}
ExprResult buildRValueOperation(Expr *op);
@@ -313,11 +321,10 @@ namespace {
Selector AtIndexSetterSelector;
public:
- ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr) :
- PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
- RefExpr(refExpr),
- InstanceBase(nullptr), InstanceKey(nullptr),
- AtIndexGetter(nullptr), AtIndexSetter(nullptr) {}
+ ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr, bool IsUnique)
+ : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique),
+ RefExpr(refExpr), InstanceBase(nullptr), InstanceKey(nullptr),
+ AtIndexGetter(nullptr), AtIndexSetter(nullptr) {}
ExprResult buildRValueOperation(Expr *op);
ExprResult buildAssignmentOperation(Scope *Sc,
@@ -341,11 +348,11 @@ namespace {
MSPropertyRefExpr *getBaseMSProperty(MSPropertySubscriptExpr *E);
public:
- MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr) :
- PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
- RefExpr(refExpr), InstanceBase(nullptr) {}
- MSPropertyOpBuilder(Sema &S, MSPropertySubscriptExpr *refExpr)
- : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
+ MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr, bool IsUnique)
+ : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique),
+ RefExpr(refExpr), InstanceBase(nullptr) {}
+ MSPropertyOpBuilder(Sema &S, MSPropertySubscriptExpr *refExpr, bool IsUnique)
+ : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique),
InstanceBase(nullptr) {
RefExpr = getBaseMSProperty(refExpr);
}
@@ -364,7 +371,9 @@ OpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) {
new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(),
e->getValueKind(), e->getObjectKind(),
e);
-
+ if (IsUnique)
+ captured->setIsUnique(true);
+
// Make sure we bind that in the semantics.
addSemanticExpr(captured);
return captured;
@@ -396,6 +405,8 @@ OpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) {
if (e == Semantics[index]) break;
}
ResultIndex = index;
+ // An OVE is not unique if it is used as the result expression.
+ cast<OpaqueValueExpr>(e)->setIsUnique(false);
return cast<OpaqueValueExpr>(e);
}
@@ -527,9 +538,12 @@ PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
(result.get()->isTypeDependent() || CanCaptureValue(result.get())))
setResultToLastSemantic();
- UnaryOperator *syntactic =
- new (S.Context) UnaryOperator(syntacticOp, opcode, resultType,
- VK_LValue, OK_Ordinary, opcLoc);
+ UnaryOperator *syntactic = new (S.Context) UnaryOperator(
+ syntacticOp, opcode, resultType, VK_LValue, OK_Ordinary, opcLoc,
+ !resultType->isDependentType()
+ ? S.Context.getTypeSize(resultType) >=
+ S.Context.getTypeSize(S.Context.IntTy)
+ : false);
return complete(syntactic);
}
@@ -961,11 +975,11 @@ ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
}
ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) {
- if (isWeakProperty() &&
+ if (isWeakProperty() && !S.isUnevaluatedContext() &&
!S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak,
SyntacticForm->getLocStart()))
- S.recordUseOfEvaluatedWeak(SyntacticRefExpr,
- SyntacticRefExpr->isMessagingGetter());
+ S.getCurFunction()->recordUseOfWeak(SyntacticRefExpr,
+ SyntacticRefExpr->isMessagingGetter());
return PseudoOpBuilder::complete(SyntacticForm);
}
@@ -1524,20 +1538,20 @@ ExprResult Sema::checkPseudoObjectRValue(Expr *E) {
Expr *opaqueRef = E->IgnoreParens();
if (ObjCPropertyRefExpr *refExpr
= dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
- ObjCPropertyOpBuilder builder(*this, refExpr);
+ ObjCPropertyOpBuilder builder(*this, refExpr, true);
return builder.buildRValueOperation(E);
}
else if (ObjCSubscriptRefExpr *refExpr
= dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
- ObjCSubscriptOpBuilder builder(*this, refExpr);
+ ObjCSubscriptOpBuilder builder(*this, refExpr, true);
return builder.buildRValueOperation(E);
} else if (MSPropertyRefExpr *refExpr
= dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
- MSPropertyOpBuilder builder(*this, refExpr);
+ MSPropertyOpBuilder builder(*this, refExpr, true);
return builder.buildRValueOperation(E);
} else if (MSPropertySubscriptExpr *RefExpr =
dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
- MSPropertyOpBuilder Builder(*this, RefExpr);
+ MSPropertyOpBuilder Builder(*this, RefExpr, true);
return Builder.buildRValueOperation(E);
} else {
llvm_unreachable("unknown pseudo-object kind!");
@@ -1550,24 +1564,24 @@ ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc,
// Do nothing if the operand is dependent.
if (op->isTypeDependent())
return new (Context) UnaryOperator(op, opcode, Context.DependentTy,
- VK_RValue, OK_Ordinary, opcLoc);
+ VK_RValue, OK_Ordinary, opcLoc, false);
assert(UnaryOperator::isIncrementDecrementOp(opcode));
Expr *opaqueRef = op->IgnoreParens();
if (ObjCPropertyRefExpr *refExpr
= dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
- ObjCPropertyOpBuilder builder(*this, refExpr);
+ ObjCPropertyOpBuilder builder(*this, refExpr, false);
return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
} else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) {
Diag(opcLoc, diag::err_illegal_container_subscripting_op);
return ExprError();
} else if (MSPropertyRefExpr *refExpr
= dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
- MSPropertyOpBuilder builder(*this, refExpr);
+ MSPropertyOpBuilder builder(*this, refExpr, false);
return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
} else if (MSPropertySubscriptExpr *RefExpr
= dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
- MSPropertyOpBuilder Builder(*this, RefExpr);
+ MSPropertyOpBuilder Builder(*this, RefExpr, false);
return Builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
} else {
llvm_unreachable("unknown pseudo-object kind!");
@@ -1590,22 +1604,23 @@ ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
RHS = result.get();
}
+ bool IsSimpleAssign = opcode == BO_Assign;
Expr *opaqueRef = LHS->IgnoreParens();
if (ObjCPropertyRefExpr *refExpr
= dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
- ObjCPropertyOpBuilder builder(*this, refExpr);
+ ObjCPropertyOpBuilder builder(*this, refExpr, IsSimpleAssign);
return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
} else if (ObjCSubscriptRefExpr *refExpr
= dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
- ObjCSubscriptOpBuilder builder(*this, refExpr);
+ ObjCSubscriptOpBuilder builder(*this, refExpr, IsSimpleAssign);
return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
} else if (MSPropertyRefExpr *refExpr
= dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
- MSPropertyOpBuilder builder(*this, refExpr);
+ MSPropertyOpBuilder builder(*this, refExpr, IsSimpleAssign);
return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
} else if (MSPropertySubscriptExpr *RefExpr
= dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
- MSPropertyOpBuilder Builder(*this, RefExpr);
+ MSPropertyOpBuilder Builder(*this, RefExpr, IsSimpleAssign);
return Builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
} else {
llvm_unreachable("unknown pseudo-object kind!");
@@ -1633,9 +1648,9 @@ Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) {
Expr *syntax = E->getSyntacticForm();
if (UnaryOperator *uop = dyn_cast<UnaryOperator>(syntax)) {
Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr());
- return new (Context) UnaryOperator(op, uop->getOpcode(), uop->getType(),
- uop->getValueKind(), uop->getObjectKind(),
- uop->getOperatorLoc());
+ return new (Context) UnaryOperator(
+ op, uop->getOpcode(), uop->getType(), uop->getValueKind(),
+ uop->getObjectKind(), uop->getOperatorLoc(), uop->canOverflow());
} else if (CompoundAssignOperator *cop
= dyn_cast<CompoundAssignOperator>(syntax)) {
Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS());
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
index 1ebc36716a88..b2f9783d44f1 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
@@ -121,7 +121,7 @@ void Sema::ActOnForEachDeclStmt(DeclGroupPtrTy dg) {
}
}
-/// \brief Diagnose unused comparisons, both builtin and overloaded operators.
+/// Diagnose unused comparisons, both builtin and overloaded operators.
/// For '==' and '!=', suggest fixits for '=' or '|='.
///
/// Adding a cast to void (or other expression wrappers) will prevent the
@@ -337,8 +337,8 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
DiagRuntimeBehavior(Loc, nullptr, PDiag(DiagID) << R1 << R2);
}
-void Sema::ActOnStartOfCompoundStmt() {
- PushCompoundScope();
+void Sema::ActOnStartOfCompoundStmt(bool IsStmtExpr) {
+ PushCompoundScope(IsStmtExpr);
}
void Sema::ActOnFinishOfCompoundStmt() {
@@ -392,65 +392,79 @@ StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
return CompoundStmt::Create(Context, Elts, L, R);
}
+ExprResult
+Sema::ActOnCaseExpr(SourceLocation CaseLoc, ExprResult Val) {
+ if (!Val.get())
+ return Val;
+
+ if (DiagnoseUnexpandedParameterPack(Val.get()))
+ return ExprError();
+
+ // If we're not inside a switch, let the 'case' statement handling diagnose
+ // this. Just clean up after the expression as best we can.
+ if (!getCurFunction()->SwitchStack.empty()) {
+ Expr *CondExpr =
+ getCurFunction()->SwitchStack.back().getPointer()->getCond();
+ if (!CondExpr)
+ return ExprError();
+ QualType CondType = CondExpr->getType();
+
+ auto CheckAndFinish = [&](Expr *E) {
+ if (CondType->isDependentType() || E->isTypeDependent())
+ return ExprResult(E);
+
+ if (getLangOpts().CPlusPlus11) {
+ // C++11 [stmt.switch]p2: the constant-expression shall be a converted
+ // constant expression of the promoted type of the switch condition.
+ llvm::APSInt TempVal;
+ return CheckConvertedConstantExpression(E, CondType, TempVal,
+ CCEK_CaseValue);
+ }
+
+ ExprResult ER = E;
+ if (!E->isValueDependent())
+ ER = VerifyIntegerConstantExpression(E);
+ if (!ER.isInvalid())
+ ER = DefaultLvalueConversion(ER.get());
+ if (!ER.isInvalid())
+ ER = ImpCastExprToType(ER.get(), CondType, CK_IntegralCast);
+ return ER;
+ };
+
+ ExprResult Converted = CorrectDelayedTyposInExpr(Val, CheckAndFinish);
+ if (Converted.get() == Val.get())
+ Converted = CheckAndFinish(Val.get());
+ if (Converted.isInvalid())
+ return ExprError();
+ Val = Converted;
+ }
+
+ return ActOnFinishFullExpr(Val.get(), Val.get()->getExprLoc(), false,
+ getLangOpts().CPlusPlus11);
+}
+
StmtResult
-Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal,
- SourceLocation DotDotDotLoc, Expr *RHSVal,
+Sema::ActOnCaseStmt(SourceLocation CaseLoc, ExprResult LHSVal,
+ SourceLocation DotDotDotLoc, ExprResult RHSVal,
SourceLocation ColonLoc) {
- assert(LHSVal && "missing expression in case statement");
+ assert((LHSVal.isInvalid() || LHSVal.get()) && "missing LHS value");
+ assert((DotDotDotLoc.isInvalid() ? RHSVal.isUnset()
+ : RHSVal.isInvalid() || RHSVal.get()) &&
+ "missing RHS value");
if (getCurFunction()->SwitchStack.empty()) {
Diag(CaseLoc, diag::err_case_not_in_switch);
return StmtError();
}
- ExprResult LHS =
- CorrectDelayedTyposInExpr(LHSVal, [this](class Expr *E) {
- if (!getLangOpts().CPlusPlus11)
- return VerifyIntegerConstantExpression(E);
- if (Expr *CondExpr =
- getCurFunction()->SwitchStack.back()->getCond()) {
- QualType CondType = CondExpr->getType();
- llvm::APSInt TempVal;
- return CheckConvertedConstantExpression(E, CondType, TempVal,
- CCEK_CaseValue);
- }
- return ExprError();
- });
- if (LHS.isInvalid())
+ if (LHSVal.isInvalid() || RHSVal.isInvalid()) {
+ getCurFunction()->SwitchStack.back().setInt(true);
return StmtError();
- LHSVal = LHS.get();
-
- if (!getLangOpts().CPlusPlus11) {
- // C99 6.8.4.2p3: The expression shall be an integer constant.
- // However, GCC allows any evaluatable integer expression.
- if (!LHSVal->isTypeDependent() && !LHSVal->isValueDependent()) {
- LHSVal = VerifyIntegerConstantExpression(LHSVal).get();
- if (!LHSVal)
- return StmtError();
- }
-
- // GCC extension: The expression shall be an integer constant.
-
- if (RHSVal && !RHSVal->isTypeDependent() && !RHSVal->isValueDependent()) {
- RHSVal = VerifyIntegerConstantExpression(RHSVal).get();
- // Recover from an error by just forgetting about it.
- }
}
- LHS = ActOnFinishFullExpr(LHSVal, LHSVal->getExprLoc(), false,
- getLangOpts().CPlusPlus11);
- if (LHS.isInvalid())
- return StmtError();
-
- auto RHS = RHSVal ? ActOnFinishFullExpr(RHSVal, RHSVal->getExprLoc(), false,
- getLangOpts().CPlusPlus11)
- : ExprResult();
- if (RHS.isInvalid())
- return StmtError();
-
CaseStmt *CS = new (Context)
- CaseStmt(LHS.get(), RHS.get(), CaseLoc, DotDotDotLoc, ColonLoc);
- getCurFunction()->SwitchStack.back()->addSwitchCase(CS);
+ CaseStmt(LHSVal.get(), RHSVal.get(), CaseLoc, DotDotDotLoc, ColonLoc);
+ getCurFunction()->SwitchStack.back().getPointer()->addSwitchCase(CS);
return CS;
}
@@ -473,7 +487,7 @@ Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc,
}
DefaultStmt *DS = new (Context) DefaultStmt(DefaultLoc, ColonLoc, SubStmt);
- getCurFunction()->SwitchStack.back()->addSwitchCase(DS);
+ getCurFunction()->SwitchStack.back().getPointer()->addSwitchCase(DS);
return DS;
}
@@ -557,7 +571,7 @@ StmtResult Sema::BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr,
return StmtError();
if (IsConstexpr || isa<ObjCAvailabilityCheckExpr>(Cond.get().second))
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
DiagnoseUnusedExprResult(thenStmt);
DiagnoseUnusedExprResult(elseStmt);
@@ -679,20 +693,44 @@ ExprResult Sema::CheckSwitchCondition(SourceLocation SwitchLoc, Expr *Cond) {
if (CondResult.isInvalid())
return ExprError();
+ // FIXME: PerformContextualImplicitConversion doesn't always tell us if it
+ // failed and produced a diagnostic.
+ Cond = CondResult.get();
+ if (!Cond->isTypeDependent() &&
+ !Cond->getType()->isIntegralOrEnumerationType())
+ return ExprError();
+
// C99 6.8.4.2p5 - Integer promotions are performed on the controlling expr.
- return UsualUnaryConversions(CondResult.get());
+ return UsualUnaryConversions(Cond);
}
StmtResult Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
Stmt *InitStmt, ConditionResult Cond) {
- if (Cond.isInvalid())
- return StmtError();
+ Expr *CondExpr = Cond.get().second;
+ assert((Cond.isInvalid() || CondExpr) && "switch with no condition");
+
+ if (CondExpr && !CondExpr->isTypeDependent()) {
+ // We have already converted the expression to an integral or enumeration
+ // type, when we parsed the switch condition. If we don't have an
+ // appropriate type now, enter the switch scope but remember that it's
+ // invalid.
+ assert(CondExpr->getType()->isIntegralOrEnumerationType() &&
+ "invalid condition type");
+ if (CondExpr->isKnownToHaveBooleanValue()) {
+ // switch(bool_expr) {...} is often a programmer error, e.g.
+ // switch(n && mask) { ... } // Doh - should be "n & mask".
+ // One can always use an if statement instead of switch(bool_expr).
+ Diag(SwitchLoc, diag::warn_bool_switch_condition)
+ << CondExpr->getSourceRange();
+ }
+ }
- getCurFunction()->setHasBranchIntoScope();
+ setFunctionHasBranchIntoScope();
SwitchStmt *SS = new (Context)
- SwitchStmt(Context, InitStmt, Cond.get().first, Cond.get().second);
- getCurFunction()->SwitchStack.push_back(SS);
+ SwitchStmt(Context, InitStmt, Cond.get().first, CondExpr);
+ getCurFunction()->SwitchStack.push_back(
+ FunctionScopeInfo::SwitchInfo(SS, false));
return SS;
}
@@ -705,6 +743,10 @@ static void AdjustAPSInt(llvm::APSInt &Val, unsigned BitWidth, bool IsSigned) {
/// type.
static void checkCaseValue(Sema &S, SourceLocation Loc, const llvm::APSInt &Val,
unsigned UnpromotedWidth, bool UnpromotedSign) {
+ // In C++11 onwards, this is checked by the language rules.
+ if (S.getLangOpts().CPlusPlus11)
+ return;
+
// If the case value was signed and negative and the switch expression is
// unsigned, don't bother to warn: this is implementation-defined behavior.
// FIXME: Introduce a second, default-ignored warning for this case?
@@ -759,7 +801,7 @@ static bool ShouldDiagnoseSwitchCaseNotInEnum(const Sema &S,
static void checkEnumTypesInSwitchStmt(Sema &S, const Expr *Cond,
const Expr *Case) {
- QualType CondType = GetTypeBeforeIntegralPromotion(Cond);
+ QualType CondType = Cond->getType();
QualType CaseType = Case->getType();
const EnumType *CondEnumType = CondType->getAs<EnumType>();
@@ -787,7 +829,8 @@ StmtResult
Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
Stmt *BodyStmt) {
SwitchStmt *SS = cast<SwitchStmt>(Switch);
- assert(SS == getCurFunction()->SwitchStack.back() &&
+ bool CaseListIsIncomplete = getCurFunction()->SwitchStack.back().getInt();
+ assert(SS == getCurFunction()->SwitchStack.back().getPointer() &&
"switch stack missing push/pop!");
getCurFunction()->SwitchStack.pop_back();
@@ -800,10 +843,6 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
QualType CondType = CondExpr->getType();
- const Expr *CondExprBeforePromotion = CondExpr;
- QualType CondTypeBeforePromotion =
- GetTypeBeforeIntegralPromotion(CondExprBeforePromotion);
-
// C++ 6.4.2.p2:
// Integral promotions are performed (on the switch condition).
//
@@ -811,21 +850,9 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
// type (before the promotion) doesn't make sense, even when it can
// be represented by the promoted type. Therefore we need to find
// the pre-promotion type of the switch condition.
- if (!CondExpr->isTypeDependent()) {
- // We have already converted the expression to an integral or enumeration
- // type, when we started the switch statement. If we don't have an
- // appropriate type now, just return an error.
- if (!CondType->isIntegralOrEnumerationType())
- return StmtError();
-
- if (CondExpr->isKnownToHaveBooleanValue()) {
- // switch(bool_expr) {...} is often a programmer error, e.g.
- // switch(n && mask) { ... } // Doh - should be "n & mask".
- // One can always use an if statement instead of switch(bool_expr).
- Diag(SwitchLoc, diag::warn_bool_switch_condition)
- << CondExpr->getSourceRange();
- }
- }
+ const Expr *CondExprBeforePromotion = CondExpr;
+ QualType CondTypeBeforePromotion =
+ GetTypeBeforeIntegralPromotion(CondExprBeforePromotion);
// Get the bitwidth of the switched-on value after promotions. We must
// convert the integer case values to this width before comparison.
@@ -878,50 +905,32 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
Expr *Lo = CS->getLHS();
- if (Lo->isTypeDependent() || Lo->isValueDependent()) {
+ if (Lo->isValueDependent()) {
HasDependentValue = true;
break;
}
- checkEnumTypesInSwitchStmt(*this, CondExpr, Lo);
-
- llvm::APSInt LoVal;
-
- if (getLangOpts().CPlusPlus11) {
- // C++11 [stmt.switch]p2: the constant-expression shall be a converted
- // constant expression of the promoted type of the switch condition.
- ExprResult ConvLo =
- CheckConvertedConstantExpression(Lo, CondType, LoVal, CCEK_CaseValue);
- if (ConvLo.isInvalid()) {
- CaseListIsErroneous = true;
- continue;
- }
- Lo = ConvLo.get();
- } else {
- // We already verified that the expression has a i-c-e value (C99
- // 6.8.4.2p3) - get that value now.
- LoVal = Lo->EvaluateKnownConstInt(Context);
-
- // If the LHS is not the same type as the condition, insert an implicit
- // cast.
- Lo = DefaultLvalueConversion(Lo).get();
- Lo = ImpCastExprToType(Lo, CondType, CK_IntegralCast).get();
- }
+ // We already verified that the expression has a constant value;
+ // get that value (prior to conversions).
+ const Expr *LoBeforePromotion = Lo;
+ GetTypeBeforeIntegralPromotion(LoBeforePromotion);
+ llvm::APSInt LoVal = LoBeforePromotion->EvaluateKnownConstInt(Context);
// Check the unconverted value is within the range of possible values of
// the switch expression.
checkCaseValue(*this, Lo->getLocStart(), LoVal,
CondWidthBeforePromotion, CondIsSignedBeforePromotion);
+ // FIXME: This duplicates the check performed for warn_not_in_enum below.
+ checkEnumTypesInSwitchStmt(*this, CondExprBeforePromotion,
+ LoBeforePromotion);
+
// Convert the value to the same width/sign as the condition.
AdjustAPSInt(LoVal, CondWidth, CondIsSigned);
- CS->setLHS(Lo);
-
// If this is a case range, remember it in CaseRanges, otherwise CaseVals.
if (CS->getRHS()) {
- if (CS->getRHS()->isTypeDependent() ||
- CS->getRHS()->isValueDependent()) {
+ if (CS->getRHS()->isValueDependent()) {
HasDependentValue = true;
break;
}
@@ -1002,27 +1011,10 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
llvm::APSInt &LoVal = CaseRanges[i].first;
CaseStmt *CR = CaseRanges[i].second;
Expr *Hi = CR->getRHS();
- llvm::APSInt HiVal;
-
- if (getLangOpts().CPlusPlus11) {
- // C++11 [stmt.switch]p2: the constant-expression shall be a converted
- // constant expression of the promoted type of the switch condition.
- ExprResult ConvHi =
- CheckConvertedConstantExpression(Hi, CondType, HiVal,
- CCEK_CaseValue);
- if (ConvHi.isInvalid()) {
- CaseListIsErroneous = true;
- continue;
- }
- Hi = ConvHi.get();
- } else {
- HiVal = Hi->EvaluateKnownConstInt(Context);
- // If the RHS is not the same type as the condition, insert an
- // implicit cast.
- Hi = DefaultLvalueConversion(Hi).get();
- Hi = ImpCastExprToType(Hi, CondType, CK_IntegralCast).get();
- }
+ const Expr *HiBeforePromotion = Hi;
+ GetTypeBeforeIntegralPromotion(HiBeforePromotion);
+ llvm::APSInt HiVal = HiBeforePromotion->EvaluateKnownConstInt(Context);
// Check the unconverted value is within the range of possible values of
// the switch expression.
@@ -1032,8 +1024,6 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
// Convert the value to the same width/sign as the condition.
AdjustAPSInt(HiVal, CondWidth, CondIsSigned);
- CR->setRHS(Hi);
-
// 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)
@@ -1104,7 +1094,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
}
// Complain if we have a constant condition and we didn't find a match.
- if (!CaseListIsErroneous && ShouldCheckConstantCond) {
+ if (!CaseListIsErroneous && !CaseListIsIncomplete &&
+ ShouldCheckConstantCond) {
// TODO: it would be nice if we printed enums as enums, chars as
// chars, etc.
Diag(CondExpr->getExprLoc(), diag::warn_missing_case_for_condition)
@@ -1120,8 +1111,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
const EnumType *ET = CondTypeBeforePromotion->getAs<EnumType>();
// If switch has default case, then ignore it.
- if (!CaseListIsErroneous && !HasConstantCond && ET &&
- ET->getDecl()->isCompleteDefinition()) {
+ if (!CaseListIsErroneous && !CaseListIsIncomplete && !HasConstantCond &&
+ ET && ET->getDecl()->isCompleteDefinition()) {
const EnumDecl *ED = ET->getDecl();
EnumValsTy EnumVals;
@@ -1873,7 +1864,7 @@ StmtResult
Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
Stmt *First, Expr *collection,
SourceLocation RParenLoc) {
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
ExprResult CollectionExprResult =
CheckObjCForCollectionOperand(ForLoc, collection);
@@ -2025,7 +2016,7 @@ void NoteForRangeBeginEndFunction(Sema &SemaRef, Expr *E,
/// Build a variable declaration for a for-range statement.
VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc,
- QualType Type, const char *Name) {
+ QualType Type, StringRef Name) {
DeclContext *DC = SemaRef.CurContext;
IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
@@ -2094,10 +2085,12 @@ 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();
VarDecl *RangeVar = BuildForRangeVarDecl(*this, RangeLoc,
Context.getAutoRRefDeductType(),
- "__range");
+ std::string("__range") + DepthStr);
if (FinishForRangeVarDecl(*this, RangeVar, Range, RangeLoc,
diag::err_for_range_deduction_failure)) {
LoopVar->setInvalidDecl();
@@ -2119,7 +2112,7 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,
DS, RParenLoc, Kind);
}
-/// \brief Create the initialization, compare, and increment steps for
+/// Create the initialization, compare, and increment steps for
/// the range-based for loop expression.
/// This function does not handle array-based for loops,
/// which are created in Sema::BuildCXXForRangeStmt.
@@ -2340,10 +2333,12 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
return StmtError();
// Build auto __begin = begin-expr, __end = end-expr.
+ // Divide by 2, since the variables are in the inner scope (loop body).
+ const auto DepthStr = std::to_string(S->getDepth() / 2);
VarDecl *BeginVar = BuildForRangeVarDecl(*this, ColonLoc, AutoType,
- "__begin");
+ std::string("__begin") + DepthStr);
VarDecl *EndVar = BuildForRangeVarDecl(*this, ColonLoc, AutoType,
- "__end");
+ std::string("__end") + DepthStr);
// Build begin-expr and end-expr and attach to __begin and __end variables.
ExprResult BeginExpr, EndExpr;
@@ -2387,7 +2382,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
// FIXME: This results in codegen generating IR that recalculates the
// run-time number of elements (as opposed to just using the IR Value
// that corresponds to the run-time value of each bound that was
- // generated when the array was created.) If this proves too embarassing
+ // generated when the array was created.) If this proves too embarrassing
// even for unoptimized IR, consider passing a magic-value/cookie to
// codegen that then knows to simply use that initial llvm::Value (that
// corresponds to the bound at time of array creation) within
@@ -2657,7 +2652,7 @@ static void DiagnoseForRangeReferenceVariableCopies(Sema &SemaRef,
if (ReturnsReference) {
// Loop variable creates a temporary. Suggest either to go with
- // non-reference loop variable to indiciate a copy is made, or
+ // non-reference loop variable to indicate a copy is made, or
// the correct time to bind a const reference.
SemaRef.Diag(VD->getLocation(), diag::warn_for_range_const_reference_copy)
<< VD << VariableType << E->getType();
@@ -2718,7 +2713,7 @@ static void DiagnoseForRangeConstVariableCopies(Sema &SemaRef,
/// DiagnoseForRangeVariableCopies - Diagnose three cases and fixes for them.
/// 1) for (const foo &x : foos) where foos only returns a copy. Suggest
/// using "const foo x" to show that a copy is made
-/// 2) for (const bar &x : foos) where bar is a temporary intialized by bar.
+/// 2) for (const bar &x : foos) where bar is a temporary initialized by bar.
/// Suggest either "const bar x" to keep the copying or "const foo& x" to
/// prevent the copy.
/// 3) for (const foo x : foos) where x is constructed from a reference foo.
@@ -2780,7 +2775,7 @@ StmtResult Sema::FinishCXXForRangeStmt(Stmt *S, Stmt *B) {
StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc,
SourceLocation LabelLoc,
LabelDecl *TheDecl) {
- getCurFunction()->setHasBranchIntoScope();
+ setFunctionHasBranchIntoScope();
TheDecl->markUsed(Context);
return new (Context) GotoStmt(TheDecl, GotoLoc, LabelLoc);
}
@@ -2807,7 +2802,7 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc,
return StmtError();
E = ExprRes.get();
- getCurFunction()->setHasIndirectGoto();
+ setFunctionHasIndirectGoto();
return new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E);
}
@@ -2847,7 +2842,7 @@ Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) {
return new (Context) BreakStmt(BreakLoc);
}
-/// \brief Determine whether the given expression is a candidate for
+/// Determine whether the given expression is a candidate for
/// copy elision in either a return statement or a throw expression.
///
/// \param ReturnType If we're determining the copy elision candidate for
@@ -2858,7 +2853,7 @@ Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) {
/// \param E The expression being returned from the function or block, or
/// being thrown.
///
-/// \param AllowParamOrMoveConstructible Whether we allow function parameters or
+/// \param CESK Whether we allow function parameters or
/// id-expressions that could be moved out of the function to be considered NRVO
/// candidates. C++ prohibits these for NRVO itself, but we re-use this logic to
/// determine whether we should try to move as part of a return or throw (which
@@ -2867,10 +2862,7 @@ Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) {
/// \returns The NRVO candidate variable, if the return statement may use the
/// NRVO, or NULL if there is no such candidate.
VarDecl *Sema::getCopyElisionCandidate(QualType ReturnType, Expr *E,
- bool AllowParamOrMoveConstructible) {
- if (!getLangOpts().CPlusPlus)
- return nullptr;
-
+ CopyElisionSemanticsKind CESK) {
// - in a return statement in a function [where] ...
// ... the expression is the name of a non-volatile automatic object ...
DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E->IgnoreParens());
@@ -2880,13 +2872,13 @@ VarDecl *Sema::getCopyElisionCandidate(QualType ReturnType, Expr *E,
if (!VD)
return nullptr;
- if (isCopyElisionCandidate(ReturnType, VD, AllowParamOrMoveConstructible))
+ if (isCopyElisionCandidate(ReturnType, VD, CESK))
return VD;
return nullptr;
}
bool Sema::isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD,
- bool AllowParamOrMoveConstructible) {
+ CopyElisionSemanticsKind CESK) {
QualType VDType = VD->getType();
// - in a return statement in a function with ...
// ... a class return type ...
@@ -2895,16 +2887,17 @@ bool Sema::isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD,
return false;
// ... the same cv-unqualified type as the function return type ...
// When considering moving this expression out, allow dissimilar types.
- if (!AllowParamOrMoveConstructible && !VDType->isDependentType() &&
+ if (!(CESK & CES_AllowDifferentTypes) && !VDType->isDependentType() &&
!Context.hasSameUnqualifiedType(ReturnType, VDType))
return false;
}
// ...object (other than a function or catch-clause parameter)...
if (VD->getKind() != Decl::Var &&
- !(AllowParamOrMoveConstructible && VD->getKind() == Decl::ParmVar))
+ !((CESK & CES_AllowParameters) && VD->getKind() == Decl::ParmVar))
+ return false;
+ if (!(CESK & CES_AllowExceptionVariables) && VD->isExceptionVariable())
return false;
- if (VD->isExceptionVariable()) return false;
// ...automatic...
if (!VD->hasLocalStorage()) return false;
@@ -2914,7 +2907,7 @@ bool Sema::isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD,
// variable will no longer be used.
if (VD->hasAttr<BlocksAttr>()) return false;
- if (AllowParamOrMoveConstructible)
+ if (CESK & CES_AllowDifferentTypes)
return true;
// ...non-volatile...
@@ -2929,7 +2922,95 @@ bool Sema::isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD,
return true;
}
-/// \brief Perform the initialization of a potentially-movable value, which
+/// Try to perform the initialization of a potentially-movable value,
+/// which is the operand to a return or throw statement.
+///
+/// This routine implements C++14 [class.copy]p32, which attempts to treat
+/// returned lvalues as rvalues in certain cases (to prefer move construction),
+/// then falls back to treating them as lvalues if that failed.
+///
+/// \param ConvertingConstructorsOnly If true, follow [class.copy]p32 and reject
+/// resolutions that find non-constructors, such as derived-to-base conversions
+/// or `operator T()&&` member functions. If false, do consider such
+/// conversion sequences.
+///
+/// \param Res We will fill this in if move-initialization was possible.
+/// If move-initialization is not possible, such that we must fall back to
+/// treating the operand as an lvalue, we will leave Res in its original
+/// invalid state.
+static void TryMoveInitialization(Sema& S,
+ const InitializedEntity &Entity,
+ const VarDecl *NRVOCandidate,
+ QualType ResultType,
+ Expr *&Value,
+ bool ConvertingConstructorsOnly,
+ ExprResult &Res) {
+ ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, Value->getType(),
+ CK_NoOp, Value, VK_XValue);
+
+ Expr *InitExpr = &AsRvalue;
+
+ InitializationKind Kind = InitializationKind::CreateCopy(
+ Value->getLocStart(), Value->getLocStart());
+
+ InitializationSequence Seq(S, Entity, Kind, InitExpr);
+
+ if (!Seq)
+ return;
+
+ for (const InitializationSequence::Step &Step : Seq.steps()) {
+ if (Step.Kind != InitializationSequence::SK_ConstructorInitialization &&
+ Step.Kind != InitializationSequence::SK_UserConversion)
+ continue;
+
+ FunctionDecl *FD = Step.Function.Function;
+ if (ConvertingConstructorsOnly) {
+ if (isa<CXXConstructorDecl>(FD)) {
+ // C++14 [class.copy]p32:
+ // [...] If the first overload resolution fails or was not performed,
+ // or if the type of the first parameter of the selected constructor
+ // is not an rvalue reference to the object's type (possibly
+ // cv-qualified), overload resolution is performed again, considering
+ // the object as an lvalue.
+ const RValueReferenceType *RRefType =
+ FD->getParamDecl(0)->getType()->getAs<RValueReferenceType>();
+ if (!RRefType)
+ break;
+ if (!S.Context.hasSameUnqualifiedType(RRefType->getPointeeType(),
+ NRVOCandidate->getType()))
+ break;
+ } else {
+ continue;
+ }
+ } else {
+ if (isa<CXXConstructorDecl>(FD)) {
+ // Check that overload resolution selected a constructor taking an
+ // rvalue reference. If it selected an lvalue reference, then we
+ // didn't need to cast this thing to an rvalue in the first place.
+ if (!isa<RValueReferenceType>(FD->getParamDecl(0)->getType()))
+ break;
+ } else if (isa<CXXMethodDecl>(FD)) {
+ // Check that overload resolution selected a conversion operator
+ // taking an rvalue reference.
+ if (cast<CXXMethodDecl>(FD)->getRefQualifier() != RQ_RValue)
+ break;
+ } else {
+ continue;
+ }
+ }
+
+ // Promote "AsRvalue" to the heap, since we now need this
+ // expression node to persist.
+ Value = ImplicitCastExpr::Create(S.Context, Value->getType(), CK_NoOp,
+ Value, nullptr, VK_XValue);
+
+ // Complete type-checking the initialization of the return type
+ // using the constructor we found.
+ Res = Seq.Perform(S, Entity, Kind, Value);
+ }
+}
+
+/// Perform the initialization of a potentially-movable value, which
/// is the result of return value.
///
/// This routine implements C++14 [class.copy]p32, which attempts to treat
@@ -2952,52 +3033,82 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
// were designated by an rvalue.
ExprResult Res = ExprError();
- if (AllowNRVO && !NRVOCandidate)
- NRVOCandidate = getCopyElisionCandidate(ResultType, Value, true);
-
- if (AllowNRVO && NRVOCandidate) {
- ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, Value->getType(),
- CK_NoOp, Value, VK_XValue);
-
- Expr *InitExpr = &AsRvalue;
-
- InitializationKind Kind = InitializationKind::CreateCopy(
- Value->getLocStart(), Value->getLocStart());
-
- InitializationSequence Seq(*this, Entity, Kind, InitExpr);
- if (Seq) {
- for (const InitializationSequence::Step &Step : Seq.steps()) {
- if (!(Step.Kind ==
- InitializationSequence::SK_ConstructorInitialization ||
- (Step.Kind == InitializationSequence::SK_UserConversion &&
- isa<CXXConstructorDecl>(Step.Function.Function))))
- continue;
-
- CXXConstructorDecl *Constructor =
- cast<CXXConstructorDecl>(Step.Function.Function);
-
- const RValueReferenceType *RRefType
- = Constructor->getParamDecl(0)->getType()
- ->getAs<RValueReferenceType>();
-
- // [...] If the first overload resolution fails or was not performed, or
- // if the type of the first parameter of the selected constructor is not
- // an rvalue reference to the object's type (possibly cv-qualified),
- // overload resolution is performed again, considering the object as an
- // lvalue.
- if (!RRefType ||
- !Context.hasSameUnqualifiedType(RRefType->getPointeeType(),
- NRVOCandidate->getType()))
- break;
+ if (AllowNRVO) {
+ bool AffectedByCWG1579 = false;
+
+ if (!NRVOCandidate) {
+ NRVOCandidate = getCopyElisionCandidate(ResultType, Value, CES_Default);
+ if (NRVOCandidate &&
+ !getDiagnostics().isIgnored(diag::warn_return_std_move_in_cxx11,
+ Value->getExprLoc())) {
+ const VarDecl *NRVOCandidateInCXX11 =
+ getCopyElisionCandidate(ResultType, Value, CES_FormerDefault);
+ AffectedByCWG1579 = (!NRVOCandidateInCXX11);
+ }
+ }
- // Promote "AsRvalue" to the heap, since we now need this
- // expression node to persist.
- Value = ImplicitCastExpr::Create(Context, Value->getType(), CK_NoOp,
- Value, nullptr, VK_XValue);
+ if (NRVOCandidate) {
+ TryMoveInitialization(*this, Entity, NRVOCandidate, ResultType, Value,
+ true, Res);
+ }
- // Complete type-checking the initialization of the return type
- // using the constructor we found.
- Res = Seq.Perform(*this, Entity, Kind, Value);
+ if (!Res.isInvalid() && AffectedByCWG1579) {
+ QualType QT = NRVOCandidate->getType();
+ if (QT.getNonReferenceType()
+ .getUnqualifiedType()
+ .isTriviallyCopyableType(Context)) {
+ // Adding 'std::move' around a trivially copyable variable is probably
+ // pointless. Don't suggest it.
+ } else {
+ // Common cases for this are returning unique_ptr<Derived> from a
+ // function of return type unique_ptr<Base>, or returning T from a
+ // function of return type Expected<T>. This is totally fine in a
+ // post-CWG1579 world, but was not fine before.
+ assert(!ResultType.isNull());
+ SmallString<32> Str;
+ Str += "std::move(";
+ Str += NRVOCandidate->getDeclName().getAsString();
+ Str += ")";
+ Diag(Value->getExprLoc(), diag::warn_return_std_move_in_cxx11)
+ << Value->getSourceRange()
+ << NRVOCandidate->getDeclName() << ResultType << QT;
+ Diag(Value->getExprLoc(), diag::note_add_std_move_in_cxx11)
+ << FixItHint::CreateReplacement(Value->getSourceRange(), Str);
+ }
+ } else if (Res.isInvalid() &&
+ !getDiagnostics().isIgnored(diag::warn_return_std_move,
+ Value->getExprLoc())) {
+ const VarDecl *FakeNRVOCandidate =
+ getCopyElisionCandidate(QualType(), Value, CES_AsIfByStdMove);
+ if (FakeNRVOCandidate) {
+ QualType QT = FakeNRVOCandidate->getType();
+ if (QT->isLValueReferenceType()) {
+ // Adding 'std::move' around an lvalue reference variable's name is
+ // dangerous. Don't suggest it.
+ } else if (QT.getNonReferenceType()
+ .getUnqualifiedType()
+ .isTriviallyCopyableType(Context)) {
+ // Adding 'std::move' around a trivially copyable variable is probably
+ // pointless. Don't suggest it.
+ } else {
+ ExprResult FakeRes = ExprError();
+ Expr *FakeValue = Value;
+ TryMoveInitialization(*this, Entity, FakeNRVOCandidate, ResultType,
+ FakeValue, false, FakeRes);
+ if (!FakeRes.isInvalid()) {
+ bool IsThrow =
+ (Entity.getKind() == InitializedEntity::EK_Exception);
+ SmallString<32> Str;
+ Str += "std::move(";
+ Str += FakeNRVOCandidate->getDeclName().getAsString();
+ Str += ")";
+ Diag(Value->getExprLoc(), diag::warn_return_std_move)
+ << Value->getSourceRange()
+ << FakeNRVOCandidate->getDeclName() << IsThrow;
+ Diag(Value->getExprLoc(), diag::note_add_std_move)
+ << FixItHint::CreateReplacement(Value->getSourceRange(), Str);
+ }
+ }
}
}
}
@@ -3011,7 +3122,7 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
return Res;
}
-/// \brief Determine whether the declared return type of the specified function
+/// Determine whether the declared return type of the specified function
/// contains 'auto'.
static bool hasDeducedReturnType(FunctionDecl *FD) {
const FunctionProtoType *FPT =
@@ -3145,7 +3256,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// In C++ the return statement is handled via a copy initialization.
// the C version of which boils down to CheckSingleAssignmentConstraints.
- NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false);
+ NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, CES_Strict);
InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc,
FnRetType,
NRVOCandidate != nullptr);
@@ -3158,7 +3269,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
RetValExp = Res.get();
CheckReturnValExpr(RetValExp, FnRetType, ReturnLoc);
} else {
- NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false);
+ NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, CES_Strict);
}
if (RetValExp) {
@@ -3183,7 +3294,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
}
namespace {
-/// \brief Marks all typedefs in all local classes in a type referenced.
+/// Marks all typedefs in all local classes in a type referenced.
///
/// In a function like
/// auto f() {
@@ -3528,7 +3639,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// In C++ the return statement is handled via a copy initialization,
// the C version of which boils down to CheckSingleAssignmentConstraints.
if (RetValExp)
- NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false);
+ NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, CES_Strict);
if (!HasDependentReturnType && !RetValExp->isTypeDependent()) {
// we have a non-void function with an expression, continue checking
InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc,
@@ -3603,7 +3714,7 @@ Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try,
if (!getLangOpts().ObjCExceptions)
Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@try";
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
unsigned NumCatchStmts = CatchStmts.size();
return ObjCAtTryStmt::Create(Context, AtLoc, Try, CatchStmts.data(),
NumCatchStmts, Finally);
@@ -3694,7 +3805,7 @@ StmtResult
Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *SyncExpr,
Stmt *SyncBody) {
// We can't jump into or indirect-jump out of a @synchronized block.
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return new (Context) ObjCAtSynchronizedStmt(AtLoc, SyncExpr, SyncBody);
}
@@ -3710,7 +3821,7 @@ Sema::ActOnCXXCatchBlock(SourceLocation CatchLoc, Decl *ExDecl,
StmtResult
Sema::ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body) {
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return new (Context) ObjCAutoreleasePoolStmt(AtLoc, Body);
}
@@ -3822,7 +3933,11 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
ArrayRef<Stmt *> Handlers) {
// Don't report an error if 'try' is used in system headers.
if (!getLangOpts().CXXExceptions &&
- !getSourceManager().isInSystemHeader(TryLoc))
+ !getSourceManager().isInSystemHeader(TryLoc) &&
+ (!getLangOpts().OpenMPIsDevice ||
+ !getLangOpts().OpenMPHostCXXExceptions ||
+ isInOpenMPTargetExecutionDirective() ||
+ isInOpenMPDeclareTargetContext()))
Diag(TryLoc, diag::err_exceptions_disabled) << "try";
// Exceptions aren't allowed in CUDA device code.
@@ -4036,32 +4151,29 @@ Sema::CreateCapturedStmtRecordDecl(CapturedDecl *&CD, SourceLocation Loc,
return RD;
}
-static void buildCapturedStmtCaptureList(
- SmallVectorImpl<CapturedStmt::Capture> &Captures,
- SmallVectorImpl<Expr *> &CaptureInits,
- ArrayRef<CapturingScopeInfo::Capture> Candidates) {
-
- typedef ArrayRef<CapturingScopeInfo::Capture>::const_iterator CaptureIter;
- for (CaptureIter Cap = Candidates.begin(); Cap != Candidates.end(); ++Cap) {
-
- if (Cap->isThisCapture()) {
- Captures.push_back(CapturedStmt::Capture(Cap->getLocation(),
+static void
+buildCapturedStmtCaptureList(SmallVectorImpl<CapturedStmt::Capture> &Captures,
+ SmallVectorImpl<Expr *> &CaptureInits,
+ ArrayRef<sema::Capture> Candidates) {
+ for (const sema::Capture &Cap : Candidates) {
+ if (Cap.isThisCapture()) {
+ Captures.push_back(CapturedStmt::Capture(Cap.getLocation(),
CapturedStmt::VCK_This));
- CaptureInits.push_back(Cap->getInitExpr());
+ CaptureInits.push_back(Cap.getInitExpr());
continue;
- } else if (Cap->isVLATypeCapture()) {
+ } else if (Cap.isVLATypeCapture()) {
Captures.push_back(
- CapturedStmt::Capture(Cap->getLocation(), CapturedStmt::VCK_VLAType));
+ CapturedStmt::Capture(Cap.getLocation(), CapturedStmt::VCK_VLAType));
CaptureInits.push_back(nullptr);
continue;
}
- Captures.push_back(CapturedStmt::Capture(Cap->getLocation(),
- Cap->isReferenceCapture()
+ Captures.push_back(CapturedStmt::Capture(Cap.getLocation(),
+ Cap.isReferenceCapture()
? CapturedStmt::VCK_ByRef
: CapturedStmt::VCK_ByCopy,
- Cap->getVariable()));
- CaptureInits.push_back(Cap->getInitExpr());
+ Cap.getVariable()));
+ CaptureInits.push_back(Cap.getInitExpr());
}
}
@@ -4111,7 +4223,9 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
assert(!ContextIsFound &&
"null type has been found already for '__context' parameter");
IdentifierInfo *ParamName = &Context.Idents.get("__context");
- QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD));
+ QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD))
+ .withConst()
+ .withRestrict();
auto *Param =
ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType,
ImplicitParamDecl::CapturedContext);
@@ -4160,7 +4274,7 @@ void Sema::ActOnCapturedRegionError() {
SmallVector<Decl*, 4> Fields(Record->fields());
ActOnFields(/*Scope=*/nullptr, Record->getLocation(), Record, Fields,
- SourceLocation(), SourceLocation(), /*AttributeList=*/nullptr);
+ SourceLocation(), SourceLocation(), ParsedAttributesView());
PopDeclContext();
PopFunctionScopeInfo();
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
index fc1cc7bbe544..7e26b71c0482 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
@@ -109,7 +109,7 @@ static bool CheckNakedParmReference(Expr *E, Sema &S) {
return false;
}
-/// \brief Returns true if given expression is not compatible with inline
+/// Returns true if given expression is not compatible with inline
/// assembly's memory constraint; false otherwise.
static bool checkExprMemoryConstraintCompat(Sema &S, Expr *E,
TargetInfo::ConstraintInfo &Info,
@@ -793,7 +793,7 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
ArrayRef<Expr*> Exprs,
SourceLocation EndLoc) {
bool IsSimple = (NumOutputs != 0 || NumInputs != 0);
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
MSAsmStmt *NS =
new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
/*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp
index e55e20c2827f..e39a65c6ce0c 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp
@@ -23,7 +23,7 @@
using namespace clang;
using namespace sema;
-static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const AttributeList &A,
+static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const ParsedAttr &A,
SourceRange Range) {
FallThroughAttr Attr(A.getRange(), S.Context,
A.getAttributeSpellingListIndex());
@@ -53,7 +53,7 @@ static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const AttributeList &A,
return ::new (S.Context) auto(Attr);
}
-static Attr *handleSuppressAttr(Sema &S, Stmt *St, const AttributeList &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)
@@ -78,7 +78,7 @@ static Attr *handleSuppressAttr(Sema &S, Stmt *St, const AttributeList &A,
DiagnosticIdentifiers.size(), A.getAttributeSpellingListIndex());
}
-static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
+static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
SourceRange) {
IdentifierLoc *PragmaNameLoc = A.getArgAsIdent(0);
IdentifierLoc *OptionLoc = A.getArgAsIdent(1);
@@ -246,7 +246,7 @@ CheckForIncompatibleAttributes(Sema &S,
}
}
-static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const AttributeList &A,
+static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A,
SourceRange Range) {
// Although the feature was introduced only in OpenCL C v2.0 s6.11.5, it's
// useful for OpenCL 1.x too and doesn't require HW support.
@@ -288,21 +288,21 @@ static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const AttributeList &A,
return OpenCLUnrollHintAttr::CreateImplicit(S.Context, UnrollFactor);
}
-static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A,
+static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
SourceRange Range) {
switch (A.getKind()) {
- case AttributeList::UnknownAttribute:
+ case ParsedAttr::UnknownAttribute:
S.Diag(A.getLoc(), A.isDeclspecAttribute() ?
diag::warn_unhandled_ms_attribute_ignored :
diag::warn_unknown_attribute_ignored) << A.getName();
return nullptr;
- case AttributeList::AT_FallThrough:
+ case ParsedAttr::AT_FallThrough:
return handleFallThroughAttr(S, St, A, Range);
- case AttributeList::AT_LoopHint:
+ case ParsedAttr::AT_LoopHint:
return handleLoopHintAttr(S, St, A, Range);
- case AttributeList::AT_OpenCLUnrollHint:
+ case ParsedAttr::AT_OpenCLUnrollHint:
return handleOpenCLUnrollHint(S, St, A, Range);
- case AttributeList::AT_Suppress:
+ case ParsedAttr::AT_Suppress:
return handleSuppressAttr(S, St, A, Range);
default:
// if we're here, then we parsed a known attribute, but didn't recognize
@@ -313,11 +313,12 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A,
}
}
-StmtResult Sema::ProcessStmtAttributes(Stmt *S, AttributeList *AttrList,
+StmtResult Sema::ProcessStmtAttributes(Stmt *S,
+ const ParsedAttributesView &AttrList,
SourceRange Range) {
SmallVector<const Attr*, 8> Attrs;
- for (const AttributeList* l = AttrList; l; l = l->getNext()) {
- if (Attr *a = ProcessStmtAttribute(*this, S, *l, Range))
+ for (const ParsedAttr &AL : AttrList) {
+ if (Attr *a = ProcessStmtAttribute(*this, S, AL, Range))
Attrs.push_back(a);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
index 7c6af5793fc5..dd1163267119 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
@@ -46,7 +46,7 @@ clang::getTemplateParamsRange(TemplateParameterList const * const *Ps,
}
namespace clang {
-/// \brief [temp.constr.decl]p2: A template's associated constraints are
+/// [temp.constr.decl]p2: A template's associated constraints are
/// defined as a single constraint-expression derived from the introduced
/// constraint-expressions [ ... ].
///
@@ -65,7 +65,7 @@ static Expr *clang::formAssociatedConstraints(TemplateParameterList *Params,
return Params->getRequiresClause();
}
-/// \brief Determine whether the declaration found is acceptable as the name
+/// Determine whether the declaration found is acceptable as the name
/// of a template and, if so, return that template declaration. Otherwise,
/// returns NULL.
static NamedDecl *isAcceptableTemplateName(ASTContext &Context,
@@ -105,6 +105,12 @@ static NamedDecl *isAcceptableTemplateName(ASTContext &Context,
return nullptr;
}
+ // 'using Dependent::foo;' can resolve to a template name.
+ // 'using typename Dependent::foo;' cannot (not even if 'foo' is an
+ // injected-class-name).
+ if (isa<UnresolvedUsingValueDecl>(D))
+ return D;
+
return nullptr;
}
@@ -158,7 +164,7 @@ bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R,
TemplateNameKind Sema::isTemplateName(Scope *S,
CXXScopeSpec &SS,
bool hasTemplateKeyword,
- UnqualifiedId &Name,
+ const UnqualifiedId &Name,
ParsedType ObjectTypePtr,
bool EnteringContext,
TemplateTy &TemplateResult,
@@ -189,8 +195,9 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
QualType ObjectType = ObjectTypePtr.get();
LookupResult R(*this, TName, Name.getLocStart(), LookupOrdinaryName);
- LookupTemplateName(R, S, SS, ObjectType, EnteringContext,
- MemberOfUnknownSpecialization);
+ if (LookupTemplateName(R, S, SS, ObjectType, EnteringContext,
+ MemberOfUnknownSpecialization))
+ return TNK_Non_template;
if (R.empty()) return TNK_Non_template;
if (R.isAmbiguous()) {
// Suppress diagnostics; we'll redo this lookup later.
@@ -213,6 +220,10 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
// We'll do this lookup again later.
R.suppressDiagnostics();
+ } else if (isa<UnresolvedUsingValueDecl>((*R.begin())->getUnderlyingDecl())) {
+ // We don't yet know whether this is a template-name or not.
+ MemberOfUnknownSpecialization = true;
+ return TNK_Non_template;
} else {
TemplateDecl *TD = cast<TemplateDecl>((*R.begin())->getUnderlyingDecl());
@@ -252,8 +263,10 @@ bool Sema::isDeductionGuideName(Scope *S, const IdentifierInfo &Name,
// syntactic form of a deduction guide is enough to identify it even
// if we can't look up the template name at all.
LookupResult R(*this, DeclarationName(&Name), NameLoc, LookupOrdinaryName);
- LookupTemplateName(R, S, SS, /*ObjectType*/QualType(),
- /*EnteringContext*/false, MemberOfUnknownSpecialization);
+ if (LookupTemplateName(R, S, SS, /*ObjectType*/ QualType(),
+ /*EnteringContext*/ false,
+ MemberOfUnknownSpecialization))
+ return false;
if (R.empty()) return false;
if (R.isAmbiguous()) {
@@ -298,39 +311,40 @@ bool Sema::DiagnoseUnknownTemplateName(const IdentifierInfo &II,
return true;
}
-void Sema::LookupTemplateName(LookupResult &Found,
+bool Sema::LookupTemplateName(LookupResult &Found,
Scope *S, CXXScopeSpec &SS,
QualType ObjectType,
bool EnteringContext,
- bool &MemberOfUnknownSpecialization) {
+ bool &MemberOfUnknownSpecialization,
+ SourceLocation TemplateKWLoc) {
// Determine where to perform name lookup
MemberOfUnknownSpecialization = false;
DeclContext *LookupCtx = nullptr;
- bool isDependent = false;
+ bool IsDependent = false;
if (!ObjectType.isNull()) {
// This nested-name-specifier occurs in a member access expression, e.g.,
// x->B::f, and we are looking into the type of the object.
assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist");
LookupCtx = computeDeclContext(ObjectType);
- isDependent = ObjectType->isDependentType();
- assert((isDependent || !ObjectType->isIncompleteType() ||
+ IsDependent = !LookupCtx;
+ assert((IsDependent || !ObjectType->isIncompleteType() ||
ObjectType->castAs<TagType>()->isBeingDefined()) &&
"Caller should have completed object type");
// Template names cannot appear inside an Objective-C class or object type.
if (ObjectType->isObjCObjectOrInterfaceType()) {
Found.clear();
- return;
+ return false;
}
} else if (SS.isSet()) {
// This nested-name-specifier occurs after another nested-name-specifier,
// so long into the context associated with the prior nested-name-specifier.
LookupCtx = computeDeclContext(SS, EnteringContext);
- isDependent = isDependentScopeSpecifier(SS);
+ IsDependent = !LookupCtx;
// The declaration context must be complete.
if (LookupCtx && RequireCompleteDeclContext(SS, LookupCtx))
- return;
+ return true;
}
bool ObjectTypeSearchedInScope = false;
@@ -341,34 +355,43 @@ void Sema::LookupTemplateName(LookupResult &Found,
// expression or the declaration context associated with a prior
// nested-name-specifier.
LookupQualifiedName(Found, LookupCtx);
- if (!ObjectType.isNull() && Found.empty()) {
- // C++ [basic.lookup.classref]p1:
- // In a class member access expression (5.2.5), if the . or -> token is
- // immediately followed by an identifier followed by a <, the
- // identifier must be looked up to determine whether the < is the
- // beginning of a template argument list (14.2) or a less-than operator.
- // The identifier is first looked up in the class of the object
- // expression. If the identifier is not found, it is then looked up in
- // the context of the entire postfix-expression and shall name a class
- // or function template.
- if (S) LookupName(Found, S);
- ObjectTypeSearchedInScope = true;
+
+ // FIXME: The C++ standard does not clearly specify what happens in the
+ // case where the object type is dependent, and implementations vary. In
+ // Clang, we treat a name after a . or -> as a template-name if lookup
+ // finds a non-dependent member or member of the current instantiation that
+ // is a type template, or finds no such members and lookup in the context
+ // of the postfix-expression finds a type template. In the latter case, the
+ // name is nonetheless dependent, and we may resolve it to a member of an
+ // unknown specialization when we come to instantiate the template.
+ IsDependent |= Found.wasNotFoundInCurrentInstantiation();
+ }
+
+ if (!SS.isSet() && (ObjectType.isNull() || Found.empty())) {
+ // C++ [basic.lookup.classref]p1:
+ // In a class member access expression (5.2.5), if the . or -> token is
+ // immediately followed by an identifier followed by a <, the
+ // identifier must be looked up to determine whether the < is the
+ // beginning of a template argument list (14.2) or a less-than operator.
+ // The identifier is first looked up in the class of the object
+ // expression. If the identifier is not found, it is then looked up in
+ // the context of the entire postfix-expression and shall name a class
+ // template.
+ if (S)
+ LookupName(Found, S);
+
+ if (!ObjectType.isNull()) {
+ // FIXME: We should filter out all non-type templates here, particularly
+ // variable templates and concepts. But the exclusion of alias templates
+ // and template template parameters is a wording defect.
AllowFunctionTemplatesInLookup = false;
+ ObjectTypeSearchedInScope = true;
}
- } else if (isDependent && (!S || ObjectType.isNull())) {
- // We cannot look into a dependent object type or nested nme
- // specifier.
- MemberOfUnknownSpecialization = true;
- return;
- } else {
- // Perform unqualified name lookup in the current scope.
- LookupName(Found, S);
- if (!ObjectType.isNull())
- AllowFunctionTemplatesInLookup = false;
+ IsDependent |= Found.wasNotFoundInCurrentInstantiation();
}
- if (Found.empty() && !isDependent) {
+ if (Found.empty() && !IsDependent) {
// If we did not find any names, attempt to correct any typos.
DeclarationName Name = Found.getLookupName();
Found.clear();
@@ -402,11 +425,27 @@ void Sema::LookupTemplateName(LookupResult &Found,
}
}
+ NamedDecl *ExampleLookupResult =
+ Found.empty() ? nullptr : Found.getRepresentativeDecl();
FilterAcceptableTemplateNames(Found, AllowFunctionTemplatesInLookup);
if (Found.empty()) {
- if (isDependent)
+ if (IsDependent) {
MemberOfUnknownSpecialization = true;
- return;
+ return false;
+ }
+
+ // If a 'template' keyword was used, a lookup that finds only non-template
+ // names is an error.
+ if (ExampleLookupResult && TemplateKWLoc.isValid()) {
+ Diag(Found.getNameLoc(), diag::err_template_kw_refers_to_non_template)
+ << Found.getLookupName() << SS.getRange();
+ Diag(ExampleLookupResult->getUnderlyingDecl()->getLocation(),
+ diag::note_template_kw_refers_to_non_template)
+ << Found.getLookupName();
+ return true;
+ }
+
+ return false;
}
if (S && !ObjectType.isNull() && !ObjectTypeSearchedInScope &&
@@ -453,6 +492,8 @@ void Sema::LookupTemplateName(LookupResult &Found,
}
}
}
+
+ return false;
}
void Sema::diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName,
@@ -467,20 +508,41 @@ void Sema::diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName,
DeclContext *LookupCtx = nullptr;
NamedDecl *Found = nullptr;
+ bool MissingTemplateKeyword = false;
// Figure out what name we looked up.
- if (auto *ME = dyn_cast<MemberExpr>(TemplateName.get())) {
+ if (auto *DRE = dyn_cast<DeclRefExpr>(TemplateName.get())) {
+ NameInfo = DRE->getNameInfo();
+ SS.Adopt(DRE->getQualifierLoc());
+ LookupKind = LookupOrdinaryName;
+ Found = DRE->getFoundDecl();
+ } else if (auto *ME = dyn_cast<MemberExpr>(TemplateName.get())) {
NameInfo = ME->getMemberNameInfo();
SS.Adopt(ME->getQualifierLoc());
LookupKind = LookupMemberName;
LookupCtx = ME->getBase()->getType()->getAsCXXRecordDecl();
Found = ME->getMemberDecl();
+ } else if (auto *DSDRE =
+ dyn_cast<DependentScopeDeclRefExpr>(TemplateName.get())) {
+ NameInfo = DSDRE->getNameInfo();
+ SS.Adopt(DSDRE->getQualifierLoc());
+ MissingTemplateKeyword = true;
+ } else if (auto *DSME =
+ dyn_cast<CXXDependentScopeMemberExpr>(TemplateName.get())) {
+ NameInfo = DSME->getMemberNameInfo();
+ SS.Adopt(DSME->getQualifierLoc());
+ MissingTemplateKeyword = true;
} else {
- auto *DRE = cast<DeclRefExpr>(TemplateName.get());
- NameInfo = DRE->getNameInfo();
- SS.Adopt(DRE->getQualifierLoc());
- LookupKind = LookupOrdinaryName;
- Found = DRE->getFoundDecl();
+ llvm_unreachable("unexpected kind of potential template name");
+ }
+
+ // 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);
+ return;
}
// Try to correct the name by looking for templates and C++ named casts.
@@ -765,7 +827,7 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef,
llvm_unreachable("Unhandled parsed template argument");
}
-/// \brief Translates template arguments as provided by the parser
+/// Translates template arguments as provided by the parser
/// into template arguments used by semantic analysis.
void Sema::translateTemplateArguments(const ASTTemplateArgsPtr &TemplateArgsIn,
TemplateArgumentListInfo &TemplateArgs) {
@@ -783,6 +845,56 @@ static void maybeDiagnoseTemplateParameterShadow(Sema &SemaRef, Scope *S,
SemaRef.DiagnoseTemplateParameterShadow(Loc, PrevDecl);
}
+/// Convert a parsed type into a parsed template argument. This is mostly
+/// trivial, except that we may have parsed a C++17 deduced class template
+/// specialization type, in which case we should form a template template
+/// argument instead of a type template argument.
+ParsedTemplateArgument Sema::ActOnTemplateTypeArgument(TypeResult ParsedType) {
+ TypeSourceInfo *TInfo;
+ QualType T = GetTypeFromParser(ParsedType.get(), &TInfo);
+ if (T.isNull())
+ return ParsedTemplateArgument();
+ assert(TInfo && "template argument with no location");
+
+ // If we might have formed a deduced template specialization type, convert
+ // it to a template template argument.
+ if (getLangOpts().CPlusPlus17) {
+ TypeLoc TL = TInfo->getTypeLoc();
+ SourceLocation EllipsisLoc;
+ if (auto PET = TL.getAs<PackExpansionTypeLoc>()) {
+ EllipsisLoc = PET.getEllipsisLoc();
+ TL = PET.getPatternLoc();
+ }
+
+ CXXScopeSpec SS;
+ if (auto ET = TL.getAs<ElaboratedTypeLoc>()) {
+ SS.Adopt(ET.getQualifierLoc());
+ TL = ET.getNamedTypeLoc();
+ }
+
+ if (auto DTST = TL.getAs<DeducedTemplateSpecializationTypeLoc>()) {
+ TemplateName Name = DTST.getTypePtr()->getTemplateName();
+ if (SS.isSet())
+ Name = Context.getQualifiedTemplateName(SS.getScopeRep(),
+ /*HasTemplateKeyword*/ false,
+ Name.getAsTemplateDecl());
+ ParsedTemplateArgument Result(SS, TemplateTy::make(Name),
+ DTST.getTemplateNameLoc());
+ if (EllipsisLoc.isValid())
+ Result = Result.getTemplatePackExpansion(EllipsisLoc);
+ return Result;
+ }
+ }
+
+ // This is a normal type template argument. Note, if the type template
+ // argument is an injected-class-name for a template, it has a dual nature
+ // and can be used as either a type or a template. We handle that in
+ // convertTypeTemplateArgumentToTemplate.
+ return ParsedTemplateArgument(ParsedTemplateArgument::Type,
+ ParsedType.get().getAsOpaquePtr(),
+ TInfo->getTypeLoc().getLocStart());
+}
+
/// ActOnTypeParameter - Called when a C++ template type parameter
/// (e.g., "typename T") has been parsed. Typename specifies whether
/// the keyword "typename" was used to declare the type parameter
@@ -854,7 +966,7 @@ NamedDecl *Sema::ActOnTypeParameter(Scope *S, bool Typename,
return Param;
}
-/// \brief Check that the type of a non-type template parameter is
+/// Check that the type of a non-type template parameter is
/// well-formed.
///
/// \returns the (possibly-promoted) parameter type if valid;
@@ -933,9 +1045,9 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
auto CheckValidDeclSpecifiers = [this, &D] {
// C++ [temp.param]
// p1
- // template-parameter:
- // ...
- // parameter-declaration
+ // template-parameter:
+ // ...
+ // parameter-declaration
// p2
// ... A storage class shall not be specified in a template-parameter
// declaration.
@@ -1151,17 +1263,13 @@ static void SetNestedNameSpecifier(TagDecl *T, const CXXScopeSpec &SS) {
T->setQualifierInfo(SS.getWithLocInContext(T->getASTContext()));
}
-DeclResult
-Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
- SourceLocation KWLoc, CXXScopeSpec &SS,
- IdentifierInfo *Name, SourceLocation NameLoc,
- AttributeList *Attr,
- TemplateParameterList *TemplateParams,
- AccessSpecifier AS, SourceLocation ModulePrivateLoc,
- SourceLocation FriendLoc,
- unsigned NumOuterTemplateParamLists,
- TemplateParameterList** OuterTemplateParamLists,
- SkipBodyInfo *SkipBody) {
+DeclResult Sema::CheckClassTemplate(
+ Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
+ CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc,
+ const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams,
+ AccessSpecifier AS, SourceLocation ModulePrivateLoc,
+ SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists,
+ TemplateParameterList **OuterTemplateParamLists, SkipBodyInfo *SkipBody) {
assert(TemplateParams && TemplateParams->size() > 0 &&
"No template parameters");
assert(TUK != TUK_Reference && "Can only declare or define class templates");
@@ -1212,7 +1320,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams))
Invalid = true;
} else if (TUK != TUK_Friend && TUK != TUK_Reference)
- diagnoseQualifiedDeclaration(SS, SemanticContext, Name, NameLoc);
+ diagnoseQualifiedDeclaration(SS, SemanticContext, Name, NameLoc, false);
LookupQualifiedName(Previous, SemanticContext);
} else {
@@ -1501,8 +1609,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
if (TUK == TUK_Definition)
NewClass->startDefinition();
- if (Attr)
- ProcessDeclAttributeList(S, NewClass, Attr);
+ ProcessDeclAttributeList(S, NewClass, Attr);
if (PrevClassTemplate)
mergeDeclAttributes(NewClass, PrevClassTemplate->getTemplatedDecl());
@@ -1885,6 +1992,8 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
// FIXME: Add a kind for this to give more meaningful diagnostics. But can
// this substitution process actually fail?
InstantiatingTemplate BuildingDeductionGuides(*this, Loc, Template);
+ if (BuildingDeductionGuides.isInvalid())
+ return;
// Convert declared constructors into deduction guide templates.
// FIXME: Skip constructors for which deduction must necessarily fail (those
@@ -1925,7 +2034,7 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
->setIsCopyDeductionCandidate();
}
-/// \brief Diagnose the presence of a default template argument on a
+/// Diagnose the presence of a default template argument on a
/// template parameter, which is ill-formed in certain contexts.
///
/// \returns true if the default template argument should be dropped.
@@ -1981,7 +2090,7 @@ static bool DiagnoseDefaultTemplateArgument(Sema &S,
llvm_unreachable("Invalid TemplateParamListContext!");
}
-/// \brief Check for unexpanded parameter packs within the template parameters
+/// Check for unexpanded parameter packs within the template parameters
/// of a template template parameter, recursively.
static bool DiagnoseUnexpandedParameterPacks(Sema &S,
TemplateTemplateParmDecl *TTP) {
@@ -2012,7 +2121,7 @@ static bool DiagnoseUnexpandedParameterPacks(Sema &S,
return false;
}
-/// \brief Checks the validity of a template parameter list, possibly
+/// Checks the validity of a template parameter list, possibly
/// considering the template parameter list from a previous
/// declaration.
///
@@ -2379,7 +2488,7 @@ static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context,
return SourceRange();
}
-/// \brief Match the given template parameter lists to the given scope
+/// Match the given template parameter lists to the given scope
/// specifier, returning the template parameter list that applies to the
/// name.
///
@@ -3476,7 +3585,7 @@ noteNonDeducibleParameters(Sema &S, TemplateParameterList *TemplateParams,
const llvm::SmallBitVector &DeducibleParams) {
for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) {
if (!DeducibleParams[I]) {
- NamedDecl *Param = cast<NamedDecl>(TemplateParams->getParam(I));
+ NamedDecl *Param = TemplateParams->getParam(I);
if (Param->getDeclName())
S.Diag(Param->getLocation(), diag::note_non_deducible_parameter)
<< Param->getDeclName();
@@ -3754,7 +3863,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
}
namespace {
-/// \brief A partial specialization whose template arguments have matched
+/// A partial specialization whose template arguments have matched
/// a given template-id.
struct PartialSpecMatchResult {
VarTemplatePartialSpecializationDecl *Partial;
@@ -3938,6 +4047,16 @@ Sema::CheckVarTemplateId(const CXXScopeSpec &SS,
/*FoundD=*/nullptr, TemplateArgs);
}
+void Sema::diagnoseMissingTemplateArguments(TemplateName Name,
+ SourceLocation Loc) {
+ Diag(Loc, diag::err_template_missing_args)
+ << (int)getTemplateNameKindForDiagnostics(Name) << Name;
+ if (TemplateDecl *TD = Name.getAsTemplateDecl()) {
+ Diag(TD->getLocation(), diag::note_template_decl_here)
+ << TD->getTemplateParameters()->getSourceRange();
+ }
+}
+
ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
LookupResult &R,
@@ -3957,11 +4076,23 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
assert(!R.empty() && "empty lookup results when building templateid");
assert(!R.isAmbiguous() && "ambiguous lookup when building templateid");
+ // Non-function templates require a template argument list.
+ if (auto *TD = R.getAsSingle<TemplateDecl>()) {
+ if (!TemplateArgs && !isa<FunctionTemplateDecl>(TD)) {
+ diagnoseMissingTemplateArguments(TemplateName(TD), R.getNameLoc());
+ return ExprError();
+ }
+ }
+
+ auto AnyDependentArguments = [&]() -> bool {
+ bool InstantiationDependent;
+ return TemplateArgs &&
+ TemplateSpecializationType::anyDependentTemplateArguments(
+ *TemplateArgs, InstantiationDependent);
+ };
+
// In C++1y, check variable template ids.
- bool InstantiationDependent;
- if (R.getAsSingle<VarTemplateDecl>() &&
- !TemplateSpecializationType::anyDependentTemplateArguments(
- *TemplateArgs, InstantiationDependent)) {
+ if (R.getAsSingle<VarTemplateDecl>() && !AnyDependentArguments()) {
return CheckVarTemplateId(SS, R.getLookupNameInfo(),
R.getAsSingle<VarTemplateDecl>(),
TemplateKWLoc, TemplateArgs);
@@ -3997,15 +4128,17 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
bool MemberOfUnknownSpecialization;
LookupResult R(*this, NameInfo, LookupOrdinaryName);
- LookupTemplateName(R, (Scope*)nullptr, SS, QualType(), /*Entering*/ false,
- MemberOfUnknownSpecialization);
+ if (LookupTemplateName(R, (Scope *)nullptr, SS, QualType(),
+ /*Entering*/false, MemberOfUnknownSpecialization,
+ TemplateKWLoc))
+ return ExprError();
if (R.isAmbiguous())
return ExprError();
if (R.empty()) {
- Diag(NameInfo.getLoc(), diag::err_template_kw_refers_to_non_template)
- << NameInfo.getName() << SS.getRange();
+ Diag(NameInfo.getLoc(), diag::err_no_member)
+ << NameInfo.getName() << DC << SS.getRange();
return ExprError();
}
@@ -4020,7 +4153,7 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL*/ false, TemplateArgs);
}
-/// \brief Form a dependent template name.
+/// Form a dependent template name.
///
/// This action forms a dependent template name given the template
/// name and its (presumably dependent) scope specifier. For
@@ -4030,7 +4163,7 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
- UnqualifiedId &Name,
+ const UnqualifiedId &Name,
ParsedType ObjectType,
bool EnteringContext,
TemplateTy &Result,
@@ -4068,17 +4201,20 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
TemplateNameKind TNK = isTemplateName(S, SS, TemplateKWLoc.isValid(), Name,
ObjectType, EnteringContext, Result,
MemberOfUnknownSpecialization);
- if (TNK == TNK_Non_template && LookupCtx->isDependentContext() &&
- isa<CXXRecordDecl>(LookupCtx) &&
- (!cast<CXXRecordDecl>(LookupCtx)->hasDefinition() ||
- cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases())) {
+ if (TNK == TNK_Non_template && MemberOfUnknownSpecialization) {
// This is a dependent template. Handle it below.
} else if (TNK == TNK_Non_template) {
- Diag(Name.getLocStart(),
- diag::err_template_kw_refers_to_non_template)
- << GetNameFromUnqualifiedId(Name).getName()
- << Name.getSourceRange()
- << TemplateKWLoc;
+ // Do the lookup again to determine if this is a "nothing found" case or
+ // 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(),
+ LookupOrdinaryName);
+ bool MOUS;
+ if (!LookupTemplateName(R, S, SS, ObjectType.get(), EnteringContext,
+ MOUS, TemplateKWLoc))
+ Diag(Name.getLocStart(), diag::err_no_member)
+ << DNI.getName() << LookupCtx << SS.getRange();
return TNK_Non_template;
} else {
// We found something; return it.
@@ -4148,16 +4284,13 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
ArgType = Arg.getAsType();
TSI = AL.getTypeSourceInfo();
break;
- case TemplateArgument::Template: {
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion: {
// We have a template type parameter but the template argument
// is a template without any arguments.
SourceRange SR = AL.getSourceRange();
- TemplateName Name = Arg.getAsTemplate();
- Diag(SR.getBegin(), diag::err_template_missing_args)
- << (int)getTemplateNameKindForDiagnostics(Name) << Name << SR;
- if (TemplateDecl *Decl = Name.getAsTemplateDecl())
- Diag(Decl->getLocation(), diag::note_template_decl_here);
-
+ TemplateName Name = Arg.getAsTemplateOrTemplatePattern();
+ diagnoseMissingTemplateArguments(Name, SR.getEnd());
return true;
}
case TemplateArgument::Expression: {
@@ -4250,7 +4383,7 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
return false;
}
-/// \brief Substitute template arguments into the default template argument for
+/// Substitute template arguments into the default template argument for
/// the given template type parameter.
///
/// \param SemaRef the semantic analysis object for which we are performing
@@ -4306,7 +4439,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
return ArgType;
}
-/// \brief Substitute template arguments into the default template argument for
+/// Substitute template arguments into the default template argument for
/// the given non-type template parameter.
///
/// \param SemaRef the semantic analysis object for which we are performing
@@ -4354,7 +4487,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
return SemaRef.SubstExpr(Param->getDefaultArgument(), TemplateArgLists);
}
-/// \brief Substitute template arguments into the default template argument for
+/// Substitute template arguments into the default template argument for
/// the given template template parameter.
///
/// \param SemaRef the semantic analysis object for which we are performing
@@ -4418,7 +4551,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
TemplateArgLists);
}
-/// \brief If the given template parameter has a default template
+/// If the given template parameter has a default template
/// argument, substitute into that default template argument and
/// return the corresponding template argument.
TemplateArgumentLoc
@@ -4519,7 +4652,7 @@ static TemplateArgumentLoc convertTypeTemplateArgumentToTemplate(TypeLoc TLoc) {
return TemplateArgumentLoc();
}
-/// \brief Check that the given template argument corresponds to the given
+/// Check that the given template argument corresponds to the given
/// template parameter.
///
/// \param Param The template parameter against which the argument will be
@@ -4566,6 +4699,8 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
if (NTTP->isParameterPack() && NTTP->isExpandedParameterPack())
NTTPType = NTTP->getExpansionType(ArgumentPackIndex);
+ // FIXME: Do we need to substitute into parameters here if they're
+ // instantiation-dependent but not dependent?
if (NTTPType->isDependentType() &&
!isa<TemplateTemplateParmDecl>(Template) &&
!Template->getDeclContext()->isDependentContext()) {
@@ -4597,11 +4732,15 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
case TemplateArgument::Expression: {
TemplateArgument Result;
+ unsigned CurSFINAEErrors = NumSFINAEErrors;
ExprResult Res =
CheckTemplateArgument(NTTP, NTTPType, Arg.getArgument().getAsExpr(),
Result, CTAK);
if (Res.isInvalid())
return true;
+ // If the current template argument causes an error, give up now.
+ if (CurSFINAEErrors < NumSFINAEErrors)
+ return true;
// If the resulting expression is new, then use it in place of the
// old expression in the template argument.
@@ -4705,9 +4844,15 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
// Check template template parameters.
TemplateTemplateParmDecl *TempParm = cast<TemplateTemplateParmDecl>(Param);
+ TemplateParameterList *Params = TempParm->getTemplateParameters();
+ if (TempParm->isExpandedParameterPack())
+ Params = TempParm->getExpansionTemplateParameters(ArgumentPackIndex);
+
// Substitute into the template parameter list of the template
// template parameter, since previously-supplied template arguments
// may appear within the template template parameter.
+ //
+ // FIXME: Skip this if the parameters aren't instantiation-dependent.
{
// Set up a template instantiation context.
LocalInstantiationScope Scope(*this);
@@ -4718,10 +4863,9 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
return true;
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted);
- TempParm = cast_or_null<TemplateTemplateParmDecl>(
- SubstDecl(TempParm, CurContext,
- MultiLevelTemplateArgumentList(TemplateArgs)));
- if (!TempParm)
+ Params = SubstTemplateParams(Params, CurContext,
+ MultiLevelTemplateArgumentList(TemplateArgs));
+ if (!Params)
return true;
}
@@ -4742,7 +4886,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
- if (CheckTemplateArgument(TempParm, Arg, ArgumentPackIndex))
+ if (CheckTemplateTemplateArgument(Params, Arg))
return true;
Converted.push_back(Arg.getArgument());
@@ -4770,28 +4914,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
return false;
}
-/// \brief Diagnose an arity mismatch in the
-static bool diagnoseArityMismatch(Sema &S, TemplateDecl *Template,
- SourceLocation TemplateLoc,
- TemplateArgumentListInfo &TemplateArgs) {
- TemplateParameterList *Params = Template->getTemplateParameters();
- unsigned NumParams = Params->size();
- unsigned NumArgs = TemplateArgs.size();
-
- SourceRange Range;
- if (NumArgs > NumParams)
- Range = SourceRange(TemplateArgs[NumParams].getLocation(),
- TemplateArgs.getRAngleLoc());
- S.Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
- << (NumArgs > NumParams)
- << (int)S.getTemplateNameKindForDiagnostics(TemplateName(Template))
- << Template << Range;
- S.Diag(Template->getLocation(), diag::note_template_decl_here)
- << Params->getSourceRange();
- return true;
-}
-
-/// \brief Check whether the template parameter is a pack expansion, and if so,
+/// Check whether the template parameter is a pack expansion, and if so,
/// determine the number of parameters produced by that expansion. For instance:
///
/// \code
@@ -4844,10 +4967,18 @@ static bool diagnoseMissingArgument(Sema &S, SourceLocation Loc,
// FIXME: If there's a more recent default argument that *is* visible,
// diagnose that it was declared too late.
- return diagnoseArityMismatch(S, TD, Loc, Args);
+ TemplateParameterList *Params = TD->getTemplateParameters();
+
+ S.Diag(Loc, diag::err_template_arg_list_different_arity)
+ << /*not enough args*/0
+ << (int)S.getTemplateNameKindForDiagnostics(TemplateName(TD))
+ << TD;
+ S.Diag(TD->getLocation(), diag::note_template_decl_here)
+ << Params->getSourceRange();
+ return true;
}
-/// \brief Check that the given template argument list is well-formed
+/// Check that the given template argument list is well-formed
/// for specializing the given template.
bool Sema::CheckTemplateArgumentList(
TemplateDecl *Template, SourceLocation TemplateLoc,
@@ -4896,7 +5027,7 @@ bool Sema::CheckTemplateArgumentList(
} else if (ArgIdx == NumArgs && !PartialTemplateArgs) {
// Not enough arguments for this parameter pack.
Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
- << false
+ << /*not enough args*/0
<< (int)getTemplateNameKindForDiagnostics(TemplateName(Template))
<< Template;
Diag(Template->getLocation(), diag::note_template_decl_here)
@@ -5091,8 +5222,16 @@ bool Sema::CheckTemplateArgumentList(
// If we have any leftover arguments, then there were too many arguments.
// Complain and fail.
- if (ArgIdx < NumArgs)
- return diagnoseArityMismatch(*this, Template, TemplateLoc, NewArgs);
+ if (ArgIdx < NumArgs) {
+ Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
+ << /*too many args*/1
+ << (int)getTemplateNameKindForDiagnostics(TemplateName(Template))
+ << Template
+ << SourceRange(NewArgs[ArgIdx].getLocation(), NewArgs.getRAngleLoc());
+ Diag(Template->getLocation(), diag::note_template_decl_here)
+ << Params->getSourceRange();
+ return true;
+ }
// No problems found with the new argument list, propagate changes back
// to caller.
@@ -5197,6 +5336,11 @@ bool UnnamedLocalNoLinkageFinder::VisitVectorType(const VectorType* T) {
return Visit(T->getElementType());
}
+bool UnnamedLocalNoLinkageFinder::VisitDependentVectorType(
+ const DependentVectorType *T) {
+ return Visit(T->getElementType());
+}
+
bool UnnamedLocalNoLinkageFinder::VisitExtVectorType(const ExtVectorType* T) {
return Visit(T->getElementType());
}
@@ -5354,7 +5498,7 @@ bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier(
llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
}
-/// \brief Check a template argument against its corresponding
+/// Check a template argument against its corresponding
/// template type parameter.
///
/// This routine implements the semantics of C++ [temp.arg.type]. It
@@ -5392,7 +5536,7 @@ enum NullPointerValueKind {
NPV_Error
};
-/// \brief Determine whether the given template argument is a null pointer
+/// Determine whether the given template argument is a null pointer
/// value of the appropriate type.
static NullPointerValueKind
isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param,
@@ -5488,7 +5632,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param,
return NPV_NotNullPointer;
}
-/// \brief Checks whether the given template argument is compatible with its
+/// Checks whether the given template argument is compatible with its
/// template parameter.
static bool CheckTemplateArgumentIsCompatibleWithParameter(
Sema &S, NonTypeTemplateParmDecl *Param, QualType ParamType, Expr *ArgIn,
@@ -5545,7 +5689,7 @@ static bool CheckTemplateArgumentIsCompatibleWithParameter(
return false;
}
-/// \brief Checks whether the given template argument is the address
+/// Checks whether the given template argument is the address
/// of an object or function according to C++ [temp.arg.nontype]p1.
static bool
CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
@@ -5833,7 +5977,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
return false;
}
-/// \brief Checks whether the given template argument is a pointer to
+/// Checks whether the given template argument is a pointer to
/// member constant according to C++ [temp.arg.nontype]p1.
static bool CheckTemplateArgumentPointerToMember(Sema &S,
NonTypeTemplateParmDecl *Param,
@@ -5883,17 +6027,16 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
}
// A constant of pointer-to-member type.
else if ((DRE = dyn_cast<DeclRefExpr>(Arg))) {
- if (ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl())) {
- if (VD->getType()->isMemberPointerType()) {
- if (isa<NonTypeTemplateParmDecl>(VD)) {
- if (Arg->isTypeDependent() || Arg->isValueDependent()) {
- Converted = TemplateArgument(Arg);
- } else {
- VD = cast<ValueDecl>(VD->getCanonicalDecl());
- Converted = TemplateArgument(VD, ParamType);
- }
- return Invalid;
+ ValueDecl *VD = DRE->getDecl();
+ if (VD->getType()->isMemberPointerType()) {
+ if (isa<NonTypeTemplateParmDecl>(VD)) {
+ if (Arg->isTypeDependent() || Arg->isValueDependent()) {
+ Converted = TemplateArgument(Arg);
+ } else {
+ VD = cast<ValueDecl>(VD->getCanonicalDecl());
+ Converted = TemplateArgument(VD, ParamType);
}
+ return Invalid;
}
}
@@ -5963,7 +6106,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
return true;
}
-/// \brief Check a template argument against its corresponding
+/// Check a template argument against its corresponding
/// non-type template parameter.
///
/// This routine implements the semantics of C++ [temp.arg.nontype].
@@ -6118,7 +6261,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// -- a predefined __func__ variable
if (auto *E = Value.getLValueBase().dyn_cast<const Expr*>()) {
if (isa<CXXUuidofExpr>(E)) {
- Converted = TemplateArgument(const_cast<Expr*>(E));
+ Converted = TemplateArgument(ArgResult.get());
break;
}
Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref)
@@ -6481,14 +6624,13 @@ static void DiagnoseTemplateParameterListArityMismatch(
Sema &S, TemplateParameterList *New, TemplateParameterList *Old,
Sema::TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc);
-/// \brief Check a template argument against its corresponding
+/// Check a template argument against its corresponding
/// template template parameter.
///
/// This routine implements the semantics of C++ [temp.arg.template].
/// It returns true if an error occurred, and false otherwise.
-bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
- TemplateArgumentLoc &Arg,
- unsigned ArgumentPackIndex) {
+bool Sema::CheckTemplateTemplateArgument(TemplateParameterList *Params,
+ TemplateArgumentLoc &Arg) {
TemplateName Name = Arg.getArgument().getAsTemplateOrTemplatePattern();
TemplateDecl *Template = Name.getAsTemplateDecl();
if (!Template) {
@@ -6523,10 +6665,6 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
<< Template;
}
- TemplateParameterList *Params = Param->getTemplateParameters();
- if (Param->isExpandedParameterPack())
- Params = Param->getExpansionTemplateParameters(ArgumentPackIndex);
-
// C++1z [temp.arg.template]p3: (DR 150)
// A template-argument matches a template template-parameter P when P
// is at least as specialized as the template-argument A.
@@ -6553,7 +6691,7 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
Arg.getLocation());
}
-/// \brief Given a non-type template argument that refers to a
+/// Given a non-type template argument that refers to a
/// declaration and the type of its corresponding non-type template
/// parameter, produce an expression that properly refers to that
/// declaration.
@@ -6584,7 +6722,7 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
assert(Arg.getKind() == TemplateArgument::Declaration &&
"Only declaration template arguments permitted here");
- ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
+ ValueDecl *VD = Arg.getAsDecl();
if (VD->getDeclContext()->isRecord() &&
(isa<CXXMethodDecl>(VD) || isa<FieldDecl>(VD) ||
@@ -6676,7 +6814,7 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
return BuildDeclRefExpr(VD, T, VK, Loc);
}
-/// \brief Construct a new expression that refers to the given
+/// Construct a new expression that refers to the given
/// integral template argument with the given source-location
/// information.
///
@@ -6701,11 +6839,11 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
Expr *E;
if (T->isAnyCharacterType()) {
- // This does not need to handle u8 character literals because those are
- // of type char, and so can also be covered by an ASCII character literal.
CharacterLiteral::CharacterKind Kind;
if (T->isWideCharType())
Kind = CharacterLiteral::Wide;
+ else if (T->isChar8Type() && getLangOpts().Char8)
+ Kind = CharacterLiteral::UTF8;
else if (T->isChar16Type())
Kind = CharacterLiteral::UTF16;
else if (T->isChar32Type())
@@ -6736,7 +6874,7 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
return E;
}
-/// \brief Match two template parameters within template parameter lists.
+/// Match two template parameters within template parameter lists.
static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old,
bool Complain,
Sema::TemplateParameterListEqualKind Kind,
@@ -6839,7 +6977,7 @@ static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old,
return true;
}
-/// \brief Diagnose a known arity mismatch when comparing template argument
+/// Diagnose a known arity mismatch when comparing template argument
/// lists.
static
void DiagnoseTemplateParameterListArityMismatch(Sema &S,
@@ -6861,7 +6999,7 @@ void DiagnoseTemplateParameterListArityMismatch(Sema &S,
<< SourceRange(Old->getTemplateLoc(), Old->getRAngleLoc());
}
-/// \brief Determine whether the given template parameter lists are
+/// Determine whether the given template parameter lists are
/// equivalent.
///
/// \param New The new template parameter list, typically written in the
@@ -6953,7 +7091,7 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
return true;
}
-/// \brief Check whether a template can be declared within this scope.
+/// Check whether a template can be declared within this scope.
///
/// If the template declaration is valid in this scope, returns
/// false. Otherwise, issues a diagnostic and returns true.
@@ -7002,7 +7140,7 @@ Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) {
<< TemplateParams->getSourceRange();
}
-/// \brief Determine what kind of template specialization the given declaration
+/// Determine what kind of template specialization the given declaration
/// is.
static TemplateSpecializationKind getTemplateSpecializationKind(Decl *D) {
if (!D)
@@ -7018,7 +7156,7 @@ static TemplateSpecializationKind getTemplateSpecializationKind(Decl *D) {
return TSK_Undeclared;
}
-/// \brief Check whether a specialization is well-formed in the current
+/// Check whether a specialization is well-formed in the current
/// context.
///
/// This routine determines whether a template specialization can be declared
@@ -7072,120 +7210,43 @@ static bool CheckTemplateSpecializationScope(Sema &S,
}
// C++ [temp.expl.spec]p2:
- // An explicit specialization shall be declared in the namespace
- // of which the template is a member, or, for member templates, in
- // the namespace of which the enclosing class or enclosing class
- // template is a member. An explicit specialization of a member
- // function, member class or static data member of a class
- // template shall be declared in the namespace of which the class
- // template is a member. Such a declaration may also be a
- // definition. If the declaration is not a definition, the
- // specialization may be defined later in the name- space in which
- // the explicit specialization was declared, or in a namespace
- // that encloses the one in which the explicit specialization was
- // declared.
+ // An explicit specialization may be declared in any scope in which
+ // the corresponding primary template may be defined.
if (S.CurContext->getRedeclContext()->isFunctionOrMethod()) {
S.Diag(Loc, diag::err_template_spec_decl_function_scope)
<< Specialized;
return true;
}
- if (S.CurContext->isRecord() && !IsPartialSpecialization) {
- if (S.getLangOpts().MicrosoftExt) {
- // Do not warn for class scope explicit specialization during
- // instantiation, warning was already emitted during pattern
- // semantic analysis.
- if (!S.inTemplateInstantiation())
- S.Diag(Loc, diag::ext_function_specialization_in_class)
- << Specialized;
- } else {
- S.Diag(Loc, diag::err_template_spec_decl_class_scope)
- << Specialized;
- return true;
- }
- }
-
- if (S.CurContext->isRecord() &&
- !S.CurContext->Equals(Specialized->getDeclContext())) {
- // Make sure that we're specializing in the right record context.
- // Otherwise, things can go horribly wrong.
- S.Diag(Loc, diag::err_template_spec_decl_class_scope)
- << Specialized;
- return true;
- }
-
// C++ [temp.class.spec]p6:
- // A class template partial specialization may be declared or redeclared
- // in any namespace scope in which its definition may be defined (14.5.1
- // and 14.5.2).
- DeclContext *SpecializedContext
- = Specialized->getDeclContext()->getEnclosingNamespaceContext();
- DeclContext *DC = S.CurContext->getEnclosingNamespaceContext();
-
- // Make sure that this redeclaration (or definition) occurs in an enclosing
- // namespace.
- // Note that HandleDeclarator() performs this check for explicit
- // specializations of function templates, static data members, and member
- // functions, so we skip the check here for those kinds of entities.
- // FIXME: HandleDeclarator's diagnostics aren't quite as good, though.
- // Should we refactor that check, so that it occurs later?
- if (!DC->Encloses(SpecializedContext) &&
- !(isa<FunctionTemplateDecl>(Specialized) ||
- isa<FunctionDecl>(Specialized) ||
- isa<VarTemplateDecl>(Specialized) ||
- isa<VarDecl>(Specialized))) {
+ // A class template partial specialization may be declared in any
+ // scope in which the primary template may be defined.
+ DeclContext *SpecializedContext =
+ Specialized->getDeclContext()->getRedeclContext();
+ DeclContext *DC = S.CurContext->getRedeclContext();
+
+ // Make sure that this redeclaration (or definition) occurs in the same
+ // scope or an enclosing namespace.
+ if (!(DC->isFileContext() ? DC->Encloses(SpecializedContext)
+ : DC->Equals(SpecializedContext))) {
if (isa<TranslationUnitDecl>(SpecializedContext))
S.Diag(Loc, diag::err_template_spec_redecl_global_scope)
<< EntityKind << Specialized;
- else if (isa<NamespaceDecl>(SpecializedContext)) {
+ else {
+ auto *ND = cast<NamedDecl>(SpecializedContext);
int Diag = diag::err_template_spec_redecl_out_of_scope;
- if (S.getLangOpts().MicrosoftExt)
+ if (S.getLangOpts().MicrosoftExt && !DC->isRecord())
Diag = diag::ext_ms_template_spec_redecl_out_of_scope;
S.Diag(Loc, Diag) << EntityKind << Specialized
- << cast<NamedDecl>(SpecializedContext);
- } else
- llvm_unreachable("unexpected namespace context for specialization");
+ << ND << isa<CXXRecordDecl>(ND);
+ }
S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
- } else if ((!PrevDecl ||
- getTemplateSpecializationKind(PrevDecl) == TSK_Undeclared ||
- getTemplateSpecializationKind(PrevDecl) ==
- TSK_ImplicitInstantiation)) {
- // C++ [temp.exp.spec]p2:
- // An explicit specialization shall be declared in the namespace of which
- // the template is a member, or, for member templates, in the namespace
- // of which the enclosing class or enclosing class template is a member.
- // An explicit specialization of a member function, member class or
- // static data member of a class template shall be declared in the
- // namespace of which the class template is a member.
- //
- // C++11 [temp.expl.spec]p2:
- // An explicit specialization shall be declared in a namespace enclosing
- // the specialized template.
- // C++11 [temp.explicit]p3:
- // An explicit instantiation shall appear in an enclosing namespace of its
- // template.
- if (!DC->InEnclosingNamespaceSetOf(SpecializedContext)) {
- bool IsCPlusPlus11Extension = DC->Encloses(SpecializedContext);
- if (isa<TranslationUnitDecl>(SpecializedContext)) {
- assert(!IsCPlusPlus11Extension &&
- "DC encloses TU but isn't in enclosing namespace set");
- S.Diag(Loc, diag::err_template_spec_decl_out_of_scope_global)
- << EntityKind << Specialized;
- } else if (isa<NamespaceDecl>(SpecializedContext)) {
- int Diag;
- if (!IsCPlusPlus11Extension)
- Diag = diag::err_template_spec_decl_out_of_scope;
- else if (!S.getLangOpts().CPlusPlus11)
- Diag = diag::ext_template_spec_decl_out_of_scope;
- else
- Diag = diag::warn_cxx98_compat_template_spec_decl_out_of_scope;
- S.Diag(Loc, Diag)
- << EntityKind << Specialized << cast<NamedDecl>(SpecializedContext);
- }
- S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
- }
+ // Don't allow specializing in the wrong class during error recovery.
+ // Otherwise, things can go horribly wrong.
+ if (DC->isRecord())
+ return true;
}
return false;
@@ -7211,7 +7272,7 @@ static SourceRange findTemplateParameter(unsigned Depth, TypeLoc TL) {
return Checker.MatchLoc;
}
-/// \brief Subroutine of Sema::CheckTemplatePartialSpecializationArgs
+/// Subroutine of Sema::CheckTemplatePartialSpecializationArgs
/// that checks non-type template partial specialization arguments.
static bool CheckNonTypeTemplatePartialSpecializationArgs(
Sema &S, SourceLocation TemplateNameLoc, NonTypeTemplateParmDecl *Param,
@@ -7299,7 +7360,7 @@ static bool CheckNonTypeTemplatePartialSpecializationArgs(
return false;
}
-/// \brief Check the non-type template arguments of a class template
+/// Check the non-type template arguments of a class template
/// partial specialization according to C++ [temp.class.spec]p9.
///
/// \param TemplateNameLoc the location of the template name.
@@ -7335,16 +7396,11 @@ bool Sema::CheckTemplatePartialSpecializationArgs(
return false;
}
-DeclResult
-Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
- TagUseKind TUK,
- SourceLocation KWLoc,
- SourceLocation ModulePrivateLoc,
- TemplateIdAnnotation &TemplateId,
- AttributeList *Attr,
- MultiTemplateParamsArg
- TemplateParameterLists,
- SkipBodyInfo *SkipBody) {
+DeclResult Sema::ActOnClassTemplateSpecialization(
+ Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
+ SourceLocation ModulePrivateLoc, TemplateIdAnnotation &TemplateId,
+ const ParsedAttributesView &Attr,
+ MultiTemplateParamsArg TemplateParameterLists, SkipBodyInfo *SkipBody) {
assert(TUK != TUK_Reference && "References are not specializations");
CXXScopeSpec &SS = TemplateId.SS;
@@ -7586,10 +7642,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
ClassTemplate->AddSpecialization(Specialization, InsertPos);
if (CurContext->isDependentContext()) {
- // -fms-extensions permits specialization of nested classes without
- // fully specializing the outer class(es).
- assert(getLangOpts().MicrosoftExt &&
- "Only possible with -fms-extensions!");
TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
CanonType = Context.getTemplateSpecializationType(
CanonTemplate, Converted);
@@ -7649,8 +7701,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
}
}
- if (Attr)
- ProcessDeclAttributeList(S, Specialization, Attr);
+ ProcessDeclAttributeList(S, Specialization, Attr);
// Add alignment attributes if necessary; these attributes are checked when
// the ASTContext lays out the structure.
@@ -7717,7 +7768,7 @@ Decl *Sema::ActOnTemplateDeclarator(Scope *S,
return NewDecl;
}
-/// \brief Strips various properties off an implicit instantiation
+/// Strips various properties off an implicit instantiation
/// that has just been explicitly specialized.
static void StripImplicitInstantiation(NamedDecl *D) {
D->dropAttr<DLLImportAttr>();
@@ -7727,7 +7778,7 @@ static void StripImplicitInstantiation(NamedDecl *D) {
FD->setInlineSpecified(false);
}
-/// \brief Compute the diagnostic location for an explicit instantiation
+/// Compute the diagnostic location for an explicit instantiation
// declaration or definition.
static SourceLocation DiagLocForExplicitInstantiation(
NamedDecl* D, SourceLocation PointOfInstantiation) {
@@ -7744,7 +7795,7 @@ static SourceLocation DiagLocForExplicitInstantiation(
return PrevDiagLoc;
}
-/// \brief Diagnose cases where we have an explicit template specialization
+/// Diagnose cases where we have an explicit template specialization
/// before/after an explicit template instantiation, producing diagnostics
/// for those cases where they are required and determining whether the
/// new specialization/instantiation will have any effect.
@@ -7890,7 +7941,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
return false;
case TSK_ExplicitInstantiationDeclaration:
- // We're explicity instantiating a definition for something for which we
+ // We're explicitly instantiating a definition for something for which we
// were previously asked to suppress instantiations. That's fine.
// C++0x [temp.explicit]p4:
@@ -7929,7 +7980,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
llvm_unreachable("Missing specialization/instantiation case?");
}
-/// \brief Perform semantic analysis for the given dependent function
+/// Perform semantic analysis for the given dependent function
/// template specialization.
///
/// The only possible way to get a dependent function template specialization
@@ -7952,24 +8003,41 @@ Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD,
// the correct context.
DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext();
LookupResult::Filter F = Previous.makeFilter();
+ enum DiscardReason { NotAFunctionTemplate, NotAMemberOfEnclosing };
+ SmallVector<std::pair<DiscardReason, Decl *>, 8> DiscardedCandidates;
while (F.hasNext()) {
NamedDecl *D = F.next()->getUnderlyingDecl();
- if (!isa<FunctionTemplateDecl>(D) ||
- !FDLookupContext->InEnclosingNamespaceSetOf(
- D->getDeclContext()->getRedeclContext()))
+ if (!isa<FunctionTemplateDecl>(D)) {
+ F.erase();
+ DiscardedCandidates.push_back(std::make_pair(NotAFunctionTemplate, D));
+ continue;
+ }
+
+ if (!FDLookupContext->InEnclosingNamespaceSetOf(
+ D->getDeclContext()->getRedeclContext())) {
F.erase();
+ DiscardedCandidates.push_back(std::make_pair(NotAMemberOfEnclosing, D));
+ continue;
+ }
}
F.done();
- // Should this be diagnosed here?
- if (Previous.empty()) return true;
+ if (Previous.empty()) {
+ Diag(FD->getLocation(),
+ diag::err_dependent_function_template_spec_no_match);
+ for (auto &P : DiscardedCandidates)
+ Diag(P.second->getLocation(),
+ diag::note_dependent_function_template_spec_discard_reason)
+ << P.first;
+ return true;
+ }
FD->setDependentTemplateSpecialization(Context, Previous.asUnresolvedSet(),
ExplicitTemplateArgs);
return false;
}
-/// \brief Perform semantic analysis for the given function template
+/// Perform semantic analysis for the given function template
/// specialization.
///
/// This routine performs all of the semantic analysis required for an
@@ -8192,7 +8260,7 @@ bool Sema::CheckFunctionTemplateSpecialization(
return false;
}
-/// \brief Perform semantic analysis for the given non-template member
+/// Perform semantic analysis for the given non-template member
/// specialization.
///
/// This routine performs all of the semantic analysis required for an
@@ -8402,7 +8470,7 @@ void Sema::CompleteMemberSpecialization(NamedDecl *Member,
llvm_unreachable("unknown member specialization kind");
}
-/// \brief Check the scope of an explicit instantiation.
+/// Check the scope of an explicit instantiation.
///
/// \returns true if a serious error occurs, false otherwise.
static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
@@ -8456,7 +8524,7 @@ static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
return false;
}
-/// \brief Determine whether the given scope specifier has a template-id in it.
+/// Determine whether the given scope specifier has a template-id in it.
static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) {
if (!SS.isSet())
return false;
@@ -8502,19 +8570,12 @@ static void dllExportImportClassTemplateSpecialization(
}
// Explicit instantiation of a class template specialization
-DeclResult
-Sema::ActOnExplicitInstantiation(Scope *S,
- SourceLocation ExternLoc,
- SourceLocation TemplateLoc,
- unsigned TagSpec,
- SourceLocation KWLoc,
- const CXXScopeSpec &SS,
- TemplateTy TemplateD,
- SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgsIn,
- SourceLocation RAngleLoc,
- AttributeList *Attr) {
+DeclResult Sema::ActOnExplicitInstantiation(
+ Scope *S, SourceLocation ExternLoc, SourceLocation TemplateLoc,
+ unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS,
+ TemplateTy TemplateD, SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn,
+ SourceLocation RAngleLoc, const ParsedAttributesView &Attr) {
// Find the class template we're specializing
TemplateName Name = TemplateD.get();
TemplateDecl *TD = Name.getAsTemplateDecl();
@@ -8555,11 +8616,11 @@ Sema::ActOnExplicitInstantiation(Scope *S,
if (TSK == TSK_ExplicitInstantiationDeclaration) {
// Check for dllexport class template instantiation declarations.
- for (AttributeList *A = Attr; A; A = A->getNext()) {
- if (A->getKind() == AttributeList::AT_DLLExport) {
+ for (const ParsedAttr &AL : Attr) {
+ if (AL.getKind() == ParsedAttr::AT_DLLExport) {
Diag(ExternLoc,
diag::warn_attribute_dllexport_explicit_instantiation_decl);
- Diag(A->getLoc(), diag::note_attribute);
+ Diag(AL.getLoc(), diag::note_attribute);
break;
}
}
@@ -8579,10 +8640,10 @@ Sema::ActOnExplicitInstantiation(Scope *S,
// Check for dllimport class template instantiation definitions.
bool DLLImport =
ClassTemplate->getTemplatedDecl()->getAttr<DLLImportAttr>();
- for (AttributeList *A = Attr; A; A = A->getNext()) {
- if (A->getKind() == AttributeList::AT_DLLImport)
+ for (const ParsedAttr &AL : Attr) {
+ if (AL.getKind() == ParsedAttr::AT_DLLImport)
DLLImport = true;
- if (A->getKind() == AttributeList::AT_DLLExport) {
+ if (AL.getKind() == ParsedAttr::AT_DLLExport) {
// dllexport trumps dllimport here.
DLLImport = false;
break;
@@ -8692,8 +8753,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
Specialization->setBraceRange(SourceRange());
bool PreviouslyDLLExported = Specialization->hasAttr<DLLExportAttr>();
- if (Attr)
- ProcessDeclAttributeList(S, Specialization, Attr);
+ ProcessDeclAttributeList(S, Specialization, Attr);
// Add the explicit instantiation into its lexical context. However,
// since explicit instantiations are never found by name lookup, we
@@ -8791,15 +8851,11 @@ Sema::ActOnExplicitInstantiation(Scope *S,
// Explicit instantiation of a member class of a class template.
DeclResult
-Sema::ActOnExplicitInstantiation(Scope *S,
- SourceLocation ExternLoc,
- SourceLocation TemplateLoc,
- unsigned TagSpec,
- SourceLocation KWLoc,
- CXXScopeSpec &SS,
- IdentifierInfo *Name,
- SourceLocation NameLoc,
- AttributeList *Attr) {
+Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc,
+ SourceLocation TemplateLoc, unsigned TagSpec,
+ SourceLocation KWLoc, CXXScopeSpec &SS,
+ IdentifierInfo *Name, SourceLocation NameLoc,
+ const ParsedAttributesView &Attr) {
bool Owned = false;
bool IsDependent = false;
@@ -9101,8 +9157,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
if (PrevTemplate) {
// Merge attributes.
- if (AttributeList *Attr = D.getDeclSpec().getAttributes().getList())
- ProcessDeclAttributeList(S, Prev, Attr);
+ ProcessDeclAttributeList(S, Prev, D.getDeclSpec().getAttributes());
}
if (TSK == TSK_ExplicitInstantiationDefinition)
InstantiateVariableDefinition(D.getIdentifierLoc(), Prev);
@@ -9138,7 +9193,6 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
// template.
UnresolvedSet<8> TemplateMatches;
FunctionDecl *NonTemplateMatch = nullptr;
- AttributeList *Attr = D.getDeclSpec().getAttributes().getList();
TemplateSpecCandidateSet FailedCandidates(D.getIdentifierLoc());
for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
P != PEnd; ++P) {
@@ -9186,7 +9240,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
if (LangOpts.CUDA &&
IdentifyCUDATarget(Specialization,
/* IgnoreImplicitHDAttributes = */ true) !=
- IdentifyCUDATarget(Attr)) {
+ IdentifyCUDATarget(D.getDeclSpec().getAttributes())) {
FailedCandidates.addCandidate().set(
P.getPair(), FunTmpl->getTemplatedDecl(),
MakeDeductionFailureInfo(Context, TDK_CUDATargetMismatch, Info));
@@ -9265,8 +9319,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
return (Decl*) nullptr;
}
- if (Attr)
- ProcessDeclAttributeList(S, Specialization, Attr);
+ ProcessDeclAttributeList(S, Specialization, D.getDeclSpec().getAttributes());
// In MSVC mode, dllimported explicit instantiation definitions are treated as
// instantiation declarations.
@@ -9478,8 +9531,7 @@ static bool isEnableIf(NestedNameSpecifierLoc NNS, const IdentifierInfo &II,
EnableIfTy.getAs<TemplateSpecializationTypeLoc>();
if (!EnableIfTSTLoc || EnableIfTSTLoc.getNumArgs() == 0)
return false;
- const TemplateSpecializationType *EnableIfTST =
- cast<TemplateSpecializationType>(EnableIfTSTLoc.getTypePtr());
+ const TemplateSpecializationType *EnableIfTST = EnableIfTSTLoc.getTypePtr();
// ... which names a complete class template declaration...
const TemplateDecl *EnableIfDecl =
@@ -9511,7 +9563,7 @@ static bool isEnableIf(NestedNameSpecifierLoc NNS, const IdentifierInfo &II,
return true;
}
-/// \brief Build the type that describes a C++ typename specifier,
+/// Build the type that describes a C++ typename specifier,
/// e.g., "typename T::type".
QualType
Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
@@ -9686,7 +9738,7 @@ namespace {
: TreeTransform<CurrentInstantiationRebuilder>(SemaRef),
Loc(Loc), Entity(Entity) { }
- /// \brief Determine whether the given type \p T has already been
+ /// Determine whether the given type \p T has already been
/// transformed.
///
/// For the purposes of type reconstruction, a type has already been
@@ -9695,14 +9747,14 @@ namespace {
return T.isNull() || !T->isDependentType();
}
- /// \brief Returns the location of the entity whose type is being
+ /// Returns the location of the entity whose type is being
/// rebuilt.
SourceLocation getBaseLocation() { return Loc; }
- /// \brief Returns the name of the entity whose type is being rebuilt.
+ /// Returns the name of the entity whose type is being rebuilt.
DeclarationName getBaseEntity() { return Entity; }
- /// \brief Sets the "base" location and entity when that
+ /// Sets the "base" location and entity when that
/// information is known based on another transformation.
void setBase(SourceLocation Loc, DeclarationName Entity) {
this->Loc = Loc;
@@ -9716,7 +9768,7 @@ namespace {
};
} // end anonymous namespace
-/// \brief Rebuilds a type within the context of the current instantiation.
+/// Rebuilds a type within the context of the current instantiation.
///
/// The type \p T is part of the type of an out-of-line member definition of
/// a class template (or class template partial specialization) that was parsed
@@ -9774,7 +9826,7 @@ bool Sema::RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS) {
return false;
}
-/// \brief Rebuild the template parameters now that we know we're in a current
+/// Rebuild the template parameters now that we know we're in a current
/// instantiation.
bool Sema::RebuildTemplateParamsInCurrentInstantiation(
TemplateParameterList *Params) {
@@ -9813,7 +9865,7 @@ bool Sema::RebuildTemplateParamsInCurrentInstantiation(
return false;
}
-/// \brief Produces a formatted string that describes the binding of
+/// Produces a formatted string that describes the binding of
/// template parameters to template arguments.
std::string
Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params,
@@ -9891,7 +9943,7 @@ bool Sema::IsInsideALocalClassWithinATemplateFunction() {
}
namespace {
-/// \brief Walk the path from which a declaration was instantiated, and check
+/// Walk the path from which a declaration was instantiated, and check
/// that every explicit specialization along that path is visible. This enforces
/// C++ [temp.expl.spec]/6:
///
@@ -10027,7 +10079,7 @@ void Sema::checkSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec) {
ExplicitSpecializationVisibilityChecker(*this, Loc).check(Spec);
}
-/// \brief Check whether a template partial specialization that we've discovered
+/// Check whether a template partial specialization that we've discovered
/// is hidden, and produce suitable diagnostics if so.
void Sema::checkPartialSpecializationVisibility(SourceLocation Loc,
NamedDecl *Spec) {
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
index d09cf9933ecf..633b2837e1fe 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -1,60 +1,97 @@
-//===------- SemaTemplateDeduction.cpp - Template Argument Deduction ------===/
+//===- SemaTemplateDeduction.cpp - Template Argument Deduction ------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
-//===----------------------------------------------------------------------===/
//
-// This file implements C++ template argument deduction.
+//===----------------------------------------------------------------------===//
//
-//===----------------------------------------------------------------------===/
+// This file implements C++ template argument deduction.
+//
+//===----------------------------------------------------------------------===//
#include "clang/Sema/TemplateDeduction.h"
#include "TreeTransform.h"
+#include "TypeLocBuilder.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
-#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclAccessPair.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
-#include "clang/AST/StmtVisitor.h"
-#include "clang/AST/TypeOrdering.h"
-#include "clang/Sema/DeclSpec.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/TemplateName.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/AST/UnresolvedSet.h"
+#include "clang/Basic/AddressSpaces.h"
+#include "clang/Basic/ExceptionSpecificationType.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Sema/Ownership.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/Template.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallBitVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
+#include <cassert>
+#include <tuple>
+#include <utility>
namespace clang {
- using namespace sema;
- /// \brief Various flags that control template argument deduction.
+
+ /// Various flags that control template argument deduction.
///
/// These flags can be bitwise-OR'd together.
enum TemplateDeductionFlags {
- /// \brief No template argument deduction flags, which indicates the
+ /// No template argument deduction flags, which indicates the
/// strictest results for template argument deduction (as used for, e.g.,
/// matching class template partial specializations).
TDF_None = 0,
- /// \brief Within template argument deduction from a function call, we are
+
+ /// Within template argument deduction from a function call, we are
/// matching with a parameter type for which the original parameter was
/// a reference.
TDF_ParamWithReferenceType = 0x1,
- /// \brief Within template argument deduction from a function call, we
+
+ /// Within template argument deduction from a function call, we
/// are matching in a case where we ignore cv-qualifiers.
TDF_IgnoreQualifiers = 0x02,
- /// \brief Within template argument deduction from a function call,
+
+ /// Within template argument deduction from a function call,
/// we are matching in a case where we can perform template argument
/// deduction from a template-id of a derived class of the argument type.
TDF_DerivedClass = 0x04,
- /// \brief Allow non-dependent types to differ, e.g., when performing
+
+ /// Allow non-dependent types to differ, e.g., when performing
/// template argument deduction from a function call where conversions
/// may apply.
TDF_SkipNonDependent = 0x08,
- /// \brief Whether we are performing template argument deduction for
+
+ /// Whether we are performing template argument deduction for
/// parameters and arguments in a top-level template argument
TDF_TopLevelParameterTypeList = 0x10,
- /// \brief Within template argument deduction from overload resolution per
+
+ /// Within template argument deduction from overload resolution per
/// C++ [over.over] allow matching function types that are compatible in
/// terms of noreturn and default calling convention adjustments, or
/// similarly matching a declared template specialization against a
@@ -62,12 +99,18 @@ namespace clang {
/// deduction where the parameter is a function type that can be converted
/// to the argument type.
TDF_AllowCompatibleFunctionType = 0x20,
+
+ /// Within template argument deduction for a conversion function, we are
+ /// matching with an argument type for which the original argument was
+ /// a reference.
+ TDF_ArgWithReferenceType = 0x40,
};
}
using namespace clang;
+using namespace sema;
-/// \brief Compare two APSInts, extending and switching the sign as
+/// Compare two APSInts, extending and switching the sign as
/// necessary to compare their values regardless of underlying type.
static bool hasSameExtendedValue(llvm::APSInt X, llvm::APSInt Y) {
if (Y.getBitWidth() > X.getBitWidth())
@@ -125,14 +168,14 @@ static void MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
bool OnlyDeduced, unsigned Level,
llvm::SmallBitVector &Deduced);
-/// \brief If the given expression is of a form that permits the deduction
+/// If the given expression is of a form that permits the deduction
/// of a non-type template parameter, return the declaration of that
/// non-type template parameter.
static NonTypeTemplateParmDecl *
getDeducedParameterFromExpr(TemplateDeductionInfo &Info, Expr *E) {
// If we are within an alias template, the expression may have undergone
// any number of parameter substitutions already.
- while (1) {
+ while (true) {
if (ImplicitCastExpr *IC = dyn_cast<ImplicitCastExpr>(E))
E = IC->getSubExpr();
else if (SubstNonTypeTemplateParmExpr *Subst =
@@ -150,7 +193,7 @@ getDeducedParameterFromExpr(TemplateDeductionInfo &Info, Expr *E) {
return nullptr;
}
-/// \brief Determine whether two declaration pointers refer to the same
+/// Determine whether two declaration pointers refer to the same
/// declaration.
static bool isSameDeclaration(Decl *X, Decl *Y) {
if (NamedDecl *NX = dyn_cast<NamedDecl>(X))
@@ -161,7 +204,7 @@ static bool isSameDeclaration(Decl *X, Decl *Y) {
return X->getCanonicalDecl() == Y->getCanonicalDecl();
}
-/// \brief Verify that the given, deduced template arguments are compatible.
+/// Verify that the given, deduced template arguments are compatible.
///
/// \returns The deduced template argument, or a NULL template argument if
/// the deduced template arguments were incompatible.
@@ -270,7 +313,7 @@ checkDeducedTemplateArguments(ASTContext &Context,
return Y;
}
- // If we deduced two declarations, make sure they they refer to the
+ // If we deduced two declarations, make sure that they refer to the
// same declaration.
if (Y.getKind() == TemplateArgument::Declaration &&
isSameDeclaration(X.getAsDecl(), Y.getAsDecl()))
@@ -297,7 +340,7 @@ checkDeducedTemplateArguments(ASTContext &Context,
// All other combinations are incompatible.
return DeducedTemplateArgument();
- case TemplateArgument::Pack:
+ case TemplateArgument::Pack: {
if (Y.getKind() != TemplateArgument::Pack ||
X.pack_size() != Y.pack_size())
return DeducedTemplateArgument();
@@ -319,11 +362,12 @@ checkDeducedTemplateArguments(ASTContext &Context,
TemplateArgument::CreatePackCopy(Context, NewPack),
X.wasDeducedFromArrayBound() && Y.wasDeducedFromArrayBound());
}
+ }
llvm_unreachable("Invalid TemplateArgument Kind!");
}
-/// \brief Deduce the value of the given non-type template parameter
+/// Deduce the value of the given non-type template parameter
/// as the given deduced template argument. All non-type template parameter
/// deduction is funneled through here.
static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
@@ -371,7 +415,7 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
/*ArrayBound=*/NewDeduced.wasDeducedFromArrayBound());
}
-/// \brief Deduce the value of the given non-type template parameter
+/// Deduce the value of the given non-type template parameter
/// from the given integral constant.
static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
Sema &S, TemplateParameterList *TemplateParams,
@@ -385,7 +429,7 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
ValueType, Info, Deduced);
}
-/// \brief Deduce the value of the given non-type template parameter
+/// Deduce the value of the given non-type template parameter
/// from the given null pointer template argument type.
static Sema::TemplateDeductionResult DeduceNullPtrTemplateArgument(
Sema &S, TemplateParameterList *TemplateParams,
@@ -402,7 +446,7 @@ static Sema::TemplateDeductionResult DeduceNullPtrTemplateArgument(
Value->getType(), Info, Deduced);
}
-/// \brief Deduce the value of the given non-type template parameter
+/// Deduce the value of the given non-type template parameter
/// from the given type- or value-dependent expression.
///
/// \returns true if deduction succeeded, false otherwise.
@@ -415,7 +459,7 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
Value->getType(), Info, Deduced);
}
-/// \brief Deduce the value of the given non-type template parameter
+/// Deduce the value of the given non-type template parameter
/// from the given declaration.
///
/// \returns true if deduction succeeded, false otherwise.
@@ -475,7 +519,7 @@ DeduceTemplateArguments(Sema &S,
return Sema::TDK_NonDeducedMismatch;
}
-/// \brief Deduce the template arguments by comparing the template parameter
+/// Deduce the template arguments by comparing the template parameter
/// type (which is a template-id) with the template argument type.
///
/// \param S the Sema
@@ -560,7 +604,7 @@ DeduceTemplateArguments(Sema &S,
Deduced, /*NumberOfArgumentsMustMatch=*/true);
}
-/// \brief Determines whether the given type is an opaque type that
+/// Determines whether the given type is an opaque type that
/// might be more qualified when instantiated.
static bool IsPossiblyOpaquelyQualifiedType(QualType T) {
switch (T->getTypeClass()) {
@@ -584,30 +628,7 @@ static bool IsPossiblyOpaquelyQualifiedType(QualType T) {
}
}
-/// \brief Retrieve the depth and index of a template parameter.
-static std::pair<unsigned, unsigned>
-getDepthAndIndex(NamedDecl *ND) {
- if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
- return std::make_pair(TTP->getDepth(), TTP->getIndex());
-
- if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND))
- return std::make_pair(NTTP->getDepth(), NTTP->getIndex());
-
- TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
- return std::make_pair(TTP->getDepth(), TTP->getIndex());
-}
-
-/// \brief Retrieve the depth and index of an unexpanded parameter pack.
-static std::pair<unsigned, unsigned>
-getDepthAndIndex(UnexpandedParameterPack UPP) {
- if (const TemplateTypeParmType *TTP
- = UPP.first.dyn_cast<const TemplateTypeParmType *>())
- return std::make_pair(TTP->getDepth(), TTP->getIndex());
-
- return getDepthAndIndex(UPP.first.get<NamedDecl *>());
-}
-
-/// \brief Helper function to build a TemplateParameter when we don't
+/// Helper function to build a TemplateParameter when we don't
/// know its type statically.
static TemplateParameter makeTemplateParameter(Decl *D) {
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(D))
@@ -618,10 +639,21 @@ static TemplateParameter makeTemplateParameter(Decl *D) {
return TemplateParameter(cast<TemplateTemplateParmDecl>(D));
}
+/// If \p Param is an expanded parameter pack, get the number of expansions.
+static Optional<unsigned> getExpandedPackSize(NamedDecl *Param) {
+ if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param))
+ if (NTTP->isExpandedParameterPack())
+ return NTTP->getNumExpansionTypes();
+
+ if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Param))
+ if (TTP->isExpandedParameterPack())
+ return TTP->getNumExpansionTemplateParameters();
+
+ return None;
+}
+
/// A pack that we're currently deducing.
struct clang::DeducedPack {
- DeducedPack(unsigned Index) : Index(Index), Outer(nullptr) {}
-
// The index of the pack.
unsigned Index;
@@ -636,17 +668,93 @@ struct clang::DeducedPack {
SmallVector<DeducedTemplateArgument, 4> New;
// The outer deduction for this pack, if any.
- DeducedPack *Outer;
+ DeducedPack *Outer = nullptr;
+
+ DeducedPack(unsigned Index) : Index(Index) {}
};
namespace {
+
/// A scope in which we're performing pack deduction.
class PackDeductionScope {
public:
+ /// Prepare to deduce the packs named within Pattern.
PackDeductionScope(Sema &S, TemplateParameterList *TemplateParams,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
TemplateDeductionInfo &Info, TemplateArgument Pattern)
: S(S), TemplateParams(TemplateParams), Deduced(Deduced), Info(Info) {
+ unsigned NumNamedPacks = addPacks(Pattern);
+ finishConstruction(NumNamedPacks);
+ }
+
+ /// Prepare to directly deduce arguments of the parameter with index \p Index.
+ PackDeductionScope(Sema &S, TemplateParameterList *TemplateParams,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ TemplateDeductionInfo &Info, unsigned Index)
+ : S(S), TemplateParams(TemplateParams), Deduced(Deduced), Info(Info) {
+ addPack(Index);
+ finishConstruction(1);
+ }
+
+private:
+ void addPack(unsigned Index) {
+ // Save the deduced template argument for the parameter pack expanded
+ // by this pack expansion, then clear out the deduction.
+ DeducedPack Pack(Index);
+ Pack.Saved = Deduced[Index];
+ Deduced[Index] = TemplateArgument();
+
+ // FIXME: What if we encounter multiple packs with different numbers of
+ // pre-expanded expansions? (This should already have been diagnosed
+ // during substitution.)
+ if (Optional<unsigned> ExpandedPackExpansions =
+ getExpandedPackSize(TemplateParams->getParam(Index)))
+ FixedNumExpansions = ExpandedPackExpansions;
+
+ Packs.push_back(Pack);
+ }
+
+ unsigned addPacks(TemplateArgument Pattern) {
+ // Compute the set of template parameter indices that correspond to
+ // parameter packs expanded by the pack expansion.
+ llvm::SmallBitVector SawIndices(TemplateParams->size());
+
+ auto AddPack = [&](unsigned Index) {
+ if (SawIndices[Index])
+ return;
+ SawIndices[Index] = true;
+ addPack(Index);
+ };
+
+ // First look for unexpanded packs in the pattern.
+ SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+ for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
+ unsigned Depth, Index;
+ std::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
+ if (Depth == Info.getDeducedDepth())
+ AddPack(Index);
+ }
+ assert(!Packs.empty() && "Pack expansion without unexpanded packs?");
+
+ unsigned NumNamedPacks = Packs.size();
+
+ // We can also have deduced template parameters that do not actually
+ // appear in the pattern, but can be deduced by it (the type of a non-type
+ // template parameter pack, in particular). These won't have prevented us
+ // from partially expanding the pack.
+ llvm::SmallBitVector Used(TemplateParams->size());
+ MarkUsedTemplateParameters(S.Context, Pattern, /*OnlyDeduced*/true,
+ Info.getDeducedDepth(), Used);
+ for (int Index = Used.find_first(); Index != -1;
+ Index = Used.find_next(Index))
+ if (TemplateParams->getParam(Index)->isParameterPack())
+ AddPack(Index);
+
+ return NumNamedPacks;
+ }
+
+ void finishConstruction(unsigned NumNamedPacks) {
// Dig out the partially-substituted pack, if there is one.
const TemplateArgument *PartialPackArgs = nullptr;
unsigned NumPartialPackArgs = 0;
@@ -656,60 +764,29 @@ public:
&PartialPackArgs, &NumPartialPackArgs))
PartialPackDepthIndex = getDepthAndIndex(Partial);
- // Compute the set of template parameter indices that correspond to
- // parameter packs expanded by the pack expansion.
- {
- llvm::SmallBitVector SawIndices(TemplateParams->size());
-
- auto AddPack = [&](unsigned Index) {
- if (SawIndices[Index])
- return;
- SawIndices[Index] = true;
-
- // Save the deduced template argument for the parameter pack expanded
- // by this pack expansion, then clear out the deduction.
- DeducedPack Pack(Index);
- Pack.Saved = Deduced[Index];
- Deduced[Index] = TemplateArgument();
-
- Packs.push_back(Pack);
- };
-
- // First look for unexpanded packs in the pattern.
- SmallVector<UnexpandedParameterPack, 2> Unexpanded;
- S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
- for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
- unsigned Depth, Index;
- std::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
- if (Depth == Info.getDeducedDepth())
- AddPack(Index);
+ // This pack expansion will have been partially or fully expanded if
+ // it only names explicitly-specified parameter packs (including the
+ // partially-substituted one, if any).
+ bool IsExpanded = true;
+ for (unsigned I = 0; I != NumNamedPacks; ++I) {
+ if (Packs[I].Index >= Info.getNumExplicitArgs()) {
+ IsExpanded = false;
+ IsPartiallyExpanded = false;
+ break;
+ }
+ if (PartialPackDepthIndex ==
+ std::make_pair(Info.getDeducedDepth(), Packs[I].Index)) {
+ IsPartiallyExpanded = true;
}
- assert(!Packs.empty() && "Pack expansion without unexpanded packs?");
-
- // This pack expansion will have been partially expanded iff the only
- // unexpanded parameter pack within it is the partially-substituted pack.
- IsPartiallyExpanded =
- Packs.size() == 1 &&
- PartialPackDepthIndex ==
- std::make_pair(Info.getDeducedDepth(), Packs.front().Index);
-
- // Skip over the pack elements that were expanded into separate arguments.
- if (IsPartiallyExpanded)
- PackElements += NumPartialPackArgs;
-
- // We can also have deduced template parameters that do not actually
- // appear in the pattern, but can be deduced by it (the type of a non-type
- // template parameter pack, in particular). These won't have prevented us
- // from partially expanding the pack.
- llvm::SmallBitVector Used(TemplateParams->size());
- MarkUsedTemplateParameters(S.Context, Pattern, /*OnlyDeduced*/true,
- Info.getDeducedDepth(), Used);
- for (int Index = Used.find_first(); Index != -1;
- Index = Used.find_next(Index))
- if (TemplateParams->getParam(Index)->isParameterPack())
- AddPack(Index);
}
+ // Skip over the pack elements that were expanded into separate arguments.
+ // If we partially expanded, this is the number of partial arguments.
+ if (IsPartiallyExpanded)
+ PackElements += NumPartialPackArgs;
+ else if (IsExpanded)
+ PackElements += *FixedNumExpansions;
+
for (auto &Pack : Packs) {
if (Info.PendingDeducedPacks.size() > Pack.Index)
Pack.Outer = Info.PendingDeducedPacks[Pack.Index];
@@ -728,12 +805,13 @@ public:
// FIXME: If we could represent a "depth i, index j, pack elem k"
// parameter, we could substitute the partially-substituted pack
// everywhere and avoid this.
- if (Pack.New.size() > PackElements)
+ if (!IsPartiallyExpanded)
Deduced[Pack.Index] = Pack.New[PackElements];
}
}
}
+public:
~PackDeductionScope() {
for (auto &Pack : Packs)
Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
@@ -743,6 +821,18 @@ public:
/// sequence of (prior) function parameters / template arguments.
bool isPartiallyExpanded() { return IsPartiallyExpanded; }
+ /// Determine whether this pack expansion scope has a known, fixed arity.
+ /// This happens if it involves a pack from an outer template that has
+ /// (notionally) already been expanded.
+ bool hasFixedArity() { return FixedNumExpansions.hasValue(); }
+
+ /// Determine whether the next element of the argument is still part of this
+ /// pack. This is the case unless the pack is already expanded to a fixed
+ /// length.
+ bool hasNextElement() {
+ return !FixedNumExpansions || *FixedNumExpansions > PackElements;
+ }
+
/// Move to deducing the next element in each pack that is being deduced.
void nextPackElement() {
// Capture the deduced template arguments for each parameter pack expanded
@@ -765,16 +855,24 @@ public:
++PackElements;
}
- /// \brief Finish template argument deduction for a set of argument packs,
+ /// Finish template argument deduction for a set of argument packs,
/// producing the argument packs and checking for consistency with prior
/// deductions.
- Sema::TemplateDeductionResult finish() {
+ Sema::TemplateDeductionResult
+ finish(bool TreatNoDeductionsAsNonDeduced = true) {
// Build argument packs for each of the parameter packs expanded by this
// pack expansion.
for (auto &Pack : Packs) {
// Put back the old value for this pack.
Deduced[Pack.Index] = Pack.Saved;
+ // If we are deducing the size of this pack even if we didn't deduce any
+ // values for it, then make sure we build a pack of the right size.
+ // FIXME: Should we always deduce the size, even if the pack appears in
+ // a non-deduced context?
+ if (!TreatNoDeductionsAsNonDeduced)
+ Pack.New.resize(PackElements);
+
// Build or find a new value for this pack.
DeducedTemplateArgument NewPack;
if (PackElements && Pack.New.empty()) {
@@ -830,14 +928,24 @@ public:
Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
}
+ NamedDecl *Param = TemplateParams->getParam(Pack.Index);
if (Result.isNull()) {
- Info.Param =
- makeTemplateParameter(TemplateParams->getParam(Pack.Index));
+ Info.Param = makeTemplateParameter(Param);
Info.FirstArg = OldPack;
Info.SecondArg = NewPack;
return Sema::TDK_Inconsistent;
}
+ // If we have a pre-expanded pack and we didn't deduce enough elements
+ // for it, fail deduction.
+ if (Optional<unsigned> Expansions = getExpandedPackSize(Param)) {
+ if (*Expansions != PackElements) {
+ Info.Param = makeTemplateParameter(Param);
+ Info.FirstArg = Result;
+ return Sema::TDK_IncompletePack;
+ }
+ }
+
*Loc = Result;
}
@@ -851,12 +959,15 @@ private:
TemplateDeductionInfo &Info;
unsigned PackElements = 0;
bool IsPartiallyExpanded = false;
+ /// The number of expansions, if we have a fully-expanded pack in this scope.
+ Optional<unsigned> FixedNumExpansions;
SmallVector<DeducedPack, 2> Packs;
};
+
} // namespace
-/// \brief Deduce the template arguments by comparing the list of parameter
+/// Deduce the template arguments by comparing the list of parameter
/// types to the list of argument types, as in the parameter-type-lists of
/// function types (C++ [temp.deduct.type]p10).
///
@@ -895,12 +1006,6 @@ DeduceTemplateArguments(Sema &S,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
unsigned TDF,
bool PartialOrdering = false) {
- // Fast-path check to see if we have too many/too few arguments.
- if (NumParams != NumArgs &&
- !(NumParams && isa<PackExpansionType>(Params[NumParams - 1])) &&
- !(NumArgs && isa<PackExpansionType>(Args[NumArgs - 1])))
- return Sema::TDK_MiscellaneousDeductionFailure;
-
// C++0x [temp.deduct.type]p10:
// Similarly, if P has a form that contains (T), then each parameter type
// Pi of the respective parameter-type- list of P is compared with the
@@ -937,13 +1042,6 @@ DeduceTemplateArguments(Sema &S,
continue;
}
- // C++0x [temp.deduct.type]p5:
- // The non-deduced contexts are:
- // - A function parameter pack that does not occur at the end of the
- // parameter-declaration-clause.
- if (ParamIdx + 1 < NumParams)
- return Sema::TDK_Success;
-
// C++0x [temp.deduct.type]p10:
// If the parameter-declaration corresponding to Pi is a function
// parameter pack, then the type of its declarator- id is compared with
@@ -954,15 +1052,43 @@ DeduceTemplateArguments(Sema &S,
QualType Pattern = Expansion->getPattern();
PackDeductionScope PackScope(S, TemplateParams, Deduced, Info, Pattern);
- for (; ArgIdx < NumArgs; ++ArgIdx) {
- // Deduce template arguments from the pattern.
- if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, Pattern,
- Args[ArgIdx], Info, Deduced,
- TDF, PartialOrdering))
- return Result;
+ // A pack scope with fixed arity is not really a pack any more, so is not
+ // a non-deduced context.
+ if (ParamIdx + 1 == NumParams || PackScope.hasFixedArity()) {
+ for (; ArgIdx < NumArgs && PackScope.hasNextElement(); ++ArgIdx) {
+ // Deduce template arguments from the pattern.
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, Pattern,
+ Args[ArgIdx], Info, Deduced,
+ TDF, PartialOrdering))
+ return Result;
- PackScope.nextPackElement();
+ PackScope.nextPackElement();
+ }
+ } else {
+ // C++0x [temp.deduct.type]p5:
+ // The non-deduced contexts are:
+ // - A function parameter pack that does not occur at the end of the
+ // parameter-declaration-clause.
+ //
+ // FIXME: There is no wording to say what we should do in this case. We
+ // choose to resolve this by applying the same rule that is applied for a
+ // function call: that is, deduce all contained packs to their
+ // explicitly-specified values (or to <> if there is no such value).
+ //
+ // This is seemingly-arbitrarily different from the case of a template-id
+ // with a non-trailing pack-expansion in its arguments, which renders the
+ // entire template-argument-list a non-deduced context.
+
+ // If the parameter type contains an explicitly-specified pack that we
+ // could not expand, skip the number of parameters notionally created
+ // by the expansion.
+ Optional<unsigned> NumExpansions = Expansion->getNumExpansions();
+ if (NumExpansions && !PackScope.isPartiallyExpanded()) {
+ for (unsigned I = 0; I != *NumExpansions && ArgIdx < NumArgs;
+ ++I, ++ArgIdx)
+ PackScope.nextPackElement();
+ }
}
// Build argument packs for each of the parameter packs expanded by this
@@ -978,8 +1104,10 @@ DeduceTemplateArguments(Sema &S,
return Sema::TDK_Success;
}
-/// \brief Determine whether the parameter has qualifiers that are either
-/// inconsistent with or a superset of the argument's qualifiers.
+/// Determine whether the parameter has qualifiers that the argument
+/// lacks. Put another way, determine whether there is no way to add
+/// a deduced set of qualifiers to the ParamType that would result in
+/// its qualifiers matching those of the ArgType.
static bool hasInconsistentOrSupersetQualifiersOf(QualType ParamType,
QualType ArgType) {
Qualifiers ParamQs = ParamType.getQualifiers();
@@ -1003,13 +1131,11 @@ static bool hasInconsistentOrSupersetQualifiersOf(QualType ParamType,
ParamQs.hasObjCLifetime())
return true;
- // CVR qualifier superset.
- return (ParamQs.getCVRQualifiers() != ArgQs.getCVRQualifiers()) &&
- ((ParamQs.getCVRQualifiers() | ArgQs.getCVRQualifiers())
- == ParamQs.getCVRQualifiers());
+ // CVR qualifiers inconsistent or a superset.
+ return (ParamQs.getCVRQualifiers() & ~ArgQs.getCVRQualifiers()) != 0;
}
-/// \brief Compare types for equality with respect to possibly compatible
+/// Compare types for equality with respect to possibly compatible
/// function types (noreturn adjustment, implicit calling conventions). If any
/// of parameter and argument is not a function, just perform type comparison.
///
@@ -1061,7 +1187,7 @@ static bool isForwardingReference(QualType Param, unsigned FirstInnerIndex) {
return false;
}
-/// \brief Deduce the template arguments by comparing the parameter type and
+/// Deduce the template arguments by comparing the parameter type and
/// the argument type (C++ [temp.deduct.type]).
///
/// \param S the semantic analysis object within which we are deducing
@@ -1232,6 +1358,12 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
return Sema::TDK_Underqualified;
}
+ // Do not match a function type with a cv-qualified type.
+ // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1584
+ if (Arg->isFunctionType() && Param.hasQualifiers()) {
+ return Sema::TDK_NonDeducedMismatch;
+ }
+
assert(TemplateTypeParm->getDepth() == Info.getDeducedDepth() &&
"saw template type parameter with wrong depth");
assert(Arg != S.Context.OverloadTy && "Unresolved overloaded function");
@@ -1307,6 +1439,18 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
if (TDF & TDF_ParamWithReferenceType) {
if (hasInconsistentOrSupersetQualifiersOf(Param, Arg))
return Sema::TDK_NonDeducedMismatch;
+ } else if (TDF & TDF_ArgWithReferenceType) {
+ // C++ [temp.deduct.conv]p4:
+ // If the original A is a reference type, A can be more cv-qualified
+ // than the deduced A
+ if (!Arg.getQualifiers().compatiblyIncludes(Param.getQualifiers()))
+ return Sema::TDK_NonDeducedMismatch;
+
+ // Strip out all extra qualifiers from the argument to figure out the
+ // type we're converting to, prior to the qualification conversion.
+ Qualifiers Quals;
+ Arg = S.Context.getUnqualifiedArrayType(Arg, Quals);
+ Arg = S.Context.getQualifiedType(Arg, Param.getQualifiers());
} else if (!IsPossiblyOpaquelyQualifiedType(Param)) {
if (Param.getCVRQualifiers() != Arg.getCVRQualifiers())
return Sema::TDK_NonDeducedMismatch;
@@ -1357,7 +1501,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
case Type::Enum:
case Type::ObjCObject:
case Type::ObjCInterface:
- case Type::ObjCObjectPointer: {
+ case Type::ObjCObjectPointer:
if (TDF & TDF_SkipNonDependent)
return Sema::TDK_Success;
@@ -1367,7 +1511,6 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
}
return Param == Arg? Sema::TDK_Success : Sema::TDK_NonDeducedMismatch;
- }
// _Complex T [placeholder extension]
case Type::Complex:
@@ -1561,7 +1704,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
"saw non-type template parameter with wrong depth");
llvm::APSInt Noexcept(1);
- switch (FunctionProtoArg->canThrow(S.Context)) {
+ switch (FunctionProtoArg->canThrow()) {
case CT_Cannot:
Noexcept = 1;
LLVM_FALLTHROUGH;
@@ -1582,11 +1725,14 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
}
}
// FIXME: Detect non-deduced exception specification mismatches?
+ //
+ // Careful about [temp.deduct.call] and [temp.deduct.conv], which allow
+ // top-level differences in noexcept-specifications.
return Sema::TDK_Success;
}
- case Type::InjectedClassName: {
+ case Type::InjectedClassName:
// Treat a template's injected-class-name as if the template
// specialization type had been used.
Param = cast<InjectedClassNameType>(Param)
@@ -1594,7 +1740,6 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
assert(isa<TemplateSpecializationType>(Param) &&
"injected class name is not a template specialization type");
LLVM_FALLTHROUGH;
- }
// template-name<T> (where template-name refers to a class template)
// template-name<i>
@@ -1792,6 +1937,54 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
return Sema::TDK_NonDeducedMismatch;
}
+ case Type::DependentVector: {
+ const auto *VectorParam = cast<DependentVectorType>(Param);
+
+ if (const auto *VectorArg = dyn_cast<VectorType>(Arg)) {
+ // Perform deduction on the element types.
+ if (Sema::TemplateDeductionResult Result =
+ DeduceTemplateArgumentsByTypeMatch(
+ S, TemplateParams, VectorParam->getElementType(),
+ VectorArg->getElementType(), Info, Deduced, TDF))
+ return Result;
+
+ // Perform deduction on the vector size, if we can.
+ NonTypeTemplateParmDecl *NTTP =
+ getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr());
+ if (!NTTP)
+ return Sema::TDK_Success;
+
+ llvm::APSInt ArgSize(S.Context.getTypeSize(S.Context.IntTy), false);
+ ArgSize = VectorArg->getNumElements();
+ // Note that we use the "array bound" rules here; just like in that
+ // case, we don't have any particular type for the vector size, but
+ // we can provide one if necessary.
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP, ArgSize,
+ S.Context.UnsignedIntTy, true,
+ Info, Deduced);
+ }
+
+ if (const auto *VectorArg = dyn_cast<DependentVectorType>(Arg)) {
+ // Perform deduction on the element types.
+ if (Sema::TemplateDeductionResult Result =
+ DeduceTemplateArgumentsByTypeMatch(
+ S, TemplateParams, VectorParam->getElementType(),
+ VectorArg->getElementType(), Info, Deduced, TDF))
+ return Result;
+
+ // Perform deduction on the vector size, if we can.
+ NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(
+ Info, VectorParam->getSizeExpr());
+ if (!NTTP)
+ return Sema::TDK_Success;
+
+ return DeduceNonTypeTemplateArgument(
+ S, TemplateParams, NTTP, VectorArg->getSizeExpr(), Info, Deduced);
+ }
+
+ return Sema::TDK_NonDeducedMismatch;
+ }
+
// (clang extension)
//
// T __attribute__(((ext_vector_type(N))))
@@ -1996,7 +2189,7 @@ DeduceTemplateArguments(Sema &S,
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
- case TemplateArgument::Expression: {
+ case TemplateArgument::Expression:
if (NonTypeTemplateParmDecl *NTTP
= getDeducedParameterFromExpr(Info, Param.getAsExpr())) {
if (Arg.getKind() == TemplateArgument::Integral)
@@ -2025,7 +2218,7 @@ DeduceTemplateArguments(Sema &S,
// Can't deduce anything, but that's okay.
return Sema::TDK_Success;
- }
+
case TemplateArgument::Pack:
llvm_unreachable("Argument packs should be expanded by the caller!");
}
@@ -2033,7 +2226,7 @@ DeduceTemplateArguments(Sema &S,
llvm_unreachable("Invalid TemplateArgument Kind!");
}
-/// \brief Determine whether there is a template argument to be used for
+/// Determine whether there is a template argument to be used for
/// deduction.
///
/// This routine "expands" argument packs in-place, overriding its input
@@ -2056,7 +2249,7 @@ static bool hasTemplateArgumentForDeduction(ArrayRef<TemplateArgument> &Args,
return ArgIdx < Args.size();
}
-/// \brief Determine whether the given set of template arguments has a pack
+/// Determine whether the given set of template arguments has a pack
/// expansion that is not the last template argument.
static bool hasPackExpansionBeforeEnd(ArrayRef<TemplateArgument> Args) {
bool FoundPackExpansion = false;
@@ -2067,6 +2260,8 @@ static bool hasPackExpansionBeforeEnd(ArrayRef<TemplateArgument> Args) {
if (A.getKind() == TemplateArgument::Pack)
return hasPackExpansionBeforeEnd(A.pack_elements());
+ // FIXME: If this is a fixed-arity pack expansion from an outer level of
+ // templates, it should not be treated as a pack expansion.
if (A.isPackExpansion())
FoundPackExpansion = true;
}
@@ -2130,17 +2325,15 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
// template parameter packs expanded by Pi.
TemplateArgument Pattern = Params[ParamIdx].getPackExpansionPattern();
- // FIXME: If there are no remaining arguments, we can bail out early
- // and set any deduced parameter packs to an empty argument pack.
- // The latter part of this is a (minor) correctness issue.
-
// Prepare to deduce the packs within the pattern.
PackDeductionScope PackScope(S, TemplateParams, Deduced, Info, Pattern);
// Keep track of the deduced template arguments for each parameter pack
// expanded by this pack expansion (the outer index) and for each
// template argument (the inner SmallVectors).
- for (; hasTemplateArgumentForDeduction(Args, ArgIdx); ++ArgIdx) {
+ for (; hasTemplateArgumentForDeduction(Args, ArgIdx) &&
+ PackScope.hasNextElement();
+ ++ArgIdx) {
// Deduce template arguments from the pattern.
if (Sema::TemplateDeductionResult Result
= DeduceTemplateArguments(S, TemplateParams, Pattern, Args[ArgIdx],
@@ -2171,7 +2364,7 @@ DeduceTemplateArguments(Sema &S,
/*NumberOfArgumentsMustMatch*/false);
}
-/// \brief Determine whether two template arguments are the same.
+/// Determine whether two template arguments are the same.
static bool isSameTemplateArg(ASTContext &Context,
TemplateArgument X,
const TemplateArgument &Y,
@@ -2232,7 +2425,7 @@ static bool isSameTemplateArg(ASTContext &Context,
llvm_unreachable("Invalid TemplateArgument Kind!");
}
-/// \brief Allocate a TemplateArgumentLoc where all locations have
+/// Allocate a TemplateArgumentLoc where all locations have
/// been initialized to the given location.
///
/// \param Arg The template argument we are producing template argument
@@ -2307,8 +2500,7 @@ Sema::getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
llvm_unreachable("Invalid TemplateArgument Kind!");
}
-
-/// \brief Convert the given deduced template argument and add it to the set of
+/// Convert the given deduced template argument and add it to the set of
/// fully-converted template arguments.
static bool
ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
@@ -2413,6 +2605,16 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments(
for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
NamedDecl *Param = TemplateParams->getParam(I);
+ // C++0x [temp.arg.explicit]p3:
+ // A trailing template parameter pack (14.5.3) not otherwise deduced will
+ // be deduced to an empty sequence of template arguments.
+ // FIXME: Where did the word "trailing" come from?
+ if (Deduced[I].isNull() && Param->isTemplateParameterPack()) {
+ if (auto Result = PackDeductionScope(S, TemplateParams, Deduced, Info, I)
+ .finish(/*TreatNoDeductionsAsNonDeduced*/false))
+ return Result;
+ }
+
if (!Deduced[I].isNull()) {
if (I < NumAlreadyConverted) {
// We may have had explicitly-specified template arguments for a
@@ -2447,40 +2649,6 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments(
continue;
}
- // C++0x [temp.arg.explicit]p3:
- // A trailing template parameter pack (14.5.3) not otherwise deduced will
- // be deduced to an empty sequence of template arguments.
- // FIXME: Where did the word "trailing" come from?
- if (Param->isTemplateParameterPack()) {
- // We may have had explicitly-specified template arguments for this
- // template parameter pack. If so, our empty deduction extends the
- // explicitly-specified set (C++0x [temp.arg.explicit]p9).
- const TemplateArgument *ExplicitArgs;
- unsigned NumExplicitArgs;
- if (CurrentInstantiationScope &&
- CurrentInstantiationScope->getPartiallySubstitutedPack(
- &ExplicitArgs, &NumExplicitArgs) == Param) {
- Builder.push_back(TemplateArgument(
- llvm::makeArrayRef(ExplicitArgs, NumExplicitArgs)));
-
- // Forget the partially-substituted pack; its substitution is now
- // complete.
- CurrentInstantiationScope->ResetPartiallySubstitutedPack();
- } else {
- // Go through the motions of checking the empty argument pack against
- // the parameter pack.
- DeducedTemplateArgument DeducedPack(TemplateArgument::getEmptyPack());
- if (ConvertDeducedTemplateArgument(S, Param, DeducedPack, Template,
- Info, IsDeduced, Builder)) {
- Info.Param = makeTemplateParameter(Param);
- // FIXME: These template arguments are temporary. Free them!
- Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder));
- return Sema::TDK_SubstitutionFailure;
- }
- }
- continue;
- }
-
// Substitute into the default template argument, if available.
bool HasDefaultArg = false;
TemplateDecl *TD = dyn_cast<TemplateDecl>(Template);
@@ -2663,7 +2831,7 @@ static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction(
}
-/// \brief Perform template argument deduction to determine whether
+/// Perform template argument deduction to determine whether
/// the given template arguments match the given class template
/// partial specialization per C++ [temp.class.spec.match].
Sema::TemplateDeductionResult
@@ -2706,7 +2874,7 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
*this, Partial, /*PartialOrdering=*/false, TemplateArgs, Deduced, Info);
}
-/// \brief Perform template argument deduction to determine whether
+/// Perform template argument deduction to determine whether
/// the given template arguments match the given variable template
/// partial specialization per C++ [temp.class.spec.match].
Sema::TemplateDeductionResult
@@ -2747,7 +2915,7 @@ Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
*this, Partial, /*PartialOrdering=*/false, TemplateArgs, Deduced, Info);
}
-/// \brief Determine whether the given type T is a simple-template-id type.
+/// Determine whether the given type T is a simple-template-id type.
static bool isSimpleTemplateIdType(QualType T) {
if (const TemplateSpecializationType *Spec
= T->getAs<TemplateSpecializationType>())
@@ -2767,7 +2935,7 @@ static bool isSimpleTemplateIdType(QualType T) {
return false;
}
-/// \brief Substitute the explicitly-provided template arguments into the
+/// Substitute the explicitly-provided template arguments into the
/// given function template according to C++ [temp.arg.explicit].
///
/// \param FunctionTemplate the function template into which the explicit
@@ -2841,7 +3009,7 @@ Sema::SubstituteExplicitTemplateArguments(
Trap.hasErrorOccurred()) {
unsigned Index = Builder.size();
if (Index >= TemplateParams->size())
- Index = TemplateParams->size() - 1;
+ return TDK_SubstitutionFailure;
Info.Param = makeTemplateParameter(TemplateParams->getParam(Index));
return TDK_InvalidExplicitArguments;
}
@@ -2850,7 +3018,7 @@ Sema::SubstituteExplicitTemplateArguments(
// template arguments.
TemplateArgumentList *ExplicitArgumentList
= TemplateArgumentList::CreateCopy(Context, Builder);
- Info.reset(ExplicitArgumentList);
+ Info.setExplicitArgs(ExplicitArgumentList);
// Template argument deduction and the final substitution should be
// done in the context of the templated declaration. Explicit
@@ -2862,14 +3030,19 @@ Sema::SubstituteExplicitTemplateArguments(
// note that the template argument pack is partially substituted and record
// the explicit template arguments. They'll be used as part of deduction
// for this template parameter pack.
- for (unsigned I = 0, N = Builder.size(); I != N; ++I) {
- const TemplateArgument &Arg = Builder[I];
+ unsigned PartiallySubstitutedPackIndex = -1u;
+ if (!Builder.empty()) {
+ const TemplateArgument &Arg = Builder.back();
if (Arg.getKind() == TemplateArgument::Pack) {
- CurrentInstantiationScope->SetPartiallySubstitutedPack(
- TemplateParams->getParam(I),
- Arg.pack_begin(),
- Arg.pack_size());
- break;
+ auto *Param = TemplateParams->getParam(Builder.size() - 1);
+ // If this is a fully-saturated fixed-size pack, it should be
+ // fully-substituted, not partially-substituted.
+ Optional<unsigned> Expansions = getExpandedPackSize(Param);
+ if (!Expansions || Arg.pack_size() < *Expansions) {
+ PartiallySubstitutedPackIndex = Builder.size() - 1;
+ CurrentInstantiationScope->SetPartiallySubstitutedPack(
+ Param, Arg.pack_begin(), Arg.pack_size());
+ }
}
}
@@ -2959,13 +3132,13 @@ Sema::SubstituteExplicitTemplateArguments(
// case, the empty template argument list <> itself may also be omitted.
//
// Take all of the explicitly-specified arguments and put them into
- // the set of deduced template arguments. Explicitly-specified
- // parameter packs, however, will be set to NULL since the deduction
- // mechanisms handle explicitly-specified argument packs directly.
+ // the set of deduced template arguments. The partially-substituted
+ // parameter pack, however, will be set to NULL since the deduction
+ // mechanism handles the partially-substituted argument pack directly.
Deduced.reserve(TemplateParams->size());
for (unsigned I = 0, N = ExplicitArgumentList->size(); I != N; ++I) {
const TemplateArgument &Arg = ExplicitArgumentList->get(I);
- if (Arg.getKind() == TemplateArgument::Pack)
+ if (I == PartiallySubstitutedPackIndex)
Deduced.push_back(DeducedTemplateArgument());
else
Deduced.push_back(Arg);
@@ -2974,7 +3147,7 @@ Sema::SubstituteExplicitTemplateArguments(
return TDK_Success;
}
-/// \brief Check whether the deduced argument type for a call to a function
+/// Check whether the deduced argument type for a call to a function
/// template matches the actual argument type per C++ [temp.deduct.call]p4.
static Sema::TemplateDeductionResult
CheckOriginalCallArgDeduction(Sema &S, TemplateDeductionInfo &Info,
@@ -3084,7 +3257,7 @@ CheckOriginalCallArgDeduction(Sema &S, TemplateDeductionInfo &Info,
return Sema::TDK_Success;
if (A->isRecordType() && isSimpleTemplateIdType(OriginalParamType) &&
- S.IsDerivedFrom(SourceLocation(), A, DeducedA))
+ S.IsDerivedFrom(Info.getLocation(), A, DeducedA))
return Sema::TDK_Success;
return Failed();
@@ -3120,7 +3293,7 @@ static unsigned getPackIndexForParam(Sema &S,
llvm_unreachable("parameter index would not be produced from template");
}
-/// \brief Finish template argument deduction for a function template,
+/// Finish template argument deduction for a function template,
/// checking the deduced template arguments for completeness and forming
/// the function template specialization.
///
@@ -3271,13 +3444,14 @@ static QualType GetTypeOfFunction(Sema &S, const OverloadExpr::FindResult &R,
// We may need to deduce the return type of the function now.
if (S.getLangOpts().CPlusPlus14 && Fn->getReturnType()->isUndeducedType() &&
S.DeduceReturnType(Fn, R.Expression->getExprLoc(), /*Diagnose*/ false))
- return QualType();
+ return {};
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn))
if (Method->isInstance()) {
// An instance method that's referenced in a form that doesn't
// look like a member pointer is just invalid.
- if (!R.HasFormOfMemberPointer) return QualType();
+ if (!R.HasFormOfMemberPointer)
+ return {};
return S.Context.getMemberPointerType(Fn->getType(),
S.Context.getTypeDeclType(Method->getParent()).getTypePtr());
@@ -3326,7 +3500,7 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
S.resolveAddressOfOnlyViableOverloadCandidate(Arg, DAP))
return GetTypeOfFunction(S, R, Viable);
- return QualType();
+ return {};
}
// Gather the explicit template arguments, if any.
@@ -3343,7 +3517,7 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
// function templates, the parameter is treated as a
// non-deduced context.
if (!Ovl->hasExplicitTemplateArgs())
- return QualType();
+ return {};
// Otherwise, see if we can resolve a function type
FunctionDecl *Specialization = nullptr;
@@ -3383,14 +3557,15 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
= DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, ParamType,
ArgType, Info, Deduced, TDF);
if (Result) continue;
- if (!Match.isNull()) return QualType();
+ if (!Match.isNull())
+ return {};
Match = ArgType;
}
return Match;
}
-/// \brief Perform the adjustments to the parameter and argument types
+/// Perform the adjustments to the parameter and argument types
/// described in C++ [temp.deduct.call].
///
/// \returns true if the caller should not attempt to perform any template
@@ -3497,7 +3672,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument(
SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs,
bool DecomposedParam, unsigned ArgIdx, unsigned TDF);
-/// \brief Attempt template argument deduction from an initializer list
+/// Attempt template argument deduction from an initializer list
/// deemed to be an argument in a function call.
static Sema::TemplateDeductionResult DeduceFromInitializerList(
Sema &S, TemplateParameterList *TemplateParams, QualType AdjustedParamType,
@@ -3558,7 +3733,7 @@ static Sema::TemplateDeductionResult DeduceFromInitializerList(
return Sema::TDK_Success;
}
-/// \brief Perform template argument deduction per [temp.deduct.call] for a
+/// Perform template argument deduction per [temp.deduct.call] for a
/// single parameter / argument pair.
static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument(
Sema &S, TemplateParameterList *TemplateParams, unsigned FirstInnerIndex,
@@ -3591,7 +3766,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument(
ArgType, Info, Deduced, TDF);
}
-/// \brief Perform template argument deduction from a function call
+/// Perform template argument deduction from a function call
/// (C++ [temp.deduct.call]).
///
/// \param FunctionTemplate the function template for which we are performing
@@ -3729,8 +3904,9 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
// the length of the explicitly-specified pack if it's expanded by the
// parameter pack and 0 otherwise, and we treat each deduction as a
// non-deduced context.
- if (ParamIdx + 1 == NumParamTypes) {
- for (; ArgIdx < Args.size(); PackScope.nextPackElement(), ++ArgIdx) {
+ if (ParamIdx + 1 == NumParamTypes || PackScope.hasFixedArity()) {
+ for (; ArgIdx < Args.size() && PackScope.hasNextElement();
+ PackScope.nextPackElement(), ++ArgIdx) {
ParamTypesForArgChecking.push_back(ParamPattern);
if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx))
return Result;
@@ -3757,10 +3933,16 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
return Result;
}
+ // Capture the context in which the function call is made. This is the context
+ // that is needed when the accessibility of template arguments is checked.
+ DeclContext *CallingCtx = CurContext;
+
return FinishTemplateArgumentDeduction(
FunctionTemplate, Deduced, NumExplicitlySpecified, Specialization, Info,
- &OriginalCallArgs, PartialOverloading,
- [&]() { return CheckNonDependent(ParamTypesForArgChecking); });
+ &OriginalCallArgs, PartialOverloading, [&, CallingCtx]() {
+ ContextRAII SavedContext(*this, CallingCtx);
+ return CheckNonDependent(ParamTypesForArgChecking);
+ });
}
QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType,
@@ -3802,7 +3984,7 @@ QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType,
ArgFunctionTypeP->getParamTypes(), EPI);
}
-/// \brief Deduce template arguments when taking the address of a function
+/// Deduce template arguments when taking the address of a function
/// template (C++ [temp.deduct.funcaddr]) or matching a specialization to
/// a template.
///
@@ -3944,7 +4126,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
return TDK_Success;
}
-/// \brief Deduce template arguments for a templated conversion
+/// Deduce template arguments for a templated conversion
/// function (C++ [temp.deduct.conv]) and, if successful, produce a
/// conversion function template specialization.
Sema::TemplateDeductionResult
@@ -3973,12 +4155,20 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
// C++0x [temp.deduct.conv]p4:
// [...] If A is a reference type, the type referred to by A is used
// for type deduction.
- if (const ReferenceType *ARef = A->getAs<ReferenceType>())
- A = ARef->getPointeeType().getUnqualifiedType();
+ if (const ReferenceType *ARef = A->getAs<ReferenceType>()) {
+ A = ARef->getPointeeType();
+ // We work around a defect in the standard here: cv-qualifiers are also
+ // removed from P and A in this case, unless P was a reference type. This
+ // seems to mostly match what other compilers are doing.
+ if (!FromType->getAs<ReferenceType>()) {
+ A = A.getUnqualifiedType();
+ P = P.getUnqualifiedType();
+ }
+
// C++ [temp.deduct.conv]p3:
//
// If A is not a reference type:
- else {
+ } else {
assert(!A->isReferenceType() && "Reference types were handled above");
// - If P is an array type, the pointer type produced by the
@@ -4027,7 +4217,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
// cv-qualified than the deduced A (i.e., the type referred to
// by the reference)
if (ToType->isReferenceType())
- TDF |= TDF_ParamWithReferenceType;
+ TDF |= TDF_ArgWithReferenceType;
// - The deduced A can be another pointer or pointer to member
// type that can be converted to A via a qualification
// conversion.
@@ -4054,7 +4244,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
return Result;
}
-/// \brief Deduce template arguments for a function template when there is
+/// Deduce template arguments for a function template when there is
/// nothing to deduce against (C++0x [temp.arg.explicit]p3).
///
/// \param FunctionTemplate the function template for which we are performing
@@ -4089,12 +4279,14 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
}
namespace {
+
/// Substitute the 'auto' specifier or deduced template specialization type
/// specifier within a type for a given replacement type.
class SubstituteDeducedTypeTransform :
public TreeTransform<SubstituteDeducedTypeTransform> {
QualType Replacement;
bool UseTypeSugar;
+
public:
SubstituteDeducedTypeTransform(Sema &SemaRef, QualType Replacement,
bool UseTypeSugar = true)
@@ -4156,7 +4348,8 @@ namespace {
return TransformType(TLB, TL);
}
};
-}
+
+} // namespace
Sema::DeduceAutoResult
Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *&Init, QualType &Result,
@@ -4190,7 +4383,7 @@ static bool diagnoseAutoDeductionFailure(Sema &S,
}
}
-/// \brief Deduce the type for an auto type-specifier (C++11 [dcl.spec.auto]p6)
+/// Deduce the type for an auto type-specifier (C++11 [dcl.spec.auto]p6)
///
/// Note that this is done even if the initializer is dependent. (This is
/// necessary to support partial ordering of templates using 'auto'.)
@@ -4449,7 +4642,7 @@ bool Sema::DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
return StillUndeduced;
}
-/// \brief If this is a non-static member function,
+/// If this is a non-static member function,
static void
AddImplicitObjectParameterType(ASTContext &Context,
CXXMethodDecl *Method,
@@ -4471,7 +4664,7 @@ AddImplicitObjectParameterType(ASTContext &Context,
ArgTypes.push_back(ArgTy);
}
-/// \brief Determine whether the function template \p FT1 is at least as
+/// Determine whether the function template \p FT1 is at least as
/// specialized as \p FT2.
static bool isAtLeastAsSpecializedAs(Sema &S,
SourceLocation Loc,
@@ -4622,7 +4815,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
return true;
}
-/// \brief Determine whether this a function template whose parameter-type-list
+/// Determine whether this a function template whose parameter-type-list
/// ends with a function parameter pack.
static bool isVariadicFunctionTemplate(FunctionTemplateDecl *FunTmpl) {
FunctionDecl *Function = FunTmpl->getTemplatedDecl();
@@ -4643,7 +4836,7 @@ static bool isVariadicFunctionTemplate(FunctionTemplateDecl *FunTmpl) {
return true;
}
-/// \brief Returns the more specialized function template according
+/// Returns the more specialized function template according
/// to the rules of function template partial ordering (C++ [temp.func.order]).
///
/// \param FT1 the first function template
@@ -4690,7 +4883,7 @@ Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
return nullptr;
}
-/// \brief Determine if the two templates are equivalent.
+/// Determine if the two templates are equivalent.
static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) {
if (T1 == T2)
return true;
@@ -4701,7 +4894,7 @@ static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) {
return T1->getCanonicalDecl() == T2->getCanonicalDecl();
}
-/// \brief Retrieve the most specialized of the given function template
+/// Retrieve the most specialized of the given function template
/// specializations.
///
/// \param SpecBegin the start iterator of the function template
@@ -4860,7 +5053,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, QualType T1, QualType T2,
return true;
}
-/// \brief Returns the more specialized class template partial specialization
+/// Returns the more specialized class template partial specialization
/// according to the rules of partial ordering of class template partial
/// specializations (C++ [temp.class.order]).
///
@@ -5015,7 +5208,7 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs(
return isAtLeastAsSpecializedAs(*this, PType, AType, AArg, Info);
}
-/// \brief Mark the template parameters that are used by the given
+/// Mark the template parameters that are used by the given
/// expression.
static void
MarkUsedTemplateParameters(ASTContext &Ctx,
@@ -5029,7 +5222,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
// Skip through any implicit casts we added while type-checking, and any
// substitutions performed by template alias expansion.
- while (1) {
+ while (true) {
if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
E = ICE->getSubExpr();
else if (const SubstNonTypeTemplateParmExpr *Subst =
@@ -5059,7 +5252,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
MarkUsedTemplateParameters(Ctx, NTTP->getType(), OnlyDeduced, Depth, Used);
}
-/// \brief Mark the template parameters that are used by the given
+/// Mark the template parameters that are used by the given
/// nested name specifier.
static void
MarkUsedTemplateParameters(ASTContext &Ctx,
@@ -5076,7 +5269,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
OnlyDeduced, Depth, Used);
}
-/// \brief Mark the template parameters that are used by the given
+/// Mark the template parameters that are used by the given
/// template name.
static void
MarkUsedTemplateParameters(ASTContext &Ctx,
@@ -5101,7 +5294,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
Depth, Used);
}
-/// \brief Mark the template parameters that are used by the given
+/// Mark the template parameters that are used by the given
/// type.
static void
MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
@@ -5172,6 +5365,14 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
OnlyDeduced, Depth, Used);
break;
+ case Type::DependentVector: {
+ const auto *VecType = cast<DependentVectorType>(T);
+ MarkUsedTemplateParameters(Ctx, VecType->getElementType(), OnlyDeduced,
+ Depth, Used);
+ MarkUsedTemplateParameters(Ctx, VecType->getSizeExpr(), OnlyDeduced, Depth,
+ Used);
+ break;
+ }
case Type::DependentSizedExtVector: {
const DependentSizedExtVectorType *VecType
= cast<DependentSizedExtVectorType>(T);
@@ -5197,9 +5398,24 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
MarkUsedTemplateParameters(Ctx, Proto->getReturnType(), OnlyDeduced, Depth,
Used);
- for (unsigned I = 0, N = Proto->getNumParams(); I != N; ++I)
- MarkUsedTemplateParameters(Ctx, Proto->getParamType(I), OnlyDeduced,
- Depth, Used);
+ for (unsigned I = 0, N = Proto->getNumParams(); I != N; ++I) {
+ // C++17 [temp.deduct.type]p5:
+ // The non-deduced contexts are: [...]
+ // -- A function parameter pack that does not occur at the end of the
+ // parameter-declaration-list.
+ if (!OnlyDeduced || I + 1 == N ||
+ !Proto->getParamType(I)->getAs<PackExpansionType>()) {
+ MarkUsedTemplateParameters(Ctx, Proto->getParamType(I), OnlyDeduced,
+ Depth, Used);
+ } else {
+ // FIXME: C++17 [temp.deduct.call]p1:
+ // When a function parameter pack appears in a non-deduced context,
+ // the type of that pack is never deduced.
+ //
+ // We should also track a set of "never deduced" parameters, and
+ // subtract that from the list of deduced parameters after marking.
+ }
+ }
if (auto *E = Proto->getNoexceptExpr())
MarkUsedTemplateParameters(Ctx, E, OnlyDeduced, Depth, Used);
break;
@@ -5354,7 +5570,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
}
}
-/// \brief Mark the template parameters that are used by this
+/// Mark the template parameters that are used by this
/// template argument.
static void
MarkUsedTemplateParameters(ASTContext &Ctx,
@@ -5397,7 +5613,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
}
}
-/// \brief Mark which template parameters can be deduced from a given
+/// Mark which template parameters can be deduced from a given
/// template argument list.
///
/// \param TemplateArgs the template argument list from which template
@@ -5423,7 +5639,7 @@ Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
Depth, Used);
}
-/// \brief Marks all of the template parameters that will be deduced by a
+/// Marks all of the template parameters that will be deduced by a
/// call to the given function template.
void Sema::MarkDeducedTemplateParameters(
ASTContext &Ctx, const FunctionTemplateDecl *FunctionTemplate,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
index a48e2466a84d..bc2ee42400b7 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -18,13 +18,14 @@
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
-#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
+#include "clang/Sema/TemplateInstCallback.h"
using namespace clang;
using namespace sema;
@@ -33,7 +34,7 @@ using namespace sema;
// Template Instantiation Support
//===----------------------------------------------------------------------===/
-/// \brief Retrieve the template argument list(s) that should be used to
+/// Retrieve the template argument list(s) that should be used to
/// instantiate the definition of the given declaration.
///
/// \param D the declaration for which we are computing template instantiation
@@ -199,6 +200,10 @@ bool Sema::CodeSynthesisContext::isInstantiationRecord() const {
case DeclaringSpecialMember:
case DefiningSynthesizedFunction:
return false;
+
+ // This function should never be called when Kind's value is Memoization.
+ case Memoization:
+ break;
}
llvm_unreachable("Invalid SynthesisKind!");
@@ -235,6 +240,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
!SemaRef.InstantiatingSpecializations
.insert(std::make_pair(Inst.Entity->getCanonicalDecl(), Inst.Kind))
.second;
+ atTemplateBegin(SemaRef.TemplateInstCallbacks, SemaRef, Inst);
}
}
@@ -394,8 +400,10 @@ void Sema::InstantiatingTemplate::Clear() {
std::make_pair(Active.Entity, Active.Kind));
}
- SemaRef.popCodeSynthesisContext();
+ atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef,
+ SemaRef.CodeSynthesisContexts.back());
+ SemaRef.popCodeSynthesisContext();
Invalid = true;
}
}
@@ -419,7 +427,7 @@ bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
return true;
}
-/// \brief Prints the current instantiation stack through a series of
+/// Prints the current instantiation stack through a series of
/// notes.
void Sema::PrintInstantiationStack() {
// Determine which template instantiations to skip, if any.
@@ -626,7 +634,7 @@ void Sema::PrintInstantiationStack() {
<< cast<CXXRecordDecl>(Active->Entity) << Active->SpecialMember;
break;
- case CodeSynthesisContext::DefiningSynthesizedFunction:
+ case CodeSynthesisContext::DefiningSynthesizedFunction: {
// FIXME: For synthesized members other than special members, produce a note.
auto *MD = dyn_cast<CXXMethodDecl>(Active->Entity);
auto CSM = MD ? getSpecialMember(MD) : CXXInvalid;
@@ -637,6 +645,10 @@ void Sema::PrintInstantiationStack() {
}
break;
}
+
+ case CodeSynthesisContext::Memoization:
+ break;
+ }
}
}
@@ -682,6 +694,9 @@ Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
// This happens in a context unrelated to template instantiation, so
// there is no SFINAE.
return None;
+
+ case CodeSynthesisContext::Memoization:
+ break;
}
// The inner context was transparent for SFINAE. If it occurred within a
@@ -693,19 +708,6 @@ Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
return None;
}
-/// \brief Retrieve the depth and index of a parameter pack.
-static std::pair<unsigned, unsigned>
-getDepthAndIndex(NamedDecl *ND) {
- if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
- return std::make_pair(TTP->getDepth(), TTP->getIndex());
-
- if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND))
- return std::make_pair(NTTP->getDepth(), NTTP->getIndex());
-
- TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
- return std::make_pair(TTP->getDepth(), TTP->getIndex());
-}
-
//===----------------------------------------------------------------------===/
// Template Instantiation for Types
//===----------------------------------------------------------------------===/
@@ -725,20 +727,20 @@ namespace {
: inherited(SemaRef), TemplateArgs(TemplateArgs), Loc(Loc),
Entity(Entity) { }
- /// \brief Determine whether the given type \p T has already been
+ /// Determine whether the given type \p T has already been
/// transformed.
///
/// For the purposes of template instantiation, a type has already been
/// transformed if it is NULL or if it is not dependent.
bool AlreadyTransformed(QualType T);
- /// \brief Returns the location of the entity being instantiated, if known.
+ /// Returns the location of the entity being instantiated, if known.
SourceLocation getBaseLocation() { return Loc; }
- /// \brief Returns the name of the entity being instantiated, if any.
+ /// Returns the name of the entity being instantiated, if any.
DeclarationName getBaseEntity() { return Entity; }
- /// \brief Sets the "base" location and entity when that
+ /// Sets the "base" location and entity when that
/// information is known based on another transformation.
void setBase(SourceLocation Loc, DeclarationName Entity) {
this->Loc = Loc;
@@ -793,7 +795,7 @@ namespace {
}
}
- /// \brief Transform the given declaration by instantiating a reference to
+ /// Transform the given declaration by instantiating a reference to
/// this declaration.
Decl *TransformDecl(SourceLocation Loc, Decl *D);
@@ -824,15 +826,15 @@ namespace {
SemaRef.PerformDependentDiagnostics(DC, TemplateArgs);
}
- /// \brief Transform the definition of the given declaration by
+ /// Transform the definition of the given declaration by
/// instantiating it.
Decl *TransformDefinition(SourceLocation Loc, Decl *D);
- /// \brief Transform the first qualifier within a scope by instantiating the
+ /// Transform the first qualifier within a scope by instantiating the
/// declaration.
NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc);
- /// \brief Rebuild the exception declaration and register the declaration
+ /// Rebuild the exception declaration and register the declaration
/// as an instantiated local.
VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl,
TypeSourceInfo *Declarator,
@@ -840,12 +842,12 @@ namespace {
SourceLocation NameLoc,
IdentifierInfo *Name);
- /// \brief Rebuild the Objective-C exception declaration and register the
+ /// Rebuild the Objective-C exception declaration and register the
/// declaration as an instantiated local.
VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
TypeSourceInfo *TSInfo, QualType T);
- /// \brief Check for tag mismatches when instantiating an
+ /// Check for tag mismatches when instantiating an
/// elaborated type.
QualType RebuildElaboratedType(SourceLocation KeywordLoc,
ElaboratedTypeKeyword Keyword,
@@ -870,14 +872,14 @@ namespace {
ExprResult TransformSubstNonTypeTemplateParmPackExpr(
SubstNonTypeTemplateParmPackExpr *E);
- /// \brief Rebuild a DeclRefExpr for a ParmVarDecl reference.
+ /// Rebuild a DeclRefExpr for a ParmVarDecl reference.
ExprResult RebuildParmVarDeclRefExpr(ParmVarDecl *PD, SourceLocation Loc);
- /// \brief Transform a reference to a function parameter pack.
+ /// Transform a reference to a function parameter pack.
ExprResult TransformFunctionParmPackRefExpr(DeclRefExpr *E,
ParmVarDecl *PD);
- /// \brief Transform a FunctionParmPackExpr which was built when we couldn't
+ /// Transform a FunctionParmPackExpr which was built when we couldn't
/// expand a function parameter pack reference which refers to an expanded
/// pack.
ExprResult TransformFunctionParmPackExpr(FunctionParmPackExpr *E);
@@ -900,12 +902,12 @@ namespace {
Optional<unsigned> NumExpansions,
bool ExpectParameterPack);
- /// \brief Transforms a template type parameter type by performing
+ /// Transforms a template type parameter type by performing
/// substitution of the corresponding template type argument.
QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
TemplateTypeParmTypeLoc TL);
- /// \brief Transforms an already-substituted template type parameter pack
+ /// Transforms an already-substituted template type parameter pack
/// into either itself (if we aren't substituting into its pack expansion)
/// or the appropriate substituted argument.
QualType TransformSubstTemplateTypeParmPackType(TypeLocBuilder &TLB,
@@ -1197,11 +1199,11 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
NTTP->getDeclName());
if (TargetType.isNull())
return ExprError();
-
- return new (SemaRef.Context) SubstNonTypeTemplateParmPackExpr(TargetType,
- NTTP,
- E->getLocation(),
- Arg);
+
+ return new (SemaRef.Context) SubstNonTypeTemplateParmPackExpr(
+ TargetType.getNonLValueExprType(SemaRef.Context),
+ TargetType->isReferenceType() ? VK_LValue : VK_RValue, NTTP,
+ E->getLocation(), Arg);
}
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
@@ -1246,7 +1248,7 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
arg.getKind() == TemplateArgument::NullPtr) {
ValueDecl *VD;
if (arg.getKind() == TemplateArgument::Declaration) {
- VD = cast<ValueDecl>(arg.getAsDecl());
+ VD = arg.getAsDecl();
// Find the instantiation of the template argument. This is
// required for nested templates.
@@ -1525,7 +1527,7 @@ TemplateInstantiator::TransformSubstTemplateTypeParmPackType(
return Result;
}
-/// \brief Perform substitution on the type T with a given set of template
+/// Perform substitution on the type T with a given set of template
/// arguments.
///
/// This routine substitutes the given template arguments into the
@@ -1820,7 +1822,7 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
return NewParm;
}
-/// \brief Substitute the given template arguments into the given set of
+/// Substitute the given template arguments into the given set of
/// parameters, producing the set of parameter types that would be generated
/// from such a substitution.
bool Sema::SubstParmTypes(
@@ -1840,7 +1842,7 @@ bool Sema::SubstParmTypes(
Loc, Params, nullptr, ExtParamInfos, ParamTypes, OutParams, ParamInfos);
}
-/// \brief Perform substitution on the base class specifiers of the
+/// Perform substitution on the base class specifiers of the
/// given class template specialization.
///
/// Produces a diagnostic and returns true on error, returns false and
@@ -1960,7 +1962,7 @@ namespace clang {
}
}
-/// \brief Instantiate the definition of a class from a given pattern.
+/// Instantiate the definition of a class from a given pattern.
///
/// \param PointOfInstantiation The point of instantiation within the
/// source code.
@@ -1996,7 +1998,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
return true;
Pattern = PatternDef;
- // \brief Record the point of instantiation.
+ // Record the point of instantiation.
if (MemberSpecializationInfo *MSInfo
= Instantiation->getMemberSpecializationInfo()) {
MSInfo->setTemplateSpecializationKind(TSK);
@@ -2011,7 +2013,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
if (Inst.isInvalid())
return true;
assert(!Inst.isAlreadyInstantiating() && "should have been caught by caller");
- PrettyDeclStackTraceEntry CrashInfo(*this, Instantiation, SourceLocation(),
+ PrettyDeclStackTraceEntry CrashInfo(Context, Instantiation, SourceLocation(),
"instantiating class definition");
// Enter the scope of this instantiation. We don't use
@@ -2068,6 +2070,11 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
if (Member->getDeclContext() != Pattern)
continue;
+ // BlockDecls can appear in a default-member-initializer. They must be the
+ // child of a BlockExpr, so we only know how to instantiate them from there.
+ if (isa<BlockDecl>(Member))
+ continue;
+
if (Member->isInvalidDecl()) {
Instantiation->setInvalidDecl();
continue;
@@ -2110,7 +2117,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
// Finish checking fields.
ActOnFields(nullptr, Instantiation->getLocation(), Instantiation, Fields,
- SourceLocation(), SourceLocation(), nullptr);
+ SourceLocation(), SourceLocation(), ParsedAttributesView());
CheckCompletedCXXClass(Instantiation);
// Default arguments are parsed, if not instantiated. We can go instantiate
@@ -2196,7 +2203,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
return Instantiation->isInvalidDecl();
}
-/// \brief Instantiate the definition of an enum from a given pattern.
+/// Instantiate the definition of an enum from a given pattern.
///
/// \param PointOfInstantiation The point of instantiation within the
/// source code.
@@ -2234,7 +2241,7 @@ bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation,
return true;
if (Inst.isAlreadyInstantiating())
return false;
- PrettyDeclStackTraceEntry CrashInfo(*this, Instantiation, SourceLocation(),
+ PrettyDeclStackTraceEntry CrashInfo(Context, Instantiation, SourceLocation(),
"instantiating enum definition");
// The instantiation is visible here, even if it was first declared in an
@@ -2262,7 +2269,7 @@ bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation,
}
-/// \brief Instantiate the definition of a field from the given pattern.
+/// Instantiate the definition of a field from the given pattern.
///
/// \param PointOfInstantiation The point of instantiation within the
/// source code.
@@ -2310,7 +2317,7 @@ bool Sema::InstantiateInClassInitializer(
<< Instantiation;
return true;
}
- PrettyDeclStackTraceEntry CrashInfo(*this, Instantiation, SourceLocation(),
+ PrettyDeclStackTraceEntry CrashInfo(Context, Instantiation, SourceLocation(),
"instantiating default member init");
// Enter the scope of this instantiation. We don't use PushDeclContext because
@@ -2340,7 +2347,7 @@ bool Sema::InstantiateInClassInitializer(
}
namespace {
- /// \brief A partial specialization whose template arguments have matched
+ /// A partial specialization whose template arguments have matched
/// a given template-id.
struct PartialSpecMatchResult {
ClassTemplatePartialSpecializationDecl *Partial;
@@ -2379,127 +2386,137 @@ getPatternForClassTemplateSpecialization(
if (Inst.isInvalid() || Inst.isAlreadyInstantiating())
return nullptr;
- ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
- CXXRecordDecl *Pattern = nullptr;
-
- // C++ [temp.class.spec.match]p1:
- // When a class template is used in a context that requires an
- // instantiation of the class, it is necessary to determine
- // whether the instantiation is to be generated using the primary
- // template or one of the partial specializations. This is done by
- // matching the template arguments of the class template
- // specialization with the template argument lists of the partial
- // specializations.
- typedef PartialSpecMatchResult MatchResult;
- SmallVector<MatchResult, 4> Matched;
- SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
- Template->getPartialSpecializations(PartialSpecs);
- TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation);
- for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
- ClassTemplatePartialSpecializationDecl *Partial = PartialSpecs[I];
- TemplateDeductionInfo Info(FailedCandidates.getLocation());
- if (Sema::TemplateDeductionResult Result = S.DeduceTemplateArguments(
- Partial, ClassTemplateSpec->getTemplateArgs(), Info)) {
- // Store the failed-deduction information for use in diagnostics, later.
- // TODO: Actually use the failed-deduction info?
- FailedCandidates.addCandidate().set(
- DeclAccessPair::make(Template, AS_public), Partial,
- MakeDeductionFailureInfo(S.Context, Result, Info));
- (void)Result;
- } else {
- Matched.push_back(PartialSpecMatchResult());
- Matched.back().Partial = Partial;
- Matched.back().Args = Info.take();
+ llvm::PointerUnion<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *>
+ Specialized = ClassTemplateSpec->getSpecializedTemplateOrPartial();
+ if (!Specialized.is<ClassTemplatePartialSpecializationDecl *>()) {
+ // Find best matching specialization.
+ ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
+
+ // C++ [temp.class.spec.match]p1:
+ // When a class template is used in a context that requires an
+ // instantiation of the class, it is necessary to determine
+ // whether the instantiation is to be generated using the primary
+ // template or one of the partial specializations. This is done by
+ // matching the template arguments of the class template
+ // specialization with the template argument lists of the partial
+ // specializations.
+ typedef PartialSpecMatchResult MatchResult;
+ SmallVector<MatchResult, 4> Matched;
+ SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
+ Template->getPartialSpecializations(PartialSpecs);
+ TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation);
+ for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
+ ClassTemplatePartialSpecializationDecl *Partial = PartialSpecs[I];
+ TemplateDeductionInfo Info(FailedCandidates.getLocation());
+ if (Sema::TemplateDeductionResult Result = S.DeduceTemplateArguments(
+ Partial, ClassTemplateSpec->getTemplateArgs(), Info)) {
+ // Store the failed-deduction information for use in diagnostics, later.
+ // TODO: Actually use the failed-deduction info?
+ FailedCandidates.addCandidate().set(
+ DeclAccessPair::make(Template, AS_public), Partial,
+ MakeDeductionFailureInfo(S.Context, Result, Info));
+ (void)Result;
+ } else {
+ Matched.push_back(PartialSpecMatchResult());
+ Matched.back().Partial = Partial;
+ Matched.back().Args = Info.take();
+ }
}
- }
- // If we're dealing with a member template where the template parameters
- // have been instantiated, this provides the original template parameters
- // from which the member template's parameters were instantiated.
+ // If we're dealing with a member template where the template parameters
+ // have been instantiated, this provides the original template parameters
+ // from which the member template's parameters were instantiated.
- if (Matched.size() >= 1) {
- SmallVectorImpl<MatchResult>::iterator Best = Matched.begin();
- if (Matched.size() == 1) {
- // -- If exactly one matching specialization is found, the
- // instantiation is generated from that specialization.
- // We don't need to do anything for this.
- } else {
- // -- If more than one matching specialization is found, the
- // partial order rules (14.5.4.2) are used to determine
- // whether one of the specializations is more specialized
- // than the others. If none of the specializations is more
- // specialized than all of the other matching
- // specializations, then the use of the class template is
- // ambiguous and the program is ill-formed.
- for (SmallVectorImpl<MatchResult>::iterator P = Best + 1,
- PEnd = Matched.end();
- P != PEnd; ++P) {
- if (S.getMoreSpecializedPartialSpecialization(
- P->Partial, Best->Partial, PointOfInstantiation) == P->Partial)
- Best = P;
- }
-
- // Determine if the best partial specialization is more specialized than
- // the others.
- bool Ambiguous = false;
- for (SmallVectorImpl<MatchResult>::iterator P = Matched.begin(),
- PEnd = Matched.end();
- P != PEnd; ++P) {
- if (P != Best &&
- S.getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial,
- PointOfInstantiation) !=
- Best->Partial) {
- Ambiguous = true;
- break;
+ if (Matched.size() >= 1) {
+ SmallVectorImpl<MatchResult>::iterator Best = Matched.begin();
+ if (Matched.size() == 1) {
+ // -- If exactly one matching specialization is found, the
+ // instantiation is generated from that specialization.
+ // We don't need to do anything for this.
+ } else {
+ // -- If more than one matching specialization is found, the
+ // partial order rules (14.5.4.2) are used to determine
+ // whether one of the specializations is more specialized
+ // than the others. If none of the specializations is more
+ // specialized than all of the other matching
+ // specializations, then the use of the class template is
+ // ambiguous and the program is ill-formed.
+ for (SmallVectorImpl<MatchResult>::iterator P = Best + 1,
+ PEnd = Matched.end();
+ P != PEnd; ++P) {
+ if (S.getMoreSpecializedPartialSpecialization(
+ P->Partial, Best->Partial, PointOfInstantiation) ==
+ P->Partial)
+ Best = P;
}
- }
-
- if (Ambiguous) {
- // Partial ordering did not produce a clear winner. Complain.
- Inst.Clear();
- ClassTemplateSpec->setInvalidDecl();
- S.Diag(PointOfInstantiation, diag::err_partial_spec_ordering_ambiguous)
- << ClassTemplateSpec;
-
- // Print the matching partial specializations.
+
+ // Determine if the best partial specialization is more specialized than
+ // the others.
+ bool Ambiguous = false;
for (SmallVectorImpl<MatchResult>::iterator P = Matched.begin(),
PEnd = Matched.end();
- P != PEnd; ++P)
- S.Diag(P->Partial->getLocation(), diag::note_partial_spec_match)
- << S.getTemplateArgumentBindingsText(
- P->Partial->getTemplateParameters(), *P->Args);
+ P != PEnd; ++P) {
+ if (P != Best && S.getMoreSpecializedPartialSpecialization(
+ P->Partial, Best->Partial,
+ PointOfInstantiation) != Best->Partial) {
+ Ambiguous = true;
+ break;
+ }
+ }
+
+ if (Ambiguous) {
+ // Partial ordering did not produce a clear winner. Complain.
+ Inst.Clear();
+ ClassTemplateSpec->setInvalidDecl();
+ S.Diag(PointOfInstantiation,
+ diag::err_partial_spec_ordering_ambiguous)
+ << ClassTemplateSpec;
+
+ // Print the matching partial specializations.
+ for (SmallVectorImpl<MatchResult>::iterator P = Matched.begin(),
+ PEnd = Matched.end();
+ P != PEnd; ++P)
+ S.Diag(P->Partial->getLocation(), diag::note_partial_spec_match)
+ << S.getTemplateArgumentBindingsText(
+ P->Partial->getTemplateParameters(), *P->Args);
- return nullptr;
+ return nullptr;
+ }
}
+
+ ClassTemplateSpec->setInstantiationOf(Best->Partial, Best->Args);
+ } else {
+ // -- If no matches are found, the instantiation is generated
+ // from the primary template.
}
-
+ }
+
+ CXXRecordDecl *Pattern = nullptr;
+ Specialized = ClassTemplateSpec->getSpecializedTemplateOrPartial();
+ if (auto *PartialSpec =
+ Specialized.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
// Instantiate using the best class template partial specialization.
- ClassTemplatePartialSpecializationDecl *OrigPartialSpec = Best->Partial;
- while (OrigPartialSpec->getInstantiatedFromMember()) {
+ while (PartialSpec->getInstantiatedFromMember()) {
// If we've found an explicit specialization of this class template,
// stop here and use that as the pattern.
- if (OrigPartialSpec->isMemberSpecialization())
+ if (PartialSpec->isMemberSpecialization())
break;
-
- OrigPartialSpec = OrigPartialSpec->getInstantiatedFromMember();
+
+ PartialSpec = PartialSpec->getInstantiatedFromMember();
}
-
- Pattern = OrigPartialSpec;
- ClassTemplateSpec->setInstantiationOf(Best->Partial, Best->Args);
+ Pattern = PartialSpec;
} else {
- // -- If no matches are found, the instantiation is generated
- // from the primary template.
- ClassTemplateDecl *OrigTemplate = Template;
- while (OrigTemplate->getInstantiatedFromMemberTemplate()) {
+ ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
+ while (Template->getInstantiatedFromMemberTemplate()) {
// If we've found an explicit specialization of this class template,
// stop here and use that as the pattern.
- if (OrigTemplate->isMemberSpecialization())
+ if (Template->isMemberSpecialization())
break;
-
- OrigTemplate = OrigTemplate->getInstantiatedFromMemberTemplate();
+
+ Template = Template->getInstantiatedFromMemberTemplate();
}
-
- Pattern = OrigTemplate->getTemplatedDecl();
+ Pattern = Template->getTemplatedDecl();
}
return Pattern;
@@ -2525,7 +2542,7 @@ bool Sema::InstantiateClassTemplateSpecialization(
Complain);
}
-/// \brief Instantiates the definitions of all of the member
+/// Instantiates the definitions of all of the member
/// of the given class, which is an instantiation of a class template
/// or a member class of a template.
void
@@ -2732,7 +2749,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
}
}
-/// \brief Instantiate the definitions of all of the members of the
+/// Instantiate the definitions of all of the members of the
/// given class template specialization, which was named as part of an
/// explicit instantiation.
void
@@ -2808,7 +2825,7 @@ Sema::SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
return Instantiator.TransformNestedNameSpecifierLoc(NNS);
}
-/// \brief Do template substitution on declaration name info.
+/// Do template substitution on declaration name info.
DeclarationNameInfo
Sema::SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
const MultiLevelTemplateArgumentList &TemplateArgs) {
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 9163fbc6f7e8..5109dc8290f9 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -18,11 +18,12 @@
#include "clang/AST/DependentDiagnostic.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
-#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Template.h"
+#include "clang/Sema/TemplateInstCallback.h"
using namespace clang;
@@ -175,7 +176,8 @@ static void instantiateDependentAllocAlignAttr(
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
const AllocAlignAttr *Align, Decl *New) {
Expr *Param = IntegerLiteral::Create(
- S.getASTContext(), llvm::APInt(64, Align->getParamIndex()),
+ S.getASTContext(),
+ llvm::APInt(64, Align->getParamIndex().getSourceIndex()),
S.getASTContext().UnsignedLongLongTy, Align->getLocation());
S.AddAllocAlignAttr(Align->getLocation(), New, Param,
Align->getSpellingListIndex());
@@ -343,14 +345,6 @@ static void instantiateOMPDeclareSimdDeclAttr(
Attr.getRange());
}
-static bool DeclContainsAttr(const Decl *D, const Attr *NewAttr) {
- if (!D->hasAttrs() || NewAttr->duplicatesAllowed())
- return false;
- return llvm::find_if(D->getAttrs(), [NewAttr](const Attr *Attr) {
- return Attr->getKind() == NewAttr->getKind();
- }) != D->getAttrs().end();
-}
-
void Sema::InstantiateAttrsForDecl(
const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Tmpl,
Decl *New, LateInstantiatedAttrVec *LateAttrs,
@@ -365,7 +359,7 @@ void Sema::InstantiateAttrsForDecl(
Attr *NewAttr = sema::instantiateTemplateAttributeForDecl(
TmplAttr, Context, *this, TemplateArgs);
- if (NewAttr && !DeclContainsAttr(New, NewAttr))
+ if (NewAttr)
New->addAttr(NewAttr);
}
}
@@ -470,8 +464,7 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context,
*this, TemplateArgs);
-
- if (NewAttr && !DeclContainsAttr(New, NewAttr))
+ if (NewAttr)
New->addAttr(NewAttr);
}
}
@@ -749,7 +742,7 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
if (D->isNRVOVariable()) {
QualType ReturnType = cast<FunctionDecl>(DC)->getReturnType();
- if (SemaRef.isCopyElisionCandidate(ReturnType, Var, false))
+ if (SemaRef.isCopyElisionCandidate(ReturnType, Var, Sema::CES_Strict))
Var->setNRVOVariable(true);
}
@@ -1049,8 +1042,7 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
SemaRef.SubstType(TI->getType(), TemplateArgs,
UnderlyingLoc, DeclarationName());
SemaRef.CheckEnumRedeclaration(Def->getLocation(), Def->isScoped(),
- DefnUnderlying,
- /*EnumUnderlyingIsImplicit=*/false, Enum);
+ DefnUnderlying, /*IsFixed=*/true, Enum);
}
}
@@ -1126,8 +1118,7 @@ void TemplateDeclInstantiator::InstantiateEnumDefinition(
}
SemaRef.ActOnEnumBody(Enum->getLocation(), Enum->getBraceRange(), Enum,
- Enumerators,
- nullptr, nullptr);
+ Enumerators, nullptr, ParsedAttributesView());
}
Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) {
@@ -1564,7 +1555,7 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
return Record;
}
-/// \brief Adjust the given function type for an instantiation of the
+/// Adjust the given function type for an instantiation of the
/// given declaration, to cope with modifications to the function's type that
/// aren't reflected in the type-source information.
///
@@ -1661,6 +1652,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
NameInfo, T, TInfo, D->getSourceRange().getEnd());
if (DGuide->isCopyDeductionCandidate())
cast<CXXDeductionGuideDecl>(Function)->setIsCopyDeductionCandidate();
+ Function->setAccess(D->getAccess());
} else {
Function = FunctionDecl::Create(
SemaRef.Context, DC, D->getInnerLocStart(), NameInfo, T, TInfo,
@@ -1815,45 +1807,24 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
// apply to non-template function declarations and definitions also apply
// to these implicit definitions.
if (D->isThisDeclarationADefinition()) {
- // Check for a function body.
- const FunctionDecl *Definition = nullptr;
- if (Function->isDefined(Definition) &&
- Definition->getTemplateSpecializationKind() == TSK_Undeclared) {
- SemaRef.Diag(Function->getLocation(), diag::err_redefinition)
- << Function->getDeclName();
- SemaRef.Diag(Definition->getLocation(), diag::note_previous_definition);
- }
- // Check for redefinitions due to other instantiations of this or
- // a similar friend function.
- else for (auto R : Function->redecls()) {
- if (R == Function)
- continue;
-
- // If some prior declaration of this function has been used, we need
- // to instantiate its definition.
- if (!QueuedInstantiation && R->isUsed(false)) {
- if (MemberSpecializationInfo *MSInfo =
- Function->getMemberSpecializationInfo()) {
- if (MSInfo->getPointOfInstantiation().isInvalid()) {
- SourceLocation Loc = R->getLocation(); // FIXME
- MSInfo->setPointOfInstantiation(Loc);
- SemaRef.PendingLocalImplicitInstantiations.push_back(
- std::make_pair(Function, Loc));
- QueuedInstantiation = true;
- }
- }
- }
-
- // If some prior declaration of this function was a friend with an
- // uninstantiated definition, reject it.
- if (R->getFriendObjectKind()) {
- if (const FunctionDecl *RPattern =
- R->getTemplateInstantiationPattern()) {
- if (RPattern->isDefined(RPattern)) {
- SemaRef.Diag(Function->getLocation(), diag::err_redefinition)
- << Function->getDeclName();
- SemaRef.Diag(R->getLocation(), diag::note_previous_definition);
- break;
+ SemaRef.CheckForFunctionRedefinition(Function);
+ if (!Function->isInvalidDecl()) {
+ for (auto R : Function->redecls()) {
+ if (R == Function)
+ continue;
+
+ // If some prior declaration of this function has been used, we need
+ // to instantiate its definition.
+ if (!QueuedInstantiation && R->isUsed(false)) {
+ if (MemberSpecializationInfo *MSInfo =
+ Function->getMemberSpecializationInfo()) {
+ if (MSInfo->getPointOfInstantiation().isInvalid()) {
+ SourceLocation Loc = R->getLocation(); // FIXME
+ MSInfo->setPointOfInstantiation(Loc);
+ SemaRef.PendingLocalImplicitInstantiations.push_back(
+ std::make_pair(Function, Loc));
+ QueuedInstantiation = true;
+ }
}
}
}
@@ -2676,7 +2647,8 @@ Decl *TemplateDeclInstantiator::instantiateUnresolvedUsingDecl(
NamedDecl *UD = SemaRef.BuildUsingDeclaration(
/*Scope*/ nullptr, D->getAccess(), D->getUsingLoc(),
- /*HasTypename*/ TD, TypenameLoc, SS, NameInfo, EllipsisLoc, nullptr,
+ /*HasTypename*/ TD, TypenameLoc, SS, NameInfo, EllipsisLoc,
+ ParsedAttributesView(),
/*IsInstantiation*/ true);
if (UD)
SemaRef.Context.setInstantiatedFromUsingDecl(UD, D);
@@ -2697,9 +2669,9 @@ Decl *TemplateDeclInstantiator::VisitUnresolvedUsingValueDecl(
Decl *TemplateDeclInstantiator::VisitUsingPackDecl(UsingPackDecl *D) {
SmallVector<NamedDecl*, 8> Expansions;
for (auto *UD : D->expansions()) {
- if (auto *NewUD =
+ if (NamedDecl *NewUD =
SemaRef.FindInstantiatedDecl(D->getLocation(), UD, TemplateArgs))
- Expansions.push_back(cast<NamedDecl>(NewUD));
+ Expansions.push_back(NewUD);
else
return nullptr;
}
@@ -2740,6 +2712,8 @@ Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl(
assert(Specialization && "Class scope Specialization is null");
SemaRef.Context.setClassScopeSpecializationPattern(Specialization, OldFD);
+ // FIXME: If this is a definition, check for redefinition errors!
+
return NewFD;
}
@@ -2859,7 +2833,10 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
Decl *
TemplateDeclInstantiator::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
- return VisitFunctionDecl(D, nullptr);
+ Decl *Inst = VisitFunctionDecl(D, nullptr);
+ if (Inst && !D->getDescribedFunctionTemplate())
+ Owner->addDecl(Inst);
+ return Inst;
}
Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
@@ -3112,7 +3089,7 @@ Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner,
return Instantiator.Visit(D);
}
-/// \brief Instantiates a nested template parameter list in the current
+/// Instantiates a nested template parameter list in the current
/// instantiation context.
///
/// \param L The parameter list to instantiate
@@ -3148,7 +3125,14 @@ TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) {
return InstL;
}
-/// \brief Instantiate the declaration of a class template partial
+TemplateParameterList *
+Sema::SubstTemplateParams(TemplateParameterList *Params, DeclContext *Owner,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs);
+ return Instantiator.SubstTemplateParams(Params);
+}
+
+/// Instantiate the declaration of a class template partial
/// specialization.
///
/// \param ClassTemplate the (instantiated) class template that is partially
@@ -3282,7 +3266,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
return InstPartialSpec;
}
-/// \brief Instantiate the declaration of a variable template partial
+/// Instantiate the declaration of a variable template partial
/// specialization.
///
/// \param VarTemplate the (instantiated) variable template that is partially
@@ -3624,7 +3608,7 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
TemplateArgs);
}
-/// \brief Initializes the common fields of an instantiation function
+/// Initializes the common fields of an instantiation function
/// declaration (New) from the corresponding fields of its template (Tmpl).
///
/// \returns true if there was an error
@@ -3657,8 +3641,10 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
assert(FunTmpl->getTemplatedDecl() == Tmpl &&
"Deduction from the wrong function template?");
(void) FunTmpl;
+ atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef, ActiveInst);
ActiveInst.Kind = ActiveInstType::TemplateInstantiation;
ActiveInst.Entity = New;
+ atTemplateBegin(SemaRef.TemplateInstCallbacks, SemaRef, ActiveInst);
}
}
@@ -3710,7 +3696,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
return false;
}
-/// \brief Initializes common fields of an instantiated method
+/// Initializes common fields of an instantiated method
/// declaration (New) from the corresponding fields of its template
/// (Tmpl).
///
@@ -3774,7 +3760,7 @@ static void InstantiateDefaultCtorDefaultArgs(Sema &S,
}
}
-/// \brief Instantiate the definition of the given function from its
+/// Instantiate the definition of the given function from its
/// template.
///
/// \param PointOfInstantiation the point at which the instantiation was
@@ -3854,8 +3840,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
if (PatternDecl->isLateTemplateParsed() &&
!LateTemplateParser) {
Function->setInstantiationIsPending(true);
- PendingInstantiations.push_back(
- std::make_pair(Function, PointOfInstantiation));
+ LateParsedInstantiations.push_back(
+ std::make_pair(Function, PointOfInstantiation));
return;
}
@@ -3912,7 +3898,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
InstantiatingTemplate Inst(*this, PointOfInstantiation, Function);
if (Inst.isInvalid() || Inst.isAlreadyInstantiating())
return;
- PrettyDeclStackTraceEntry CrashInfo(*this, Function, SourceLocation(),
+ PrettyDeclStackTraceEntry CrashInfo(Context, Function, SourceLocation(),
"instantiating function definition");
// The instantiation is visible here, even if it was first declared in an
@@ -3957,8 +3943,10 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
TemplateArgs))
return;
+ StmtResult Body;
if (PatternDecl->hasSkippedBody()) {
ActOnSkippedFunctionBody(Function);
+ Body = nullptr;
} else {
if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Function)) {
// If this is a constructor, instantiate the member initializers.
@@ -3974,16 +3962,14 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
}
// Instantiate the function body.
- StmtResult Body = SubstStmt(Pattern, TemplateArgs);
+ Body = SubstStmt(Pattern, TemplateArgs);
if (Body.isInvalid())
Function->setInvalidDecl();
-
- // FIXME: finishing the function body while in an expression evaluation
- // context seems wrong. Investigate more.
- ActOnFinishFunctionBody(Function, Body.get(),
- /*IsInstantiation=*/true);
}
+ // FIXME: finishing the function body while in an expression evaluation
+ // context seems wrong. Investigate more.
+ ActOnFinishFunctionBody(Function, Body.get(), /*IsInstantiation=*/true);
PerformDependentDiagnostics(PatternDecl, TemplateArgs);
@@ -4050,7 +4036,7 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
VarTemplate, FromVar, InsertPos, TemplateArgsInfo, Converted));
}
-/// \brief Instantiates a variable template specialization by completing it
+/// Instantiates a variable template specialization by completing it
/// with appropriate type information and initializer.
VarTemplateSpecializationDecl *Sema::CompleteVarTemplateSpecializationDecl(
VarTemplateSpecializationDecl *VarSpec, VarDecl *PatternDecl,
@@ -4100,6 +4086,7 @@ void Sema::BuildVariableInstantiation(
NewVar->setTSCSpec(OldVar->getTSCSpec());
NewVar->setInitStyle(OldVar->getInitStyle());
NewVar->setCXXForRangeDecl(OldVar->isCXXForRangeDecl());
+ NewVar->setObjCForDecl(OldVar->isObjCForDecl());
NewVar->setConstexpr(OldVar->isConstexpr());
NewVar->setInitCapture(OldVar->isInitCapture());
NewVar->setPreviousDeclInSameBlockScope(
@@ -4173,7 +4160,7 @@ void Sema::BuildVariableInstantiation(
DiagnoseUnusedDecl(NewVar);
}
-/// \brief Instantiate the initializer of a variable.
+/// Instantiate the initializer of a variable.
void Sema::InstantiateVariableInitializer(
VarDecl *Var, VarDecl *OldVar,
const MultiLevelTemplateArgumentList &TemplateArgs) {
@@ -4219,7 +4206,9 @@ void Sema::InstantiateVariableInitializer(
Var->setInvalidDecl();
}
} else {
- if (Var->isStaticDataMember()) {
+ // `inline` variables are a definition and declaration all in one; we won't
+ // pick up an initializer from anywhere else.
+ if (Var->isStaticDataMember() && !Var->isInline()) {
if (!Var->isOutOfLine())
return;
@@ -4230,14 +4219,17 @@ void Sema::InstantiateVariableInitializer(
}
// We'll add an initializer to a for-range declaration later.
- if (Var->isCXXForRangeDecl())
+ if (Var->isCXXForRangeDecl() || Var->isObjCForDecl())
return;
ActOnUninitializedDecl(Var);
}
+
+ if (getLangOpts().CUDA)
+ checkAllowedCUDAInitializer(Var);
}
-/// \brief Instantiate the definition of the given variable from its
+/// Instantiate the definition of the given variable from its
/// template.
///
/// \param PointOfInstantiation the point at which the instantiation was
@@ -4321,7 +4313,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
if (Inst.isInvalid() || Inst.isAlreadyInstantiating())
return;
- PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(),
+ PrettyDeclStackTraceEntry CrashInfo(Context, Var, SourceLocation(),
"instantiating variable initializer");
// The instantiation is visible here, even if it was first declared in an
@@ -4434,7 +4426,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
if (Inst.isInvalid() || Inst.isAlreadyInstantiating())
return;
- PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(),
+ PrettyDeclStackTraceEntry CrashInfo(Context, Var, SourceLocation(),
"instantiating variable definition");
// If we're performing recursive template instantiation, create our own
@@ -4856,7 +4848,7 @@ static NamedDecl *findInstantiationOf(ASTContext &Ctx,
return nullptr;
}
-/// \brief Finds the instantiation of the given declaration context
+/// Finds the instantiation of the given declaration context
/// within the current instantiation.
///
/// \returns NULL if there was an error
@@ -4868,7 +4860,7 @@ DeclContext *Sema::FindInstantiatedContext(SourceLocation Loc, DeclContext* DC,
} else return DC;
}
-/// \brief Find the instantiation of the given declaration within the
+/// Find the instantiation of the given declaration within the
/// current instantiation.
///
/// This routine is intended to be used when \p D is a declaration
@@ -5181,7 +5173,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
return D;
}
-/// \brief Performs template instantiation for all implicit template
+/// Performs template instantiation for all implicit template
/// instantiations we have seen until this point.
void Sema::PerformPendingInstantiations(bool LocalOnly) {
while (!PendingLocalImplicitInstantiations.empty() ||
@@ -5238,7 +5230,7 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) {
break;
}
- PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(),
+ PrettyDeclStackTraceEntry CrashInfo(Context, Var, SourceLocation(),
"instantiating variable definition");
bool DefinitionRequired = Var->getTemplateSpecializationKind() ==
TSK_ExplicitInstantiationDefinition;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
index d81837dad508..fc1641334273 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -26,21 +26,8 @@ using namespace clang;
// Visitor that collects unexpanded parameter packs
//----------------------------------------------------------------------------
-/// \brief Retrieve the depth and index of a parameter pack.
-static std::pair<unsigned, unsigned>
-getDepthAndIndex(NamedDecl *ND) {
- if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
- return std::make_pair(TTP->getDepth(), TTP->getIndex());
-
- if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND))
- return std::make_pair(NTTP->getDepth(), NTTP->getIndex());
-
- TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
- return std::make_pair(TTP->getDepth(), TTP->getIndex());
-}
-
namespace {
- /// \brief A class that collects unexpanded parameter packs.
+ /// A class that collects unexpanded parameter packs.
class CollectUnexpandedParameterPacksVisitor :
public RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor>
{
@@ -83,14 +70,14 @@ namespace {
// Recording occurrences of (unexpanded) parameter packs.
//------------------------------------------------------------------------
- /// \brief Record occurrences of template type parameter packs.
+ /// Record occurrences of template type parameter packs.
bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
if (TL.getTypePtr()->isParameterPack())
addUnexpanded(TL.getTypePtr(), TL.getNameLoc());
return true;
}
- /// \brief Record occurrences of template type parameter packs
+ /// Record occurrences of template type parameter packs
/// when we don't have proper source-location information for
/// them.
///
@@ -102,7 +89,7 @@ namespace {
return true;
}
- /// \brief Record occurrences of function and non-type template
+ /// Record occurrences of function and non-type template
/// parameter packs in an expression.
bool VisitDeclRefExpr(DeclRefExpr *E) {
if (E->getDecl()->isParameterPack())
@@ -111,7 +98,7 @@ namespace {
return true;
}
- /// \brief Record occurrences of template template parameter packs.
+ /// Record occurrences of template template parameter packs.
bool TraverseTemplateName(TemplateName Template) {
if (auto *TTP = dyn_cast_or_null<TemplateTemplateParmDecl>(
Template.getAsTemplateDecl())) {
@@ -122,7 +109,7 @@ namespace {
return inherited::TraverseTemplateName(Template);
}
- /// \brief Suppress traversal into Objective-C container literal
+ /// Suppress traversal into Objective-C container literal
/// elements that are pack expansions.
bool TraverseObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
if (!E->containsUnexpandedParameterPack())
@@ -142,7 +129,7 @@ namespace {
// Pruning the search for unexpanded parameter packs.
//------------------------------------------------------------------------
- /// \brief Suppress traversal into statements and expressions that
+ /// Suppress traversal into statements and expressions that
/// do not contain unexpanded parameter packs.
bool TraverseStmt(Stmt *S) {
Expr *E = dyn_cast_or_null<Expr>(S);
@@ -152,7 +139,7 @@ namespace {
return true;
}
- /// \brief Suppress traversal into types that do not contain
+ /// Suppress traversal into types that do not contain
/// unexpanded parameter packs.
bool TraverseType(QualType T) {
if ((!T.isNull() && T->containsUnexpandedParameterPack()) || InLambda)
@@ -161,7 +148,7 @@ namespace {
return true;
}
- /// \brief Suppress traversal into types with location information
+ /// Suppress traversal into types with location information
/// that do not contain unexpanded parameter packs.
bool TraverseTypeLoc(TypeLoc TL) {
if ((!TL.getType().isNull() &&
@@ -172,7 +159,7 @@ namespace {
return true;
}
- /// \brief Suppress traversal of parameter packs.
+ /// Suppress traversal of parameter packs.
bool TraverseDecl(Decl *D) {
// A function parameter pack is a pack expansion, so cannot contain
// an unexpanded parameter pack. Likewise for a template parameter
@@ -183,7 +170,7 @@ namespace {
return inherited::TraverseDecl(D);
}
- /// \brief Suppress traversal of pack-expanded attributes.
+ /// Suppress traversal of pack-expanded attributes.
bool TraverseAttr(Attr *A) {
if (A->isPackExpansion())
return true;
@@ -191,7 +178,7 @@ namespace {
return inherited::TraverseAttr(A);
}
- /// \brief Suppress traversal of pack expansion expressions and types.
+ /// Suppress traversal of pack expansion expressions and types.
///@{
bool TraversePackExpansionType(PackExpansionType *T) { return true; }
bool TraversePackExpansionTypeLoc(PackExpansionTypeLoc TL) { return true; }
@@ -200,7 +187,7 @@ namespace {
///@}
- /// \brief Suppress traversal of using-declaration pack expansion.
+ /// Suppress traversal of using-declaration pack expansion.
bool TraverseUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
if (D->isPackExpansion())
return true;
@@ -208,7 +195,7 @@ namespace {
return inherited::TraverseUnresolvedUsingValueDecl(D);
}
- /// \brief Suppress traversal of using-declaration pack expansion.
+ /// Suppress traversal of using-declaration pack expansion.
bool TraverseUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
if (D->isPackExpansion())
return true;
@@ -216,7 +203,7 @@ namespace {
return inherited::TraverseUnresolvedUsingTypenameDecl(D);
}
- /// \brief Suppress traversal of template argument pack expansions.
+ /// Suppress traversal of template argument pack expansions.
bool TraverseTemplateArgument(const TemplateArgument &Arg) {
if (Arg.isPackExpansion())
return true;
@@ -224,7 +211,7 @@ namespace {
return inherited::TraverseTemplateArgument(Arg);
}
- /// \brief Suppress traversal of template argument pack expansions.
+ /// Suppress traversal of template argument pack expansions.
bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
if (ArgLoc.getArgument().isPackExpansion())
return true;
@@ -232,7 +219,7 @@ namespace {
return inherited::TraverseTemplateArgumentLoc(ArgLoc);
}
- /// \brief Suppress traversal of base specifier pack expansions.
+ /// Suppress traversal of base specifier pack expansions.
bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base) {
if (Base.isPackExpansion())
return true;
@@ -240,7 +227,7 @@ namespace {
return inherited::TraverseCXXBaseSpecifier(Base);
}
- /// \brief Suppress traversal of mem-initializer pack expansions.
+ /// Suppress traversal of mem-initializer pack expansions.
bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
if (Init->isPackExpansion())
return true;
@@ -248,7 +235,7 @@ namespace {
return inherited::TraverseConstructorInitializer(Init);
}
- /// \brief Note whether we're traversing a lambda containing an unexpanded
+ /// Note whether we're traversing a lambda containing an unexpanded
/// parameter pack. In this case, the unexpanded pack can occur anywhere,
/// including all the places where we normally wouldn't look. Within a
/// lambda, we don't propagate the 'contains unexpanded parameter pack' bit
@@ -284,7 +271,7 @@ namespace {
};
}
-/// \brief Determine whether it's possible for an unexpanded parameter pack to
+/// Determine whether it's possible for an unexpanded parameter pack to
/// be valid in this location. This only happens when we're in a declaration
/// that is nested within an expression that could be expanded, such as a
/// lambda-expression within a function call.
@@ -298,7 +285,7 @@ bool Sema::isUnexpandedParameterPackPermitted() {
return false;
}
-/// \brief Diagnose all of the unexpanded parameter packs in the given
+/// Diagnose all of the unexpanded parameter packs in the given
/// vector.
bool
Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
@@ -314,8 +301,18 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
// later.
SmallVector<UnexpandedParameterPack, 4> LambdaParamPackReferences;
for (unsigned N = FunctionScopes.size(); N; --N) {
- if (sema::LambdaScopeInfo *LSI =
- dyn_cast<sema::LambdaScopeInfo>(FunctionScopes[N-1])) {
+ sema::FunctionScopeInfo *Func = FunctionScopes[N-1];
+ // We do not permit pack expansion that would duplicate a statement
+ // expression, not even within a lambda.
+ // FIXME: We could probably support this for statement expressions that do
+ // not contain labels, and for pack expansions that expand both the stmt
+ // expr and the enclosing lambda.
+ if (std::any_of(
+ Func->CompoundScopes.begin(), Func->CompoundScopes.end(),
+ [](sema::CompoundScopeInfo &CSI) { return CSI.IsStmtExpr; }))
+ break;
+
+ if (auto *LSI = dyn_cast<sema::LambdaScopeInfo>(Func)) {
if (N == FunctionScopes.size()) {
for (auto &Param : Unexpanded) {
auto *PD = dyn_cast_or_null<ParmVarDecl>(
@@ -636,7 +633,9 @@ bool Sema::CheckParameterPacksForExpansion(
RetainExpansion = false;
std::pair<IdentifierInfo *, SourceLocation> FirstPack;
bool HaveFirstPack = false;
-
+ Optional<unsigned> NumPartialExpansions;
+ SourceLocation PartiallySubstitutedPackLoc;
+
for (ArrayRef<UnexpandedParameterPack>::iterator i = Unexpanded.begin(),
end = Unexpanded.end();
i != end; ++i) {
@@ -701,8 +700,13 @@ bool Sema::CheckParameterPacksForExpansion(
= CurrentInstantiationScope->getPartiallySubstitutedPack()){
unsigned PartialDepth, PartialIndex;
std::tie(PartialDepth, PartialIndex) = getDepthAndIndex(PartialPack);
- if (PartialDepth == Depth && PartialIndex == Index)
+ if (PartialDepth == Depth && PartialIndex == Index) {
RetainExpansion = true;
+ // We don't actually know the new pack size yet.
+ NumPartialExpansions = NewPackSize;
+ PartiallySubstitutedPackLoc = i->second;
+ continue;
+ }
}
}
@@ -732,6 +736,28 @@ bool Sema::CheckParameterPacksForExpansion(
}
}
+ // If we're performing a partial expansion but we also have a full expansion,
+ // expand to the number of common arguments. For example, given:
+ //
+ // template<typename ...T> struct A {
+ // template<typename ...U> void f(pair<T, U>...);
+ // };
+ //
+ // ... a call to 'A<int, int>().f<int>' should expand the pack once and
+ // retain an expansion.
+ if (NumPartialExpansions) {
+ if (NumExpansions && *NumExpansions < *NumPartialExpansions) {
+ NamedDecl *PartialPack =
+ CurrentInstantiationScope->getPartiallySubstitutedPack();
+ Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_partial)
+ << PartialPack << *NumPartialExpansions << *NumExpansions
+ << SourceRange(PartiallySubstitutedPackLoc);
+ return true;
+ }
+
+ NumExpansions = NumPartialExpansions;
+ }
+
return false;
}
@@ -812,6 +838,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
case TST_void:
case TST_char:
case TST_wchar:
+ case TST_char8:
case TST_char16:
case TST_char32:
case TST_int:
@@ -819,6 +846,8 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
case TST_half:
case TST_float:
case TST_double:
+ case TST_Accum:
+ case TST_Fract:
case TST_Float16:
case TST_float128:
case TST_bool:
@@ -871,14 +900,14 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
->containsUnexpandedParameterPack())
return true;
}
- } else if (Chunk.Fun.getExceptionSpecType() == EST_ComputedNoexcept &&
+ } else if (isComputedNoexcept(Chunk.Fun.getExceptionSpecType()) &&
Chunk.Fun.NoexceptExpr->containsUnexpandedParameterPack())
return true;
if (Chunk.Fun.hasTrailingReturnType()) {
QualType T = Chunk.Fun.getTrailingReturnType().get();
- if (!T.isNull() && T->containsUnexpandedParameterPack())
- return true;
+ if (!T.isNull() && T->containsUnexpandedParameterPack())
+ return true;
}
break;
@@ -889,7 +918,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
break;
}
}
-
+
return false;
}
@@ -906,7 +935,7 @@ class ParameterPackValidatorCCC : public CorrectionCandidateCallback {
}
-/// \brief Called when an expression computing the size of a parameter pack
+/// Called when an expression computing the size of a parameter pack
/// is parsed.
///
/// \code
@@ -951,12 +980,12 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S,
case LookupResult::FoundOverloaded:
case LookupResult::FoundUnresolvedValue:
break;
-
+
case LookupResult::Ambiguous:
DiagnoseAmbiguousLookup(R);
return ExprError();
}
-
+
if (!ParameterPack || !ParameterPack->isParameterPack()) {
Diag(NameLoc, diag::err_sizeof_pack_no_pack_name)
<< &Name;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
index af060cf21b5f..ac04cecaf774 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
@@ -31,6 +31,7 @@
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
+#include "clang/Sema/TemplateInstCallback.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
@@ -63,13 +64,17 @@ static bool isOmittedBlockReturnType(const Declarator &D) {
/// diagnoseBadTypeAttribute - Diagnoses a type attribute which
/// doesn't apply to the given type.
-static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
+static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr,
QualType type) {
TypeDiagSelector WhichType;
bool useExpansionLoc = true;
switch (attr.getKind()) {
- case AttributeList::AT_ObjCGC: WhichType = TDS_Pointer; break;
- case AttributeList::AT_ObjCOwnership: WhichType = TDS_ObjCObjOrBlock; break;
+ case ParsedAttr::AT_ObjCGC:
+ WhichType = TDS_Pointer;
+ break;
+ case ParsedAttr::AT_ObjCOwnership:
+ WhichType = TDS_ObjCObjOrBlock;
+ break;
default:
// Assume everything else was a function attribute.
WhichType = TDS_Function;
@@ -97,47 +102,48 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
// objc_gc applies to Objective-C pointers or, otherwise, to the
// smallest available pointer type (i.e. 'void*' in 'void**').
-#define OBJC_POINTER_TYPE_ATTRS_CASELIST \
- case AttributeList::AT_ObjCGC: \
- case AttributeList::AT_ObjCOwnership
+#define OBJC_POINTER_TYPE_ATTRS_CASELIST \
+ case ParsedAttr::AT_ObjCGC: \
+ case ParsedAttr::AT_ObjCOwnership
// Calling convention attributes.
-#define CALLING_CONV_ATTRS_CASELIST \
- case AttributeList::AT_CDecl: \
- case AttributeList::AT_FastCall: \
- case AttributeList::AT_StdCall: \
- case AttributeList::AT_ThisCall: \
- case AttributeList::AT_RegCall: \
- case AttributeList::AT_Pascal: \
- case AttributeList::AT_SwiftCall: \
- case AttributeList::AT_VectorCall: \
- case AttributeList::AT_MSABI: \
- case AttributeList::AT_SysVABI: \
- case AttributeList::AT_Pcs: \
- case AttributeList::AT_IntelOclBicc: \
- case AttributeList::AT_PreserveMost: \
- case AttributeList::AT_PreserveAll
+#define CALLING_CONV_ATTRS_CASELIST \
+ case ParsedAttr::AT_CDecl: \
+ case ParsedAttr::AT_FastCall: \
+ case ParsedAttr::AT_StdCall: \
+ case ParsedAttr::AT_ThisCall: \
+ case ParsedAttr::AT_RegCall: \
+ case ParsedAttr::AT_Pascal: \
+ case ParsedAttr::AT_SwiftCall: \
+ case ParsedAttr::AT_VectorCall: \
+ case ParsedAttr::AT_MSABI: \
+ case ParsedAttr::AT_SysVABI: \
+ case ParsedAttr::AT_Pcs: \
+ case ParsedAttr::AT_IntelOclBicc: \
+ case ParsedAttr::AT_PreserveMost: \
+ case ParsedAttr::AT_PreserveAll
// Function type attributes.
-#define FUNCTION_TYPE_ATTRS_CASELIST \
- case AttributeList::AT_NSReturnsRetained: \
- case AttributeList::AT_NoReturn: \
- case AttributeList::AT_Regparm: \
- case AttributeList::AT_AnyX86NoCallerSavedRegisters: \
+#define FUNCTION_TYPE_ATTRS_CASELIST \
+ case ParsedAttr::AT_NSReturnsRetained: \
+ case ParsedAttr::AT_NoReturn: \
+ case ParsedAttr::AT_Regparm: \
+ case ParsedAttr::AT_AnyX86NoCallerSavedRegisters: \
+ case ParsedAttr::AT_AnyX86NoCfCheck: \
CALLING_CONV_ATTRS_CASELIST
// Microsoft-specific type qualifiers.
-#define MS_TYPE_ATTRS_CASELIST \
- case AttributeList::AT_Ptr32: \
- case AttributeList::AT_Ptr64: \
- case AttributeList::AT_SPtr: \
- case AttributeList::AT_UPtr
+#define MS_TYPE_ATTRS_CASELIST \
+ case ParsedAttr::AT_Ptr32: \
+ case ParsedAttr::AT_Ptr64: \
+ case ParsedAttr::AT_SPtr: \
+ case ParsedAttr::AT_UPtr
// Nullability qualifiers.
-#define NULLABILITY_TYPE_ATTRS_CASELIST \
- case AttributeList::AT_TypeNonNull: \
- case AttributeList::AT_TypeNullable: \
- case AttributeList::AT_TypeNullUnspecified
+#define NULLABILITY_TYPE_ATTRS_CASELIST \
+ case ParsedAttr::AT_TypeNonNull: \
+ case ParsedAttr::AT_TypeNullable: \
+ case ParsedAttr::AT_TypeNullUnspecified
namespace {
/// An object which stores processing state for the entire
@@ -160,11 +166,11 @@ namespace {
bool hasSavedAttrs;
/// The original set of attributes on the DeclSpec.
- SmallVector<AttributeList*, 2> savedAttrs;
+ SmallVector<ParsedAttr *, 2> savedAttrs;
/// A list of attributes to diagnose the uselessness of when the
/// processing is complete.
- SmallVector<AttributeList*, 2> ignoredTypeAttrs;
+ SmallVector<ParsedAttr *, 2> ignoredTypeAttrs;
public:
TypeProcessingState(Sema &sema, Declarator &declarator)
@@ -193,10 +199,10 @@ namespace {
chunkIndex = idx;
}
- AttributeList *&getCurrentAttrListRef() const {
+ ParsedAttributesView &getCurrentAttributes() const {
if (isProcessingDeclSpec())
- return getMutableDeclSpec().getAttributes().getListRef();
- return declarator.getTypeObject(chunkIndex).getAttrListRef();
+ return getMutableDeclSpec().getAttributes();
+ return declarator.getTypeObject(chunkIndex).getAttrs();
}
/// Save the current set of attributes on the DeclSpec.
@@ -205,16 +211,15 @@ namespace {
if (hasSavedAttrs) return;
DeclSpec &spec = getMutableDeclSpec();
- for (AttributeList *attr = spec.getAttributes().getList(); attr;
- attr = attr->getNext())
- savedAttrs.push_back(attr);
+ for (ParsedAttr &AL : spec.getAttributes())
+ savedAttrs.push_back(&AL);
trivial &= savedAttrs.empty();
hasSavedAttrs = true;
}
/// Record that we had nowhere to put the given type attribute.
/// We will diagnose such attributes later.
- void addIgnoredTypeAttr(AttributeList &attr) {
+ void addIgnoredTypeAttr(ParsedAttr &attr) {
ignoredTypeAttrs.push_back(&attr);
}
@@ -239,46 +244,18 @@ namespace {
void restoreDeclSpecAttrs() {
assert(hasSavedAttrs);
- if (savedAttrs.empty()) {
- getMutableDeclSpec().getAttributes().set(nullptr);
- return;
- }
-
- getMutableDeclSpec().getAttributes().set(savedAttrs[0]);
- for (unsigned i = 0, e = savedAttrs.size() - 1; i != e; ++i)
- savedAttrs[i]->setNext(savedAttrs[i+1]);
- savedAttrs.back()->setNext(nullptr);
+ getMutableDeclSpec().getAttributes().clearListOnly();
+ for (ParsedAttr *AL : savedAttrs)
+ getMutableDeclSpec().getAttributes().addAtStart(AL);
}
};
} // end anonymous namespace
-static void spliceAttrIntoList(AttributeList &attr, AttributeList *&head) {
- attr.setNext(head);
- head = &attr;
-}
-
-static void spliceAttrOutOfList(AttributeList &attr, AttributeList *&head) {
- if (head == &attr) {
- head = attr.getNext();
- return;
- }
-
- AttributeList *cur = head;
- while (true) {
- assert(cur && cur->getNext() && "ran out of attrs?");
- if (cur->getNext() == &attr) {
- cur->setNext(attr.getNext());
- return;
- }
- cur = cur->getNext();
- }
-}
-
-static void moveAttrFromListToList(AttributeList &attr,
- AttributeList *&fromList,
- AttributeList *&toList) {
- spliceAttrOutOfList(attr, fromList);
- spliceAttrIntoList(attr, toList);
+static void moveAttrFromListToList(ParsedAttr &attr,
+ ParsedAttributesView &fromList,
+ ParsedAttributesView &toList) {
+ fromList.remove(&attr);
+ toList.addAtStart(&attr);
}
/// The location of a type attribute.
@@ -291,29 +268,26 @@ enum TypeAttrLocation {
TAL_DeclName
};
-static void processTypeAttrs(TypeProcessingState &state,
- QualType &type, TypeAttrLocation TAL,
- AttributeList *attrs);
+static void processTypeAttrs(TypeProcessingState &state, QualType &type,
+ TypeAttrLocation TAL, ParsedAttributesView &attrs);
-static bool handleFunctionTypeAttr(TypeProcessingState &state,
- AttributeList &attr,
+static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
QualType &type);
static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &state,
- AttributeList &attr,
- QualType &type);
+ ParsedAttr &attr, QualType &type);
-static bool handleObjCGCTypeAttr(TypeProcessingState &state,
- AttributeList &attr, QualType &type);
+static bool handleObjCGCTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
+ QualType &type);
static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
- AttributeList &attr, QualType &type);
+ ParsedAttr &attr, QualType &type);
static bool handleObjCPointerTypeAttr(TypeProcessingState &state,
- AttributeList &attr, QualType &type) {
- if (attr.getKind() == AttributeList::AT_ObjCGC)
+ ParsedAttr &attr, QualType &type) {
+ if (attr.getKind() == ParsedAttr::AT_ObjCGC)
return handleObjCGCTypeAttr(state, attr, type);
- assert(attr.getKind() == AttributeList::AT_ObjCOwnership);
+ assert(attr.getKind() == ParsedAttr::AT_ObjCOwnership);
return handleObjCOwnershipTypeAttr(state, attr, type);
}
@@ -395,8 +369,7 @@ static DeclaratorChunk *maybeMovePastReturnType(Declarator &declarator,
/// didn't apply in whatever position it was written in, try to move
/// it to a more appropriate position.
static void distributeObjCPointerTypeAttr(TypeProcessingState &state,
- AttributeList &attr,
- QualType type) {
+ ParsedAttr &attr, QualType type) {
Declarator &declarator = state.getDeclarator();
// Move it to the outermost normal or block pointer declarator.
@@ -409,13 +382,13 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state,
// of a block.
DeclaratorChunk *destChunk = nullptr;
if (state.isProcessingDeclSpec() &&
- attr.getKind() == AttributeList::AT_ObjCOwnership)
+ attr.getKind() == ParsedAttr::AT_ObjCOwnership)
destChunk = maybeMovePastReturnType(declarator, i - 1,
/*onlyBlockPointers=*/true);
if (!destChunk) destChunk = &chunk;
- moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
- destChunk->getAttrListRef());
+ moveAttrFromListToList(attr, state.getCurrentAttributes(),
+ destChunk->getAttrs());
return;
}
@@ -426,12 +399,12 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state,
// We may be starting at the return type of a block.
case DeclaratorChunk::Function:
if (state.isProcessingDeclSpec() &&
- attr.getKind() == AttributeList::AT_ObjCOwnership) {
+ attr.getKind() == ParsedAttr::AT_ObjCOwnership) {
if (DeclaratorChunk *dest = maybeMovePastReturnType(
declarator, i,
/*onlyBlockPointers=*/true)) {
- moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
- dest->getAttrListRef());
+ moveAttrFromListToList(attr, state.getCurrentAttributes(),
+ dest->getAttrs());
return;
}
}
@@ -451,10 +424,8 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state,
/// Distribute an objc_gc type attribute that was written on the
/// declarator.
-static void
-distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state,
- AttributeList &attr,
- QualType &declSpecType) {
+static void distributeObjCPointerTypeAttrFromDeclarator(
+ TypeProcessingState &state, ParsedAttr &attr, QualType &declSpecType) {
Declarator &declarator = state.getDeclarator();
// objc_gc goes on the innermost pointer to something that's not a
@@ -491,8 +462,8 @@ distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state,
// attribute from being applied multiple times and gives
// the source-location-filler something to work with.
state.saveDeclSpecAttrs();
- moveAttrFromListToList(attr, declarator.getAttrListRef(),
- declarator.getMutableDeclSpec().getAttributes().getListRef());
+ moveAttrFromListToList(attr, declarator.getAttributes(),
+ declarator.getMutableDeclSpec().getAttributes());
return;
}
}
@@ -500,13 +471,13 @@ distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state,
// Otherwise, if we found an appropriate chunk, splice the attribute
// into it.
if (innermost != -1U) {
- moveAttrFromListToList(attr, declarator.getAttrListRef(),
- declarator.getTypeObject(innermost).getAttrListRef());
+ moveAttrFromListToList(attr, declarator.getAttributes(),
+ declarator.getTypeObject(innermost).getAttrs());
return;
}
// Otherwise, diagnose when we're done building the type.
- spliceAttrOutOfList(attr, declarator.getAttrListRef());
+ declarator.getAttributes().remove(&attr);
state.addIgnoredTypeAttr(attr);
}
@@ -515,8 +486,7 @@ distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state,
/// that it didn't apply in whatever position it was written in, try
/// to move it to a more appropriate position.
static void distributeFunctionTypeAttr(TypeProcessingState &state,
- AttributeList &attr,
- QualType type) {
+ ParsedAttr &attr, QualType type) {
Declarator &declarator = state.getDeclarator();
// Try to push the attribute from the return type of a function to
@@ -525,8 +495,8 @@ static void distributeFunctionTypeAttr(TypeProcessingState &state,
DeclaratorChunk &chunk = declarator.getTypeObject(i-1);
switch (chunk.Kind) {
case DeclaratorChunk::Function:
- moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
- chunk.getAttrListRef());
+ moveAttrFromListToList(attr, state.getCurrentAttributes(),
+ chunk.getAttrs());
return;
case DeclaratorChunk::Paren:
@@ -546,11 +516,9 @@ static void distributeFunctionTypeAttr(TypeProcessingState &state,
/// Try to distribute a function type attribute to the innermost
/// function chunk or type. Returns true if the attribute was
/// distributed, false if no location was found.
-static bool
-distributeFunctionTypeAttrToInnermost(TypeProcessingState &state,
- AttributeList &attr,
- AttributeList *&attrList,
- QualType &declSpecType) {
+static bool distributeFunctionTypeAttrToInnermost(
+ TypeProcessingState &state, ParsedAttr &attr,
+ ParsedAttributesView &attrList, QualType &declSpecType) {
Declarator &declarator = state.getDeclarator();
// Put it on the innermost function chunk, if there is one.
@@ -558,7 +526,7 @@ distributeFunctionTypeAttrToInnermost(TypeProcessingState &state,
DeclaratorChunk &chunk = declarator.getTypeObject(i);
if (chunk.Kind != DeclaratorChunk::Function) continue;
- moveAttrFromListToList(attr, attrList, chunk.getAttrListRef());
+ moveAttrFromListToList(attr, attrList, chunk.getAttrs());
return true;
}
@@ -567,25 +535,23 @@ distributeFunctionTypeAttrToInnermost(TypeProcessingState &state,
/// A function type attribute was written in the decl spec. Try to
/// apply it somewhere.
-static void
-distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state,
- AttributeList &attr,
- QualType &declSpecType) {
+static void distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state,
+ ParsedAttr &attr,
+ QualType &declSpecType) {
state.saveDeclSpecAttrs();
// C++11 attributes before the decl specifiers actually appertain to
// the declarators. Move them straight there. We don't support the
// 'put them wherever you like' semantics we allow for GNU attributes.
if (attr.isCXX11Attribute()) {
- moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
- state.getDeclarator().getAttrListRef());
+ moveAttrFromListToList(attr, state.getCurrentAttributes(),
+ state.getDeclarator().getAttributes());
return;
}
// Try to distribute to the innermost.
- if (distributeFunctionTypeAttrToInnermost(state, attr,
- state.getCurrentAttrListRef(),
- declSpecType))
+ if (distributeFunctionTypeAttrToInnermost(
+ state, attr, state.getCurrentAttributes(), declSpecType))
return;
// If that failed, diagnose the bad attribute when the declarator is
@@ -595,25 +561,23 @@ distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state,
/// A function type attribute was written on the declarator. Try to
/// apply it somewhere.
-static void
-distributeFunctionTypeAttrFromDeclarator(TypeProcessingState &state,
- AttributeList &attr,
- QualType &declSpecType) {
+static void distributeFunctionTypeAttrFromDeclarator(TypeProcessingState &state,
+ ParsedAttr &attr,
+ QualType &declSpecType) {
Declarator &declarator = state.getDeclarator();
// Try to distribute to the innermost.
- if (distributeFunctionTypeAttrToInnermost(state, attr,
- declarator.getAttrListRef(),
- declSpecType))
+ if (distributeFunctionTypeAttrToInnermost(
+ state, attr, declarator.getAttributes(), declSpecType))
return;
// If that failed, diagnose the bad attribute when the declarator is
// fully built.
- spliceAttrOutOfList(attr, declarator.getAttrListRef());
+ declarator.getAttributes().remove(&attr);
state.addIgnoredTypeAttr(attr);
}
-/// \brief Given that there are attributes written on the declarator
+/// Given that there are attributes written on the declarator
/// itself, try to distribute any type attributes to the appropriate
/// declarator chunk.
///
@@ -625,24 +589,25 @@ distributeFunctionTypeAttrFromDeclarator(TypeProcessingState &state,
static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state,
QualType &declSpecType) {
// Collect all the type attributes from the declarator itself.
- assert(state.getDeclarator().getAttributes() && "declarator has no attrs!");
- AttributeList *attr = state.getDeclarator().getAttributes();
- AttributeList *next;
- do {
- next = attr->getNext();
-
+ assert(!state.getDeclarator().getAttributes().empty() &&
+ "declarator has no attrs!");
+ // The called functions in this loop actually remove things from the current
+ // list, so iterating over the existing list isn't possible. Instead, make a
+ // non-owning copy and iterate over that.
+ ParsedAttributesView AttrsCopy{state.getDeclarator().getAttributes()};
+ for (ParsedAttr &attr : AttrsCopy) {
// Do not distribute C++11 attributes. They have strict rules for what
// they appertain to.
- if (attr->isCXX11Attribute())
+ if (attr.isCXX11Attribute())
continue;
- switch (attr->getKind()) {
+ switch (attr.getKind()) {
OBJC_POINTER_TYPE_ATTRS_CASELIST:
- distributeObjCPointerTypeAttrFromDeclarator(state, *attr, declSpecType);
+ distributeObjCPointerTypeAttrFromDeclarator(state, attr, declSpecType);
break;
FUNCTION_TYPE_ATTRS_CASELIST:
- distributeFunctionTypeAttrFromDeclarator(state, *attr, declSpecType);
+ distributeFunctionTypeAttrFromDeclarator(state, attr, declSpecType);
break;
MS_TYPE_ATTRS_CASELIST:
@@ -653,13 +618,13 @@ static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state,
// Nullability specifiers cannot go after the declarator-id.
// Objective-C __kindof does not get distributed.
- case AttributeList::AT_ObjCKindOf:
+ case ParsedAttr::AT_ObjCKindOf:
continue;
default:
break;
}
- } while ((attr = next));
+ }
}
/// Add a synthetic '()' to a block-literal declarator if it is
@@ -759,28 +724,18 @@ static bool checkOmittedBlockReturnType(Sema &S, Declarator &declarator,
return false;
// Warn if we see type attributes for omitted return type on a block literal.
- AttributeList *&attrs =
- declarator.getMutableDeclSpec().getAttributes().getListRef();
- AttributeList *prev = nullptr;
- for (AttributeList *cur = attrs; cur; cur = cur->getNext()) {
- AttributeList &attr = *cur;
- // Skip attributes that were marked to be invalid or non-type
- // attributes.
- if (attr.isInvalid() || !attr.isTypeAttr()) {
- prev = cur;
+ SmallVector<ParsedAttr *, 2> ToBeRemoved;
+ for (ParsedAttr &AL : declarator.getMutableDeclSpec().getAttributes()) {
+ if (AL.isInvalid() || !AL.isTypeAttr())
continue;
- }
- S.Diag(attr.getLoc(),
+ S.Diag(AL.getLoc(),
diag::warn_block_literal_attributes_on_omitted_return_type)
- << attr.getName();
- // Remove cur from the list.
- if (prev) {
- prev->setNext(cur->getNext());
- prev = cur;
- } else {
- attrs = cur->getNext();
- }
+ << AL.getName();
+ ToBeRemoved.push_back(&AL);
}
+ // Remove bad attributes from the list.
+ for (ParsedAttr *AL : ToBeRemoved)
+ declarator.getMutableDeclSpec().getAttributes().remove(AL);
// Warn if we see type qualifiers for omitted return type on a block literal.
const DeclSpec &DS = declarator.getDeclSpec();
@@ -1208,22 +1163,15 @@ TypeResult Sema::actOnObjCTypeArgsAndProtocolQualifiers(
return CreateParsedType(Result, ResultTInfo);
}
-static OpenCLAccessAttr::Spelling getImageAccess(const AttributeList *Attrs) {
- if (Attrs) {
- const AttributeList *Next = Attrs;
- do {
- const AttributeList &Attr = *Next;
- Next = Attr.getNext();
- if (Attr.getKind() == AttributeList::AT_OpenCLAccess) {
- return static_cast<OpenCLAccessAttr::Spelling>(
- Attr.getSemanticSpelling());
- }
- } while (Next);
- }
+static OpenCLAccessAttr::Spelling
+getImageAccess(const ParsedAttributesView &Attrs) {
+ for (const ParsedAttr &AL : Attrs)
+ if (AL.getKind() == ParsedAttr::AT_OpenCLAccess)
+ return static_cast<OpenCLAccessAttr::Spelling>(AL.getSemanticSpelling());
return OpenCLAccessAttr::Keyword_read_only;
}
-/// \brief Convert the specified declspec to the appropriate type
+/// Convert the specified declspec to the appropriate type
/// object.
/// \param state Specifies the declarator containing the declaration specifier
/// to be converted, along with other associated processing state.
@@ -1235,7 +1183,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
Sema &S = state.getSema();
Declarator &declarator = state.getDeclarator();
- const DeclSpec &DS = declarator.getDeclSpec();
+ DeclSpec &DS = declarator.getMutableDeclSpec();
SourceLocation DeclLoc = declarator.getIdentifierLoc();
if (DeclLoc.isInvalid())
DeclLoc = DS.getLocStart();
@@ -1275,6 +1223,11 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
Result = Context.getUnsignedWCharType();
}
break;
+ case DeclSpec::TST_char8:
+ assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
+ "Unknown TSS value");
+ Result = Context.Char8Ty;
+ break;
case DeclSpec::TST_char16:
assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
"Unknown TSS value");
@@ -1384,6 +1337,52 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
}
break;
}
+ case DeclSpec::TST_accum: {
+ switch (DS.getTypeSpecWidth()) {
+ case DeclSpec::TSW_short:
+ Result = Context.ShortAccumTy;
+ break;
+ case DeclSpec::TSW_unspecified:
+ Result = Context.AccumTy;
+ break;
+ case DeclSpec::TSW_long:
+ Result = Context.LongAccumTy;
+ break;
+ case DeclSpec::TSW_longlong:
+ llvm_unreachable("Unable to specify long long as _Accum width");
+ }
+
+ if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned)
+ Result = Context.getCorrespondingUnsignedType(Result);
+
+ if (DS.isTypeSpecSat())
+ Result = Context.getCorrespondingSaturatedType(Result);
+
+ break;
+ }
+ case DeclSpec::TST_fract: {
+ switch (DS.getTypeSpecWidth()) {
+ case DeclSpec::TSW_short:
+ Result = Context.ShortFractTy;
+ break;
+ case DeclSpec::TSW_unspecified:
+ Result = Context.FractTy;
+ break;
+ case DeclSpec::TSW_long:
+ Result = Context.LongFractTy;
+ break;
+ case DeclSpec::TSW_longlong:
+ llvm_unreachable("Unable to specify long long as _Fract width");
+ }
+
+ if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned)
+ Result = Context.getCorrespondingUnsignedType(Result);
+
+ if (DS.isTypeSpecSat())
+ Result = Context.getCorrespondingSaturatedType(Result);
+
+ break;
+ }
case DeclSpec::TST_int128:
if (!S.Context.getTargetInfo().hasInt128Type())
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported)
@@ -1422,7 +1421,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
case DeclSpec::TST_union:
case DeclSpec::TST_struct:
case DeclSpec::TST_interface: {
- TypeDecl *D = dyn_cast_or_null<TypeDecl>(DS.getRepAsDecl());
+ TagDecl *D = dyn_cast_or_null<TagDecl>(DS.getRepAsDecl());
if (!D) {
// This can happen in C++ with ambiguous lookups.
Result = Context.IntTy;
@@ -1442,7 +1441,8 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// In both C and C++, make an ElaboratedType.
ElaboratedTypeKeyword Keyword
= ElaboratedType::getKeywordForTypeSpec(DS.getTypeSpecType());
- Result = S.getElaboratedType(Keyword, DS.getTypeSpecScope(), Result);
+ Result = S.getElaboratedType(Keyword, DS.getTypeSpecScope(), Result,
+ DS.isTypeSpecOwned() ? D : nullptr);
break;
}
case DeclSpec::TST_typename: {
@@ -1528,16 +1528,19 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
}
break;
-#define GENERIC_IMAGE_TYPE(ImgType, Id) \
- case DeclSpec::TST_##ImgType##_t: \
- switch (getImageAccess(DS.getAttributes().getList())) { \
- case OpenCLAccessAttr::Keyword_write_only: \
- Result = Context.Id##WOTy; break; \
- case OpenCLAccessAttr::Keyword_read_write: \
- Result = Context.Id##RWTy; break; \
- case OpenCLAccessAttr::Keyword_read_only: \
- Result = Context.Id##ROTy; break; \
- } \
+#define GENERIC_IMAGE_TYPE(ImgType, Id) \
+ case DeclSpec::TST_##ImgType##_t: \
+ switch (getImageAccess(DS.getAttributes())) { \
+ case OpenCLAccessAttr::Keyword_write_only: \
+ Result = Context.Id##WOTy; \
+ break; \
+ case OpenCLAccessAttr::Keyword_read_write: \
+ Result = Context.Id##RWTy; \
+ break; \
+ case OpenCLAccessAttr::Keyword_read_only: \
+ Result = Context.Id##ROTy; \
+ break; \
+ } \
break;
#include "clang/Basic/OpenCLImageTypes.def"
@@ -1551,6 +1554,15 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
S.checkOpenCLDisabledTypeDeclSpec(DS, Result))
declarator.setInvalidType(true);
+ bool IsFixedPointType = DS.getTypeSpecType() == DeclSpec::TST_accum ||
+ DS.getTypeSpecType() == DeclSpec::TST_fract;
+
+ // Only fixed point types can be saturated
+ if (DS.isTypeSpecSat() && !IsFixedPointType)
+ S.Diag(DS.getTypeSpecSatLoc(), diag::err_invalid_saturation_spec)
+ << DS.getSpecifierName(DS.getTypeSpecType(),
+ Context.getPrintingPolicy());
+
// Handle complex types.
if (DS.getTypeSpecComplex() == DeclSpec::TSC_complex) {
if (S.getLangOpts().Freestanding)
@@ -1581,7 +1593,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// attributes are pushed around.
// pipe attributes will be handled later ( at GetFullTypeForDeclarator )
if (!DS.isTypeSpecPipe())
- processTypeAttrs(state, Result, TAL_DeclSpec, DS.getAttributes().getList());
+ processTypeAttrs(state, Result, TAL_DeclSpec, DS.getAttributes());
// Apply const/volatile/restrict qualifiers to T.
if (unsigned TypeQuals = DS.getTypeQualifiers()) {
@@ -1748,7 +1760,7 @@ QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
return BuildQualifiedType(T, Loc, Q, DS);
}
-/// \brief Build a paren type including \p T.
+/// Build a paren type including \p T.
QualType Sema::BuildParenType(QualType T) {
return Context.getParenType(T);
}
@@ -1858,7 +1870,7 @@ static bool checkQualifiedFunction(Sema &S, QualType T, SourceLocation Loc,
return true;
}
-/// \brief Build a pointer type.
+/// Build a pointer type.
///
/// \param T The type to which we'll be building a pointer.
///
@@ -1898,7 +1910,7 @@ QualType Sema::BuildPointerType(QualType T,
return Context.getPointerType(T);
}
-/// \brief Build a reference type.
+/// Build a reference type.
///
/// \param T The type to which we'll be building a reference.
///
@@ -1960,7 +1972,7 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
return Context.getRValueReferenceType(T);
}
-/// \brief Build a Read-only Pipe type.
+/// Build a Read-only Pipe type.
///
/// \param T The type to which we'll be building a Pipe.
///
@@ -1972,7 +1984,7 @@ QualType Sema::BuildReadPipeType(QualType T, SourceLocation Loc) {
return Context.getReadPipeType(T);
}
-/// \brief Build a Write-only Pipe type.
+/// Build a Write-only Pipe type.
///
/// \param T The type to which we'll be building a Pipe.
///
@@ -2006,7 +2018,7 @@ static bool isArraySizeVLA(Sema &S, Expr *ArraySize, llvm::APSInt &SizeVal) {
S.LangOpts.OpenCL).isInvalid();
}
-/// \brief Build an array type.
+/// Build an array type.
///
/// \param T The type of each element in the array.
///
@@ -2231,7 +2243,59 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
return T;
}
-/// \brief Build an ext-vector type.
+QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr,
+ SourceLocation AttrLoc) {
+ // The base type must be integer (not Boolean or enumeration) or float, and
+ // can't already be a vector.
+ if (!CurType->isDependentType() &&
+ (!CurType->isBuiltinType() || CurType->isBooleanType() ||
+ (!CurType->isIntegerType() && !CurType->isRealFloatingType()))) {
+ Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << CurType;
+ return QualType();
+ }
+
+ if (SizeExpr->isTypeDependent() || SizeExpr->isValueDependent())
+ return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc,
+ VectorType::GenericVector);
+
+ llvm::APSInt VecSize(32);
+ if (!SizeExpr->isIntegerConstantExpr(VecSize, Context)) {
+ Diag(AttrLoc, diag::err_attribute_argument_type)
+ << "vector_size" << AANT_ArgumentIntegerConstant
+ << SizeExpr->getSourceRange();
+ return QualType();
+ }
+
+ if (CurType->isDependentType())
+ return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc,
+ VectorType::GenericVector);
+
+ unsigned VectorSize = static_cast<unsigned>(VecSize.getZExtValue() * 8);
+ unsigned TypeSize = static_cast<unsigned>(Context.getTypeSize(CurType));
+
+ if (VectorSize == 0) {
+ Diag(AttrLoc, diag::err_attribute_zero_size) << SizeExpr->getSourceRange();
+ return QualType();
+ }
+
+ // vecSize is specified in bytes - convert to bits.
+ if (VectorSize % TypeSize) {
+ Diag(AttrLoc, diag::err_attribute_invalid_size)
+ << SizeExpr->getSourceRange();
+ return QualType();
+ }
+
+ if (VectorType::isVectorSizeTooLarge(VectorSize / TypeSize)) {
+ Diag(AttrLoc, diag::err_attribute_size_too_large)
+ << SizeExpr->getSourceRange();
+ return QualType();
+ }
+
+ return Context.getVectorType(CurType, VectorSize / TypeSize,
+ VectorType::GenericVector);
+}
+
+/// Build an ext-vector type.
///
/// Run the required checks for the extended vector type.
QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize,
@@ -2402,7 +2466,7 @@ QualType Sema::BuildFunctionType(QualType T,
return Context.getFunctionType(T, ParamTypes, EPI);
}
-/// \brief Build a member pointer type \c T Class::*.
+/// Build a member pointer type \c T Class::*.
///
/// \param T the type to which the member pointer refers.
/// \param Class the class type into which the member pointer points.
@@ -2451,7 +2515,7 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
return Context.getMemberPointerType(T, Class.getTypePtr());
}
-/// \brief Build a block pointer type.
+/// Build a block pointer type.
///
/// \param T The type to which we'll be building a block pointer.
///
@@ -2583,9 +2647,8 @@ static void inferARCWriteback(TypeProcessingState &state,
if (chunk.Kind != DeclaratorChunk::Pointer &&
chunk.Kind != DeclaratorChunk::BlockPointer)
return;
- for (const AttributeList *attr = chunk.getAttrs(); attr;
- attr = attr->getNext())
- if (attr->getKind() == AttributeList::AT_ObjCOwnership)
+ for (const ParsedAttr &AL : chunk.getAttrs())
+ if (AL.getKind() == ParsedAttr::AT_ObjCOwnership)
return;
transferARCOwnershipToDeclaratorChunk(state, Qualifiers::OCL_Autoreleasing,
@@ -2750,7 +2813,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// "void" instead.
T = SemaRef.Context.VoidTy;
processTypeAttrs(state, T, TAL_DeclSpec,
- D.getDeclSpec().getAttributes().getList());
+ D.getMutableDeclSpec().getAttributes());
break;
case UnqualifiedIdKind::IK_DeductionGuideName:
@@ -2767,7 +2830,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
break;
}
- if (D.getAttributes())
+ if (!D.getAttributes().empty())
distributeTypeAttrsFromDeclarator(state, T);
// C++11 [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context.
@@ -2851,6 +2914,14 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
case DeclaratorContext::BlockLiteralContext:
Error = 9; // Block literal
break;
+ case DeclaratorContext::TemplateArgContext:
+ // Within a template argument list, a deduced template specialization
+ // type will be reinterpreted as a template template argument.
+ if (isa<DeducedTemplateSpecializationType>(Deduced) &&
+ !D.getNumTypeObjects() &&
+ D.getDeclSpec().getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier)
+ break;
+ LLVM_FALLTHROUGH;
case DeclaratorContext::TemplateTypeArgContext:
Error = 10; // Template type argument
break;
@@ -2859,6 +2930,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
Error = 12; // Type alias
break;
case DeclaratorContext::TrailingReturnContext:
+ case DeclaratorContext::TrailingReturnVarContext:
if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType)
Error = 13; // Function return type
break;
@@ -2945,9 +3017,11 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
T = SemaRef.Context.IntTy;
D.setInvalidType(true);
- } else if (!HaveTrailing) {
+ } else if (!HaveTrailing &&
+ 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;
@@ -2961,6 +3035,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
unsigned DiagID = 0;
switch (D.getContext()) {
case DeclaratorContext::TrailingReturnContext:
+ case DeclaratorContext::TrailingReturnVarContext:
// Class and enumeration definitions are syntactically not allowed in
// trailing return types.
llvm_unreachable("parser should not have allowed this");
@@ -2988,6 +3063,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
case DeclaratorContext::CXXNewContext:
case DeclaratorContext::CXXCatchContext:
case DeclaratorContext::ObjCCatchContext:
+ case DeclaratorContext::TemplateArgContext:
case DeclaratorContext::TemplateTypeArgContext:
DiagID = diag::err_type_defined_in_type_specifier;
break;
@@ -3238,21 +3314,20 @@ static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) {
/// this is the outermost chunk, then we can determine the CC from the
/// declarator context. If not, then this could be either a member function
/// type or normal function type.
-static CallingConv
-getCCForDeclaratorChunk(Sema &S, Declarator &D,
- const DeclaratorChunk::FunctionTypeInfo &FTI,
- unsigned ChunkIndex) {
+static CallingConv getCCForDeclaratorChunk(
+ Sema &S, Declarator &D, const ParsedAttributesView &AttrList,
+ const DeclaratorChunk::FunctionTypeInfo &FTI, unsigned ChunkIndex) {
assert(D.getTypeObject(ChunkIndex).Kind == DeclaratorChunk::Function);
// Check for an explicit CC attribute.
- for (auto Attr = FTI.AttrList; Attr; Attr = Attr->getNext()) {
- switch (Attr->getKind()) {
- CALLING_CONV_ATTRS_CASELIST: {
+ for (const ParsedAttr &AL : AttrList) {
+ switch (AL.getKind()) {
+ CALLING_CONV_ATTRS_CASELIST : {
// Ignore attributes that don't validate or can't apply to the
// function type. We'll diagnose the failure to apply them in
// handleFunctionTypeAttr.
CallingConv CC;
- if (!S.CheckCallingConvAttr(*Attr, CC) &&
+ if (!S.CheckCallingConvAttr(AL, CC) &&
(!FTI.isVariadic || supportsVariadicCall(CC))) {
return CC;
}
@@ -3308,9 +3383,8 @@ getCCForDeclaratorChunk(Sema &S, Declarator &D,
// convention attribute. This is the simplest place to infer
// calling convention for OpenCL kernels.
if (S.getLangOpts().OpenCL) {
- for (const AttributeList *Attr = D.getDeclSpec().getAttributes().getList();
- Attr; Attr = Attr->getNext()) {
- if (Attr->getKind() == AttributeList::AT_OpenCLKernel) {
+ for (const ParsedAttr &AL : D.getDeclSpec().getAttributes()) {
+ if (AL.getKind() == ParsedAttr::AT_OpenCLKernel) {
CC = CC_OpenCLKernel;
break;
}
@@ -3361,12 +3435,11 @@ IdentifierInfo *Sema::getNSErrorIdent() {
/// Check whether there is a nullability attribute of any kind in the given
/// attribute list.
-static bool hasNullabilityAttr(const AttributeList *attrs) {
- for (const AttributeList *attr = attrs; attr;
- attr = attr->getNext()) {
- if (attr->getKind() == AttributeList::AT_TypeNonNull ||
- attr->getKind() == AttributeList::AT_TypeNullable ||
- attr->getKind() == AttributeList::AT_TypeNullUnspecified)
+static bool hasNullabilityAttr(const ParsedAttributesView &attrs) {
+ for (const ParsedAttr &AL : attrs) {
+ if (AL.getKind() == ParsedAttr::AT_TypeNonNull ||
+ AL.getKind() == ParsedAttr::AT_TypeNullable ||
+ AL.getKind() == ParsedAttr::AT_TypeNullUnspecified)
return true;
}
@@ -3914,6 +3987,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case DeclaratorContext::ObjCResultContext:
case DeclaratorContext::PrototypeContext:
case DeclaratorContext::TrailingReturnContext:
+ case DeclaratorContext::TrailingReturnVarContext:
isFunctionOrMethod = true;
LLVM_FALLTHROUGH;
@@ -3967,19 +4041,15 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// On pointer-to-pointer parameters marked cf_returns_retained or
// cf_returns_not_retained, if the outer pointer is explicit then
// infer the inner pointer as _Nullable.
- auto hasCFReturnsAttr = [](const AttributeList *NextAttr) -> bool {
- while (NextAttr) {
- if (NextAttr->getKind() == AttributeList::AT_CFReturnsRetained ||
- NextAttr->getKind() == AttributeList::AT_CFReturnsNotRetained)
- return true;
- NextAttr = NextAttr->getNext();
- }
- return false;
+ auto hasCFReturnsAttr =
+ [](const ParsedAttributesView &AttrList) -> bool {
+ return AttrList.hasAttribute(ParsedAttr::AT_CFReturnsRetained) ||
+ AttrList.hasAttribute(ParsedAttr::AT_CFReturnsNotRetained);
};
if (const auto *InnermostChunk = D.getInnermostNonParenChunk()) {
if (hasCFReturnsAttr(D.getAttributes()) ||
hasCFReturnsAttr(InnermostChunk->getAttrs()) ||
- hasCFReturnsAttr(D.getDeclSpec().getAttributes().getList())) {
+ hasCFReturnsAttr(D.getDeclSpec().getAttributes())) {
inferNullability = NullabilityKind::Nullable;
inferNullabilityInnerOnly = true;
}
@@ -4007,6 +4077,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case DeclaratorContext::LambdaExprParameterContext:
case DeclaratorContext::ObjCCatchContext:
case DeclaratorContext::TemplateParamContext:
+ case DeclaratorContext::TemplateArgContext:
case DeclaratorContext::TemplateTypeArgContext:
case DeclaratorContext::TypeNameContext:
case DeclaratorContext::FunctionalCastContext:
@@ -4034,10 +4105,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Local function that checks the nullability for a given pointer declarator.
// Returns true if _Nonnull was inferred.
- auto inferPointerNullability = [&](SimplePointerKind pointerKind,
- SourceLocation pointerLoc,
- SourceLocation pointerEndLoc,
- AttributeList *&attrs) -> AttributeList * {
+ auto inferPointerNullability =
+ [&](SimplePointerKind pointerKind, SourceLocation pointerLoc,
+ SourceLocation pointerEndLoc,
+ ParsedAttributesView &attrs) -> ParsedAttr * {
// We've seen a pointer.
if (NumPointersRemaining > 0)
--NumPointersRemaining;
@@ -4048,18 +4119,16 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// If we're supposed to infer nullability, do so now.
if (inferNullability && !inferNullabilityInnerOnlyComplete) {
- AttributeList::Syntax syntax
- = inferNullabilityCS ? AttributeList::AS_ContextSensitiveKeyword
- : AttributeList::AS_Keyword;
- AttributeList *nullabilityAttr = state.getDeclarator().getAttributePool()
- .create(
- S.getNullabilityKeyword(
- *inferNullability),
- SourceRange(pointerLoc),
- nullptr, SourceLocation(),
- nullptr, 0, syntax);
-
- spliceAttrIntoList(*nullabilityAttr, attrs);
+ ParsedAttr::Syntax syntax = inferNullabilityCS
+ ? ParsedAttr::AS_ContextSensitiveKeyword
+ : ParsedAttr::AS_Keyword;
+ ParsedAttr *nullabilityAttr =
+ state.getDeclarator().getAttributePool().create(
+ S.getNullabilityKeyword(*inferNullability),
+ SourceRange(pointerLoc), nullptr, SourceLocation(), nullptr, 0,
+ syntax);
+
+ attrs.addAtStart(nullabilityAttr);
if (inferNullabilityCS) {
state.getDeclarator().getMutableDeclSpec().getObjCQualifiers()
@@ -4114,9 +4183,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
pointerKind = SimplePointerKind::MemberPointer;
if (auto *attr = inferPointerNullability(
- pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(),
- D.getDeclSpec().getLocEnd(),
- D.getMutableDeclSpec().getAttributes().getListRef())) {
+ pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(),
+ D.getDeclSpec().getLocEnd(),
+ D.getMutableDeclSpec().getAttributes())) {
T = Context.getAttributedType(
AttributedType::getNullabilityAttrKind(*inferNullability),T,T);
attr->setUsedAsTypeAttr();
@@ -4154,7 +4223,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Handle pointer nullability.
inferPointerNullability(SimplePointerKind::BlockPointer, DeclType.Loc,
- DeclType.EndLoc, DeclType.getAttrListRef());
+ DeclType.EndLoc, DeclType.getAttrs());
T = S.BuildBlockPointerType(T, D.getIdentifierLoc(), Name);
if (DeclType.Cls.TypeQuals || LangOpts.OpenCL) {
@@ -4176,7 +4245,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Handle pointer nullability
inferPointerNullability(SimplePointerKind::Pointer, DeclType.Loc,
- DeclType.EndLoc, DeclType.getAttrListRef());
+ DeclType.EndLoc, DeclType.getAttrs());
if (LangOpts.ObjC1 && T->getAs<ObjCObjectType>()) {
T = Context.getObjCObjectPointerType(T);
@@ -4450,20 +4519,17 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
SourceLocation AttrLoc;
if (chunkIndex + 1 < D.getNumTypeObjects()) {
DeclaratorChunk ReturnTypeChunk = D.getTypeObject(chunkIndex + 1);
- for (const AttributeList *Attr = ReturnTypeChunk.getAttrs();
- Attr; Attr = Attr->getNext()) {
- if (Attr->getKind() == AttributeList::AT_ObjCOwnership) {
- AttrLoc = Attr->getLoc();
+ for (const ParsedAttr &AL : ReturnTypeChunk.getAttrs()) {
+ if (AL.getKind() == ParsedAttr::AT_ObjCOwnership) {
+ AttrLoc = AL.getLoc();
break;
}
}
}
if (AttrLoc.isInvalid()) {
- for (const AttributeList *Attr
- = D.getDeclSpec().getAttributes().getList();
- Attr; Attr = Attr->getNext()) {
- if (Attr->getKind() == AttributeList::AT_ObjCOwnership) {
- AttrLoc = Attr->getLoc();
+ for (const ParsedAttr &AL : D.getDeclSpec().getAttributes()) {
+ if (AL.getKind() == ParsedAttr::AT_ObjCOwnership) {
+ AttrLoc = AL.getLoc();
break;
}
}
@@ -4474,7 +4540,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// the predefined
// __strong/__weak/__autoreleasing/__unsafe_unretained.
if (AttrLoc.isMacroID())
- AttrLoc = S.SourceMgr.getImmediateExpansionRange(AttrLoc).first;
+ AttrLoc =
+ S.SourceMgr.getImmediateExpansionRange(AttrLoc).getBegin();
S.Diag(AttrLoc, diag::warn_arc_lifetime_result_type)
<< T.getQualifiers().getObjCLifetime();
@@ -4502,7 +4569,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (FTI.isAmbiguous)
warnAboutAmbiguousFunction(S, D, DeclType, T);
- FunctionType::ExtInfo EI(getCCForDeclaratorChunk(S, D, FTI, chunkIndex));
+ FunctionType::ExtInfo EI(
+ getCCForDeclaratorChunk(S, D, DeclType.getAttrs(), FTI, chunkIndex));
if (!FTI.NumParams && !FTI.isVariadic && !LangOpts.CPlusPlus
&& !LangOpts.OpenCL) {
@@ -4512,19 +4580,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// We allow a zero-parameter variadic function in C if the
// function is marked with the "overloadable" attribute. Scan
// for this attribute now.
- if (!FTI.NumParams && FTI.isVariadic && !LangOpts.CPlusPlus) {
- bool Overloadable = false;
- for (const AttributeList *Attrs = D.getAttributes();
- Attrs; Attrs = Attrs->getNext()) {
- if (Attrs->getKind() == AttributeList::AT_Overloadable) {
- Overloadable = true;
- break;
- }
- }
-
- if (!Overloadable)
+ if (!FTI.NumParams && FTI.isVariadic && !LangOpts.CPlusPlus)
+ if (!D.getAttributes().hasAttribute(ParsedAttr::AT_Overloadable))
S.Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_param);
- }
if (FTI.NumParams && FTI.Params[0].Param == nullptr) {
// C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function
@@ -4656,7 +4714,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
DynamicExceptions.push_back(FTI.Exceptions[I].Ty);
DynamicExceptionRanges.push_back(FTI.Exceptions[I].Range);
}
- } else if (FTI.getExceptionSpecType() == EST_ComputedNoexcept) {
+ } else if (isComputedNoexcept(FTI.getExceptionSpecType())) {
NoexceptExpr = FTI.NoexceptExpr;
}
@@ -4679,7 +4737,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Handle pointer nullability.
inferPointerNullability(SimplePointerKind::MemberPointer, DeclType.Loc,
- DeclType.EndLoc, DeclType.getAttrListRef());
+ DeclType.EndLoc, DeclType.getAttrs());
if (SS.isInvalid()) {
// Avoid emitting extra errors if we already errored on the scope.
@@ -4735,7 +4793,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case DeclaratorChunk::Pipe: {
T = S.BuildReadPipeType(T, DeclType.Loc);
processTypeAttrs(state, T, TAL_DeclSpec,
- D.getDeclSpec().getAttributes().getList());
+ D.getMutableDeclSpec().getAttributes());
break;
}
}
@@ -4746,8 +4804,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
// See if there are any attributes on this declarator chunk.
- processTypeAttrs(state, T, TAL_DeclChunk,
- const_cast<AttributeList *>(DeclType.getAttrs()));
+ processTypeAttrs(state, T, TAL_DeclChunk, DeclType.getAttrs());
}
// GNU warning -Wstrict-prototypes
@@ -4828,6 +4885,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
!(Kind == Member &&
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) &&
!IsTypedefName &&
+ D.getContext() != DeclaratorContext::TemplateArgContext &&
D.getContext() != DeclaratorContext::TemplateTypeArgContext) {
SourceLocation Loc = D.getLocStart();
SourceRange RemovalRange;
@@ -4845,8 +4903,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (Chunk.Fun.TypeQuals & Qualifiers::Restrict)
RemovalLocs.push_back(Chunk.Fun.getRestrictQualifierLoc());
if (!RemovalLocs.empty()) {
- std::sort(RemovalLocs.begin(), RemovalLocs.end(),
- BeforeThanCompare<SourceLocation>(S.getSourceManager()));
+ llvm::sort(RemovalLocs.begin(), RemovalLocs.end(),
+ BeforeThanCompare<SourceLocation>(S.getSourceManager()));
RemovalRange = SourceRange(RemovalLocs.front(), RemovalLocs.back());
Loc = RemovalLocs.front();
}
@@ -4954,6 +5012,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case DeclaratorContext::LambdaExprContext:
case DeclaratorContext::ConversionIdContext:
case DeclaratorContext::TrailingReturnContext:
+ case DeclaratorContext::TrailingReturnVarContext:
+ case DeclaratorContext::TemplateArgContext:
case DeclaratorContext::TemplateTypeArgContext:
// FIXME: We may want to allow parameter packs in block-literal contexts
// in the future.
@@ -5009,10 +5069,8 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state,
// Look for an explicit lifetime attribute.
DeclaratorChunk &chunk = D.getTypeObject(chunkIndex);
- for (const AttributeList *attr = chunk.getAttrs(); attr;
- attr = attr->getNext())
- if (attr->getKind() == AttributeList::AT_ObjCOwnership)
- return;
+ if (chunk.getAttrs().hasAttribute(ParsedAttr::AT_ObjCOwnership))
+ return;
const char *attrStr = nullptr;
switch (ownership) {
@@ -5031,16 +5089,15 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state,
// If there wasn't one, add one (with an invalid source location
// so that we don't make an AttributedType for it).
- AttributeList *attr = D.getAttributePool()
- .create(&S.Context.Idents.get("objc_ownership"), SourceLocation(),
- /*scope*/ nullptr, SourceLocation(),
- /*args*/ &Args, 1, AttributeList::AS_GNU);
- spliceAttrIntoList(*attr, chunk.getAttrListRef());
-
+ ParsedAttr *attr = D.getAttributePool().create(
+ &S.Context.Idents.get("objc_ownership"), SourceLocation(),
+ /*scope*/ nullptr, SourceLocation(),
+ /*args*/ &Args, 1, ParsedAttr::AS_GNU);
+ chunk.getAttrs().addAtStart(attr);
// TODO: mark whether we did this inference?
}
-/// \brief Used for transferring ownership in casts resulting in l-values.
+/// Used for transferring ownership in casts resulting in l-values.
static void transferARCOwnership(TypeProcessingState &state,
QualType &declSpecTy,
Qualifiers::ObjCLifetime ownership) {
@@ -5107,110 +5164,91 @@ TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) {
return GetFullTypeForDeclarator(state, declSpecTy, ReturnTypeInfo);
}
-/// Map an AttributedType::Kind to an AttributeList::Kind.
-static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
+/// Map an AttributedType::Kind to an ParsedAttr::Kind.
+static ParsedAttr::Kind getAttrListKind(AttributedType::Kind kind) {
switch (kind) {
case AttributedType::attr_address_space:
- return AttributeList::AT_AddressSpace;
+ return ParsedAttr::AT_AddressSpace;
case AttributedType::attr_regparm:
- return AttributeList::AT_Regparm;
+ return ParsedAttr::AT_Regparm;
case AttributedType::attr_vector_size:
- return AttributeList::AT_VectorSize;
+ return ParsedAttr::AT_VectorSize;
case AttributedType::attr_neon_vector_type:
- return AttributeList::AT_NeonVectorType;
+ return ParsedAttr::AT_NeonVectorType;
case AttributedType::attr_neon_polyvector_type:
- return AttributeList::AT_NeonPolyVectorType;
+ return ParsedAttr::AT_NeonPolyVectorType;
case AttributedType::attr_objc_gc:
- return AttributeList::AT_ObjCGC;
+ return ParsedAttr::AT_ObjCGC;
case AttributedType::attr_objc_ownership:
case AttributedType::attr_objc_inert_unsafe_unretained:
- return AttributeList::AT_ObjCOwnership;
+ return ParsedAttr::AT_ObjCOwnership;
case AttributedType::attr_noreturn:
- return AttributeList::AT_NoReturn;
+ return ParsedAttr::AT_NoReturn;
+ case AttributedType::attr_nocf_check:
+ return ParsedAttr::AT_AnyX86NoCfCheck;
case AttributedType::attr_cdecl:
- return AttributeList::AT_CDecl;
+ return ParsedAttr::AT_CDecl;
case AttributedType::attr_fastcall:
- return AttributeList::AT_FastCall;
+ return ParsedAttr::AT_FastCall;
case AttributedType::attr_stdcall:
- return AttributeList::AT_StdCall;
+ return ParsedAttr::AT_StdCall;
case AttributedType::attr_thiscall:
- return AttributeList::AT_ThisCall;
+ return ParsedAttr::AT_ThisCall;
case AttributedType::attr_regcall:
- return AttributeList::AT_RegCall;
+ return ParsedAttr::AT_RegCall;
case AttributedType::attr_pascal:
- return AttributeList::AT_Pascal;
+ return ParsedAttr::AT_Pascal;
case AttributedType::attr_swiftcall:
- return AttributeList::AT_SwiftCall;
+ return ParsedAttr::AT_SwiftCall;
case AttributedType::attr_vectorcall:
- return AttributeList::AT_VectorCall;
+ return ParsedAttr::AT_VectorCall;
case AttributedType::attr_pcs:
case AttributedType::attr_pcs_vfp:
- return AttributeList::AT_Pcs;
+ return ParsedAttr::AT_Pcs;
case AttributedType::attr_inteloclbicc:
- return AttributeList::AT_IntelOclBicc;
+ return ParsedAttr::AT_IntelOclBicc;
case AttributedType::attr_ms_abi:
- return AttributeList::AT_MSABI;
+ return ParsedAttr::AT_MSABI;
case AttributedType::attr_sysv_abi:
- return AttributeList::AT_SysVABI;
+ return ParsedAttr::AT_SysVABI;
case AttributedType::attr_preserve_most:
- return AttributeList::AT_PreserveMost;
+ return ParsedAttr::AT_PreserveMost;
case AttributedType::attr_preserve_all:
- return AttributeList::AT_PreserveAll;
+ return ParsedAttr::AT_PreserveAll;
case AttributedType::attr_ptr32:
- return AttributeList::AT_Ptr32;
+ return ParsedAttr::AT_Ptr32;
case AttributedType::attr_ptr64:
- return AttributeList::AT_Ptr64;
+ return ParsedAttr::AT_Ptr64;
case AttributedType::attr_sptr:
- return AttributeList::AT_SPtr;
+ return ParsedAttr::AT_SPtr;
case AttributedType::attr_uptr:
- return AttributeList::AT_UPtr;
+ return ParsedAttr::AT_UPtr;
case AttributedType::attr_nonnull:
- return AttributeList::AT_TypeNonNull;
+ return ParsedAttr::AT_TypeNonNull;
case AttributedType::attr_nullable:
- return AttributeList::AT_TypeNullable;
+ return ParsedAttr::AT_TypeNullable;
case AttributedType::attr_null_unspecified:
- return AttributeList::AT_TypeNullUnspecified;
+ return ParsedAttr::AT_TypeNullUnspecified;
case AttributedType::attr_objc_kindof:
- return AttributeList::AT_ObjCKindOf;
+ return ParsedAttr::AT_ObjCKindOf;
case AttributedType::attr_ns_returns_retained:
- return AttributeList::AT_NSReturnsRetained;
+ return ParsedAttr::AT_NSReturnsRetained;
}
llvm_unreachable("unexpected attribute kind!");
}
-static void fillAttributedTypeLoc(AttributedTypeLoc TL,
- const AttributeList *attrs,
- const AttributeList *DeclAttrs = nullptr) {
- // DeclAttrs and attrs cannot be both empty.
- assert((attrs || DeclAttrs) &&
- "no type attributes in the expected location!");
-
- AttributeList::Kind parsedKind = getAttrListKind(TL.getAttrKind());
- // Try to search for an attribute of matching kind in attrs list.
- while (attrs && attrs->getKind() != parsedKind)
- attrs = attrs->getNext();
- if (!attrs) {
- // No matching type attribute in attrs list found.
- // Try searching through C++11 attributes in the declarator attribute list.
- while (DeclAttrs && (!DeclAttrs->isCXX11Attribute() ||
- DeclAttrs->getKind() != parsedKind))
- DeclAttrs = DeclAttrs->getNext();
- attrs = DeclAttrs;
- }
-
- assert(attrs && "no matching type attribute in expected location!");
-
- TL.setAttrNameLoc(attrs->getLoc());
+static void setAttributedTypeLoc(AttributedTypeLoc TL, const ParsedAttr &attr) {
+ TL.setAttrNameLoc(attr.getLoc());
if (TL.hasAttrExprOperand()) {
- assert(attrs->isArgExpr(0) && "mismatched attribute operand kind");
- TL.setAttrExprOperand(attrs->getArgAsExpr(0));
+ assert(attr.isArgExpr(0) && "mismatched attribute operand kind");
+ TL.setAttrExprOperand(attr.getArgAsExpr(0));
} else if (TL.hasAttrEnumOperand()) {
- assert((attrs->isArgIdent(0) || attrs->isArgExpr(0)) &&
+ assert((attr.isArgIdent(0) || attr.isArgExpr(0)) &&
"unexpected attribute operand kind");
- if (attrs->isArgIdent(0))
- TL.setAttrEnumOperandLoc(attrs->getArgAsIdent(0)->Loc);
+ if (attr.isArgIdent(0))
+ TL.setAttrEnumOperandLoc(attr.getArgAsIdent(0)->Loc);
else
- TL.setAttrEnumOperandLoc(attrs->getArgAsExpr(0)->getExprLoc());
+ TL.setAttrEnumOperandLoc(attr.getArgAsExpr(0)->getExprLoc());
}
// FIXME: preserve this information to here.
@@ -5218,6 +5256,25 @@ static void fillAttributedTypeLoc(AttributedTypeLoc TL,
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!");
+}
+
namespace {
class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> {
ASTContext &Context;
@@ -5228,7 +5285,7 @@ namespace {
: Context(Context), DS(DS) {}
void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
- fillAttributedTypeLoc(TL, DS.getAttributes().getList());
+ fillAttributedTypeLoc(TL, DS.getAttributes(), ParsedAttributesView{});
Visit(TL.getModifiedLoc());
}
void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
@@ -5400,7 +5457,7 @@ namespace {
}
void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
- fillAttributedTypeLoc(TL, Chunk.getAttrs());
+ fillAttributedTypeLoc(TL, Chunk.getAttrs(), ParsedAttributesView{});
}
void VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
// nothing
@@ -5533,19 +5590,23 @@ static void fillAtomicQualLoc(AtomicTypeLoc ATL, const DeclaratorChunk &Chunk) {
ATL.setParensRange(SourceRange());
}
-static void fillDependentAddressSpaceTypeLoc(DependentAddressSpaceTypeLoc DASTL,
- const AttributeList *Attrs) {
- while (Attrs && Attrs->getKind() != AttributeList::AT_AddressSpace)
- Attrs = Attrs->getNext();
+static void
+fillDependentAddressSpaceTypeLoc(DependentAddressSpaceTypeLoc DASTL,
+ const ParsedAttributesView &Attrs) {
+ for (const ParsedAttr &AL : Attrs) {
+ if (AL.getKind() == ParsedAttr::AT_AddressSpace) {
+ DASTL.setAttrNameLoc(AL.getLoc());
+ DASTL.setAttrExprOperand(AL.getArgAsExpr(0));
+ DASTL.setAttrOperandParensRange(SourceRange());
+ return;
+ }
+ }
- assert(Attrs && "no address_space attribute found at the expected location!");
-
- DASTL.setAttrNameLoc(Attrs->getLoc());
- DASTL.setAttrExprOperand(Attrs->getArgAsExpr(0));
- DASTL.setAttrOperandParensRange(SourceRange());
+ llvm_unreachable(
+ "no address_space attribute found at the expected location!");
}
-/// \brief Create and instantiate a TypeSourceInfo with type source information.
+/// Create and instantiate a TypeSourceInfo with type source information.
///
/// \param T QualType referring to the type as written in source code.
///
@@ -5558,7 +5619,6 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
TypeSourceInfo *ReturnTypeInfo) {
TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T);
UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc();
- const AttributeList *DeclAttrs = D.getAttributes();
// Handle parameter packs whose type is a pack expansion.
if (isa<PackExpansionType>(T)) {
@@ -5582,7 +5642,8 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
}
while (AttributedTypeLoc TL = CurrTL.getAs<AttributedTypeLoc>()) {
- fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs(), DeclAttrs);
+ fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs(),
+ D.getAttributes());
CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
}
@@ -5607,7 +5668,7 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
return TInfo;
}
-/// \brief Create a LocInfoType to hold the given QualType and TypeSourceInfo.
+/// Create a LocInfoType to hold the given QualType and TypeSourceInfo.
ParsedType Sema::CreateParsedType(QualType T, TypeSourceInfo *TInfo) {
// FIXME: LocInfoTypes are "transient", only needed for passing to/from Parser
// and Sema during declaration parsing. Try deallocating/caching them when
@@ -5674,14 +5735,6 @@ QualType Sema::BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace,
SourceLocation AttrLoc) {
if (!AddrSpace->isValueDependent()) {
- // If this type is already address space qualified, reject it.
- // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "No type shall be qualified
- // by qualifiers for two or more different address spaces."
- if (T.getAddressSpace() != LangAS::Default) {
- Diag(AttrLoc, diag::err_attribute_address_multiple_qualifiers);
- return QualType();
- }
-
llvm::APSInt addrSpace(32);
if (!AddrSpace->isIntegerConstantExpr(addrSpace, Context)) {
Diag(AttrLoc, diag::err_attribute_argument_type)
@@ -5712,6 +5765,20 @@ QualType Sema::BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace,
LangAS ASIdx =
getLangASFromTargetAS(static_cast<unsigned>(addrSpace.getZExtValue()));
+ // If this type is already address space qualified with a different
+ // address space, reject it.
+ // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "No type shall be qualified
+ // by qualifiers for two or more different address spaces."
+ if (T.getAddressSpace() != LangAS::Default) {
+ if (T.getAddressSpace() != ASIdx) {
+ Diag(AttrLoc, diag::err_attribute_address_multiple_qualifiers);
+ return QualType();
+ } else
+ // Emit a warning if they are identical; it's likely unintended.
+ Diag(AttrLoc,
+ diag::warn_attribute_address_multiple_identical_qualifiers);
+ }
+
return Context.getAddrSpaceQualType(T, ASIdx);
}
@@ -5732,16 +5799,7 @@ 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 AttributeList &Attr, Sema &S){
- // If this type is already address space qualified, reject it.
- // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "No type shall be qualified by
- // qualifiers for two or more different address spaces."
- if (Type.getAddressSpace() != LangAS::Default) {
- S.Diag(Attr.getLoc(), diag::err_attribute_address_multiple_qualifiers);
- Attr.setInvalid();
- return;
- }
-
+ const ParsedAttr &Attr, Sema &S) {
// 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()) {
@@ -5751,7 +5809,7 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
}
LangAS ASIdx;
- if (Attr.getKind() == AttributeList::AT_AddressSpace) {
+ if (Attr.getKind() == ParsedAttr::AT_AddressSpace) {
// Check the attribute arguments.
if (Attr.getNumArgs() != 1) {
@@ -5790,20 +5848,35 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
} else {
// The keyword-based type attributes imply which address space to use.
switch (Attr.getKind()) {
- case AttributeList::AT_OpenCLGlobalAddressSpace:
+ case ParsedAttr::AT_OpenCLGlobalAddressSpace:
ASIdx = LangAS::opencl_global; break;
- case AttributeList::AT_OpenCLLocalAddressSpace:
+ case ParsedAttr::AT_OpenCLLocalAddressSpace:
ASIdx = LangAS::opencl_local; break;
- case AttributeList::AT_OpenCLConstantAddressSpace:
+ case ParsedAttr::AT_OpenCLConstantAddressSpace:
ASIdx = LangAS::opencl_constant; break;
- case AttributeList::AT_OpenCLGenericAddressSpace:
+ case ParsedAttr::AT_OpenCLGenericAddressSpace:
ASIdx = LangAS::opencl_generic; break;
- case AttributeList::AT_OpenCLPrivateAddressSpace:
+ case ParsedAttr::AT_OpenCLPrivateAddressSpace:
ASIdx = LangAS::opencl_private; break;
default:
llvm_unreachable("Invalid address space");
}
+ // If this type is already address space qualified with a different
+ // address space, reject it.
+ // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "No type shall be qualified by
+ // qualifiers for two or more different address spaces."
+ if (Type.getAddressSpace() != LangAS::Default) {
+ if (Type.getAddressSpace() != ASIdx) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_address_multiple_qualifiers);
+ Attr.setInvalid();
+ return;
+ } else
+ // Emit a warning if they are identical; it's likely unintended.
+ S.Diag(Attr.getLoc(),
+ diag::warn_attribute_address_multiple_identical_qualifiers);
+ }
+
Type = S.Context.getAddrSpaceQualType(Type, ASIdx);
}
}
@@ -5843,8 +5916,7 @@ static bool hasDirectOwnershipQualifier(QualType type) {
///
/// Returns 'true' if the attribute was handled.
static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
- AttributeList &attr,
- QualType &type) {
+ ParsedAttr &attr, QualType &type) {
bool NonObjCPointer = false;
if (!type->isDependentType() && !type->isUndeducedType()) {
@@ -5873,7 +5945,8 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
Sema &S = state.getSema();
SourceLocation AttrLoc = attr.getLoc();
if (AttrLoc.isMacroID())
- AttrLoc = S.getSourceManager().getImmediateExpansionRange(AttrLoc).first;
+ AttrLoc =
+ S.getSourceManager().getImmediateExpansionRange(AttrLoc).getBegin();
if (!attr.isArgIdent(0)) {
S.Diag(AttrLoc, diag::err_attribute_argument_type)
@@ -6028,8 +6101,7 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
/// attribute on the specified type. Returns true to indicate that
/// the attribute was handled, false to indicate that the type does
/// not permit the attribute.
-static bool handleObjCGCTypeAttr(TypeProcessingState &state,
- AttributeList &attr,
+static bool handleObjCGCTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
QualType &type) {
Sema &S = state.getSema();
@@ -6221,11 +6293,10 @@ namespace {
} // end anonymous namespace
static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
- AttributeList &Attr,
- QualType &Type) {
+ ParsedAttr &Attr, QualType &Type) {
Sema &S = State.getSema();
- AttributeList::Kind Kind = Attr.getKind();
+ ParsedAttr::Kind Kind = Attr.getKind();
QualType Desugared = Type;
const AttributedType *AT = dyn_cast<AttributedType>(Type);
while (AT) {
@@ -6242,16 +6313,16 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
// You cannot have both __sptr and __uptr on the same type, nor can you
// have __ptr32 and __ptr64.
if ((CurAttrKind == AttributedType::attr_ptr32 &&
- Kind == AttributeList::AT_Ptr64) ||
+ Kind == ParsedAttr::AT_Ptr64) ||
(CurAttrKind == AttributedType::attr_ptr64 &&
- Kind == AttributeList::AT_Ptr32)) {
+ Kind == ParsedAttr::AT_Ptr32)) {
S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
<< "'__ptr32'" << "'__ptr64'";
return true;
} else if ((CurAttrKind == AttributedType::attr_sptr &&
- Kind == AttributeList::AT_UPtr) ||
+ Kind == ParsedAttr::AT_UPtr) ||
(CurAttrKind == AttributedType::attr_uptr &&
- Kind == AttributeList::AT_SPtr)) {
+ Kind == ParsedAttr::AT_SPtr)) {
S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
<< "'__sptr'" << "'__uptr'";
return true;
@@ -6276,10 +6347,18 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
AttributedType::Kind TAK;
switch (Kind) {
default: llvm_unreachable("Unknown attribute kind");
- case AttributeList::AT_Ptr32: TAK = AttributedType::attr_ptr32; break;
- case AttributeList::AT_Ptr64: TAK = AttributedType::attr_ptr64; break;
- case AttributeList::AT_SPtr: TAK = AttributedType::attr_sptr; break;
- case AttributeList::AT_UPtr: TAK = AttributedType::attr_uptr; break;
+ 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);
@@ -6430,15 +6509,15 @@ bool Sema::checkObjCKindOfType(QualType &type, SourceLocation loc) {
}
/// Map a nullability attribute kind to a nullability kind.
-static NullabilityKind mapNullabilityAttrKind(AttributeList::Kind kind) {
+static NullabilityKind mapNullabilityAttrKind(ParsedAttr::Kind kind) {
switch (kind) {
- case AttributeList::AT_TypeNonNull:
+ case ParsedAttr::AT_TypeNonNull:
return NullabilityKind::NonNull;
- case AttributeList::AT_TypeNullable:
+ case ParsedAttr::AT_TypeNullable:
return NullabilityKind::Nullable;
- case AttributeList::AT_TypeNullUnspecified:
+ case ParsedAttr::AT_TypeNullUnspecified:
return NullabilityKind::Unspecified;
default:
@@ -6453,15 +6532,14 @@ static NullabilityKind mapNullabilityAttrKind(AttributeList::Kind kind) {
/// \returns true if the nullability annotation was distributed, false
/// otherwise.
static bool distributeNullabilityTypeAttr(TypeProcessingState &state,
- QualType type,
- AttributeList &attr) {
+ QualType type, ParsedAttr &attr) {
Declarator &declarator = state.getDeclarator();
/// Attempt to move the attribute to the specified chunk.
auto moveToChunk = [&](DeclaratorChunk &chunk, bool inFunction) -> bool {
// If there is already a nullability attribute there, don't add
// one.
- if (hasNullabilityAttr(chunk.getAttrListRef()))
+ if (hasNullabilityAttr(chunk.getAttrs()))
return false;
// Complain about the nullability qualifier being in the wrong
@@ -6494,8 +6572,8 @@ static bool distributeNullabilityTypeAttr(TypeProcessingState &state,
" " + attr.getName()->getName().str() + " ");
}
- moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
- chunk.getAttrListRef());
+ moveAttrFromListToList(attr, state.getCurrentAttributes(),
+ chunk.getAttrs());
return true;
};
@@ -6534,28 +6612,28 @@ static bool distributeNullabilityTypeAttr(TypeProcessingState &state,
return false;
}
-static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) {
+static AttributedType::Kind getCCTypeAttrKind(ParsedAttr &Attr) {
assert(!Attr.isInvalid());
switch (Attr.getKind()) {
default:
llvm_unreachable("not a calling convention attribute");
- case AttributeList::AT_CDecl:
+ case ParsedAttr::AT_CDecl:
return AttributedType::attr_cdecl;
- case AttributeList::AT_FastCall:
+ case ParsedAttr::AT_FastCall:
return AttributedType::attr_fastcall;
- case AttributeList::AT_StdCall:
+ case ParsedAttr::AT_StdCall:
return AttributedType::attr_stdcall;
- case AttributeList::AT_ThisCall:
+ case ParsedAttr::AT_ThisCall:
return AttributedType::attr_thiscall;
- case AttributeList::AT_RegCall:
+ case ParsedAttr::AT_RegCall:
return AttributedType::attr_regcall;
- case AttributeList::AT_Pascal:
+ case ParsedAttr::AT_Pascal:
return AttributedType::attr_pascal;
- case AttributeList::AT_SwiftCall:
+ case ParsedAttr::AT_SwiftCall:
return AttributedType::attr_swiftcall;
- case AttributeList::AT_VectorCall:
+ case ParsedAttr::AT_VectorCall:
return AttributedType::attr_vectorcall;
- case AttributeList::AT_Pcs: {
+ 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,
// but the form may not be.
@@ -6568,15 +6646,15 @@ static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) {
.Case("aapcs", AttributedType::attr_pcs)
.Case("aapcs-vfp", AttributedType::attr_pcs_vfp);
}
- case AttributeList::AT_IntelOclBicc:
+ case ParsedAttr::AT_IntelOclBicc:
return AttributedType::attr_inteloclbicc;
- case AttributeList::AT_MSABI:
+ case ParsedAttr::AT_MSABI:
return AttributedType::attr_ms_abi;
- case AttributeList::AT_SysVABI:
+ case ParsedAttr::AT_SysVABI:
return AttributedType::attr_sysv_abi;
- case AttributeList::AT_PreserveMost:
+ case ParsedAttr::AT_PreserveMost:
return AttributedType::attr_preserve_most;
- case AttributeList::AT_PreserveAll:
+ case ParsedAttr::AT_PreserveAll:
return AttributedType::attr_preserve_all;
}
llvm_unreachable("unexpected attribute kind!");
@@ -6584,15 +6662,14 @@ static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) {
/// Process an individual function attribute. Returns true to
/// indicate that the attribute was handled, false if it wasn't.
-static bool handleFunctionTypeAttr(TypeProcessingState &state,
- AttributeList &attr,
+static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
QualType &type) {
Sema &S = state.getSema();
FunctionTypeUnwrapper unwrapped(S, type);
- if (attr.getKind() == AttributeList::AT_NoReturn) {
- if (S.CheckNoReturnAttr(attr))
+ if (attr.getKind() == ParsedAttr::AT_NoReturn) {
+ if (S.CheckAttrNoArgs(attr))
return true;
// Delay if this is not a function type.
@@ -6607,7 +6684,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
// ns_returns_retained is not always a type attribute, but if we got
// here, we're treating it as one right now.
- if (attr.getKind() == AttributeList::AT_NSReturnsRetained) {
+ if (attr.getKind() == ParsedAttr::AT_NSReturnsRetained) {
if (attr.getNumArgs()) return true;
// Delay if this is not a function type.
@@ -6631,8 +6708,8 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
return true;
}
- if (attr.getKind() == AttributeList::AT_AnyX86NoCallerSavedRegisters) {
- if (S.CheckNoCallerSavedRegsAttr(attr))
+ if (attr.getKind() == ParsedAttr::AT_AnyX86NoCallerSavedRegisters) {
+ if (S.CheckAttrTarget(attr) || S.CheckAttrNoArgs(attr))
return true;
// Delay if this is not a function type.
@@ -6645,7 +6722,28 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
return true;
}
- if (attr.getKind() == AttributeList::AT_Regparm) {
+ if (attr.getKind() == ParsedAttr::AT_AnyX86NoCfCheck) {
+ if (!S.getLangOpts().CFProtectionBranch) {
+ S.Diag(attr.getLoc(), diag::warn_nocf_check_attribute_ignored);
+ attr.setInvalid();
+ return true;
+ }
+
+ if (S.CheckAttrTarget(attr) || S.CheckAttrNoArgs(attr))
+ return true;
+
+ // If this is not a function type, warning will be asserted by subject
+ // check.
+ if (!unwrapped.isFunctionType())
+ return true;
+
+ FunctionType::ExtInfo EI =
+ unwrapped.get()->getExtInfo().withNoCfCheck(true);
+ type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
+ return true;
+ }
+
+ if (attr.getKind() == ParsedAttr::AT_Regparm) {
unsigned value;
if (S.CheckRegparmAttr(attr, value))
return true;
@@ -6802,7 +6900,7 @@ void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic, bool IsCtorOrDtor,
/// The raw attribute should contain precisely 1 argument, the vector size for
/// the variable, measured in bytes. If curType and rawAttr are well formed,
/// this routine will return a new vector type.
-static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr,
+static void HandleVectorSizeAttr(QualType &CurType, const ParsedAttr &Attr,
Sema &S) {
// Check the attribute arguments.
if (Attr.getNumArgs() != 1) {
@@ -6811,58 +6909,35 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr,
Attr.setInvalid();
return;
}
- Expr *sizeExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
- llvm::APSInt vecSize(32);
- if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() ||
- !sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
- << Attr.getName() << AANT_ArgumentIntegerConstant
- << sizeExpr->getSourceRange();
- Attr.setInvalid();
- return;
- }
- // The base type must be integer (not Boolean or enumeration) or float, and
- // can't already be a vector.
- if (!CurType->isBuiltinType() || CurType->isBooleanType() ||
- (!CurType->isIntegerType() && !CurType->isRealFloatingType())) {
- S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
- Attr.setInvalid();
- return;
- }
- unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
- // vecSize is specified in bytes - convert to bits.
- unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8);
- // the vector size needs to be an integral multiple of the type size.
- if (vectorSize % typeSize) {
- S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size)
- << sizeExpr->getSourceRange();
- Attr.setInvalid();
- return;
- }
- if (VectorType::isVectorSizeTooLarge(vectorSize / typeSize)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_size_too_large)
- << sizeExpr->getSourceRange();
- Attr.setInvalid();
- return;
- }
- if (vectorSize == 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_zero_size)
- << sizeExpr->getSourceRange();
- Attr.setInvalid();
- return;
+ Expr *SizeExpr;
+ // Special case where the argument is a template id.
+ if (Attr.isArgIdent(0)) {
+ CXXScopeSpec SS;
+ SourceLocation TemplateKWLoc;
+ UnqualifiedId Id;
+ Id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc());
+
+ ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc,
+ Id, false, false);
+
+ if (Size.isInvalid())
+ return;
+ SizeExpr = Size.get();
+ } else {
+ SizeExpr = Attr.getArgAsExpr(0);
}
- // Success! Instantiate the vector type, the number of elements is > 0, and
- // not required to be a power of 2, unlike GCC.
- CurType = S.Context.getVectorType(CurType, vectorSize/typeSize,
- VectorType::GenericVector);
+ QualType T = S.BuildVectorType(CurType, SizeExpr, Attr.getLoc());
+ if (!T.isNull())
+ CurType = T;
+ else
+ Attr.setInvalid();
}
-/// \brief Process the OpenCL-like ext_vector_type attribute when it occurs on
+/// Process the OpenCL-like ext_vector_type attribute when it occurs on
/// a type.
-static void HandleExtVectorTypeAttr(QualType &CurType,
- const AttributeList &Attr,
+static void HandleExtVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr,
Sema &S) {
// check the attribute arguments.
if (Attr.getNumArgs() != 1) {
@@ -6951,9 +7026,8 @@ static bool isPermittedNeonBaseType(QualType &Ty,
/// the argument to these Neon attributes is the number of vector elements,
/// not the vector size in bytes. The vector width and element type must
/// match one of the standard Neon vector types.
-static void HandleNeonVectorTypeAttr(QualType& CurType,
- const AttributeList &Attr, Sema &S,
- VectorType::VectorKind VecKind) {
+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();
@@ -6999,7 +7073,7 @@ static void HandleNeonVectorTypeAttr(QualType& CurType,
}
/// Handle OpenCL Access Qualifier Attribute.
-static void HandleOpenCLAccessAttr(QualType &CurType, const AttributeList &Attr,
+static void HandleOpenCLAccessAttr(QualType &CurType, const ParsedAttr &Attr,
Sema &S) {
// OpenCL v2.0 s6.6 - Access qualifier can be used only for image and pipe type.
if (!(CurType->isImageType() || CurType->isPipeType())) {
@@ -7039,12 +7113,12 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
// Handle the cases where address space should not be deduced.
//
- // The pointee type of a pointer type is alwasy deduced since a pointer always
+ // The pointee type of a pointer type is always deduced since a pointer always
// points to some memory location which should has an address space.
//
// There are situations that at the point of certain declarations, the address
// space may be unknown and better to be left as default. For example, when
- // definining a typedef or struct type, they are not associated with any
+ // defining a typedef or struct type, they are not associated with any
// specific address space. Later on, they may be used with any address space
// to declare a variable.
//
@@ -7089,8 +7163,9 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
// The default address space name for arguments to a function in a
// program, or local variables of a function is __private. All function
// arguments shall be in the __private address space.
- if (State.getSema().getLangOpts().OpenCLVersion <= 120) {
- ImpAddr = LangAS::opencl_private;
+ if (State.getSema().getLangOpts().OpenCLVersion <= 120 &&
+ !State.getSema().getLangOpts().OpenCLCPlusPlus) {
+ ImpAddr = LangAS::opencl_private;
} else {
// If address space is not set, OpenCL 2.0 defines non private default
// address spaces for some cases:
@@ -7120,16 +7195,18 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
}
static void processTypeAttrs(TypeProcessingState &state, QualType &type,
- TypeAttrLocation TAL, AttributeList *attrs) {
+ TypeAttrLocation TAL,
+ ParsedAttributesView &attrs) {
// Scan through and apply attributes to this type where it makes sense. Some
// attributes (such as __address_space__, __vector_size__, etc) apply to the
// type, but others can be present in the type specifiers even though they
// apply to the decl. Here we apply type attributes and ignore the rest.
- while (attrs) {
- AttributeList &attr = *attrs;
- attrs = attr.getNext(); // reset to the next here due to early loop continue
- // stmts
+ // This loop modifies the list pretty frequently, but we still need to make
+ // sure we visit every element once. Copy the attributes list, and iterate
+ // over that.
+ ParsedAttributesView AttrsCopy{attrs};
+ for (ParsedAttr &attr : AttrsCopy) {
// Skip attributes that were marked to be invalid.
if (attr.isInvalid())
@@ -7137,14 +7214,19 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
if (attr.isCXX11Attribute()) {
// [[gnu::...]] attributes are treated as declaration attributes, so may
- // not appertain to a DeclaratorChunk, even if we handle them as type
- // attributes.
+ // 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")) {
+ bool IsTypeAttr = attr.isTypeAttr();
if (TAL == TAL_DeclChunk) {
state.getSema().Diag(attr.getLoc(),
- diag::warn_cxx11_gnu_attribute_on_type)
+ IsTypeAttr
+ ? diag::warn_gcc_ignores_type_attr
+ : diag::warn_cxx11_gnu_attribute_on_type)
<< attr.getName();
- continue;
+ if (!IsTypeAttr)
+ continue;
}
} else if (TAL != TAL_DeclChunk) {
// Otherwise, only consider type processing for a C++11 attribute if
@@ -7165,27 +7247,27 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
}
break;
- case AttributeList::UnknownAttribute:
+ case ParsedAttr::UnknownAttribute:
if (attr.isCXX11Attribute() && TAL == TAL_DeclChunk)
state.getSema().Diag(attr.getLoc(),
diag::warn_unknown_attribute_ignored)
<< attr.getName();
break;
- case AttributeList::IgnoredAttribute:
+ case ParsedAttr::IgnoredAttribute:
break;
- case AttributeList::AT_MayAlias:
+ case ParsedAttr::AT_MayAlias:
// FIXME: This attribute needs to actually be handled, but if we ignore
// it it breaks large amounts of Linux software.
attr.setUsedAsTypeAttr();
break;
- case AttributeList::AT_OpenCLPrivateAddressSpace:
- case AttributeList::AT_OpenCLGlobalAddressSpace:
- case AttributeList::AT_OpenCLLocalAddressSpace:
- case AttributeList::AT_OpenCLConstantAddressSpace:
- case AttributeList::AT_OpenCLGenericAddressSpace:
- case AttributeList::AT_AddressSpace:
+ case ParsedAttr::AT_OpenCLPrivateAddressSpace:
+ case ParsedAttr::AT_OpenCLGlobalAddressSpace:
+ case ParsedAttr::AT_OpenCLLocalAddressSpace:
+ case ParsedAttr::AT_OpenCLConstantAddressSpace:
+ case ParsedAttr::AT_OpenCLGenericAddressSpace:
+ case ParsedAttr::AT_AddressSpace:
HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
break;
@@ -7194,25 +7276,25 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
distributeObjCPointerTypeAttr(state, attr, type);
attr.setUsedAsTypeAttr();
break;
- case AttributeList::AT_VectorSize:
+ case ParsedAttr::AT_VectorSize:
HandleVectorSizeAttr(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
break;
- case AttributeList::AT_ExtVectorType:
+ case ParsedAttr::AT_ExtVectorType:
HandleExtVectorTypeAttr(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
break;
- case AttributeList::AT_NeonVectorType:
+ case ParsedAttr::AT_NeonVectorType:
HandleNeonVectorTypeAttr(type, attr, state.getSema(),
VectorType::NeonVector);
attr.setUsedAsTypeAttr();
break;
- case AttributeList::AT_NeonPolyVectorType:
+ case ParsedAttr::AT_NeonPolyVectorType:
HandleNeonVectorTypeAttr(type, attr, state.getSema(),
VectorType::NeonPolyVector);
attr.setUsedAsTypeAttr();
break;
- case AttributeList::AT_OpenCLAccess:
+ case ParsedAttr::AT_OpenCLAccess:
HandleOpenCLAccessAttr(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
break;
@@ -7251,7 +7333,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
}
break;
- case AttributeList::AT_ObjCKindOf:
+ case ParsedAttr::AT_ObjCKindOf:
// '__kindof' must be part of the decl-specifiers.
switch (TAL) {
case TAL_DeclSpec:
@@ -7337,7 +7419,7 @@ void Sema::completeExprArrayBound(Expr *E) {
}
}
-/// \brief Ensure that the type of the given expression is complete.
+/// Ensure that the type of the given expression is complete.
///
/// This routine checks whether the expression \p E has a complete type. If the
/// expression refers to an instantiable construct, that instantiation is
@@ -7374,7 +7456,7 @@ bool Sema::RequireCompleteExprType(Expr *E, unsigned DiagID) {
return RequireCompleteExprType(E, Diagnoser);
}
-/// @brief Ensure that the type T is a complete type.
+/// Ensure that the type T is a complete type.
///
/// This routine checks whether the type @p T is complete in any
/// context where a complete type is required. If @p T is a complete
@@ -7413,12 +7495,13 @@ bool Sema::hasStructuralCompatLayout(Decl *D, Decl *Suggested) {
// and isolate from other C++ specific checks.
StructuralEquivalenceContext Ctx(
D->getASTContext(), Suggested->getASTContext(), NonEquivalentDecls,
+ StructuralEquivalenceKind::Default,
false /*StrictTypeSpelling*/, true /*Complain*/,
true /*ErrorOnTagTypeMismatch*/);
- return Ctx.IsStructurallyEquivalent(D, Suggested);
+ return Ctx.IsEquivalent(D, Suggested);
}
-/// \brief Determine whether there is any declaration of \p D that was ever a
+/// Determine whether there is any declaration of \p D that was ever a
/// definition (perhaps before module merging) and is currently visible.
/// \param D The definition of the entity.
/// \param Suggested Filled in with the declaration that should be made visible
@@ -7488,7 +7571,7 @@ bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested,
/// Locks in the inheritance model for the given class and all of its bases.
static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) {
- RD = RD->getMostRecentDecl();
+ RD = RD->getMostRecentNonInjectedDecl();
if (!RD->hasAttr<MSInheritanceAttr>()) {
MSInheritanceAttr::Spelling IM;
@@ -7518,7 +7601,7 @@ static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) {
}
}
-/// \brief The implementation of RequireCompleteType
+/// The implementation of RequireCompleteType
bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
TypeDiagnoser *Diagnoser) {
// FIXME: Add this assertion to make sure we always get instantiation points.
@@ -7529,11 +7612,17 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
// assert(!T->isDependentType() &&
// "Can't ask whether a dependent type is complete");
- // We lock in the inheritance model once somebody has asked us to ensure
- // that a pointer-to-member type is complete.
- if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) {
- if (!MPTy->getClass()->isDependentType()) {
+ if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) {
+ if (!MPTy->getClass()->isDependentType()) {
+ if (getLangOpts().CompleteMemberPointers &&
+ !MPTy->getClass()->getAsCXXRecordDecl()->isBeingDefined() &&
+ RequireCompleteType(Loc, QualType(MPTy->getClass(), 0),
+ diag::err_memptr_incomplete))
+ return true;
+
+ // We lock in the inheritance model once somebody has asked us to ensure
+ // that a pointer-to-member type is complete.
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
(void)isCompleteType(Loc, QualType(MPTy->getClass(), 0));
assignInheritanceModel(*this, MPTy->getMostRecentCXXRecordDecl());
}
@@ -7557,10 +7646,18 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
// If the user is going to see an error here, recover by making the
// definition visible.
bool TreatAsComplete = Diagnoser && !isSFINAEContext();
- if (Diagnoser)
+ if (Diagnoser && SuggestedDef)
diagnoseMissingImport(Loc, SuggestedDef, MissingImportKind::Definition,
/*Recover*/TreatAsComplete);
return !TreatAsComplete;
+ } else if (Def && !TemplateInstCallbacks.empty()) {
+ CodeSynthesisContext TempInst;
+ TempInst.Kind = CodeSynthesisContext::Memoization;
+ TempInst.Template = Def;
+ TempInst.Entity = Def;
+ TempInst.PointOfInstantiation = Loc;
+ atTemplateBegin(TemplateInstCallbacks, *this, TempInst);
+ atTemplateEnd(TemplateInstCallbacks, *this, TempInst);
}
return false;
@@ -7689,7 +7786,7 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
return RequireCompleteType(Loc, T, Diagnoser);
}
-/// \brief Get diagnostic %select index for tag kind for
+/// Get diagnostic %select index for tag kind for
/// literal type diagnostic message.
/// WARNING: Indexes apply to particular diagnostics only!
///
@@ -7703,7 +7800,7 @@ static unsigned getLiteralDiagFromTagKind(TagTypeKind Tag) {
}
}
-/// @brief Ensure that the type T is a literal type.
+/// Ensure that the type T is a literal type.
///
/// This routine checks whether the type @p T is a literal type. If @p T is an
/// incomplete type, an attempt is made to complete it. If @p T is a literal
@@ -7747,6 +7844,13 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
if (RequireCompleteType(Loc, ElemType, diag::note_non_literal_incomplete, T))
return true;
+ // [expr.prim.lambda]p3:
+ // This class type is [not] a literal type.
+ if (RD->isLambda() && !getLangOpts().CPlusPlus17) {
+ Diag(RD->getLocation(), diag::note_non_literal_lambda);
+ return true;
+ }
+
// If the class has virtual base classes, then it's not an aggregate, and
// cannot have any constexpr constructors or a trivial default constructor,
// so is non-literal. This is better to diagnose than the resulting absence
@@ -7790,7 +7894,8 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
diag::note_non_literal_user_provided_dtor :
diag::note_non_literal_nontrivial_dtor) << RD;
if (!Dtor->isUserProvided())
- SpecialMemberIsTrivial(Dtor, CXXDestructor, /*Diagnose*/true);
+ SpecialMemberIsTrivial(Dtor, CXXDestructor, TAH_IgnoreTrivialABI,
+ /*Diagnose*/true);
}
return true;
@@ -7801,10 +7906,12 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID) {
return RequireLiteralType(Loc, T, Diagnoser);
}
-/// \brief Retrieve a version of the type 'T' that is elaborated by Keyword
-/// and qualified by the nested-name-specifier contained in SS.
+/// Retrieve a version of the type 'T' that is elaborated by Keyword, qualified
+/// by the nested-name-specifier contained in SS, and that is (re)declared by
+/// OwnedTagDecl, which is nullptr if this is not a (re)declaration.
QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword,
- const CXXScopeSpec &SS, QualType T) {
+ const CXXScopeSpec &SS, QualType T,
+ TagDecl *OwnedTagDecl) {
if (T.isNull())
return T;
NestedNameSpecifier *NNS;
@@ -7815,7 +7922,7 @@ QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword,
return T;
NNS = nullptr;
}
- return Context.getElaboratedType(Keyword, NNS, T);
+ return Context.getElaboratedType(Keyword, NNS, T, OwnedTagDecl);
}
QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) {
@@ -7851,11 +7958,12 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) {
//
// We apply the same rules for Objective-C ivar and property references.
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
- if (const ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl()))
- return VD->getType();
+ const ValueDecl *VD = DRE->getDecl();
+ return VD->getType();
} else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
- if (const FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
- return FD->getType();
+ if (const ValueDecl *VD = ME->getMemberDecl())
+ if (isa<FieldDecl>(VD) || isa<VarDecl>(VD))
+ return VD->getType();
} else if (const ObjCIvarRefExpr *IR = dyn_cast<ObjCIvarRefExpr>(E)) {
return IR->getDecl()->getType();
} else if (const ObjCPropertyRefExpr *PR = dyn_cast<ObjCPropertyRefExpr>(E)) {
diff --git a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
index 96969ea87a13..3b3953991000 100644
--- a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
+++ b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
@@ -41,7 +41,7 @@
namespace clang {
using namespace sema;
-/// \brief A semantic tree transformation that allows one to transform one
+/// A semantic tree transformation that allows one to transform one
/// abstract syntax tree into another.
///
/// A new tree transformation is defined by creating a new subclass \c X of
@@ -57,7 +57,7 @@ using namespace sema;
/// subclasses to customize any of its operations. Thus, a subclass can
/// override any of the transformation or rebuild operators by providing an
/// operation with the same signature as the default implementation. The
-/// overridding function should not be virtual.
+/// overriding function should not be virtual.
///
/// Semantic tree transformations are split into two stages, either of which
/// can be replaced by a subclass. The "transform" step transforms an AST node
@@ -94,7 +94,7 @@ using namespace sema;
/// (\c getBaseLocation(), \c getBaseEntity()).
template<typename Derived>
class TreeTransform {
- /// \brief Private RAII object that helps us forget and then re-remember
+ /// Private RAII object that helps us forget and then re-remember
/// the template argument corresponding to a partially-substituted parameter
/// pack.
class ForgetPartiallySubstitutedPackRAII {
@@ -114,19 +114,19 @@ class TreeTransform {
protected:
Sema &SemaRef;
- /// \brief The set of local declarations that have been transformed, for
+ /// The set of local declarations that have been transformed, for
/// cases where we are forced to build new declarations within the transformer
/// rather than in the subclass (e.g., lambda closure types).
llvm::DenseMap<Decl *, Decl *> TransformedLocalDecls;
public:
- /// \brief Initializes a new tree transformer.
+ /// Initializes a new tree transformer.
TreeTransform(Sema &SemaRef) : SemaRef(SemaRef) { }
- /// \brief Retrieves a reference to the derived class.
+ /// Retrieves a reference to the derived class.
Derived &getDerived() { return static_cast<Derived&>(*this); }
- /// \brief Retrieves a reference to the derived class.
+ /// Retrieves a reference to the derived class.
const Derived &getDerived() const {
return static_cast<const Derived&>(*this);
}
@@ -134,11 +134,11 @@ public:
static inline ExprResult Owned(Expr *E) { return E; }
static inline StmtResult Owned(Stmt *S) { return S; }
- /// \brief Retrieves a reference to the semantic analysis object used for
+ /// Retrieves a reference to the semantic analysis object used for
/// this tree transform.
Sema &getSema() const { return SemaRef; }
- /// \brief Whether the transformation should always rebuild AST nodes, even
+ /// Whether the transformation should always rebuild AST nodes, even
/// if none of the children have changed.
///
/// Subclasses may override this function to specify when the transformation
@@ -149,7 +149,7 @@ public:
/// statement node appears at most once in its containing declaration.
bool AlwaysRebuild() { return SemaRef.ArgumentPackSubstitutionIndex != -1; }
- /// \brief Returns the location of the entity being transformed, if that
+ /// Returns the location of the entity being transformed, if that
/// information was not available elsewhere in the AST.
///
/// By default, returns no source-location information. Subclasses can
@@ -157,21 +157,21 @@ public:
/// information.
SourceLocation getBaseLocation() { return SourceLocation(); }
- /// \brief Returns the name of the entity being transformed, if that
+ /// Returns the name of the entity being transformed, if that
/// information was not available elsewhere in the AST.
///
/// By default, returns an empty name. Subclasses can provide an alternative
/// implementation with a more precise name.
DeclarationName getBaseEntity() { return DeclarationName(); }
- /// \brief Sets the "base" location and entity when that
+ /// Sets the "base" location and entity when that
/// information is known based on another transformation.
///
/// By default, the source location and entity are ignored. Subclasses can
/// override this function to provide a customized implementation.
void setBase(SourceLocation Loc, DeclarationName Entity) { }
- /// \brief RAII object that temporarily sets the base location and entity
+ /// RAII object that temporarily sets the base location and entity
/// used for reporting diagnostics in types.
class TemporaryBase {
TreeTransform &Self;
@@ -193,7 +193,7 @@ public:
}
};
- /// \brief Determine whether the given type \p T has already been
+ /// Determine whether the given type \p T has already been
/// transformed.
///
/// Subclasses can provide an alternative implementation of this routine
@@ -204,7 +204,7 @@ public:
return T.isNull();
}
- /// \brief Determine whether the given call argument should be dropped, e.g.,
+ /// Determine whether the given call argument should be dropped, e.g.,
/// because it is a default argument.
///
/// Subclasses can provide an alternative implementation of this routine to
@@ -214,7 +214,7 @@ public:
return E->isDefaultArgument();
}
- /// \brief Determine whether we should expand a pack expansion with the
+ /// Determine whether we should expand a pack expansion with the
/// given set of parameter packs into separate arguments by repeatedly
/// transforming the pattern.
///
@@ -261,7 +261,7 @@ public:
return false;
}
- /// \brief "Forget" about the partially-substituted pack template argument,
+ /// "Forget" about the partially-substituted pack template argument,
/// when performing an instantiation that must preserve the parameter pack
/// use.
///
@@ -270,18 +270,18 @@ public:
return TemplateArgument();
}
- /// \brief "Remember" the partially-substituted pack template argument
+ /// "Remember" the partially-substituted pack template argument
/// after performing an instantiation that must preserve the parameter pack
/// use.
///
/// This routine is meant to be overridden by the template instantiator.
void RememberPartiallySubstitutedPack(TemplateArgument Arg) { }
- /// \brief Note to the derived class when a function parameter pack is
+ /// Note to the derived class when a function parameter pack is
/// being expanded.
void ExpandingFunctionParameterPack(ParmVarDecl *Pack) { }
- /// \brief Transforms the given type into another type.
+ /// Transforms the given type into another type.
///
/// By default, this routine transforms a type by creating a
/// TypeSourceInfo for it and delegating to the appropriate
@@ -292,7 +292,7 @@ public:
/// \returns the transformed type.
QualType TransformType(QualType T);
- /// \brief Transforms the given type-with-location into a new
+ /// Transforms the given type-with-location into a new
/// type-with-location.
///
/// By default, this routine transforms a type by delegating to the
@@ -302,13 +302,13 @@ public:
/// to alter the transformation.
TypeSourceInfo *TransformType(TypeSourceInfo *DI);
- /// \brief Transform the given type-with-location into a new
+ /// Transform the given type-with-location into a new
/// type, collecting location information in the given builder
/// as necessary.
///
QualType TransformType(TypeLocBuilder &TLB, TypeLoc TL);
- /// \brief Transform a type that is permitted to produce a
+ /// Transform a type that is permitted to produce a
/// DeducedTemplateSpecializationType.
///
/// This is used in the (relatively rare) contexts where it is acceptable
@@ -319,7 +319,7 @@ public:
TypeSourceInfo *TransformTypeWithDeducedTST(TypeSourceInfo *DI);
/// @}
- /// \brief Transform the given statement.
+ /// Transform the given statement.
///
/// By default, this routine transforms a statement by delegating to the
/// appropriate TransformXXXStmt function to transform a specific kind of
@@ -330,7 +330,7 @@ public:
/// \returns the transformed statement.
StmtResult TransformStmt(Stmt *S);
- /// \brief Transform the given statement.
+ /// Transform the given statement.
///
/// By default, this routine transforms a statement by delegating to the
/// appropriate TransformOMPXXXClause function to transform a specific kind
@@ -340,7 +340,7 @@ public:
/// \returns the transformed OpenMP clause.
OMPClause *TransformOMPClause(OMPClause *S);
- /// \brief Transform the given attribute.
+ /// Transform the given attribute.
///
/// By default, this routine transforms a statement by delegating to the
/// appropriate TransformXXXAttr function to transform a specific kind
@@ -350,7 +350,7 @@ public:
/// \returns the transformed attribute
const Attr *TransformAttr(const Attr *S);
-/// \brief Transform the specified attribute.
+/// Transform the specified attribute.
///
/// Subclasses should override the transformation of attributes with a pragma
/// spelling to transform expressions stored within the attribute.
@@ -361,7 +361,7 @@ public:
const X##Attr *Transform##X##Attr(const X##Attr *R) { return R; }
#include "clang/Basic/AttrList.inc"
- /// \brief Transform the given expression.
+ /// Transform the given expression.
///
/// By default, this routine transforms an expression by delegating to the
/// appropriate TransformXXXExpr function to build a new expression.
@@ -371,7 +371,7 @@ public:
/// \returns the transformed expression.
ExprResult TransformExpr(Expr *E);
- /// \brief Transform the given initializer.
+ /// Transform the given initializer.
///
/// By default, this routine transforms an initializer by stripping off the
/// semantic nodes added by initialization, then passing the result to
@@ -380,7 +380,7 @@ public:
/// \returns the transformed initializer.
ExprResult TransformInitializer(Expr *Init, bool NotCopyInit);
- /// \brief Transform the given list of expressions.
+ /// Transform the given list of expressions.
///
/// This routine transforms a list of expressions by invoking
/// \c TransformExpr() for each subexpression. However, it also provides
@@ -407,7 +407,7 @@ public:
SmallVectorImpl<Expr *> &Outputs,
bool *ArgChanged = nullptr);
- /// \brief Transform the given declaration, which is referenced from a type
+ /// Transform the given declaration, which is referenced from a type
/// or expression.
///
/// By default, acts as the identity function on declarations, unless the
@@ -422,7 +422,7 @@ public:
return D;
}
- /// \brief Transform the specified condition.
+ /// Transform the specified condition.
///
/// By default, this transforms the variable and expression and rebuilds
/// the condition.
@@ -430,14 +430,14 @@ public:
Expr *Expr,
Sema::ConditionKind Kind);
- /// \brief Transform the attributes associated with the given declaration and
+ /// Transform the attributes associated with the given declaration and
/// place them on the new declaration.
///
/// By default, this operation does nothing. Subclasses may override this
/// behavior to transform attributes.
void transformAttrs(Decl *Old, Decl *New) { }
- /// \brief Note that a local declaration has been transformed by this
+ /// Note that a local declaration has been transformed by this
/// transformer.
///
/// Local declarations are typically transformed via a call to
@@ -448,7 +448,7 @@ public:
TransformedLocalDecls[Old] = New;
}
- /// \brief Transform the definition of the given declaration.
+ /// Transform the definition of the given declaration.
///
/// By default, invokes TransformDecl() to transform the declaration.
/// Subclasses may override this function to provide alternate behavior.
@@ -456,7 +456,7 @@ public:
return getDerived().TransformDecl(Loc, D);
}
- /// \brief Transform the given declaration, which was the first part of a
+ /// Transform the given declaration, which was the first part of a
/// nested-name-specifier in a member access expression.
///
/// This specific declaration transformation only applies to the first
@@ -473,7 +473,7 @@ public:
bool TransformOverloadExprDecls(OverloadExpr *Old, bool RequiresADL,
LookupResult &R);
- /// \brief Transform the given nested-name-specifier with source-location
+ /// Transform the given nested-name-specifier with source-location
/// information.
///
/// By default, transforms all of the types and declarations within the
@@ -484,7 +484,7 @@ public:
QualType ObjectType = QualType(),
NamedDecl *FirstQualifierInScope = nullptr);
- /// \brief Transform the given declaration name.
+ /// Transform the given declaration name.
///
/// By default, transforms the types of conversion function, constructor,
/// and destructor names and then (if needed) rebuilds the declaration name.
@@ -493,7 +493,7 @@ public:
DeclarationNameInfo
TransformDeclarationNameInfo(const DeclarationNameInfo &NameInfo);
- /// \brief Transform the given template name.
+ /// Transform the given template name.
///
/// \param SS The nested-name-specifier that qualifies the template
/// name. This nested-name-specifier must already have been transformed.
@@ -520,7 +520,7 @@ public:
NamedDecl *FirstQualifierInScope = nullptr,
bool AllowInjectedClassName = false);
- /// \brief Transform the given template argument.
+ /// Transform the given template argument.
///
/// By default, this operation transforms the type, expression, or
/// declaration stored within the template argument and constructs a
@@ -532,7 +532,7 @@ public:
TemplateArgumentLoc &Output,
bool Uneval = false);
- /// \brief Transform the given set of template arguments.
+ /// Transform the given set of template arguments.
///
/// By default, this operation transforms all of the template arguments
/// in the input set using \c TransformTemplateArgument(), and appends
@@ -558,7 +558,7 @@ public:
Uneval);
}
- /// \brief Transform the given set of template arguments.
+ /// Transform the given set of template arguments.
///
/// By default, this operation transforms all of the template arguments
/// in the input set using \c TransformTemplateArgument(), and appends
@@ -578,11 +578,11 @@ public:
TemplateArgumentListInfo &Outputs,
bool Uneval = false);
- /// \brief Fakes up a TemplateArgumentLoc for a given TemplateArgument.
+ /// Fakes up a TemplateArgumentLoc for a given TemplateArgument.
void InventTemplateArgumentLoc(const TemplateArgument &Arg,
TemplateArgumentLoc &ArgLoc);
- /// \brief Fakes up a TypeSourceInfo for a type.
+ /// Fakes up a TypeSourceInfo for a type.
TypeSourceInfo *InventTypeSourceInfo(QualType T) {
return SemaRef.Context.getTrivialTypeSourceInfo(T,
getDerived().getBaseLocation());
@@ -622,7 +622,7 @@ public:
TypeLocBuilder &TLB, DependentTemplateSpecializationTypeLoc TL,
NestedNameSpecifierLoc QualifierLoc);
- /// \brief Transforms the parameters of a function type into the
+ /// Transforms the parameters of a function type into the
/// given vectors.
///
/// The result vectors should be kept in sync; null entries in the
@@ -636,7 +636,7 @@ public:
SmallVectorImpl<QualType> &PTypes, SmallVectorImpl<ParmVarDecl *> *PVars,
Sema::ExtParameterInfoBuilder &PInfos);
- /// \brief Transforms a single function-type parameter. Return null
+ /// Transforms a single function-type parameter. Return null
/// on error.
///
/// \param indexAdjustment - A number to add to the parameter's
@@ -684,7 +684,7 @@ public:
OMPClause *Transform ## Class(Class *S);
#include "clang/Basic/OpenMPKinds.def"
- /// \brief Build a new qualified type given its unqualified type and type
+ /// Build a new qualified type given its unqualified type and type
/// qualifiers.
///
/// By default, this routine adds type qualifiers only to types that can
@@ -694,19 +694,19 @@ public:
QualType RebuildQualifiedType(QualType T, SourceLocation Loc,
Qualifiers Quals);
- /// \brief Build a new pointer type given its pointee type.
+ /// Build a new pointer type given its pointee type.
///
/// By default, performs semantic analysis when building the pointer type.
/// Subclasses may override this routine to provide different behavior.
QualType RebuildPointerType(QualType PointeeType, SourceLocation Sigil);
- /// \brief Build a new block pointer type given its pointee type.
+ /// Build a new block pointer type given its pointee type.
///
/// By default, performs semantic analysis when building the block pointer
/// type. Subclasses may override this routine to provide different behavior.
QualType RebuildBlockPointerType(QualType PointeeType, SourceLocation Sigil);
- /// \brief Build a new reference type given the type it references.
+ /// Build a new reference type given the type it references.
///
/// By default, performs semantic analysis when building the
/// reference type. Subclasses may override this routine to provide
@@ -718,7 +718,7 @@ public:
bool LValue,
SourceLocation Sigil);
- /// \brief Build a new member pointer type given the pointee type and the
+ /// Build a new member pointer type given the pointee type and the
/// class type it refers into.
///
/// By default, performs semantic analysis when building the member pointer
@@ -732,7 +732,7 @@ public:
ArrayRef<SourceLocation> ProtocolLocs,
SourceLocation ProtocolRAngleLoc);
- /// \brief Build an Objective-C object type.
+ /// Build an Objective-C object type.
///
/// By default, performs semantic analysis when building the object type.
/// Subclasses may override this routine to provide different behavior.
@@ -746,14 +746,14 @@ public:
ArrayRef<SourceLocation> ProtocolLocs,
SourceLocation ProtocolRAngleLoc);
- /// \brief Build a new Objective-C object pointer type given the pointee type.
+ /// Build a new Objective-C object pointer type given the pointee type.
///
/// By default, directly builds the pointer type, with no additional semantic
/// analysis.
QualType RebuildObjCObjectPointerType(QualType PointeeType,
SourceLocation Star);
- /// \brief Build a new array type given the element type, size
+ /// Build a new array type given the element type, size
/// modifier, size of the array (if known), size expression, and index type
/// qualifiers.
///
@@ -767,7 +767,7 @@ public:
unsigned IndexTypeQuals,
SourceRange BracketsRange);
- /// \brief Build a new constant array type given the element type, size
+ /// Build a new constant array type given the element type, size
/// modifier, (known) size of the array, and index type qualifiers.
///
/// By default, performs semantic analysis when building the array type.
@@ -778,7 +778,7 @@ public:
unsigned IndexTypeQuals,
SourceRange BracketsRange);
- /// \brief Build a new incomplete array type given the element type, size
+ /// Build a new incomplete array type given the element type, size
/// modifier, and index type qualifiers.
///
/// By default, performs semantic analysis when building the array type.
@@ -788,7 +788,7 @@ public:
unsigned IndexTypeQuals,
SourceRange BracketsRange);
- /// \brief Build a new variable-length array type given the element type,
+ /// Build a new variable-length array type given the element type,
/// size modifier, size expression, and index type qualifiers.
///
/// By default, performs semantic analysis when building the array type.
@@ -799,7 +799,7 @@ public:
unsigned IndexTypeQuals,
SourceRange BracketsRange);
- /// \brief Build a new dependent-sized array type given the element type,
+ /// Build a new dependent-sized array type given the element type,
/// size modifier, size expression, and index type qualifiers.
///
/// By default, performs semantic analysis when building the array type.
@@ -810,7 +810,7 @@ public:
unsigned IndexTypeQuals,
SourceRange BracketsRange);
- /// \brief Build a new vector type given the element type and
+ /// Build a new vector type given the element type and
/// number of elements.
///
/// By default, performs semantic analysis when building the vector type.
@@ -818,7 +818,16 @@ public:
QualType RebuildVectorType(QualType ElementType, unsigned NumElements,
VectorType::VectorKind VecKind);
- /// \brief Build a new extended vector type given the element type and
+ /// Build a new potentially dependently-sized extended vector type
+ /// given the element type and number of elements.
+ ///
+ /// By default, performs semantic analysis when building the vector type.
+ /// Subclasses may override this routine to provide different behavior.
+ QualType RebuildDependentVectorType(QualType ElementType, Expr *SizeExpr,
+ SourceLocation AttributeLoc,
+ VectorType::VectorKind);
+
+ /// Build a new extended vector type given the element type and
/// number of elements.
///
/// By default, performs semantic analysis when building the vector type.
@@ -826,7 +835,7 @@ public:
QualType RebuildExtVectorType(QualType ElementType, unsigned NumElements,
SourceLocation AttributeLoc);
- /// \brief Build a new potentially dependently-sized extended vector type
+ /// Build a new potentially dependently-sized extended vector type
/// given the element type and number of elements.
///
/// By default, performs semantic analysis when building the vector type.
@@ -835,7 +844,7 @@ public:
Expr *SizeExpr,
SourceLocation AttributeLoc);
- /// \brief Build a new DependentAddressSpaceType or return the pointee
+ /// Build a new DependentAddressSpaceType or return the pointee
/// type variable with the correct address space (retrieved from
/// AddrSpaceExpr) applied to it. The former will be returned in cases
/// where the address space remains dependent.
@@ -847,7 +856,7 @@ public:
Expr *AddrSpaceExpr,
SourceLocation AttributeLoc);
- /// \brief Build a new function type.
+ /// Build a new function type.
///
/// By default, performs semantic analysis when building the function type.
/// Subclasses may override this routine to provide different behavior.
@@ -855,51 +864,51 @@ public:
MutableArrayRef<QualType> ParamTypes,
const FunctionProtoType::ExtProtoInfo &EPI);
- /// \brief Build a new unprototyped function type.
+ /// Build a new unprototyped function type.
QualType RebuildFunctionNoProtoType(QualType ResultType);
- /// \brief Rebuild an unresolved typename type, given the decl that
+ /// Rebuild an unresolved typename type, given the decl that
/// the UnresolvedUsingTypenameDecl was transformed to.
QualType RebuildUnresolvedUsingType(SourceLocation NameLoc, Decl *D);
- /// \brief Build a new typedef type.
+ /// Build a new typedef type.
QualType RebuildTypedefType(TypedefNameDecl *Typedef) {
return SemaRef.Context.getTypeDeclType(Typedef);
}
- /// \brief Build a new class/struct/union type.
+ /// Build a new class/struct/union type.
QualType RebuildRecordType(RecordDecl *Record) {
return SemaRef.Context.getTypeDeclType(Record);
}
- /// \brief Build a new Enum type.
+ /// Build a new Enum type.
QualType RebuildEnumType(EnumDecl *Enum) {
return SemaRef.Context.getTypeDeclType(Enum);
}
- /// \brief Build a new typeof(expr) type.
+ /// Build a new typeof(expr) type.
///
/// By default, performs semantic analysis when building the typeof type.
/// Subclasses may override this routine to provide different behavior.
QualType RebuildTypeOfExprType(Expr *Underlying, SourceLocation Loc);
- /// \brief Build a new typeof(type) type.
+ /// Build a new typeof(type) type.
///
/// By default, builds a new TypeOfType with the given underlying type.
QualType RebuildTypeOfType(QualType Underlying);
- /// \brief Build a new unary transform type.
+ /// Build a new unary transform type.
QualType RebuildUnaryTransformType(QualType BaseType,
UnaryTransformType::UTTKind UKind,
SourceLocation Loc);
- /// \brief Build a new C++11 decltype type.
+ /// Build a new C++11 decltype type.
///
/// By default, performs semantic analysis when building the decltype type.
/// Subclasses may override this routine to provide different behavior.
QualType RebuildDecltypeType(Expr *Underlying, SourceLocation Loc);
- /// \brief Build a new C++11 auto type.
+ /// Build a new C++11 auto type.
///
/// By default, builds a new AutoType with the given deduced type.
QualType RebuildAutoType(QualType Deduced, AutoTypeKeyword Keyword) {
@@ -918,7 +927,7 @@ public:
Template, Deduced, /*IsDependent*/ false);
}
- /// \brief Build a new template specialization type.
+ /// Build a new template specialization type.
///
/// By default, performs semantic analysis when building the template
/// specialization type. Subclasses may override this routine to provide
@@ -927,7 +936,7 @@ public:
SourceLocation TemplateLoc,
TemplateArgumentListInfo &Args);
- /// \brief Build a new parenthesized type.
+ /// Build a new parenthesized type.
///
/// By default, builds a new ParenType type from the inner type.
/// Subclasses may override this routine to provide different behavior.
@@ -935,7 +944,7 @@ public:
return SemaRef.BuildParenType(InnerType);
}
- /// \brief Build a new qualified name type.
+ /// Build a new qualified name type.
///
/// By default, builds a new ElaboratedType type from the keyword,
/// the nested-name-specifier and the named type.
@@ -949,7 +958,7 @@ public:
Named);
}
- /// \brief Build a new typename type that refers to a template-id.
+ /// Build a new typename type that refers to a template-id.
///
/// By default, builds a new DependentNameType type from the
/// nested-name-specifier and the given type. Subclasses may override
@@ -957,6 +966,7 @@ public:
QualType RebuildDependentTemplateSpecializationType(
ElaboratedTypeKeyword Keyword,
NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc,
const IdentifierInfo *Name,
SourceLocation NameLoc,
TemplateArgumentListInfo &Args,
@@ -965,9 +975,9 @@ public:
// TODO: avoid TemplateName abstraction
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
- TemplateName InstName
- = getDerived().RebuildTemplateName(SS, *Name, NameLoc, QualType(),
- nullptr, AllowInjectedClassName);
+ TemplateName InstName = getDerived().RebuildTemplateName(
+ SS, TemplateKWLoc, *Name, NameLoc, QualType(), nullptr,
+ AllowInjectedClassName);
if (InstName.isNull())
return QualType();
@@ -993,7 +1003,7 @@ public:
T);
}
- /// \brief Build a new typename type that refers to an identifier.
+ /// Build a new typename type that refers to an identifier.
///
/// By default, performs semantic analysis when building the typename type
/// (or elaborated type). Subclasses may override this routine to provide
@@ -1106,7 +1116,7 @@ public:
T);
}
- /// \brief Build a new pack expansion type.
+ /// Build a new pack expansion type.
///
/// By default, builds a new PackExpansionType type from the given pattern.
/// Subclasses may override this routine to provide different behavior.
@@ -1118,17 +1128,17 @@ public:
NumExpansions);
}
- /// \brief Build a new atomic type given its value type.
+ /// Build a new atomic type given its value type.
///
/// By default, performs semantic analysis when building the atomic type.
/// Subclasses may override this routine to provide different behavior.
QualType RebuildAtomicType(QualType ValueType, SourceLocation KWLoc);
- /// \brief Build a new pipe type given its value type.
+ /// Build a new pipe type given its value type.
QualType RebuildPipeType(QualType ValueType, SourceLocation KWLoc,
bool isReadPipe);
- /// \brief Build a new template name given a nested name specifier, a flag
+ /// Build a new template name given a nested name specifier, a flag
/// indicating whether the "template" keyword was provided, and the template
/// that the template name refers to.
///
@@ -1138,7 +1148,7 @@ public:
bool TemplateKW,
TemplateDecl *Template);
- /// \brief Build a new template name given a nested name specifier and the
+ /// Build a new template name given a nested name specifier and the
/// name that is referred to as a template.
///
/// By default, performs semantic analysis to determine whether the name can
@@ -1146,13 +1156,13 @@ public:
/// template name. Subclasses may override this routine to provide different
/// behavior.
TemplateName RebuildTemplateName(CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
const IdentifierInfo &Name,
- SourceLocation NameLoc,
- QualType ObjectType,
+ SourceLocation NameLoc, QualType ObjectType,
NamedDecl *FirstQualifierInScope,
bool AllowInjectedClassName);
- /// \brief Build a new template name given a nested name specifier and the
+ /// Build a new template name given a nested name specifier and the
/// overloaded operator name that is referred to as a template.
///
/// By default, performs semantic analysis to determine whether the name can
@@ -1160,12 +1170,12 @@ public:
/// template name. Subclasses may override this routine to provide different
/// behavior.
TemplateName RebuildTemplateName(CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
OverloadedOperatorKind Operator,
- SourceLocation NameLoc,
- QualType ObjectType,
+ SourceLocation NameLoc, QualType ObjectType,
bool AllowInjectedClassName);
- /// \brief Build a new template name given a template template parameter pack
+ /// Build a new template name given a template template parameter pack
/// and the
///
/// By default, performs semantic analysis to determine whether the name can
@@ -1177,7 +1187,7 @@ public:
return getSema().Context.getSubstTemplateTemplateParmPack(Param, ArgPack);
}
- /// \brief Build a new compound statement.
+ /// Build a new compound statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1189,7 +1199,7 @@ public:
IsStmtExpr);
}
- /// \brief Build a new case statement.
+ /// Build a new case statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1202,7 +1212,7 @@ public:
ColonLoc);
}
- /// \brief Attach the body to a new case statement.
+ /// Attach the body to a new case statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1211,7 +1221,7 @@ public:
return S;
}
- /// \brief Build a new default statement.
+ /// Build a new default statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1222,7 +1232,7 @@ public:
/*CurScope=*/nullptr);
}
- /// \brief Build a new label statement.
+ /// Build a new label statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1231,7 +1241,7 @@ public:
return SemaRef.ActOnLabelStmt(IdentLoc, L, ColonLoc, SubStmt);
}
- /// \brief Build a new label statement.
+ /// Build a new label statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1241,7 +1251,7 @@ public:
return SemaRef.ActOnAttributedStmt(AttrLoc, Attrs, SubStmt);
}
- /// \brief Build a new "if" statement.
+ /// Build a new "if" statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1252,7 +1262,7 @@ public:
ElseLoc, Else);
}
- /// \brief Start building a new switch statement.
+ /// Start building a new switch statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1261,7 +1271,7 @@ public:
return getSema().ActOnStartOfSwitchStmt(SwitchLoc, Init, Cond);
}
- /// \brief Attach the body to the switch statement.
+ /// Attach the body to the switch statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1270,7 +1280,7 @@ public:
return getSema().ActOnFinishSwitchStmt(SwitchLoc, Switch, Body);
}
- /// \brief Build a new while statement.
+ /// Build a new while statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1279,7 +1289,7 @@ public:
return getSema().ActOnWhileStmt(WhileLoc, Cond, Body);
}
- /// \brief Build a new do-while statement.
+ /// Build a new do-while statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1290,7 +1300,7 @@ public:
Cond, RParenLoc);
}
- /// \brief Build a new for statement.
+ /// Build a new for statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1302,7 +1312,7 @@ public:
Inc, RParenLoc, Body);
}
- /// \brief Build a new goto statement.
+ /// Build a new goto statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1311,7 +1321,7 @@ public:
return getSema().ActOnGotoStmt(GotoLoc, LabelLoc, Label);
}
- /// \brief Build a new indirect goto statement.
+ /// Build a new indirect goto statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1321,7 +1331,7 @@ public:
return getSema().ActOnIndirectGotoStmt(GotoLoc, StarLoc, Target);
}
- /// \brief Build a new return statement.
+ /// Build a new return statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1329,7 +1339,7 @@ public:
return getSema().BuildReturnStmt(ReturnLoc, Result);
}
- /// \brief Build a new declaration statement.
+ /// Build a new declaration statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1339,7 +1349,7 @@ public:
return getSema().ActOnDeclStmt(DG, StartLoc, EndLoc);
}
- /// \brief Build a new inline asm statement.
+ /// Build a new inline asm statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1354,7 +1364,7 @@ public:
AsmString, Clobbers, RParenLoc);
}
- /// \brief Build a new MS style inline asm statement.
+ /// Build a new MS style inline asm statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1371,7 +1381,7 @@ public:
Constraints, Clobbers, Exprs, EndLoc);
}
- /// \brief Build a new co_return statement.
+ /// Build a new co_return statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1380,7 +1390,7 @@ public:
return getSema().BuildCoreturnStmt(CoreturnLoc, Result, IsImplicit);
}
- /// \brief Build a new co_await expression.
+ /// Build a new co_await expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -1389,7 +1399,7 @@ public:
return getSema().BuildResolvedCoawaitExpr(CoawaitLoc, Result, IsImplicit);
}
- /// \brief Build a new co_await expression.
+ /// Build a new co_await expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -1399,7 +1409,7 @@ public:
return getSema().BuildUnresolvedCoawaitExpr(CoawaitLoc, Result, Lookup);
}
- /// \brief Build a new co_yield expression.
+ /// Build a new co_yield expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -1411,7 +1421,7 @@ public:
return getSema().BuildCoroutineBodyStmt(Args);
}
- /// \brief Build a new Objective-C \@try statement.
+ /// Build a new Objective-C \@try statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1423,7 +1433,7 @@ public:
Finally);
}
- /// \brief Rebuild an Objective-C exception declaration.
+ /// Rebuild an Objective-C exception declaration.
///
/// By default, performs semantic analysis to build the new declaration.
/// Subclasses may override this routine to provide different behavior.
@@ -1435,7 +1445,7 @@ public:
ExceptionDecl->getIdentifier());
}
- /// \brief Build a new Objective-C \@catch statement.
+ /// Build a new Objective-C \@catch statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1447,7 +1457,7 @@ public:
Var, Body);
}
- /// \brief Build a new Objective-C \@finally statement.
+ /// Build a new Objective-C \@finally statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1456,7 +1466,7 @@ public:
return getSema().ActOnObjCAtFinallyStmt(AtLoc, Body);
}
- /// \brief Build a new Objective-C \@throw statement.
+ /// Build a new Objective-C \@throw statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1465,7 +1475,7 @@ public:
return getSema().BuildObjCAtThrowStmt(AtLoc, Operand);
}
- /// \brief Build a new OpenMP executable directive.
+ /// Build a new OpenMP executable directive.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1479,7 +1489,7 @@ public:
Kind, DirName, CancelRegion, Clauses, AStmt, StartLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'if' clause.
+ /// Build a new OpenMP 'if' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1494,7 +1504,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'final' clause.
+ /// Build a new OpenMP 'final' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1505,7 +1515,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'num_threads' clause.
+ /// Build a new OpenMP 'num_threads' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1517,7 +1527,7 @@ public:
LParenLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'safelen' clause.
+ /// Build a new OpenMP 'safelen' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1527,7 +1537,7 @@ public:
return getSema().ActOnOpenMPSafelenClause(Len, StartLoc, LParenLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'simdlen' clause.
+ /// Build a new OpenMP 'simdlen' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1537,7 +1547,7 @@ public:
return getSema().ActOnOpenMPSimdlenClause(Len, StartLoc, LParenLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'collapse' clause.
+ /// Build a new OpenMP 'collapse' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1548,7 +1558,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'default' clause.
+ /// Build a new OpenMP 'default' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1561,7 +1571,7 @@ public:
StartLoc, LParenLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'proc_bind' clause.
+ /// Build a new OpenMP 'proc_bind' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1574,7 +1584,7 @@ public:
StartLoc, LParenLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'schedule' clause.
+ /// Build a new OpenMP 'schedule' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1588,7 +1598,7 @@ public:
CommaLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'ordered' clause.
+ /// Build a new OpenMP 'ordered' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1598,7 +1608,7 @@ public:
return getSema().ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Num);
}
- /// \brief Build a new OpenMP 'private' clause.
+ /// Build a new OpenMP 'private' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1610,7 +1620,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'firstprivate' clause.
+ /// Build a new OpenMP 'firstprivate' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1622,7 +1632,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'lastprivate' clause.
+ /// Build a new OpenMP 'lastprivate' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1634,7 +1644,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'shared' clause.
+ /// Build a new OpenMP 'shared' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1646,7 +1656,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'reduction' clause.
+ /// Build a new OpenMP 'reduction' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1694,7 +1704,7 @@ public:
ReductionId, UnresolvedReductions);
}
- /// \brief Build a new OpenMP 'linear' clause.
+ /// Build a new OpenMP 'linear' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1710,7 +1720,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'aligned' clause.
+ /// Build a new OpenMP 'aligned' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1723,7 +1733,7 @@ public:
LParenLoc, ColonLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'copyin' clause.
+ /// Build a new OpenMP 'copyin' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1735,7 +1745,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'copyprivate' clause.
+ /// Build a new OpenMP 'copyprivate' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1747,7 +1757,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'flush' pseudo clause.
+ /// Build a new OpenMP 'flush' pseudo clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1759,7 +1769,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'depend' pseudo clause.
+ /// Build a new OpenMP 'depend' pseudo clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1772,7 +1782,7 @@ public:
StartLoc, LParenLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'device' clause.
+ /// Build a new OpenMP 'device' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1783,7 +1793,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'map' clause.
+ /// Build a new OpenMP 'map' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1798,7 +1808,7 @@ public:
VarList, StartLoc, LParenLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'num_teams' clause.
+ /// Build a new OpenMP 'num_teams' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1809,7 +1819,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'thread_limit' clause.
+ /// Build a new OpenMP 'thread_limit' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1821,7 +1831,7 @@ public:
LParenLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'priority' clause.
+ /// Build a new OpenMP 'priority' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1832,7 +1842,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'grainsize' clause.
+ /// Build a new OpenMP 'grainsize' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1843,7 +1853,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'num_tasks' clause.
+ /// Build a new OpenMP 'num_tasks' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1854,7 +1864,7 @@ public:
EndLoc);
}
- /// \brief Build a new OpenMP 'hint' clause.
+ /// Build a new OpenMP 'hint' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1864,7 +1874,7 @@ public:
return getSema().ActOnOpenMPHintClause(Hint, StartLoc, LParenLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'dist_schedule' clause.
+ /// Build a new OpenMP 'dist_schedule' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
@@ -1877,7 +1887,7 @@ public:
Kind, ChunkSize, StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'to' clause.
+ /// Build a new OpenMP 'to' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1888,7 +1898,7 @@ public:
return getSema().ActOnOpenMPToClause(VarList, StartLoc, LParenLoc, EndLoc);
}
- /// \brief Build a new OpenMP 'from' clause.
+ /// Build a new OpenMP 'from' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1924,7 +1934,7 @@ public:
EndLoc);
}
- /// \brief Rebuild the operand to an Objective-C \@synchronized statement.
+ /// Rebuild the operand to an Objective-C \@synchronized statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1933,7 +1943,7 @@ public:
return getSema().ActOnObjCAtSynchronizedOperand(atLoc, object);
}
- /// \brief Build a new Objective-C \@synchronized statement.
+ /// Build a new Objective-C \@synchronized statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1942,7 +1952,7 @@ public:
return getSema().ActOnObjCAtSynchronizedStmt(AtLoc, Object, Body);
}
- /// \brief Build a new Objective-C \@autoreleasepool statement.
+ /// Build a new Objective-C \@autoreleasepool statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1951,7 +1961,7 @@ public:
return getSema().ActOnObjCAutoreleasePoolStmt(AtLoc, Body);
}
- /// \brief Build a new Objective-C fast enumeration statement.
+ /// Build a new Objective-C fast enumeration statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1970,7 +1980,7 @@ public:
return getSema().FinishObjCForCollectionStmt(ForEachStmt.get(), Body);
}
- /// \brief Build a new C++ exception declaration.
+ /// Build a new C++ exception declaration.
///
/// By default, performs semantic analysis to build the new decaration.
/// Subclasses may override this routine to provide different behavior.
@@ -1986,7 +1996,7 @@ public:
return Var;
}
- /// \brief Build a new C++ catch statement.
+ /// Build a new C++ catch statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -1997,7 +2007,7 @@ public:
Handler));
}
- /// \brief Build a new C++ try statement.
+ /// Build a new C++ try statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -2006,7 +2016,7 @@ public:
return getSema().ActOnCXXTryBlock(TryLoc, TryBlock, Handlers);
}
- /// \brief Build a new C++0x range-based for statement.
+ /// Build a new C++0x range-based for statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -2040,7 +2050,7 @@ public:
Sema::BFRK_Rebuild);
}
- /// \brief Build a new C++0x range-based for statement.
+ /// Build a new C++0x range-based for statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -2053,7 +2063,7 @@ public:
QualifierLoc, NameInfo, Nested);
}
- /// \brief Attach body to a C++0x range-based for statement.
+ /// Attach body to a C++0x range-based for statement.
///
/// By default, performs semantic analysis to finish the new statement.
/// Subclasses may override this routine to provide different behavior.
@@ -2075,7 +2085,7 @@ public:
return SEHFinallyStmt::Create(getSema().getASTContext(), Loc, Block);
}
- /// \brief Build a new predefined expression.
+ /// Build a new predefined expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2084,7 +2094,7 @@ public:
return getSema().BuildPredefinedExpr(Loc, IT);
}
- /// \brief Build a new expression that references a declaration.
+ /// Build a new expression that references a declaration.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2095,7 +2105,7 @@ public:
}
- /// \brief Build a new expression that references a declaration.
+ /// Build a new expression that references a declaration.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2111,7 +2121,7 @@ public:
return getSema().BuildDeclarationNameExpr(SS, NameInfo, VD);
}
- /// \brief Build a new expression in parentheses.
+ /// Build a new expression in parentheses.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2120,7 +2130,7 @@ public:
return getSema().ActOnParenExpr(LParen, RParen, SubExpr);
}
- /// \brief Build a new pseudo-destructor expression.
+ /// Build a new pseudo-destructor expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2133,7 +2143,7 @@ public:
SourceLocation TildeLoc,
PseudoDestructorTypeStorage Destroyed);
- /// \brief Build a new unary operator expression.
+ /// Build a new unary operator expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2143,7 +2153,7 @@ public:
return getSema().BuildUnaryOp(/*Scope=*/nullptr, OpLoc, Opc, SubExpr);
}
- /// \brief Build a new builtin offsetof expression.
+ /// Build a new builtin offsetof expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2155,7 +2165,7 @@ public:
RParenLoc);
}
- /// \brief Build a new sizeof, alignof or vec_step expression with a
+ /// Build a new sizeof, alignof or vec_step expression with a
/// type argument.
///
/// By default, performs semantic analysis to build the new expression.
@@ -2167,7 +2177,7 @@ public:
return getSema().CreateUnaryExprOrTypeTraitExpr(TInfo, OpLoc, ExprKind, R);
}
- /// \brief Build a new sizeof, alignof or vec step expression with an
+ /// Build a new sizeof, alignof or vec step expression with an
/// expression argument.
///
/// By default, performs semantic analysis to build the new expression.
@@ -2183,7 +2193,7 @@ public:
return Result;
}
- /// \brief Build a new array subscript expression.
+ /// Build a new array subscript expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2196,7 +2206,7 @@ public:
RBracketLoc);
}
- /// \brief Build a new array section expression.
+ /// Build a new array section expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2208,7 +2218,7 @@ public:
ColonLoc, Length, RBracketLoc);
}
- /// \brief Build a new call expression.
+ /// Build a new call expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2220,7 +2230,7 @@ public:
Args, RParenLoc, ExecConfig);
}
- /// \brief Build a new member access expression.
+ /// Build a new member access expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2239,7 +2249,6 @@ public:
// We have a reference to an unnamed field. This is always the
// base of an anonymous struct/union member access, i.e. the
// field is always of record type.
- assert(!QualifierLoc && "Can't have an unnamed field with a qualifier!");
assert(Member->getType()->isRecordType() &&
"unnamed member not of record type?");
@@ -2250,11 +2259,11 @@ public:
if (BaseResult.isInvalid())
return ExprError();
Base = BaseResult.get();
- ExprValueKind VK = isArrow ? VK_LValue : Base->getValueKind();
- MemberExpr *ME = new (getSema().Context)
- MemberExpr(Base, isArrow, OpLoc, Member, MemberNameInfo,
- cast<FieldDecl>(Member)->getType(), VK, OK_Ordinary);
- return ME;
+
+ CXXScopeSpec EmptySS;
+ return getSema().BuildFieldReferenceExpr(
+ Base, isArrow, OpLoc, EmptySS, cast<FieldDecl>(Member),
+ DeclAccessPair::make(FoundDecl, FoundDecl->getAccess()), MemberNameInfo);
}
CXXScopeSpec SS;
@@ -2279,7 +2288,7 @@ public:
/*S*/nullptr);
}
- /// \brief Build a new binary operator expression.
+ /// Build a new binary operator expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2289,7 +2298,7 @@ public:
return getSema().BuildBinOp(/*Scope=*/nullptr, OpLoc, Opc, LHS, RHS);
}
- /// \brief Build a new conditional operator expression.
+ /// Build a new conditional operator expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2302,7 +2311,7 @@ public:
LHS, RHS);
}
- /// \brief Build a new C-style cast expression.
+ /// Build a new C-style cast expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2314,7 +2323,7 @@ public:
SubExpr);
}
- /// \brief Build a new compound literal expression.
+ /// Build a new compound literal expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2326,7 +2335,7 @@ public:
Init);
}
- /// \brief Build a new extended vector element access expression.
+ /// Build a new extended vector element access expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2346,27 +2355,17 @@ public:
/*S*/ nullptr);
}
- /// \brief Build a new initializer list expression.
+ /// Build a new initializer list expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildInitList(SourceLocation LBraceLoc,
MultiExprArg Inits,
- SourceLocation RBraceLoc,
- QualType ResultTy) {
- ExprResult Result
- = SemaRef.ActOnInitList(LBraceLoc, Inits, RBraceLoc);
- if (Result.isInvalid() || ResultTy->isDependentType())
- return Result;
-
- // Patch in the result type we were given, which may have been computed
- // when the initial InitListExpr was built.
- InitListExpr *ILE = cast<InitListExpr>((Expr *)Result.get());
- ILE->setType(ResultTy);
- return Result;
+ SourceLocation RBraceLoc) {
+ return SemaRef.ActOnInitList(LBraceLoc, Inits, RBraceLoc);
}
- /// \brief Build a new designated initializer expression.
+ /// Build a new designated initializer expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2384,7 +2383,7 @@ public:
return Result;
}
- /// \brief Build a new value-initialized expression.
+ /// Build a new value-initialized expression.
///
/// By default, builds the implicit value initialization without performing
/// any semantic analysis. Subclasses may override this routine to provide
@@ -2393,7 +2392,7 @@ public:
return new (SemaRef.Context) ImplicitValueInitExpr(T);
}
- /// \brief Build a new \c va_arg expression.
+ /// Build a new \c va_arg expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2405,7 +2404,7 @@ public:
RParenLoc);
}
- /// \brief Build a new expression list in parentheses.
+ /// Build a new expression list in parentheses.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2415,7 +2414,7 @@ public:
return getSema().ActOnParenListExpr(LParenLoc, RParenLoc, SubExprs);
}
- /// \brief Build a new address-of-label expression.
+ /// Build a new address-of-label expression.
///
/// By default, performs semantic analysis, using the name of the label
/// rather than attempting to map the label statement itself.
@@ -2425,7 +2424,7 @@ public:
return getSema().ActOnAddrLabel(AmpAmpLoc, LabelLoc, Label);
}
- /// \brief Build a new GNU statement expression.
+ /// Build a new GNU statement expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2435,7 +2434,7 @@ public:
return getSema().ActOnStmtExpr(LParenLoc, SubStmt, RParenLoc);
}
- /// \brief Build a new __builtin_choose_expr expression.
+ /// Build a new __builtin_choose_expr expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2447,7 +2446,7 @@ public:
RParenLoc);
}
- /// \brief Build a new generic selection expression.
+ /// Build a new generic selection expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2461,7 +2460,7 @@ public:
ControllingExpr, Types, Exprs);
}
- /// \brief Build a new overloaded operator call expression.
+ /// Build a new overloaded operator call expression.
///
/// By default, performs semantic analysis to build the new expression.
/// The semantic analysis provides the behavior of template instantiation,
@@ -2475,7 +2474,7 @@ public:
Expr *First,
Expr *Second);
- /// \brief Build a new C++ "named" cast expression, such as static_cast or
+ /// Build a new C++ "named" cast expression, such as static_cast or
/// reinterpret_cast.
///
/// By default, this routine dispatches to one of the more-specific routines
@@ -2516,7 +2515,7 @@ public:
}
}
- /// \brief Build a new C++ static_cast expression.
+ /// Build a new C++ static_cast expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2533,7 +2532,7 @@ public:
SourceRange(LParenLoc, RParenLoc));
}
- /// \brief Build a new C++ dynamic_cast expression.
+ /// Build a new C++ dynamic_cast expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2550,7 +2549,7 @@ public:
SourceRange(LParenLoc, RParenLoc));
}
- /// \brief Build a new C++ reinterpret_cast expression.
+ /// Build a new C++ reinterpret_cast expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2567,7 +2566,7 @@ public:
SourceRange(LParenLoc, RParenLoc));
}
- /// \brief Build a new C++ const_cast expression.
+ /// Build a new C++ const_cast expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2584,20 +2583,21 @@ public:
SourceRange(LParenLoc, RParenLoc));
}
- /// \brief Build a new C++ functional-style cast expression.
+ /// Build a new C++ functional-style cast expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildCXXFunctionalCastExpr(TypeSourceInfo *TInfo,
SourceLocation LParenLoc,
Expr *Sub,
- SourceLocation RParenLoc) {
+ SourceLocation RParenLoc,
+ bool ListInitialization) {
return getSema().BuildCXXTypeConstructExpr(TInfo, LParenLoc,
- MultiExprArg(&Sub, 1),
- RParenLoc);
+ MultiExprArg(&Sub, 1), RParenLoc,
+ ListInitialization);
}
- /// \brief Build a new C++ typeid(type) expression.
+ /// Build a new C++ typeid(type) expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2610,7 +2610,7 @@ public:
}
- /// \brief Build a new C++ typeid(expr) expression.
+ /// Build a new C++ typeid(expr) expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2622,7 +2622,7 @@ public:
RParenLoc);
}
- /// \brief Build a new C++ __uuidof(type) expression.
+ /// Build a new C++ __uuidof(type) expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2634,7 +2634,7 @@ public:
RParenLoc);
}
- /// \brief Build a new C++ __uuidof(expr) expression.
+ /// Build a new C++ __uuidof(expr) expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2646,7 +2646,7 @@ public:
RParenLoc);
}
- /// \brief Build a new C++ "this" expression.
+ /// Build a new C++ "this" expression.
///
/// By default, builds a new "this" expression without performing any
/// semantic analysis. Subclasses may override this routine to provide
@@ -2658,7 +2658,7 @@ public:
return new (getSema().Context) CXXThisExpr(ThisLoc, ThisType, isImplicit);
}
- /// \brief Build a new C++ throw expression.
+ /// Build a new C++ throw expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2667,7 +2667,7 @@ public:
return getSema().BuildCXXThrow(ThrowLoc, Sub, IsThrownVariableInScope);
}
- /// \brief Build a new C++ default-argument expression.
+ /// Build a new C++ default-argument expression.
///
/// By default, builds a new default-argument expression, which does not
/// require any semantic analysis. Subclasses may override this routine to
@@ -2677,7 +2677,7 @@ public:
return CXXDefaultArgExpr::Create(getSema().Context, Loc, Param);
}
- /// \brief Build a new C++11 default-initialization expression.
+ /// Build a new C++11 default-initialization expression.
///
/// By default, builds a new default field initialization expression, which
/// does not require any semantic analysis. Subclasses may override this
@@ -2687,18 +2687,18 @@ public:
return CXXDefaultInitExpr::Create(getSema().Context, Loc, Field);
}
- /// \brief Build a new C++ zero-initialization expression.
+ /// Build a new C++ zero-initialization expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildCXXScalarValueInitExpr(TypeSourceInfo *TSInfo,
SourceLocation LParenLoc,
SourceLocation RParenLoc) {
- return getSema().BuildCXXTypeConstructExpr(TSInfo, LParenLoc,
- None, RParenLoc);
+ return getSema().BuildCXXTypeConstructExpr(
+ TSInfo, LParenLoc, None, RParenLoc, /*ListInitialization=*/false);
}
- /// \brief Build a new C++ "new" expression.
+ /// Build a new C++ "new" expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2725,7 +2725,7 @@ public:
Initializer);
}
- /// \brief Build a new C++ "delete" expression.
+ /// Build a new C++ "delete" expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2737,7 +2737,7 @@ public:
Operand);
}
- /// \brief Build a new type trait expression.
+ /// Build a new type trait expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2748,7 +2748,7 @@ public:
return getSema().BuildTypeTrait(Trait, StartLoc, Args, RParenLoc);
}
- /// \brief Build a new array type trait expression.
+ /// Build a new array type trait expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2760,7 +2760,7 @@ public:
return getSema().BuildArrayTypeTrait(Trait, StartLoc, TSInfo, DimExpr, RParenLoc);
}
- /// \brief Build a new expression trait expression.
+ /// Build a new expression trait expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2771,7 +2771,7 @@ public:
return getSema().BuildExpressionTrait(Trait, StartLoc, Queried, RParenLoc);
}
- /// \brief Build a new (previously unresolved) declaration reference
+ /// Build a new (previously unresolved) declaration reference
/// expression.
///
/// By default, performs semantic analysis to build the new expression.
@@ -2794,7 +2794,7 @@ public:
SS, NameInfo, IsAddressOfOperand, /*S*/nullptr, RecoveryTSI);
}
- /// \brief Build a new template-id expression.
+ /// Build a new template-id expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2807,7 +2807,7 @@ public:
TemplateArgs);
}
- /// \brief Build a new object-construction expression.
+ /// Build a new object-construction expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2837,7 +2837,7 @@ public:
ParenRange);
}
- /// \brief Build a new implicit construction via inherited constructor
+ /// Build a new implicit construction via inherited constructor
/// expression.
ExprResult RebuildCXXInheritedCtorInitExpr(QualType T, SourceLocation Loc,
CXXConstructorDecl *Constructor,
@@ -2847,35 +2847,33 @@ public:
Loc, T, Constructor, ConstructsVBase, InheritedFromVBase);
}
- /// \brief Build a new object-construction expression.
+ /// Build a new object-construction expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildCXXTemporaryObjectExpr(TypeSourceInfo *TSInfo,
- SourceLocation LParenLoc,
+ SourceLocation LParenOrBraceLoc,
MultiExprArg Args,
- SourceLocation RParenLoc) {
- return getSema().BuildCXXTypeConstructExpr(TSInfo,
- LParenLoc,
- Args,
- RParenLoc);
+ SourceLocation RParenOrBraceLoc,
+ bool ListInitialization) {
+ return getSema().BuildCXXTypeConstructExpr(
+ TSInfo, LParenOrBraceLoc, Args, RParenOrBraceLoc, ListInitialization);
}
- /// \brief Build a new object-construction expression.
+ /// Build a new object-construction expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildCXXUnresolvedConstructExpr(TypeSourceInfo *TSInfo,
SourceLocation LParenLoc,
MultiExprArg Args,
- SourceLocation RParenLoc) {
- return getSema().BuildCXXTypeConstructExpr(TSInfo,
- LParenLoc,
- Args,
- RParenLoc);
+ SourceLocation RParenLoc,
+ bool ListInitialization) {
+ return getSema().BuildCXXTypeConstructExpr(TSInfo, LParenLoc, Args,
+ RParenLoc, ListInitialization);
}
- /// \brief Build a new member reference expression.
+ /// Build a new member reference expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2899,7 +2897,7 @@ public:
TemplateArgs, /*S*/nullptr);
}
- /// \brief Build a new member reference expression.
+ /// Build a new member reference expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2921,7 +2919,7 @@ public:
R, TemplateArgs, /*S*/nullptr);
}
- /// \brief Build a new noexcept expression.
+ /// Build a new noexcept expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2929,7 +2927,7 @@ public:
return SemaRef.BuildCXXNoexceptExpr(Range.getBegin(), Arg, Range.getEnd());
}
- /// \brief Build a new expression to compute the length of a parameter pack.
+ /// Build a new expression to compute the length of a parameter pack.
ExprResult RebuildSizeOfPackExpr(SourceLocation OperatorLoc,
NamedDecl *Pack,
SourceLocation PackLoc,
@@ -2940,7 +2938,7 @@ public:
RParenLoc, Length, PartialArgs);
}
- /// \brief Build a new Objective-C boxed expression.
+ /// Build a new Objective-C boxed expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2948,7 +2946,7 @@ public:
return getSema().BuildObjCBoxedExpr(SR, ValueExpr);
}
- /// \brief Build a new Objective-C array literal.
+ /// Build a new Objective-C array literal.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2966,7 +2964,7 @@ public:
getterMethod, setterMethod);
}
- /// \brief Build a new Objective-C dictionary literal.
+ /// Build a new Objective-C dictionary literal.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2975,7 +2973,7 @@ public:
return getSema().BuildObjCDictionaryLiteral(Range, Elements);
}
- /// \brief Build a new Objective-C \@encode expression.
+ /// Build a new Objective-C \@encode expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -2985,7 +2983,7 @@ public:
return SemaRef.BuildObjCEncodeExpression(AtLoc, EncodeTypeInfo, RParenLoc);
}
- /// \brief Build a new Objective-C class message.
+ /// Build a new Objective-C class message.
ExprResult RebuildObjCMessageExpr(TypeSourceInfo *ReceiverTypeInfo,
Selector Sel,
ArrayRef<SourceLocation> SelectorLocs,
@@ -3000,7 +2998,7 @@ public:
RBracLoc, Args);
}
- /// \brief Build a new Objective-C instance message.
+ /// Build a new Objective-C instance message.
ExprResult RebuildObjCMessageExpr(Expr *Receiver,
Selector Sel,
ArrayRef<SourceLocation> SelectorLocs,
@@ -3015,7 +3013,7 @@ public:
RBracLoc, Args);
}
- /// \brief Build a new Objective-C instance/class message to 'super'.
+ /// Build a new Objective-C instance/class message to 'super'.
ExprResult RebuildObjCMessageExpr(SourceLocation SuperLoc,
Selector Sel,
ArrayRef<SourceLocation> SelectorLocs,
@@ -3038,7 +3036,7 @@ public:
}
- /// \brief Build a new Objective-C ivar reference expression.
+ /// Build a new Objective-C ivar reference expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -3058,7 +3056,7 @@ public:
return Result;
}
- /// \brief Build a new Objective-C property reference expression.
+ /// Build a new Objective-C property reference expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -3077,7 +3075,7 @@ public:
/*S=*/nullptr);
}
- /// \brief Build a new Objective-C property reference expression.
+ /// Build a new Objective-C property reference expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -3093,7 +3091,7 @@ public:
PropertyLoc, Base));
}
- /// \brief Build a new Objective-C "isa" expression.
+ /// Build a new Objective-C "isa" expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -3110,7 +3108,7 @@ public:
/*S=*/nullptr);
}
- /// \brief Build a new shuffle vector expression.
+ /// Build a new shuffle vector expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -3142,7 +3140,7 @@ public:
return SemaRef.SemaBuiltinShuffleVector(cast<CallExpr>(TheCall.get()));
}
- /// \brief Build a new convert vector expression.
+ /// Build a new convert vector expression.
ExprResult RebuildConvertVectorExpr(SourceLocation BuiltinLoc,
Expr *SrcExpr, TypeSourceInfo *DstTInfo,
SourceLocation RParenLoc) {
@@ -3150,7 +3148,7 @@ public:
BuiltinLoc, RParenLoc);
}
- /// \brief Build a new template argument pack expansion.
+ /// Build a new template argument pack expansion.
///
/// By default, performs semantic analysis to build a new pack expansion
/// for a template argument. Subclasses may override this routine to provide
@@ -3198,7 +3196,7 @@ public:
return TemplateArgumentLoc();
}
- /// \brief Build a new expression pack expansion.
+ /// Build a new expression pack expansion.
///
/// By default, performs semantic analysis to build a new pack expansion
/// for an expression. Subclasses may override this routine to provide
@@ -3208,7 +3206,7 @@ public:
return getSema().CheckPackExpansion(Pattern, EllipsisLoc, NumExpansions);
}
- /// \brief Build a new C++1z fold-expression.
+ /// Build a new C++1z fold-expression.
///
/// By default, performs semantic analysis in order to build a new fold
/// expression.
@@ -3220,7 +3218,7 @@ public:
RHS, RParenLoc);
}
- /// \brief Build an empty C++1z fold-expression with the given operator.
+ /// Build an empty C++1z fold-expression with the given operator.
///
/// By default, produces the fallback value for the fold-expression, or
/// produce an error if there is no fallback value.
@@ -3229,7 +3227,7 @@ public:
return getSema().BuildEmptyCXXFoldExpr(EllipsisLoc, Operator);
}
- /// \brief Build a new atomic operation expression.
+ /// Build a new atomic operation expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
@@ -3394,11 +3392,10 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init,
/*IsCall*/true, NewArgs, &ArgChanged))
return ExprError();
- // If this was list initialization, revert to list form.
+ // If this was list initialization, revert to syntactic list form.
if (Construct->isListInitialization())
return getDerived().RebuildInitList(Construct->getLocStart(), NewArgs,
- Construct->getLocEnd(),
- Construct->getType());
+ Construct->getLocEnd());
// Build a ParenListExpr to represent anything else.
SourceRange Parens = Construct->getParenOrBraceRange();
@@ -3765,8 +3762,12 @@ TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS,
ObjectType.isNull())
return Name;
+ // FIXME: Preserve the location of the "template" keyword.
+ SourceLocation TemplateKWLoc = NameLoc;
+
if (DTN->isIdentifier()) {
return getDerived().RebuildTemplateName(SS,
+ TemplateKWLoc,
*DTN->getIdentifier(),
NameLoc,
ObjectType,
@@ -3774,7 +3775,8 @@ TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS,
AllowInjectedClassName);
}
- return getDerived().RebuildTemplateName(SS, DTN->getOperator(), NameLoc,
+ return getDerived().RebuildTemplateName(SS, TemplateKWLoc,
+ DTN->getOperator(), NameLoc,
ObjectType, AllowInjectedClassName);
}
@@ -3866,6 +3868,10 @@ template<typename Derived>
bool TreeTransform<Derived>::TransformTemplateArgument(
const TemplateArgumentLoc &Input,
TemplateArgumentLoc &Output, bool Uneval) {
+ EnterExpressionEvaluationContext EEEC(
+ SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated,
+ /*LambdaContextDecl=*/nullptr, /*ExprContext=*/
+ Sema::ExpressionEvaluationContextRecord::EK_TemplateArgument);
const TemplateArgument &Arg = Input.getArgument();
switch (Arg.getKind()) {
case TemplateArgument::Null:
@@ -3933,7 +3939,7 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
return true;
}
-/// \brief Iterator adaptor that invents template argument location information
+/// Iterator adaptor that invents template argument location information
/// for each of the template arguments in its underlying iterator.
template<typename Derived, typename InputIterator>
class TemplateArgumentLocInventIterator {
@@ -4353,6 +4359,7 @@ TypeSourceInfo *TreeTransform<Derived>::TransformTSIInObjectScope(
TemplateName Template
= getDerived().RebuildTemplateName(SS,
+ SpecTL.getTemplateKeywordLoc(),
*SpecTL.getTypePtr()->getIdentifier(),
SpecTL.getTemplateNameLoc(),
ObjectType, UnqualLookup,
@@ -4752,6 +4759,44 @@ TreeTransform<Derived>::TransformDependentSizedArrayType(TypeLocBuilder &TLB,
return Result;
}
+template <typename Derived>
+QualType TreeTransform<Derived>::TransformDependentVectorType(
+ TypeLocBuilder &TLB, DependentVectorTypeLoc TL) {
+ const DependentVectorType *T = TL.getTypePtr();
+ QualType ElementType = getDerived().TransformType(T->getElementType());
+ if (ElementType.isNull())
+ return QualType();
+
+ EnterExpressionEvaluationContext Unevaluated(
+ SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+
+ ExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
+ Size = SemaRef.ActOnConstantExpression(Size);
+ if (Size.isInvalid())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() || ElementType != T->getElementType() ||
+ Size.get() != T->getSizeExpr()) {
+ Result = getDerived().RebuildDependentVectorType(
+ ElementType, Size.get(), T->getAttributeLoc(), T->getVectorKind());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ // Result might be dependent or not.
+ if (isa<DependentVectorType>(Result)) {
+ DependentVectorTypeLoc NewTL =
+ TLB.push<DependentVectorTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+ } else {
+ VectorTypeLoc NewTL = TLB.push<VectorTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+ }
+
+ return Result;
+}
+
template<typename Derived>
QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
TypeLocBuilder &TLB,
@@ -5277,30 +5322,23 @@ bool TreeTransform<Derived>::TransformExceptionSpec(
assert(ESI.Type != EST_Uninstantiated && ESI.Type != EST_Unevaluated);
// Instantiate a dynamic noexcept expression, if any.
- if (ESI.Type == EST_ComputedNoexcept) {
+ if (isComputedNoexcept(ESI.Type)) {
EnterExpressionEvaluationContext Unevaluated(
getSema(), Sema::ExpressionEvaluationContext::ConstantEvaluated);
ExprResult NoexceptExpr = getDerived().TransformExpr(ESI.NoexceptExpr);
if (NoexceptExpr.isInvalid())
return true;
- // FIXME: This is bogus, a noexcept expression is not a condition.
- NoexceptExpr = getSema().CheckBooleanCondition(Loc, NoexceptExpr.get());
+ ExceptionSpecificationType EST = ESI.Type;
+ NoexceptExpr =
+ getSema().ActOnNoexceptSpec(Loc, NoexceptExpr.get(), EST);
if (NoexceptExpr.isInvalid())
return true;
- if (!NoexceptExpr.get()->isValueDependent()) {
- NoexceptExpr = getSema().VerifyIntegerConstantExpression(
- NoexceptExpr.get(), nullptr,
- diag::err_noexcept_needs_constant_expression,
- /*AllowFold*/false);
- if (NoexceptExpr.isInvalid())
- return true;
- }
-
- if (ESI.NoexceptExpr != NoexceptExpr.get())
+ if (ESI.NoexceptExpr != NoexceptExpr.get() || EST != ESI.Type)
Changed = true;
ESI.NoexceptExpr = NoexceptExpr.get();
+ ESI.Type = EST;
}
if (ESI.Type != EST_Dynamic)
@@ -5507,7 +5545,7 @@ QualType TreeTransform<Derived>::TransformDecltypeType(TypeLocBuilder &TLB,
// decltype expressions are not potentially evaluated contexts
EnterExpressionEvaluationContext Unevaluated(
SemaRef, Sema::ExpressionEvaluationContext::Unevaluated, nullptr,
- /*IsDecltype=*/true);
+ Sema::ExpressionEvaluationContextRecord::EK_Decltype);
ExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
if (E.isInvalid())
@@ -5778,7 +5816,7 @@ QualType TreeTransform<Derived>::TransformPipeType(TypeLocBuilder &TLB,
return Result;
}
- /// \brief Simple iterator that traverses the template arguments in a
+ /// Simple iterator that traverses the template arguments in a
/// container that provides a \c getArgLoc() member function.
///
/// This iterator is intended to be used with the iterator form of
@@ -6158,8 +6196,8 @@ TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB,
return QualType();
QualType Result = getDerived().RebuildDependentTemplateSpecializationType(
- T->getKeyword(), QualifierLoc, T->getIdentifier(),
- TL.getTemplateNameLoc(), NewTemplateArgs,
+ T->getKeyword(), QualifierLoc, TL.getTemplateKeywordLoc(),
+ T->getIdentifier(), TL.getTemplateNameLoc(), NewTemplateArgs,
/*AllowInjectedClassName*/ false);
if (Result.isNull())
return QualType();
@@ -6487,13 +6525,13 @@ TreeTransform<Derived>::TransformCaseStmt(CaseStmt *S) {
// Transform the left-hand case value.
LHS = getDerived().TransformExpr(S->getLHS());
- LHS = SemaRef.ActOnConstantExpression(LHS);
+ LHS = SemaRef.ActOnCaseExpr(S->getCaseLoc(), LHS);
if (LHS.isInvalid())
return StmtError();
// Transform the right-hand case value (for the GNU case-range extension).
RHS = getDerived().TransformExpr(S->getRHS());
- RHS = SemaRef.ActOnConstantExpression(RHS);
+ RHS = SemaRef.ActOnCaseExpr(S->getCaseLoc(), RHS);
if (RHS.isInvalid())
return StmtError();
}
@@ -6956,6 +6994,8 @@ TreeTransform<Derived>::TransformCoroutineBodyStmt(CoroutineBodyStmt *S) {
// The new CoroutinePromise object needs to be built and put into the current
// FunctionScopeInfo before any transformations or rebuilding occurs.
+ if (!SemaRef.buildCoroutineParameterMoves(FD->getLocation()))
+ return StmtError();
auto *Promise = SemaRef.buildCoroutinePromise(FD->getLocation());
if (!Promise)
return StmtError();
@@ -7046,8 +7086,6 @@ TreeTransform<Derived>::TransformCoroutineBodyStmt(CoroutineBodyStmt *S) {
Builder.ReturnStmt = Res.get();
}
}
- if (!Builder.buildParameterMoves())
- return StmtError();
return getDerived().RebuildCoroutineBodyStmt(Builder);
}
@@ -7642,11 +7680,7 @@ StmtResult TreeTransform<Derived>::TransformOMPExecutableDirective(
StmtResult Body;
{
Sema::CompoundScopeRAII CompoundScope(getSema());
- int ThisCaptureLevel =
- Sema::getOpenMPCaptureLevels(D->getDirectiveKind());
- Stmt *CS = D->getAssociatedStmt();
- while (--ThisCaptureLevel >= 0)
- CS = cast<CapturedStmt>(CS)->getCapturedStmt();
+ Stmt *CS = D->getInnermostCapturedStmt()->getCapturedStmt();
Body = getDerived().TransformStmt(CS);
}
AssociatedStmt =
@@ -8905,6 +8939,12 @@ TreeTransform<Derived>::TransformIntegerLiteral(IntegerLiteral *E) {
return E;
}
+template <typename Derived>
+ExprResult TreeTransform<Derived>::TransformFixedPointLiteral(
+ FixedPointLiteral *E) {
+ return E;
+}
+
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformFloatingLiteral(FloatingLiteral *E) {
@@ -8986,7 +9026,7 @@ TreeTransform<Derived>::TransformParenExpr(ParenExpr *E) {
E->getRParen());
}
-/// \brief The operand of a unary address-of operator has special rules: it's
+/// The operand of a unary address-of operator has special rules: it's
/// allowed to refer to a non-static member of a class even if there's no 'this'
/// object available.
template<typename Derived>
@@ -9517,7 +9557,7 @@ TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E) {
}
return getDerived().RebuildInitList(E->getLBraceLoc(), Inits,
- E->getRBraceLoc(), E->getType());
+ E->getRBraceLoc());
}
template<typename Derived>
@@ -9685,7 +9725,7 @@ TreeTransform<Derived>::TransformParenListExpr(ParenListExpr *E) {
E->getRParenLoc());
}
-/// \brief Transform an address-of-label expression.
+/// Transform an address-of-label expression.
///
/// By default, the transformation of an address-of-label expression always
/// rebuilds the expression, so that the label identifier can be resolved to
@@ -9951,7 +9991,8 @@ TreeTransform<Derived>::TransformCXXFunctionalCastExpr(
return getDerived().RebuildCXXFunctionalCastExpr(Type,
E->getLParenLoc(),
SubExpr.get(),
- E->getRParenLoc());
+ E->getRParenLoc(),
+ E->isListInitialization());
}
template<typename Derived>
@@ -10403,7 +10444,7 @@ bool TreeTransform<Derived>::TransformOverloadExprDecls(OverloadExpr *Old,
// the corresponding pack is empty
if (AllEmptyPacks && !RequiresADL) {
getSema().Diag(Old->getNameLoc(), diag::err_using_pack_expansion_empty)
- << isa<UnresolvedMemberExpr>(Old) << Old->getNameInfo().getName();
+ << isa<UnresolvedMemberExpr>(Old) << Old->getName();
return true;
}
@@ -10814,7 +10855,7 @@ ExprResult TreeTransform<Derived>::TransformCXXInheritedCtorInitExpr(
E->constructsVBase(), E->inheritedFromVBase());
}
-/// \brief Transform a C++ temporary-binding expression.
+/// Transform a C++ temporary-binding expression.
///
/// Since CXXBindTemporaryExpr nodes are implicitly generated, we just
/// transform the subexpression and return that.
@@ -10824,7 +10865,7 @@ TreeTransform<Derived>::TransformCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
return getDerived().TransformExpr(E->getSubExpr());
}
-/// \brief Transform a C++ expression that contains cleanups that should
+/// Transform a C++ expression that contains cleanups that should
/// be run after the expression is evaluated.
///
/// Since ExprWithCleanups nodes are implicitly generated, we
@@ -10867,11 +10908,12 @@ TreeTransform<Derived>::TransformCXXTemporaryObjectExpr(
return SemaRef.MaybeBindToTemporary(E);
}
- // FIXME: Pass in E->isListInitialization().
- return getDerived().RebuildCXXTemporaryObjectExpr(T,
- /*FIXME:*/T->getTypeLoc().getEndLoc(),
- Args,
- E->getLocEnd());
+ // FIXME: We should just pass E->isListInitialization(), but we're not
+ // prepared to handle list-initialization without a child InitListExpr.
+ SourceLocation LParenLoc = T->getTypeLoc().getEndLoc();
+ return getDerived().RebuildCXXTemporaryObjectExpr(
+ T, LParenLoc, Args, E->getLocEnd(),
+ /*ListInitialization=*/LParenLoc.isInvalid());
}
template<typename Derived>
@@ -11157,10 +11199,8 @@ TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr(
return E;
// FIXME: we're faking the locations of the commas
- return getDerived().RebuildCXXUnresolvedConstructExpr(T,
- E->getLParenLoc(),
- Args,
- E->getRParenLoc());
+ return getDerived().RebuildCXXUnresolvedConstructExpr(
+ T, E->getLParenLoc(), Args, E->getRParenLoc(), E->isListInitialization());
}
template<typename Derived>
@@ -11408,8 +11448,10 @@ TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) {
ArgStorage = TemplateArgument(TemplateName(TTPD), None);
} else {
auto *VD = cast<ValueDecl>(Pack);
- ExprResult DRE = getSema().BuildDeclRefExpr(VD, VD->getType(),
- VK_RValue, E->getPackLoc());
+ ExprResult DRE = getSema().BuildDeclRefExpr(
+ VD, VD->getType().getNonLValueExprType(getSema().Context),
+ VD->getType()->isReferenceType() ? VK_LValue : VK_RValue,
+ E->getPackLoc());
if (DRE.isInvalid())
return ExprError();
ArgStorage = new (getSema().Context) PackExpansionExpr(
@@ -12386,6 +12428,13 @@ TreeTransform<Derived>::RebuildVectorType(QualType ElementType,
return SemaRef.Context.getVectorType(ElementType, NumElements, VecKind);
}
+template <typename Derived>
+QualType TreeTransform<Derived>::RebuildDependentVectorType(
+ QualType ElementType, Expr *SizeExpr, SourceLocation AttributeLoc,
+ VectorType::VectorKind VecKind) {
+ return SemaRef.BuildVectorType(ElementType, SizeExpr, AttributeLoc);
+}
+
template<typename Derived>
QualType TreeTransform<Derived>::RebuildExtVectorType(QualType ElementType,
unsigned NumElements,
@@ -12532,6 +12581,7 @@ TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
template<typename Derived>
TemplateName
TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
const IdentifierInfo &Name,
SourceLocation NameLoc,
QualType ObjectType,
@@ -12540,7 +12590,6 @@ TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
UnqualifiedId TemplateName;
TemplateName.setIdentifier(&Name, NameLoc);
Sema::TemplateTy Template;
- SourceLocation TemplateKWLoc; // FIXME: retrieve it from caller.
getSema().ActOnDependentTemplateName(/*Scope=*/nullptr,
SS, TemplateKWLoc, TemplateName,
ParsedType::make(ObjectType),
@@ -12552,6 +12601,7 @@ TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
template<typename Derived>
TemplateName
TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
OverloadedOperatorKind Operator,
SourceLocation NameLoc,
QualType ObjectType,
@@ -12560,7 +12610,6 @@ TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
// FIXME: Bogus location information.
SourceLocation SymbolLocations[3] = { NameLoc, NameLoc, NameLoc };
Name.setOperatorFunctionId(NameLoc, Operator, SymbolLocations);
- SourceLocation TemplateKWLoc; // FIXME: retrieve it from caller.
Sema::TemplateTy Template;
getSema().ActOnDependentTemplateName(/*Scope=*/nullptr,
SS, TemplateKWLoc, Name,
@@ -12609,9 +12658,11 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
// -> is never a builtin operation.
return SemaRef.BuildOverloadedArrowExpr(nullptr, First, OpLoc);
} else if (Second == nullptr || isPostIncDec) {
- if (!First->getType()->isOverloadableType()) {
- // The argument is not of overloadable type, so try to create a
- // built-in unary operation.
+ if (!First->getType()->isOverloadableType() ||
+ (Op == OO_Amp && getSema().isQualifiedMemberAccess(First))) {
+ // The argument is not of overloadable type, or this is an expression
+ // of the form &Class::member, so try to create a built-in unary
+ // operation.
UnaryOperatorKind Opc
= UnaryOperator::getOverloadedOpcode(Op, isPostIncDec);
diff --git a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h
index 9c77045d2e12..a088fe9de667 100644
--- a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h
+++ b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h
@@ -83,7 +83,7 @@ class TypeLocBuilder {
NumBytesAtAlign4 = NumBytesAtAlign8 = 0;
}
- /// \brief Tell the TypeLocBuilder that the type it is storing has been
+ /// Tell the TypeLocBuilder that the type it is storing has been
/// modified in some safe way that doesn't affect type-location information.
void TypeWasModifiedSafely(QualType T) {
#ifndef NDEBUG
@@ -112,7 +112,7 @@ class TypeLocBuilder {
return DI;
}
- /// \brief Copies the type-location information to the given AST context and
+ /// Copies the type-location information to the given AST context and
/// returns a \c TypeLoc referring into the AST context.
TypeLoc getTypeLocInContext(ASTContext &Context, QualType T) {
#ifndef NDEBUG
@@ -132,7 +132,7 @@ private:
/// Grow to the given capacity.
void grow(size_t NewCapacity);
- /// \brief Retrieve a temporary TypeLoc that refers into this \c TypeLocBuilder
+ /// Retrieve a temporary TypeLoc that refers into this \c TypeLocBuilder
/// object.
///
/// The resulting \c TypeLoc should only be used so long as the