summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Sema
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2014-11-24 18:11:16 +0000
committerdim <dim@FreeBSD.org>2014-11-24 18:11:16 +0000
commit6148c19c738a92f344008aa3f88f4e008bada0ee (patch)
treed4426858455f04d0d8c25a2f9eb9ea5582ffe1b6 /contrib/llvm/tools/clang/lib/Sema
parent2c8643c6396b0a3db33430cf9380e70bbb9efce0 (diff)
parent173a4f43a911175643bda81ee675e8d9269056ea (diff)
downloadFreeBSD-src-6148c19c738a92f344008aa3f88f4e008bada0ee.zip
FreeBSD-src-6148c19c738a92f344008aa3f88f4e008bada0ee.tar.gz
Merge clang 3.5.0 release from ^/vendor/clang/dist, resolve conflicts,
and preserve our customizations, where necessary.
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema')
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp604
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp72
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp178
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp24
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp23
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp169
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/Scope.cpp161
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/Sema.cpp236
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp109
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp224
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp169
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp124
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp1963
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp592
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp2814
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp3054
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp2327
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp883
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp134
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp2250
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp1162
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp470
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp990
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp861
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp460
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp1352
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp581
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp3628
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp1092
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp249
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp734
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp31
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp165
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp920
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp642
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp491
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp689
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaType.cpp942
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp353
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.h27
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TreeTransform.h1733
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h2
47 files changed, 20355 insertions, 13423 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 93e3ecf..213d6fb 100644
--- a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -65,16 +65,198 @@ namespace {
public:
UnreachableCodeHandler(Sema &s) : S(s) {}
- void HandleUnreachable(SourceLocation L, SourceRange R1, SourceRange R2) {
- S.Diag(L, diag::warn_unreachable) << R1 << R2;
+ void HandleUnreachable(reachable_code::UnreachableKind UK,
+ SourceLocation L,
+ SourceRange SilenceableCondVal,
+ SourceRange R1,
+ SourceRange R2) override {
+ unsigned diag = diag::warn_unreachable;
+ switch (UK) {
+ case reachable_code::UK_Break:
+ diag = diag::warn_unreachable_break;
+ break;
+ case reachable_code::UK_Return:
+ diag = diag::warn_unreachable_return;
+ break;
+ case reachable_code::UK_Loop_Increment:
+ diag = diag::warn_unreachable_loop_increment;
+ break;
+ case reachable_code::UK_Other:
+ break;
+ }
+
+ S.Diag(L, diag) << R1 << R2;
+
+ SourceLocation Open = SilenceableCondVal.getBegin();
+ if (Open.isValid()) {
+ SourceLocation Close = SilenceableCondVal.getEnd();
+ Close = S.getLocForEndOfToken(Close);
+ if (Close.isValid()) {
+ S.Diag(Open, diag::note_unreachable_silence)
+ << FixItHint::CreateInsertion(Open, "/* DISABLES CODE */ (")
+ << FixItHint::CreateInsertion(Close, ")");
+ }
+ }
}
};
}
/// CheckUnreachable - Check for unreachable code.
static void CheckUnreachable(Sema &S, AnalysisDeclContext &AC) {
+ // As a heuristic prune all diagnostics not in the main file. Currently
+ // the majority of warnings in headers are false positives. These
+ // are largely caused by configuration state, e.g. preprocessor
+ // defined code, etc.
+ //
+ // Note that this is also a performance optimization. Analyzing
+ // headers many times can be expensive.
+ if (!S.getSourceManager().isInMainFile(AC.getDecl()->getLocStart()))
+ return;
+
UnreachableCodeHandler UC(S);
- reachable_code::FindUnreachableCode(AC, UC);
+ reachable_code::FindUnreachableCode(AC, S.getPreprocessor(), UC);
+}
+
+/// \brief Warn on logical operator errors in CFGBuilder
+class LogicalErrorHandler : public CFGCallback {
+ Sema &S;
+
+public:
+ LogicalErrorHandler(Sema &S) : CFGCallback(), S(S) {}
+
+ static bool HasMacroID(const Expr *E) {
+ if (E->getExprLoc().isMacroID())
+ return true;
+
+ // Recurse to children.
+ for (ConstStmtRange SubStmts = E->children(); SubStmts; ++SubStmts)
+ if (*SubStmts)
+ if (const Expr *SubExpr = dyn_cast<Expr>(*SubStmts))
+ if (HasMacroID(SubExpr))
+ return true;
+
+ return false;
+ }
+
+ void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) {
+ if (HasMacroID(B))
+ return;
+
+ SourceRange DiagRange = B->getSourceRange();
+ S.Diag(B->getExprLoc(), diag::warn_tautological_overlap_comparison)
+ << DiagRange << isAlwaysTrue;
+ }
+
+ void compareBitwiseEquality(const BinaryOperator *B, bool isAlwaysTrue) {
+ if (HasMacroID(B))
+ return;
+
+ SourceRange DiagRange = B->getSourceRange();
+ S.Diag(B->getExprLoc(), diag::warn_comparison_bitwise_always)
+ << DiagRange << isAlwaysTrue;
+ }
+};
+
+
+//===----------------------------------------------------------------------===//
+// Check for infinite self-recursion in functions
+//===----------------------------------------------------------------------===//
+
+// 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
+};
+
+static void checkForFunctionCall(Sema &S, const FunctionDecl *FD,
+ CFGBlock &Block, unsigned ExitID,
+ llvm::SmallVectorImpl<RecursiveState> &States,
+ RecursiveState State) {
+ unsigned ID = Block.getBlockID();
+
+ // A block's state can only move to a higher state.
+ if (States[ID] >= State)
+ return;
+
+ States[ID] = State;
+
+ // Found a path to the exit node without a recursive call.
+ if (ID == ExitID && State == FoundPathWithNoRecursiveCall)
+ return;
+
+ if (State == FoundPathWithNoRecursiveCall) {
+ // If the current state is FoundPathWithNoRecursiveCall, the successors
+ // will be either FoundPathWithNoRecursiveCall or FoundPath. To determine
+ // which, process all the Stmt's in this block to find any recursive calls.
+ for (const auto &B : Block) {
+ if (B.getKind() != CFGElement::Statement)
+ continue;
+
+ const CallExpr *CE = dyn_cast<CallExpr>(B.getAs<CFGStmt>()->getStmt());
+ if (CE && CE->getCalleeDecl() &&
+ CE->getCalleeDecl()->getCanonicalDecl() == FD) {
+
+ // Skip function calls which are qualified with a templated class.
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(
+ CE->getCallee()->IgnoreParenImpCasts())) {
+ if (NestedNameSpecifier *NNS = DRE->getQualifier()) {
+ if (NNS->getKind() == NestedNameSpecifier::TypeSpec &&
+ isa<TemplateSpecializationType>(NNS->getAsType())) {
+ continue;
+ }
+ }
+ }
+
+ if (const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE)) {
+ if (isa<CXXThisExpr>(MCE->getImplicitObjectArgument()) ||
+ !MCE->getMethodDecl()->isVirtual()) {
+ State = FoundPath;
+ break;
+ }
+ } else {
+ State = FoundPath;
+ break;
+ }
+ }
+ }
+ }
+
+ for (CFGBlock::succ_iterator I = Block.succ_begin(), E = Block.succ_end();
+ I != E; ++I)
+ if (*I)
+ checkForFunctionCall(S, FD, **I, ExitID, States, State);
+}
+
+static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,
+ const Stmt *Body,
+ AnalysisDeclContext &AC) {
+ FD = FD->getCanonicalDecl();
+
+ // Only run on non-templated functions and non-templated members of
+ // templated classes.
+ if (FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate &&
+ FD->getTemplatedKind() != FunctionDecl::TK_MemberSpecialization)
+ return;
+
+ CFG *cfg = AC.getCFG();
+ if (!cfg) return;
+
+ // If the exit block is unreachable, skip processing the function.
+ if (cfg->getExit().pred_empty())
+ return;
+
+ // Mark all nodes as FoundNoPath, then begin processing the entry block.
+ llvm::SmallVector<RecursiveState, 16> states(cfg->getNumBlockIDs(),
+ FoundNoPath);
+ checkForFunctionCall(S, FD, cfg->getEntry(), cfg->getExit().getBlockID(),
+ states, FoundPathWithNoRecursiveCall);
+
+ // Check that the exit block is reachable. This prevents triggering the
+ // warning on functions that do not terminate.
+ if (states[cfg->getExit().getBlockID()] == FoundPath)
+ S.Diag(Body->getLocStart(), diag::warn_infinite_recursive_function);
}
//===----------------------------------------------------------------------===//
@@ -100,7 +282,7 @@ enum ControlFlowKind {
/// will return.
static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) {
CFG *cfg = AC.getCFG();
- if (cfg == 0) return UnknownFallThrough;
+ if (!cfg) return UnknownFallThrough;
// The CFG leaves in dead things, and we don't want the dead code paths to
// confuse us, so we mark all live things first.
@@ -113,14 +295,13 @@ static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) {
// When there are things remaining dead, and we didn't add EH edges
// from CallExprs to the catch clauses, we have to go back and
// mark them as live.
- for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
- CFGBlock &b = **I;
- if (!live[b.getBlockID()]) {
- if (b.pred_begin() == b.pred_end()) {
- if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator()))
+ for (const auto *B : *cfg) {
+ if (!live[B->getBlockID()]) {
+ if (B->pred_begin() == B->pred_end()) {
+ if (B->getTerminator() && isa<CXXTryStmt>(B->getTerminator()))
// When not adding EH edges from calls, catch clauses
// can otherwise seem dead. Avoid noting them as dead.
- count += reachable_code::ScanReachableFromBlock(&b, live);
+ count += reachable_code::ScanReachableFromBlock(B, live);
continue;
}
}
@@ -272,8 +453,7 @@ struct CheckFallThroughDiagnostics {
diag::err_noreturn_block_has_return_expr;
D.diag_AlwaysFallThrough_ReturnsNonVoid =
diag::err_falloff_nonvoid_block;
- D.diag_NeverFallThroughOrReturn =
- diag::warn_suggest_noreturn_block;
+ D.diag_NeverFallThroughOrReturn = 0;
D.funMode = Block;
return D;
}
@@ -297,21 +477,17 @@ struct CheckFallThroughDiagnostics {
bool HasNoReturn) const {
if (funMode == Function) {
return (ReturnsVoid ||
- D.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function,
- FuncLoc) == DiagnosticsEngine::Ignored)
- && (!HasNoReturn ||
- D.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr,
- FuncLoc) == DiagnosticsEngine::Ignored)
- && (!ReturnsVoid ||
- D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc)
- == DiagnosticsEngine::Ignored);
+ D.isIgnored(diag::warn_maybe_falloff_nonvoid_function,
+ FuncLoc)) &&
+ (!HasNoReturn ||
+ D.isIgnored(diag::warn_noreturn_function_has_return_expr,
+ FuncLoc)) &&
+ (!ReturnsVoid ||
+ D.isIgnored(diag::warn_suggest_noreturn_block, FuncLoc));
}
// For blocks / lambdas.
- return ReturnsVoid && !HasNoReturn
- && ((funMode == Lambda) ||
- D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc)
- == DiagnosticsEngine::Ignored);
+ return ReturnsVoid && !HasNoReturn;
}
};
@@ -330,18 +506,18 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
bool HasNoReturn = false;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- ReturnsVoid = FD->getResultType()->isVoidType();
+ ReturnsVoid = FD->getReturnType()->isVoidType();
HasNoReturn = FD->isNoReturn();
}
else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
- ReturnsVoid = MD->getResultType()->isVoidType();
+ ReturnsVoid = MD->getReturnType()->isVoidType();
HasNoReturn = MD->hasAttr<NoReturnAttr>();
}
else if (isa<BlockDecl>(D)) {
QualType BlockTy = blkExpr->getType();
if (const FunctionType *FT =
BlockTy->getPointeeType()->getAs<FunctionType>()) {
- if (FT->getResultType()->isVoidType())
+ if (FT->getReturnType()->isVoidType())
ReturnsVoid = true;
if (FT->getNoReturnAttr())
HasNoReturn = true;
@@ -435,8 +611,9 @@ static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) {
QualType VariableTy = VD->getType().getCanonicalType();
if (VariableTy->isBlockPointerType() &&
!VD->hasAttr<BlocksAttr>()) {
- S.Diag(VD->getLocation(), diag::note_block_var_fixit_add_initialization) << VD->getDeclName()
- << FixItHint::CreateInsertion(VD->getLocation(), "__block ");
+ S.Diag(VD->getLocation(), diag::note_block_var_fixit_add_initialization)
+ << VD->getDeclName()
+ << FixItHint::CreateInsertion(VD->getLocation(), "__block ");
return true;
}
@@ -448,7 +625,7 @@ static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) {
if (VD->getLocEnd().isMacroID())
return false;
- SourceLocation Loc = S.PP.getLocForEndOfToken(VD->getLocEnd());
+ SourceLocation Loc = S.getLocForEndOfToken(VD->getLocEnd());
// Suggest possible initialization (if any).
std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc);
@@ -744,8 +921,7 @@ namespace {
// constants, covered enums, etc.
// These blocks can contain fall-through annotations, and we don't want to
// issue a warn_fallthrough_attr_unreachable for them.
- for (CFG::iterator I = Cfg->begin(), E = Cfg->end(); I != E; ++I) {
- const CFGBlock *B = *I;
+ for (const auto *B : *Cfg) {
const Stmt *L = B->getLabel();
if (L && isa<SwitchCase>(L) && ReachableBlocks.insert(B))
BlockQueue.push_back(B);
@@ -769,13 +945,11 @@ namespace {
int UnannotatedCnt = 0;
AnnotatedCnt = 0;
- std::deque<const CFGBlock*> BlockQueue;
-
- std::copy(B.pred_begin(), B.pred_end(), std::back_inserter(BlockQueue));
-
+ std::deque<const CFGBlock*> BlockQueue(B.pred_begin(), B.pred_end());
while (!BlockQueue.empty()) {
const CFGBlock *P = BlockQueue.front();
BlockQueue.pop_front();
+ if (!P) continue;
const Stmt *Term = P->getTerminator();
if (Term && isa<SwitchStmt>(Term))
@@ -852,6 +1026,9 @@ namespace {
// methods separately.
bool TraverseDecl(Decl *D) { return true; }
+ // We analyze lambda bodies separately. Skip them here.
+ bool TraverseLambdaBody(LambdaExpr *LE) { return true; }
+
private:
static const AttributedStmt *asFallThroughAttr(const Stmt *S) {
@@ -859,7 +1036,7 @@ namespace {
if (hasSpecificAttr<FallThroughAttr>(AS->getAttrs()))
return AS;
}
- return 0;
+ return nullptr;
}
static const Stmt *getLastStmt(const CFGBlock &B) {
@@ -878,7 +1055,7 @@ namespace {
if (!isa<SwitchCase>(SW->getSubStmt()))
return SW->getSubStmt();
- return 0;
+ return nullptr;
}
bool FoundSwitchStatements;
@@ -968,31 +1145,8 @@ static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC,
}
}
- const FallthroughMapper::AttrStmts &Fallthroughs = FM.getFallthroughStmts();
- for (FallthroughMapper::AttrStmts::const_iterator I = Fallthroughs.begin(),
- E = Fallthroughs.end();
- I != E; ++I) {
- S.Diag((*I)->getLocStart(), diag::warn_fallthrough_attr_invalid_placement);
- }
-
-}
-
-namespace {
-typedef std::pair<const Stmt *,
- sema::FunctionScopeInfo::WeakObjectUseMap::const_iterator>
- StmtUsesPair;
-
-class StmtUseSorter {
- const SourceManager &SM;
-
-public:
- explicit StmtUseSorter(const SourceManager &SM) : SM(SM) { }
-
- bool operator()(const StmtUsesPair &LHS, const StmtUsesPair &RHS) {
- return SM.isBeforeInTranslationUnit(LHS.first->getLocStart(),
- RHS.first->getLocStart());
- }
-};
+ for (const auto *F : FM.getFallthroughStmts())
+ S.Diag(F->getLocStart(), diag::warn_fallthrough_attr_invalid_placement);
}
static bool isInLoop(const ASTContext &Ctx, const ParentMap &PM,
@@ -1029,6 +1183,8 @@ static void diagnoseRepeatedUseOfWeak(Sema &S,
typedef sema::FunctionScopeInfo::WeakObjectProfileTy WeakObjectProfileTy;
typedef sema::FunctionScopeInfo::WeakObjectUseMap WeakObjectUseMap;
typedef sema::FunctionScopeInfo::WeakUseVector WeakUseVector;
+ typedef std::pair<const Stmt *, WeakObjectUseMap::const_iterator>
+ StmtUsesPair;
ASTContext &Ctx = S.getASTContext();
@@ -1087,8 +1243,12 @@ static void diagnoseRepeatedUseOfWeak(Sema &S,
return;
// Sort by first use so that we emit the warnings in a deterministic order.
+ SourceManager &SM = S.getSourceManager();
std::sort(UsesByStmt.begin(), UsesByStmt.end(),
- StmtUseSorter(S.getSourceManager()));
+ [&SM](const StmtUsesPair &LHS, const StmtUsesPair &RHS) {
+ return SM.isBeforeInTranslationUnit(LHS.first->getLocStart(),
+ RHS.first->getLocStart());
+ });
// Classify the current code body for better warning text.
// This enum should stay in sync with the cases in
@@ -1112,12 +1272,10 @@ static void diagnoseRepeatedUseOfWeak(Sema &S,
FunctionKind = Function;
// Iterate through the sorted problems and emit warnings for each.
- for (SmallVectorImpl<StmtUsesPair>::const_iterator I = UsesByStmt.begin(),
- E = UsesByStmt.end();
- I != E; ++I) {
- const Stmt *FirstRead = I->first;
- const WeakObjectProfileTy &Key = I->second->first;
- const WeakUseVector &Uses = I->second->second;
+ for (const auto &P : UsesByStmt) {
+ const Stmt *FirstRead = P.first;
+ const WeakObjectProfileTy &Key = P.second->first;
+ const WeakUseVector &Uses = P.second->second;
// For complicated expressions like 'a.b.c' and 'x.b.c', WeakObjectProfileTy
// may not contain enough information to determine that these are different
@@ -1158,30 +1316,17 @@ static void diagnoseRepeatedUseOfWeak(Sema &S,
<< FirstRead->getSourceRange();
// Print all the other accesses as notes.
- for (WeakUseVector::const_iterator UI = Uses.begin(), UE = Uses.end();
- UI != UE; ++UI) {
- if (UI->getUseExpr() == FirstRead)
+ for (const auto &Use : Uses) {
+ if (Use.getUseExpr() == FirstRead)
continue;
- S.Diag(UI->getUseExpr()->getLocStart(),
+ S.Diag(Use.getUseExpr()->getLocStart(),
diag::note_arc_weak_also_accessed_here)
- << UI->getUseExpr()->getSourceRange();
+ << Use.getUseExpr()->getSourceRange();
}
}
}
-
namespace {
-struct SLocSort {
- bool operator()(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();
- SourceLocation aLoc = a.getUser()->getLocStart();
- SourceLocation bLoc = b.getUser()->getLocStart();
- return aLoc.getRawEncoding() < bLoc.getRawEncoding();
- }
-};
-
class UninitValsDiagReporter : public UninitVariablesHandler {
Sema &S;
typedef SmallVector<UninitUse, 2> UsesVec;
@@ -1193,7 +1338,7 @@ class UninitValsDiagReporter : public UninitVariablesHandler {
UsesMap *uses;
public:
- UninitValsDiagReporter(Sema &S) : S(S), uses(0) {}
+ UninitValsDiagReporter(Sema &S) : S(S), uses(nullptr) {}
~UninitValsDiagReporter() {
flushDiagnostics();
}
@@ -1208,12 +1353,13 @@ public:
return V;
}
-
- void handleUseOfUninitVariable(const VarDecl *vd, const UninitUse &use) {
+
+ void handleUseOfUninitVariable(const VarDecl *vd,
+ const UninitUse &use) override {
getUses(vd).getPointer()->push_back(use);
}
- void handleSelfInit(const VarDecl *vd) {
+ void handleSelfInit(const VarDecl *vd) override {
getUses(vd).setInt(true);
}
@@ -1221,9 +1367,9 @@ public:
if (!uses)
return;
- for (UsesMap::iterator i = uses->begin(), e = uses->end(); i != e; ++i) {
- const VarDecl *vd = i->first;
- const MappedType &V = i->second;
+ for (const auto &P : *uses) {
+ const VarDecl *vd = P.first;
+ const MappedType &V = P.second;
UsesVec *vec = V.getPointer();
bool hasSelfInit = V.getInt();
@@ -1240,12 +1386,17 @@ 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(), SLocSort());
-
- for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve;
- ++vi) {
+ std::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();
+ return a.getUser()->getLocStart() < b.getUser()->getLocStart();
+ });
+
+ for (const auto &U : *vec) {
// If we have self-init, downgrade all uses to 'may be uninitialized'.
- UninitUse Use = hasSelfInit ? UninitUse(vi->getUser(), false) : *vi;
+ UninitUse Use = hasSelfInit ? UninitUse(U.getUser(), false) : U;
if (DiagnoseUninitializedUse(S, vd, Use))
// Skip further diagnostics for this variable. We try to warn only
@@ -1262,15 +1413,12 @@ public:
private:
static bool hasAlwaysUninitializedUse(const UsesVec* vec) {
- for (UsesVec::const_iterator i = vec->begin(), e = vec->end(); i != e; ++i) {
- if (i->getKind() == UninitUse::Always ||
- i->getKind() == UninitUse::AfterCall ||
- i->getKind() == UninitUse::AfterDecl) {
- return true;
- }
+ return std::any_of(vec->begin(), vec->end(), [](const UninitUse &U) {
+ return U.getKind() == UninitUse::Always ||
+ U.getKind() == UninitUse::AfterCall ||
+ U.getKind() == UninitUse::AfterDecl;
+ });
}
- return false;
-}
};
}
@@ -1304,12 +1452,13 @@ class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler {
SourceLocation FunLocation, FunEndLocation;
// Helper functions
- void warnLockMismatch(unsigned DiagID, Name LockName, SourceLocation Loc) {
+ void warnLockMismatch(unsigned DiagID, StringRef Kind, Name LockName,
+ SourceLocation Loc) {
// Gracefully handle rare cases when the analysis can't get a more
// precise source location.
if (!Loc.isValid())
Loc = FunLocation;
- PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << LockName);
+ PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind << LockName);
Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
}
@@ -1323,31 +1472,40 @@ class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler {
/// and outputs them.
void emitDiagnostics() {
Warnings.sort(SortDiagBySourceLocation(S.getSourceManager()));
- for (DiagList::iterator I = Warnings.begin(), E = Warnings.end();
- I != E; ++I) {
- S.Diag(I->first.first, I->first.second);
- const OptionalNotes &Notes = I->second;
- for (unsigned NoteI = 0, NoteN = Notes.size(); NoteI != NoteN; ++NoteI)
- S.Diag(Notes[NoteI].first, Notes[NoteI].second);
+ for (const auto &Diag : Warnings) {
+ S.Diag(Diag.first.first, Diag.first.second);
+ for (const auto &Note : Diag.second)
+ S.Diag(Note.first, Note.second);
}
}
- void handleInvalidLockExp(SourceLocation Loc) {
- PartialDiagnosticAt Warning(Loc,
- S.PDiag(diag::warn_cannot_resolve_lock) << Loc);
+ void handleInvalidLockExp(StringRef Kind, SourceLocation Loc) override {
+ PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_cannot_resolve_lock)
+ << Loc);
Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
}
- void handleUnmatchedUnlock(Name LockName, SourceLocation Loc) {
- warnLockMismatch(diag::warn_unlock_but_no_lock, LockName, Loc);
+ void handleUnmatchedUnlock(StringRef Kind, Name LockName,
+ SourceLocation Loc) override {
+ warnLockMismatch(diag::warn_unlock_but_no_lock, Kind, LockName, Loc);
}
-
- void handleDoubleLock(Name LockName, SourceLocation Loc) {
- warnLockMismatch(diag::warn_double_lock, LockName, Loc);
+ void handleIncorrectUnlockKind(StringRef Kind, Name LockName,
+ LockKind Expected, LockKind Received,
+ SourceLocation Loc) override {
+ if (Loc.isInvalid())
+ Loc = FunLocation;
+ PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_unlock_kind_mismatch)
+ << Kind << LockName << Received
+ << Expected);
+ Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+ }
+ void handleDoubleLock(StringRef Kind, Name LockName, SourceLocation Loc) override {
+ warnLockMismatch(diag::warn_double_lock, Kind, LockName, Loc);
}
- void handleMutexHeldEndOfScope(Name LockName, SourceLocation LocLocked,
+ void handleMutexHeldEndOfScope(StringRef Kind, Name LockName,
+ SourceLocation LocLocked,
SourceLocation LocEndOfScope,
- LockErrorKind LEK){
+ LockErrorKind LEK) override {
unsigned DiagID = 0;
switch (LEK) {
case LEK_LockedSomePredecessors:
@@ -1366,29 +1524,33 @@ class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler {
if (LocEndOfScope.isInvalid())
LocEndOfScope = FunEndLocation;
- PartialDiagnosticAt Warning(LocEndOfScope, S.PDiag(DiagID) << LockName);
+ PartialDiagnosticAt Warning(LocEndOfScope, S.PDiag(DiagID) << Kind
+ << LockName);
if (LocLocked.isValid()) {
- PartialDiagnosticAt Note(LocLocked, S.PDiag(diag::note_locked_here));
+ PartialDiagnosticAt Note(LocLocked, S.PDiag(diag::note_locked_here)
+ << Kind);
Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note)));
return;
}
Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
}
-
- void handleExclusiveAndShared(Name LockName, SourceLocation Loc1,
- SourceLocation Loc2) {
- PartialDiagnosticAt Warning(
- Loc1, S.PDiag(diag::warn_lock_exclusive_and_shared) << LockName);
- PartialDiagnosticAt Note(
- Loc2, S.PDiag(diag::note_lock_exclusive_and_shared) << LockName);
+ void handleExclusiveAndShared(StringRef Kind, Name LockName,
+ SourceLocation Loc1,
+ SourceLocation Loc2) override {
+ PartialDiagnosticAt Warning(Loc1,
+ S.PDiag(diag::warn_lock_exclusive_and_shared)
+ << Kind << LockName);
+ PartialDiagnosticAt Note(Loc2, S.PDiag(diag::note_lock_exclusive_and_shared)
+ << Kind << LockName);
Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note)));
}
- void handleNoMutexHeld(const NamedDecl *D, ProtectedOperationKind POK,
- AccessKind AK, SourceLocation Loc) {
- assert((POK == POK_VarAccess || POK == POK_VarDereference)
- && "Only works for variables");
+ void handleNoMutexHeld(StringRef Kind, const NamedDecl *D,
+ ProtectedOperationKind POK, AccessKind AK,
+ SourceLocation Loc) override {
+ assert((POK == POK_VarAccess || POK == POK_VarDereference) &&
+ "Only works for variables");
unsigned DiagID = POK == POK_VarAccess?
diag::warn_variable_requires_any_lock:
diag::warn_var_deref_requires_any_lock;
@@ -1397,9 +1559,10 @@ class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler {
Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
}
- void handleMutexNotHeld(const NamedDecl *D, ProtectedOperationKind POK,
- Name LockName, LockKind LK, SourceLocation Loc,
- Name *PossibleMatch) {
+ void handleMutexNotHeld(StringRef Kind, const NamedDecl *D,
+ ProtectedOperationKind POK, Name LockName,
+ LockKind LK, SourceLocation Loc,
+ Name *PossibleMatch) override {
unsigned DiagID = 0;
if (PossibleMatch) {
switch (POK) {
@@ -1413,10 +1576,11 @@ class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler {
DiagID = diag::warn_fun_requires_lock_precise;
break;
}
- PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID)
- << D->getNameAsString() << LockName << LK);
+ PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind
+ << D->getNameAsString()
+ << LockName << LK);
PartialDiagnosticAt Note(Loc, S.PDiag(diag::note_found_mutex_near_match)
- << *PossibleMatch);
+ << *PossibleMatch);
Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note)));
} else {
switch (POK) {
@@ -1430,15 +1594,17 @@ class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler {
DiagID = diag::warn_fun_requires_lock;
break;
}
- PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID)
- << D->getNameAsString() << LockName << LK);
+ PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind
+ << D->getNameAsString()
+ << LockName << LK);
Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
}
}
- void handleFunExcludesLock(Name FunName, Name LockName, SourceLocation Loc) {
- PartialDiagnosticAt Warning(Loc,
- S.PDiag(diag::warn_fun_excludes_mutex) << FunName << LockName);
+ void handleFunExcludesLock(StringRef Kind, Name FunName, Name LockName,
+ SourceLocation Loc) override {
+ PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_fun_excludes_mutex)
+ << Kind << FunName << LockName);
Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
}
};
@@ -1461,23 +1627,18 @@ class ConsumedWarningsHandler : public ConsumedWarningsHandlerBase {
public:
ConsumedWarningsHandler(Sema &S) : S(S) {}
-
- void emitDiagnostics() {
+
+ void emitDiagnostics() override {
Warnings.sort(SortDiagBySourceLocation(S.getSourceManager()));
-
- for (DiagList::iterator I = Warnings.begin(), E = Warnings.end();
- I != E; ++I) {
-
- const OptionalNotes &Notes = I->second;
- S.Diag(I->first.first, I->first.second);
-
- for (unsigned NoteI = 0, NoteN = Notes.size(); NoteI != NoteN; ++NoteI) {
- S.Diag(Notes[NoteI].first, Notes[NoteI].second);
- }
+ for (const auto &Diag : Warnings) {
+ S.Diag(Diag.first.first, Diag.first.second);
+ for (const auto &Note : Diag.second)
+ S.Diag(Note.first, Note.second);
}
}
-
- void warnLoopStateMismatch(SourceLocation Loc, StringRef VariableName) {
+
+ void warnLoopStateMismatch(SourceLocation Loc,
+ StringRef VariableName) override {
PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_loop_state_mismatch) <<
VariableName);
@@ -1487,7 +1648,7 @@ public:
void warnParamReturnTypestateMismatch(SourceLocation Loc,
StringRef VariableName,
StringRef ExpectedState,
- StringRef ObservedState) {
+ StringRef ObservedState) override {
PartialDiagnosticAt Warning(Loc, S.PDiag(
diag::warn_param_return_typestate_mismatch) << VariableName <<
@@ -1497,7 +1658,7 @@ public:
}
void warnParamTypestateMismatch(SourceLocation Loc, StringRef ExpectedState,
- StringRef ObservedState) {
+ StringRef ObservedState) override {
PartialDiagnosticAt Warning(Loc, S.PDiag(
diag::warn_param_typestate_mismatch) << ExpectedState << ObservedState);
@@ -1506,7 +1667,7 @@ public:
}
void warnReturnTypestateForUnconsumableType(SourceLocation Loc,
- StringRef TypeName) {
+ StringRef TypeName) override {
PartialDiagnosticAt Warning(Loc, S.PDiag(
diag::warn_return_typestate_for_unconsumable_type) << TypeName);
@@ -1514,7 +1675,7 @@ public:
}
void warnReturnTypestateMismatch(SourceLocation Loc, StringRef ExpectedState,
- StringRef ObservedState) {
+ StringRef ObservedState) override {
PartialDiagnosticAt Warning(Loc, S.PDiag(
diag::warn_return_typestate_mismatch) << ExpectedState << ObservedState);
@@ -1523,7 +1684,7 @@ public:
}
void warnUseOfTempInInvalidState(StringRef MethodName, StringRef State,
- SourceLocation Loc) {
+ SourceLocation Loc) override {
PartialDiagnosticAt Warning(Loc, S.PDiag(
diag::warn_use_of_temp_in_invalid_state) << MethodName << State);
@@ -1532,7 +1693,7 @@ public:
}
void warnUseInInvalidState(StringRef MethodName, StringRef VariableName,
- StringRef State, SourceLocation Loc) {
+ StringRef State, SourceLocation Loc) override {
PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_use_in_invalid_state) <<
MethodName << VariableName << State);
@@ -1554,6 +1715,10 @@ clang::sema::AnalysisBasedWarnings::Policy::Policy() {
enableConsumedAnalysis = 0;
}
+static unsigned isEnabled(DiagnosticsEngine &D, unsigned diag) {
+ return (unsigned)!D.isIgnored(diag, SourceLocation());
+}
+
clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s)
: S(s),
NumFunctionsAnalyzed(0),
@@ -1565,26 +1730,26 @@ clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s)
MaxUninitAnalysisVariablesPerFunction(0),
NumUninitAnalysisBlockVisits(0),
MaxUninitAnalysisBlockVisitsPerFunction(0) {
+
+ using namespace diag;
DiagnosticsEngine &D = S.getDiagnostics();
- DefaultPolicy.enableCheckUnreachable = (unsigned)
- (D.getDiagnosticLevel(diag::warn_unreachable, SourceLocation()) !=
- DiagnosticsEngine::Ignored);
- DefaultPolicy.enableThreadSafetyAnalysis = (unsigned)
- (D.getDiagnosticLevel(diag::warn_double_lock, SourceLocation()) !=
- DiagnosticsEngine::Ignored);
- DefaultPolicy.enableConsumedAnalysis = (unsigned)
- (D.getDiagnosticLevel(diag::warn_use_in_invalid_state, SourceLocation()) !=
- DiagnosticsEngine::Ignored);
+
+ DefaultPolicy.enableCheckUnreachable =
+ isEnabled(D, warn_unreachable) ||
+ isEnabled(D, warn_unreachable_break) ||
+ isEnabled(D, warn_unreachable_return) ||
+ isEnabled(D, warn_unreachable_loop_increment);
+
+ DefaultPolicy.enableThreadSafetyAnalysis =
+ isEnabled(D, warn_double_lock);
+
+ DefaultPolicy.enableConsumedAnalysis =
+ isEnabled(D, warn_use_in_invalid_state);
}
-static void flushDiagnostics(Sema &S, sema::FunctionScopeInfo *fscope) {
- for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
- i = fscope->PossiblyUnreachableDiags.begin(),
- e = fscope->PossiblyUnreachableDiags.end();
- i != e; ++i) {
- const sema::PossiblyUnreachableDiag &D = *i;
+static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope) {
+ for (const auto &D : fscope->PossiblyUnreachableDiags)
S.Diag(D.Loc, D.PD);
- }
}
void clang::sema::
@@ -1620,7 +1785,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
assert(Body);
// Construct the analysis context with the specified CFG build options.
- AnalysisDeclContext AC(/* AnalysisDeclContextManager */ 0, D);
+ AnalysisDeclContext AC(/* AnalysisDeclContextManager */ nullptr, D);
// Don't generate EH edges for CallExprs as we'd like to avoid the n^2
// explosion for destructors that can result and the compile time hit.
@@ -1629,6 +1794,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
AC.getCFGBuildOptions().AddInitializers = true;
AC.getCFGBuildOptions().AddImplicitDtors = true;
AC.getCFGBuildOptions().AddTemporaryDtors = true;
+ AC.getCFGBuildOptions().AddCXXNewAllocator = false;
// Force that certain expressions appear as CFGElements in the CFG. This
// is used to speed up various analyses.
@@ -1653,31 +1819,30 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
.setAlwaysAdd(Stmt::AttributedStmtClass);
}
+ // Install the logical handler for -Wtautological-overlap-compare
+ std::unique_ptr<LogicalErrorHandler> LEH;
+ if (!Diags.isIgnored(diag::warn_tautological_overlap_comparison,
+ D->getLocStart())) {
+ LEH.reset(new LogicalErrorHandler(S));
+ AC.getCFGBuildOptions().Observer = LEH.get();
+ }
// Emit delayed diagnostics.
if (!fscope->PossiblyUnreachableDiags.empty()) {
bool analyzed = false;
// Register the expressions with the CFGBuilder.
- for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
- i = fscope->PossiblyUnreachableDiags.begin(),
- e = fscope->PossiblyUnreachableDiags.end();
- i != e; ++i) {
- if (const Stmt *stmt = i->stmt)
- AC.registerForcedBlockExpression(stmt);
+ for (const auto &D : fscope->PossiblyUnreachableDiags) {
+ if (D.stmt)
+ AC.registerForcedBlockExpression(D.stmt);
}
if (AC.getCFG()) {
analyzed = true;
- for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
- i = fscope->PossiblyUnreachableDiags.begin(),
- e = fscope->PossiblyUnreachableDiags.end();
- i != e; ++i)
- {
- const sema::PossiblyUnreachableDiag &D = *i;
+ for (const auto &D : fscope->PossiblyUnreachableDiags) {
bool processed = false;
- if (const Stmt *stmt = i->stmt) {
- const CFGBlock *block = AC.getBlockForRegisteredExpression(stmt);
+ if (D.stmt) {
+ const CFGBlock *block = AC.getBlockForRegisteredExpression(D.stmt);
CFGReverseBlockReachabilityAnalysis *cra =
AC.getCFGReachablityAnalysis();
// FIXME: We should be able to assert that block is non-null, but
@@ -1732,8 +1897,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
SourceLocation FL = AC.getDecl()->getLocation();
SourceLocation FEL = AC.getDecl()->getLocEnd();
thread_safety::ThreadSafetyReporter Reporter(S, FL, FEL);
- if (Diags.getDiagnosticLevel(diag::warn_thread_safety_beta,D->getLocStart())
- != DiagnosticsEngine::Ignored)
+ if (!Diags.isIgnored(diag::warn_thread_safety_beta, D->getLocStart()))
Reporter.setIssueBetaWarnings(true);
thread_safety::runThreadSafetyAnalysis(AC, Reporter);
@@ -1747,12 +1911,9 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
Analyzer.run(AC);
}
- if (Diags.getDiagnosticLevel(diag::warn_uninit_var, D->getLocStart())
- != DiagnosticsEngine::Ignored ||
- Diags.getDiagnosticLevel(diag::warn_sometimes_uninit_var,D->getLocStart())
- != DiagnosticsEngine::Ignored ||
- Diags.getDiagnosticLevel(diag::warn_maybe_uninit_var, D->getLocStart())
- != DiagnosticsEngine::Ignored) {
+ if (!Diags.isIgnored(diag::warn_uninit_var, D->getLocStart()) ||
+ !Diags.isIgnored(diag::warn_sometimes_uninit_var, D->getLocStart()) ||
+ !Diags.isIgnored(diag::warn_maybe_uninit_var, D->getLocStart())) {
if (CFG *cfg = AC.getCFG()) {
UninitValsDiagReporter reporter(S);
UninitVariablesAnalysisStats stats;
@@ -1775,20 +1936,33 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
}
bool FallThroughDiagFull =
- Diags.getDiagnosticLevel(diag::warn_unannotated_fallthrough,
- D->getLocStart()) != DiagnosticsEngine::Ignored;
- bool FallThroughDiagPerFunction =
- Diags.getDiagnosticLevel(diag::warn_unannotated_fallthrough_per_function,
- D->getLocStart()) != DiagnosticsEngine::Ignored;
+ !Diags.isIgnored(diag::warn_unannotated_fallthrough, D->getLocStart());
+ bool FallThroughDiagPerFunction = !Diags.isIgnored(
+ diag::warn_unannotated_fallthrough_per_function, D->getLocStart());
if (FallThroughDiagFull || FallThroughDiagPerFunction) {
DiagnoseSwitchLabelsFallthrough(S, AC, !FallThroughDiagFull);
}
if (S.getLangOpts().ObjCARCWeak &&
- Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
- D->getLocStart()) != DiagnosticsEngine::Ignored)
+ !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, D->getLocStart()))
diagnoseRepeatedUseOfWeak(S, fscope, D, AC.getParentMap());
+
+ // Check for infinite self-recursion in functions
+ if (!Diags.isIgnored(diag::warn_infinite_recursive_function,
+ D->getLocStart())) {
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ checkRecursiveFunction(S, FD, Body, AC);
+ }
+ }
+
+ // If none of the previous checks caused a CFG build, trigger one here
+ // for -Wtautological-overlap-compare
+ if (!Diags.isIgnored(diag::warn_tautological_overlap_comparison,
+ D->getLocStart())) {
+ AC.getCFG();
+ }
+
// Collect statistics about the CFG if it was built.
if (S.CollectStats && AC.isCFGBuilt()) {
++NumFunctionsAnalyzed;
diff --git a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp b/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp
index c980772..476a22b 100644
--- a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp
@@ -13,8 +13,11 @@
#include "clang/Sema/AttributeList.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
@@ -103,14 +106,6 @@ void AttributePool::takePool(AttributeList *pool) {
} while (pool);
}
-AttributeList *
-AttributePool::createIntegerAttribute(ASTContext &C, IdentifierInfo *Name,
- SourceLocation TokLoc, int Arg) {
- ArgsUnion IArg = IntegerLiteral::Create(C, llvm::APInt(32, (uint64_t) Arg),
- C.IntTy, TokLoc);
- return create(Name, TokLoc, 0, TokLoc, &IArg, 1, AttributeList::AS_GNU);
-}
-
#include "clang/Sema/AttrParsedAttrKinds.inc"
AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name,
@@ -118,21 +113,25 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name,
Syntax SyntaxUsed) {
StringRef AttrName = Name->getName();
- // Normalize the attribute name, __foo__ becomes foo.
- if (AttrName.startswith("__") && AttrName.endswith("__") &&
- AttrName.size() >= 4)
- AttrName = AttrName.substr(2, AttrName.size() - 4);
-
- SmallString<64> Buf;
+ SmallString<64> FullName;
if (ScopeName)
- Buf += ScopeName->getName();
+ FullName += ScopeName->getName();
+
+ // Normalize the attribute name, __foo__ becomes foo. This is only allowable
+ // for GNU attributes.
+ bool IsGNU = SyntaxUsed == AS_GNU || (SyntaxUsed == AS_CXX11 &&
+ FullName == "gnu");
+ if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") &&
+ AttrName.endswith("__"))
+ AttrName = AttrName.slice(2, AttrName.size() - 2);
+
// Ensure that in the case of C++11 attributes, we look for '::foo' if it is
// unscoped.
if (ScopeName || SyntaxUsed == AS_CXX11)
- Buf += "::";
- Buf += AttrName;
+ FullName += "::";
+ FullName += AttrName;
- return ::getAttrKind(Buf);
+ return ::getAttrKind(FullName, SyntaxUsed);
}
unsigned AttributeList::getAttributeSpellingListIndex() const {
@@ -149,6 +148,15 @@ struct ParsedAttrInfo {
unsigned NumArgs : 4;
unsigned OptArgs : 4;
unsigned HasCustomParsing : 1;
+ unsigned IsTargetSpecific : 1;
+ unsigned IsType : 1;
+ unsigned IsKnownToGCC : 1;
+
+ bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr,
+ const Decl *);
+ bool (*DiagLangOpts)(Sema &S, const AttributeList &Attr);
+ bool (*ExistsInTarget)(const llvm::Triple &T);
+ unsigned (*SpellingIndexToSemanticSpelling)(const AttributeList &Attr);
};
namespace {
@@ -170,3 +178,31 @@ unsigned AttributeList::getMaxArgs() const {
bool AttributeList::hasCustomParsing() const {
return getInfo(*this).HasCustomParsing;
}
+
+bool AttributeList::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
+ return getInfo(*this).DiagAppertainsToDecl(S, *this, D);
+}
+
+bool AttributeList::diagnoseLangOpts(Sema &S) const {
+ return getInfo(*this).DiagLangOpts(S, *this);
+}
+
+bool AttributeList::isTargetSpecificAttr() const {
+ return getInfo(*this).IsTargetSpecific;
+}
+
+bool AttributeList::isTypeAttr() const {
+ return getInfo(*this).IsType;
+}
+
+bool AttributeList::existsInTarget(const llvm::Triple &T) const {
+ return getInfo(*this).ExistsInTarget(T);
+}
+
+bool AttributeList::isKnownToGCC() const {
+ return getInfo(*this).IsKnownToGCC;
+}
+
+unsigned AttributeList::getSemanticSpelling() const {
+ return getInfo(*this).SpellingIndexToSemanticSpelling(*this);
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp
index 19be1cb..b2dc2d7 100644
--- a/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp
@@ -15,7 +15,6 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/Sema.h"
#include "llvm/ADT/STLExtras.h"
@@ -219,7 +218,7 @@ const char *CodeCompletionString::getAnnotation(unsigned AnnotationNr) const {
if (AnnotationNr < NumAnnotations)
return reinterpret_cast<const char * const*>(end())[AnnotationNr];
else
- return 0;
+ return nullptr;
}
@@ -248,8 +247,8 @@ const char *CodeCompletionString::getTypedText() const {
for (iterator C = begin(), CEnd = end(); C != CEnd; ++C)
if (C->Kind == CK_TypedText)
return C->Text;
-
- return 0;
+
+ return nullptr;
}
const char *CodeCompletionAllocator::CopyString(StringRef String) {
@@ -279,7 +278,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() != 0)
+ if (CachedParentName.data() != nullptr)
return StringRef();
// Find the interesting names.
@@ -406,7 +405,7 @@ CodeCompleteConsumer::OverloadCandidate::getFunction() const {
else if (getKind() == CK_FunctionTemplate)
return FunctionTemplate->getTemplatedDecl();
else
- return 0;
+ return nullptr;
}
const FunctionType *
diff --git a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
index c2f1615..d7372b7 100644
--- a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
@@ -149,8 +149,8 @@ CXXScopeSpec::getWithLocInContext(ASTContext &Context) const {
DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
bool isAmbiguous,
SourceLocation LParenLoc,
- ParamInfo *ArgInfo,
- unsigned NumArgs,
+ ParamInfo *Params,
+ unsigned NumParams,
SourceLocation EllipsisLoc,
SourceLocation RParenLoc,
unsigned TypeQuals,
@@ -178,17 +178,17 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
I.Kind = Function;
I.Loc = LocalRangeBegin;
I.EndLoc = LocalRangeEnd;
- I.Fun.AttrList = 0;
+ I.Fun.AttrList = nullptr;
I.Fun.hasPrototype = hasProto;
I.Fun.isVariadic = EllipsisLoc.isValid();
I.Fun.isAmbiguous = isAmbiguous;
I.Fun.LParenLoc = LParenLoc.getRawEncoding();
I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding();
I.Fun.RParenLoc = RParenLoc.getRawEncoding();
- I.Fun.DeleteArgInfo = false;
+ I.Fun.DeleteParams = false;
I.Fun.TypeQuals = TypeQuals;
- I.Fun.NumArgs = NumArgs;
- I.Fun.ArgInfo = 0;
+ I.Fun.NumParams = NumParams;
+ I.Fun.Params = nullptr;
I.Fun.RefQualifierIsLValueRef = RefQualifierIsLvalueRef;
I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding();
I.Fun.ConstQualifierLoc = ConstQualifierLoc.getRawEncoding();
@@ -197,28 +197,28 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
I.Fun.ExceptionSpecType = ESpecType;
I.Fun.ExceptionSpecLoc = ESpecLoc.getRawEncoding();
I.Fun.NumExceptions = 0;
- I.Fun.Exceptions = 0;
- I.Fun.NoexceptExpr = 0;
+ I.Fun.Exceptions = nullptr;
+ I.Fun.NoexceptExpr = nullptr;
I.Fun.HasTrailingReturnType = TrailingReturnType.isUsable() ||
TrailingReturnType.isInvalid();
I.Fun.TrailingReturnType = TrailingReturnType.get();
- // new[] an argument array if needed.
- if (NumArgs) {
+ // new[] a parameter array if needed.
+ if (NumParams) {
// If the 'InlineParams' in Declarator is unused and big enough, put our
// parameter list there (in an effort to avoid new/delete traffic). If it
// is already used (consider a function returning a function pointer) or too
- // small (function taking too many arguments), go to the heap.
+ // small (function with too many parameters), go to the heap.
if (!TheDeclarator.InlineParamsUsed &&
- NumArgs <= llvm::array_lengthof(TheDeclarator.InlineParams)) {
- I.Fun.ArgInfo = TheDeclarator.InlineParams;
- I.Fun.DeleteArgInfo = false;
+ NumParams <= llvm::array_lengthof(TheDeclarator.InlineParams)) {
+ I.Fun.Params = TheDeclarator.InlineParams;
+ I.Fun.DeleteParams = false;
TheDeclarator.InlineParamsUsed = true;
} else {
- I.Fun.ArgInfo = new DeclaratorChunk::ParamInfo[NumArgs];
- I.Fun.DeleteArgInfo = true;
+ I.Fun.Params = new DeclaratorChunk::ParamInfo[NumParams];
+ I.Fun.DeleteParams = true;
}
- memcpy(I.Fun.ArgInfo, ArgInfo, sizeof(ArgInfo[0])*NumArgs);
+ memcpy(I.Fun.Params, Params, sizeof(Params[0]) * NumParams);
}
// Check what exception specification information we should actually store.
@@ -285,14 +285,6 @@ bool Declarator::isDeclarationOfFunction() const {
case TST_unspecified:
case TST_void:
case TST_wchar:
- case TST_image1d_t:
- case TST_image1d_array_t:
- case TST_image1d_buffer_t:
- case TST_image2d_t:
- case TST_image2d_array_t:
- case TST_image3d_t:
- case TST_sampler_t:
- case TST_event_t:
return false;
case TST_decltype_auto:
@@ -426,12 +418,13 @@ const char *DeclSpec::getSpecifierName(TSS S) {
llvm_unreachable("Unknown typespec!");
}
-const char *DeclSpec::getSpecifierName(DeclSpec::TST T) {
+const char *DeclSpec::getSpecifierName(DeclSpec::TST T,
+ const PrintingPolicy &Policy) {
switch (T) {
case DeclSpec::TST_unspecified: return "unspecified";
case DeclSpec::TST_void: return "void";
case DeclSpec::TST_char: return "char";
- case DeclSpec::TST_wchar: return "wchar_t";
+ case DeclSpec::TST_wchar: return Policy.MSWChar ? "__wchar_t" : "wchar_t";
case DeclSpec::TST_char16: return "char16_t";
case DeclSpec::TST_char32: return "char32_t";
case DeclSpec::TST_int: return "int";
@@ -439,7 +432,7 @@ 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_bool: return "_Bool";
+ case DeclSpec::TST_bool: return Policy.Bool ? "bool" : "_Bool";
case DeclSpec::TST_decimal32: return "_Decimal32";
case DeclSpec::TST_decimal64: return "_Decimal64";
case DeclSpec::TST_decimal128: return "_Decimal128";
@@ -457,14 +450,6 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T) {
case DeclSpec::TST_underlyingType: return "__underlying_type";
case DeclSpec::TST_unknown_anytype: return "__unknown_anytype";
case DeclSpec::TST_atomic: return "_Atomic";
- case DeclSpec::TST_image1d_t: return "image1d_t";
- case DeclSpec::TST_image1d_array_t: return "image1d_array_t";
- case DeclSpec::TST_image1d_buffer_t: return "image1d_buffer_t";
- case DeclSpec::TST_image2d_t: return "image2d_t";
- case DeclSpec::TST_image2d_array_t: return "image2d_array_t";
- case DeclSpec::TST_image3d_t: return "image3d_t";
- case DeclSpec::TST_sampler_t: return "sampler_t";
- case DeclSpec::TST_event_t: return "event_t";
case DeclSpec::TST_error: return "(error)";
}
llvm_unreachable("Unknown typespec!");
@@ -483,7 +468,8 @@ const char *DeclSpec::getSpecifierName(TQ T) {
bool DeclSpec::SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc,
const char *&PrevSpec,
- unsigned &DiagID) {
+ unsigned &DiagID,
+ const PrintingPolicy &Policy) {
// OpenCL v1.1 s6.8g: "The extern, static, auto and register storage-class
// specifiers are not supported.
// It seems sensible to prohibit private_extern too
@@ -518,10 +504,10 @@ bool DeclSpec::SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc,
bool isInvalid = true;
if (TypeSpecType == TST_unspecified && S.getLangOpts().CPlusPlus) {
if (SC == SCS_auto)
- return SetTypeSpecType(TST_auto, Loc, PrevSpec, DiagID);
+ return SetTypeSpecType(TST_auto, Loc, PrevSpec, DiagID, Policy);
if (StorageClassSpec == SCS_auto) {
isInvalid = SetTypeSpecType(TST_auto, StorageClassSpecLoc,
- PrevSpec, DiagID);
+ PrevSpec, DiagID, Policy);
assert(!isInvalid && "auto SCS -> TST recovery failed");
}
}
@@ -557,7 +543,8 @@ bool DeclSpec::SetStorageClassSpecThread(TSCS TSC, SourceLocation Loc,
/// specified).
bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc,
const char *&PrevSpec,
- unsigned &DiagID) {
+ unsigned &DiagID,
+ const PrintingPolicy &Policy) {
// Overwrite TSWLoc only if TypeSpecWidth was unspecified, so that
// for 'long long' we will keep the source location of the first 'long'.
if (TypeSpecWidth == TSW_unspecified)
@@ -568,7 +555,7 @@ bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc,
TypeSpecWidth = W;
if (TypeAltiVecVector && !TypeAltiVecBool &&
((TypeSpecWidth == TSW_long) || (TypeSpecWidth == TSW_longlong))) {
- PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
DiagID = diag::warn_vector_long_decl_spec_combination;
return true;
}
@@ -598,19 +585,21 @@ bool DeclSpec::SetTypeSpecSign(TSS S, SourceLocation Loc,
bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
const char *&PrevSpec,
unsigned &DiagID,
- ParsedType Rep) {
- return SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, Rep);
+ ParsedType Rep,
+ const PrintingPolicy &Policy) {
+ return SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, Rep, Policy);
}
bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc,
SourceLocation TagNameLoc,
const char *&PrevSpec,
unsigned &DiagID,
- ParsedType Rep) {
+ ParsedType Rep,
+ const PrintingPolicy &Policy) {
assert(isTypeRep(T) && "T does not store a type");
assert(Rep && "no type provided!");
if (TypeSpecType != TST_unspecified) {
- PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
DiagID = diag::err_invalid_decl_spec_combination;
return true;
}
@@ -625,11 +614,12 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc,
bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
const char *&PrevSpec,
unsigned &DiagID,
- Expr *Rep) {
+ Expr *Rep,
+ const PrintingPolicy &Policy) {
assert(isExprRep(T) && "T does not store an expr");
assert(Rep && "no expression provided!");
if (TypeSpecType != TST_unspecified) {
- PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
DiagID = diag::err_invalid_decl_spec_combination;
return true;
}
@@ -644,20 +634,22 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
const char *&PrevSpec,
unsigned &DiagID,
- Decl *Rep, bool Owned) {
- return SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, Rep, Owned);
+ Decl *Rep, bool Owned,
+ const PrintingPolicy &Policy) {
+ return SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, Rep, Owned, Policy);
}
bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc,
SourceLocation TagNameLoc,
const char *&PrevSpec,
unsigned &DiagID,
- Decl *Rep, bool Owned) {
+ Decl *Rep, bool Owned,
+ const PrintingPolicy &Policy) {
assert(isDeclRep(T) && "T does not store a decl");
// Unlike the other cases, we don't assert that we actually get a decl.
if (TypeSpecType != TST_unspecified) {
- PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
DiagID = diag::err_invalid_decl_spec_combination;
return true;
}
@@ -665,17 +657,18 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc,
DeclRep = Rep;
TSTLoc = TagKwLoc;
TSTNameLoc = TagNameLoc;
- TypeSpecOwned = Owned && Rep != 0;
+ TypeSpecOwned = Owned && Rep != nullptr;
return false;
}
bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
const char *&PrevSpec,
- unsigned &DiagID) {
+ unsigned &DiagID,
+ const PrintingPolicy &Policy) {
assert(!isDeclRep(T) && !isTypeRep(T) && !isExprRep(T) &&
"rep required for these type-spec kinds!");
if (TypeSpecType != TST_unspecified) {
- PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
DiagID = diag::err_invalid_decl_spec_combination;
return true;
}
@@ -688,7 +681,7 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
TypeSpecType = T;
TypeSpecOwned = false;
if (TypeAltiVecVector && !TypeAltiVecBool && (TypeSpecType == TST_double)) {
- PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
DiagID = diag::err_invalid_vector_decl_spec;
return true;
}
@@ -696,9 +689,10 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
}
bool DeclSpec::SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc,
- const char *&PrevSpec, unsigned &DiagID) {
+ const char *&PrevSpec, unsigned &DiagID,
+ const PrintingPolicy &Policy) {
if (TypeSpecType != TST_unspecified) {
- PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
DiagID = diag::err_invalid_vector_decl_spec_combination;
return true;
}
@@ -708,10 +702,11 @@ bool DeclSpec::SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc,
}
bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc,
- const char *&PrevSpec, unsigned &DiagID) {
+ const char *&PrevSpec, unsigned &DiagID,
+ const PrintingPolicy &Policy) {
if (!TypeAltiVecVector || TypeAltiVecPixel ||
(TypeSpecType != TST_unspecified)) {
- PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
DiagID = diag::err_invalid_pixel_decl_spec_combination;
return true;
}
@@ -722,10 +717,11 @@ bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc,
}
bool DeclSpec::SetTypeAltiVecBool(bool isAltiVecBool, SourceLocation Loc,
- const char *&PrevSpec, unsigned &DiagID) {
+ const char *&PrevSpec, unsigned &DiagID,
+ const PrintingPolicy &Policy) {
if (!TypeAltiVecVector || TypeAltiVecBool ||
(TypeSpecType != TST_unspecified)) {
- PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
DiagID = diag::err_invalid_vector_bool_decl_spec;
return true;
}
@@ -843,7 +839,12 @@ bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID) {
if (Friend_specified) {
PrevSpec = "friend";
- DiagID = diag::ext_duplicate_declspec;
+ // Keep the later location, so that we can later diagnose ill-formed
+ // declarations like 'friend class X friend;'. Per [class.friend]p3,
+ // 'friend' must be the first token in a friend declaration that is
+ // not a function declaration.
+ FriendLoc = Loc;
+ DiagID = diag::warn_duplicate_declspec;
return true;
}
@@ -866,7 +867,13 @@ bool DeclSpec::setModulePrivateSpec(SourceLocation Loc, const char *&PrevSpec,
bool DeclSpec::SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID) {
- // 'constexpr constexpr' is ok.
+ // 'constexpr constexpr' is ok, but warn as this is likely not what the user
+ // intended.
+ if (Constexpr_specified) {
+ DiagID = diag::warn_duplicate_declspec;
+ PrevSpec = "constexpr";
+ return true;
+ }
Constexpr_specified = true;
ConstexprLoc = Loc;
return false;
@@ -906,7 +913,7 @@ void DeclSpec::SaveWrittenBuiltinSpecs() {
/// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or
/// diag::NUM_DIAGNOSTICS if there is no error. After calling this method,
/// DeclSpec is guaranteed self-consistent, even if an error occurred.
-void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP) {
+void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPolicy &Policy) {
// Before possibly changing their values, save specs as written.
SaveWrittenBuiltinSpecs();
@@ -959,7 +966,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP) {
(TypeSpecType != TST_int)) || TypeAltiVecPixel) {
Diag(D, TSTLoc, diag::err_invalid_vector_bool_decl_spec)
<< (TypeAltiVecPixel ? "__pixel" :
- getSpecifierName((TST)TypeSpecType));
+ getSpecifierName((TST)TypeSpecType, Policy));
}
// Only 'short' is valid with vector bool. (PIM 2.1)
@@ -989,7 +996,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP) {
else if (TypeSpecType != TST_int && TypeSpecType != TST_int128 &&
TypeSpecType != TST_char && TypeSpecType != TST_wchar) {
Diag(D, TSSLoc, diag::err_invalid_sign_spec)
- << getSpecifierName((TST)TypeSpecType);
+ << getSpecifierName((TST)TypeSpecType, Policy);
// signed double -> double.
TypeSpecSign = TSS_unspecified;
}
@@ -1006,7 +1013,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP) {
Diag(D, TSWLoc,
TypeSpecWidth == TSW_short ? diag::err_invalid_short_spec
: diag::err_invalid_longlong_spec)
- << getSpecifierName((TST)TypeSpecType);
+ << getSpecifierName((TST)TypeSpecType, Policy);
TypeSpecType = TST_int;
TypeSpecOwned = false;
}
@@ -1016,7 +1023,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP) {
TypeSpecType = TST_int; // long -> long int.
else if (TypeSpecType != TST_int && TypeSpecType != TST_double) {
Diag(D, TSWLoc, diag::err_invalid_long_spec)
- << getSpecifierName((TST)TypeSpecType);
+ << getSpecifierName((TST)TypeSpecType, Policy);
TypeSpecType = TST_int;
TypeSpecOwned = false;
}
@@ -1038,7 +1045,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP) {
Diag(D, TSTLoc, diag::ext_integer_complex);
} else if (TypeSpecType != TST_float && TypeSpecType != TST_double) {
Diag(D, TSCLoc, diag::err_invalid_complex_spec)
- << getSpecifierName((TST)TypeSpecType);
+ << getSpecifierName((TST)TypeSpecType, Policy);
TypeSpecComplex = TSC_unspecified;
}
}
@@ -1118,14 +1125,41 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP) {
ThreadHint = FixItHint::CreateRemoval(SCLoc);
}
- Diag(D, SCLoc, diag::err_friend_storage_spec)
+ Diag(D, SCLoc, diag::err_friend_decl_spec)
<< SpecName << StorageHint << ThreadHint;
ClearStorageClassSpecs();
}
+ // C++11 [dcl.fct.spec]p5:
+ // The virtual specifier shall be used only in the initial
+ // declaration of a non-static class member function;
+ // C++11 [dcl.fct.spec]p6:
+ // The explicit specifier shall be used only in the declaration of
+ // a constructor or conversion function within its class
+ // definition;
+ if (isFriendSpecified() && (isVirtualSpecified() || isExplicitSpecified())) {
+ StringRef Keyword;
+ SourceLocation SCLoc;
+
+ if (isVirtualSpecified()) {
+ Keyword = "virtual";
+ SCLoc = getVirtualSpecLoc();
+ } else {
+ Keyword = "explicit";
+ SCLoc = getExplicitSpecLoc();
+ }
+
+ FixItHint Hint = FixItHint::CreateRemoval(SCLoc);
+ Diag(D, SCLoc, diag::err_friend_decl_spec)
+ << Keyword << Hint;
+
+ FS_virtual_specified = FS_explicit_specified = false;
+ FS_virtualLoc = FS_explicitLoc = SourceLocation();
+ }
+
assert(!TypeSpecOwned || isDeclRep((TST) TypeSpecType));
-
+
// Okay, now we can infer the real type.
// TODO: return "auto function" and other bad things based on the real type.
@@ -1135,7 +1169,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP) {
bool DeclSpec::isMissingDeclaratorOk() {
TST tst = getTypeSpecType();
- return isDeclRep(tst) && getRepAsDecl() != 0 &&
+ return isDeclRep(tst) && getRepAsDecl() != nullptr &&
StorageClassSpec != DeclSpec::SCS_typedef;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp b/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp
index 3100432..664a6b1 100644
--- a/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp
@@ -19,19 +19,29 @@
using namespace clang;
using namespace sema;
-DelayedDiagnostic DelayedDiagnostic::makeDeprecation(SourceLocation Loc,
+DelayedDiagnostic
+DelayedDiagnostic::makeAvailability(Sema::AvailabilityDiagnostic AD,
+ SourceLocation Loc,
const NamedDecl *D,
const ObjCInterfaceDecl *UnknownObjCClass,
const ObjCPropertyDecl *ObjCProperty,
- StringRef Msg) {
+ StringRef Msg,
+ bool ObjCPropertyAccess) {
DelayedDiagnostic DD;
- DD.Kind = Deprecation;
+ switch (AD) {
+ case Sema::AD_Deprecation:
+ DD.Kind = Deprecation;
+ break;
+ case Sema::AD_Unavailable:
+ DD.Kind = Unavailable;
+ break;
+ }
DD.Triggered = false;
DD.Loc = Loc;
DD.DeprecationData.Decl = D;
DD.DeprecationData.UnknownObjCClass = UnknownObjCClass;
DD.DeprecationData.ObjCProperty = ObjCProperty;
- char *MessageData = 0;
+ char *MessageData = nullptr;
if (Msg.size()) {
MessageData = new char [Msg.size()];
memcpy(MessageData, Msg.data(), Msg.size());
@@ -39,16 +49,18 @@ DelayedDiagnostic DelayedDiagnostic::makeDeprecation(SourceLocation Loc,
DD.DeprecationData.Message = MessageData;
DD.DeprecationData.MessageLen = Msg.size();
+ DD.DeprecationData.ObjCPropertyAccess = ObjCPropertyAccess;
return DD;
}
void DelayedDiagnostic::Destroy() {
- switch (Kind) {
+ switch (static_cast<DDKind>(Kind)) {
case Access:
getAccessData().~AccessedEntity();
break;
- case Deprecation:
+ case Deprecation:
+ case Unavailable:
delete [] DeprecationData.Message;
break;
diff --git a/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp
index 6e354b9..2a5bacf 100644
--- a/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp
@@ -45,7 +45,7 @@ class IdentifierResolver::IdDeclInfoMap {
unsigned int CurIndex;
public:
- IdDeclInfoMap() : CurPool(0), CurIndex(POOL_SIZE) {}
+ IdDeclInfoMap() : CurPool(nullptr), CurIndex(POOL_SIZE) {}
~IdDeclInfoMap() {
IdDeclInfoPool *Cur = CurPool;
@@ -95,7 +95,7 @@ IdentifierResolver::~IdentifierResolver() {
/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
/// true if 'D' belongs to the given declaration context.
bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S,
- bool ExplicitInstantiationOrSpecialization) const {
+ bool AllowInlineNamespace) const {
Ctx = Ctx->getRedeclContext();
if (Ctx->isFunctionOrMethod() || S->isFunctionPrototypeScope()) {
@@ -131,9 +131,8 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S,
}
DeclContext *DCtx = D->getDeclContext()->getRedeclContext();
- return ExplicitInstantiationOrSpecialization
- ? Ctx->InEnclosingNamespaceSetOf(DCtx)
- : Ctx->Equals(DCtx);
+ return AllowInlineNamespace ? Ctx->InEnclosingNamespaceSetOf(DCtx)
+ : Ctx->Equals(DCtx);
}
/// AddDecl - Link the decl to its shadowed decl chain.
@@ -152,7 +151,7 @@ void IdentifierResolver::AddDecl(NamedDecl *D) {
IdDeclInfo *IDI;
if (isDeclPtr(Ptr)) {
- Name.setFETokenInfo(NULL);
+ Name.setFETokenInfo(nullptr);
IDI = &(*IdDeclInfos)[Name];
NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
IDI->AddDecl(PrevD);
@@ -214,7 +213,7 @@ void IdentifierResolver::RemoveDecl(NamedDecl *D) {
if (isDeclPtr(Ptr)) {
assert(D == Ptr && "Didn't find this decl on its identifier's chain!");
- Name.setFETokenInfo(NULL);
+ Name.setFETokenInfo(nullptr);
return;
}
@@ -274,10 +273,8 @@ static DeclMatchKind compareDeclarations(NamedDecl *Existing, NamedDecl *New) {
// If the existing declaration is somewhere in the previous declaration
// chain of the new declaration, then prefer the new declaration.
- for (Decl::redecl_iterator RD = New->redecls_begin(),
- RDEnd = New->redecls_end();
- RD != RDEnd; ++RD) {
- if (*RD == Existing)
+ for (auto RD : New->redecls()) {
+ if (RD == Existing)
return DMK_Replace;
if (RD->isCanonicalDecl())
@@ -317,8 +314,8 @@ bool IdentifierResolver::tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name){
Name.setFETokenInfo(D);
return true;
}
-
- Name.setFETokenInfo(NULL);
+
+ Name.setFETokenInfo(nullptr);
IDI = &(*IdDeclInfos)[Name];
// If the existing declaration is not visible in translation unit scope,
diff --git a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp
index d3de173..2558452 100644
--- a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp
@@ -32,6 +32,10 @@ namespace {
class JumpScopeChecker {
Sema &S;
+ /// Permissive - True when recovering from errors, in which case precautions
+ /// are taken to handle incomplete scope information.
+ const bool Permissive;
+
/// GotoScope - This is a record that we use to keep track of all of the
/// scopes that are introduced by VLAs and other things that scope jumps like
/// gotos. This scope tree has nothing to do with the source scope tree,
@@ -85,8 +89,10 @@ private:
};
} // end anonymous namespace
+#define CHECK_PERMISSIVE(x) (assert(Permissive || !(x)), (Permissive && (x)))
-JumpScopeChecker::JumpScopeChecker(Stmt *Body, Sema &s) : S(s) {
+JumpScopeChecker::JumpScopeChecker(Stmt *Body, Sema &s)
+ : S(s), Permissive(s.hasAnyUnrecoverableErrorsInThisFunction()) {
// Add a scope entry for function scope.
Scopes.push_back(GotoScope(~0U, ~0U, ~0U, SourceLocation()));
@@ -121,9 +127,11 @@ typedef std::pair<unsigned,unsigned> ScopePair;
/// GetDiagForGotoScopeDecl - If this decl induces a new goto scope, return a
/// diagnostic that should be emitted if control goes over it. If not, return 0.
-static ScopePair GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) {
+static ScopePair GetDiagForGotoScopeDecl(Sema &S, const Decl *D) {
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
unsigned InDiag = 0;
+ unsigned OutDiag = 0;
+
if (VD->getType()->isVariablyModifiedType())
InDiag = diag::note_protected_by_vla;
@@ -135,21 +143,24 @@ static ScopePair GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) {
return ScopePair(diag::note_protected_by_cleanup,
diag::note_exits_cleanup);
- if (Context.getLangOpts().ObjCAutoRefCount && VD->hasLocalStorage()) {
- switch (VD->getType().getObjCLifetime()) {
- case Qualifiers::OCL_None:
- case Qualifiers::OCL_ExplicitNone:
- case Qualifiers::OCL_Autoreleasing:
- break;
-
- case Qualifiers::OCL_Strong:
- case Qualifiers::OCL_Weak:
+ if (VD->hasLocalStorage()) {
+ switch (VD->getType().isDestructedType()) {
+ case QualType::DK_objc_strong_lifetime:
+ case QualType::DK_objc_weak_lifetime:
return ScopePair(diag::note_protected_by_objc_ownership,
diag::note_exits_objc_ownership);
+
+ case QualType::DK_cxx_destructor:
+ OutDiag = diag::note_exits_dtor;
+ break;
+
+ case QualType::DK_none:
+ break;
}
}
- if (Context.getLangOpts().CPlusPlus && VD->hasLocalStorage()) {
+ const Expr *Init = VD->getInit();
+ if (S.Context.getLangOpts().CPlusPlus && VD->hasLocalStorage() && Init) {
// C++11 [stmt.dcl]p3:
// A program that jumps from a point where a variable with automatic
// storage duration is not in scope to a point where it is in scope
@@ -164,68 +175,34 @@ static ScopePair GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) {
// where it is in scope is ill-formed unless the variable has
// POD type and is declared without an initializer.
- const Expr *Init = VD->getInit();
- if (!Init)
- return ScopePair(InDiag, 0);
-
- const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Init);
- if (EWC)
- Init = EWC->getSubExpr();
-
- const MaterializeTemporaryExpr *M = NULL;
- Init = Init->findMaterializedTemporary(M);
-
- SmallVector<const Expr *, 2> CommaLHSs;
- SmallVector<SubobjectAdjustment, 2> Adjustments;
- Init = Init->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments);
-
- QualType QT = Init->getType();
- if (QT.isNull())
- return ScopePair(diag::note_protected_by_variable_init, 0);
-
- const Type *T = QT.getTypePtr();
- if (T->isArrayType())
- T = T->getBaseElementTypeUnsafe();
-
- const CXXRecordDecl *Record = T->getAsCXXRecordDecl();
- if (!Record)
- return ScopePair(diag::note_protected_by_variable_init, 0);
+ InDiag = diag::note_protected_by_variable_init;
- // If we need to call a non trivial destructor for this variable,
- // record an out diagnostic.
- unsigned OutDiag = 0;
- if (!Init->isGLValue() && !Record->hasTrivialDestructor())
- OutDiag = diag::note_exits_dtor;
-
- if (const CXXConstructExpr *cce = dyn_cast<CXXConstructExpr>(Init)) {
- const CXXConstructorDecl *ctor = cce->getConstructor();
- // For a variable declared without an initializer, we will have
- // call-style initialization and the initializer will be the
- // CXXConstructExpr with no intervening nodes.
- if (ctor->isTrivial() && ctor->isDefaultConstructor() &&
- VD->getInit() == Init && VD->getInitStyle() == VarDecl::CallInit) {
+ // For a variable of (array of) class type declared without an
+ // initializer, we will have call-style initialization and the initializer
+ // will be the CXXConstructExpr with no intervening nodes.
+ if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init)) {
+ const CXXConstructorDecl *Ctor = CCE->getConstructor();
+ if (Ctor->isTrivial() && Ctor->isDefaultConstructor() &&
+ VD->getInitStyle() == VarDecl::CallInit) {
if (OutDiag)
InDiag = diag::note_protected_by_variable_nontriv_destructor;
- else if (!Record->isPOD())
+ else if (!Ctor->getParent()->isPOD())
InDiag = diag::note_protected_by_variable_non_pod;
- return ScopePair(InDiag, OutDiag);
+ else
+ InDiag = 0;
}
}
-
- return ScopePair(diag::note_protected_by_variable_init, OutDiag);
}
- return ScopePair(InDiag, 0);
- }
-
- if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
- if (TD->getUnderlyingType()->isVariablyModifiedType())
- return ScopePair(diag::note_protected_by_vla_typedef, 0);
+ return ScopePair(InDiag, OutDiag);
}
- if (const TypeAliasDecl *TD = dyn_cast<TypeAliasDecl>(D)) {
+ if (const TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
if (TD->getUnderlyingType()->isVariablyModifiedType())
- return ScopePair(diag::note_protected_by_vla_type_alias, 0);
+ return ScopePair(isa<TypedefDecl>(TD)
+ ? diag::note_protected_by_vla_typedef
+ : diag::note_protected_by_vla_type_alias,
+ 0);
}
return ScopePair(0U, 0U);
@@ -234,7 +211,7 @@ static ScopePair GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) {
/// \brief 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.Context, D);
+ std::pair<unsigned,unsigned> Diags = GetDiagForGotoScopeDecl(S, D);
if (Diags.first || Diags.second) {
Scopes.push_back(GotoScope(ParentScope, Diags.first, Diags.second,
D->getLocation()));
@@ -371,7 +348,7 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope)
}
Stmt *SubStmt = *CI;
- if (SubStmt == 0) continue;
+ if (!SubStmt) continue;
// Cases, labels, and defaults aren't "scope parents". It's also
// important to handle these iteratively instead of recursively in
@@ -396,9 +373,8 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope)
if (DeclStmt *DS = dyn_cast<DeclStmt>(SubStmt)) {
// The decl statement creates a scope if any of the decls in it are VLAs
// or have the cleanup attribute.
- for (DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
- I != E; ++I)
- BuildScopeInformation(*I, ParentScope);
+ for (auto *I : DS->decls())
+ BuildScopeInformation(I, ParentScope);
continue;
}
// Disallow jumps into any part of an @try statement by pushing a scope and
@@ -474,14 +450,32 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope)
if (ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(SubStmt)) {
for (unsigned i = 0, e = EWC->getNumObjects(); i != e; ++i) {
const BlockDecl *BDecl = EWC->getObject(i);
- for (BlockDecl::capture_const_iterator ci = BDecl->capture_begin(),
- ce = BDecl->capture_end(); ci != ce; ++ci) {
- VarDecl *variable = ci->getVariable();
+ for (const auto &CI : BDecl->captures()) {
+ VarDecl *variable = CI.getVariable();
BuildScopeInformation(variable, BDecl, ParentScope);
}
}
}
-
+
+ // Disallow jumps out of scopes containing temporaries lifetime-extended to
+ // automatic storage duration.
+ if (MaterializeTemporaryExpr *MTE =
+ dyn_cast<MaterializeTemporaryExpr>(SubStmt)) {
+ if (MTE->getStorageDuration() == SD_Automatic) {
+ SmallVector<const Expr *, 4> CommaLHS;
+ SmallVector<SubobjectAdjustment, 4> Adjustments;
+ const Expr *ExtendedObject =
+ MTE->GetTemporaryExpr()->skipRValueSubobjectAdjustments(
+ CommaLHS, Adjustments);
+ if (ExtendedObject->getType().isDestructedType()) {
+ Scopes.push_back(GotoScope(ParentScope, 0,
+ diag::note_exits_temporary_dtor,
+ ExtendedObject->getExprLoc()));
+ ParentScope = Scopes.size()-1;
+ }
+ }
+ }
+
// Recursively walk the AST.
BuildScopeInformation(SubStmt, ParentScope);
}
@@ -497,7 +491,7 @@ void JumpScopeChecker::VerifyJumps() {
if (GotoStmt *GS = dyn_cast<GotoStmt>(Jump)) {
CheckJump(GS, GS->getLabel()->getStmt(), GS->getGotoLoc(),
diag::err_goto_into_protected_scope,
- diag::warn_goto_into_protected_scope,
+ diag::ext_goto_into_protected_scope,
diag::warn_cxx98_compat_goto_into_protected_scope);
continue;
}
@@ -507,7 +501,7 @@ void JumpScopeChecker::VerifyJumps() {
LabelDecl *Target = IGS->getConstantTarget();
CheckJump(IGS, Target->getStmt(), IGS->getGotoLoc(),
diag::err_goto_into_protected_scope,
- diag::warn_goto_into_protected_scope,
+ diag::ext_goto_into_protected_scope,
diag::warn_cxx98_compat_goto_into_protected_scope);
continue;
}
@@ -515,7 +509,8 @@ void JumpScopeChecker::VerifyJumps() {
SwitchStmt *SS = cast<SwitchStmt>(Jump);
for (SwitchCase *SC = SS->getSwitchCaseList(); SC;
SC = SC->getNextSwitchCase()) {
- assert(LabelAndGotoScopes.count(SC) && "Case not visited?");
+ if (CHECK_PERMISSIVE(!LabelAndGotoScopes.count(SC)))
+ continue;
SourceLocation Loc;
if (CaseStmt *CS = dyn_cast<CaseStmt>(SC))
Loc = CS->getLocStart();
@@ -569,8 +564,8 @@ void JumpScopeChecker::VerifyIndirectJumps() {
for (SmallVectorImpl<IndirectGotoStmt*>::iterator
I = IndirectJumps.begin(), E = IndirectJumps.end(); I != E; ++I) {
IndirectGotoStmt *IG = *I;
- assert(LabelAndGotoScopes.count(IG) &&
- "indirect jump didn't get added to scopes?");
+ if (CHECK_PERMISSIVE(!LabelAndGotoScopes.count(IG)))
+ continue;
unsigned IGScope = LabelAndGotoScopes[IG];
IndirectGotoStmt *&Entry = JumpScopesMap[IGScope];
if (!Entry) Entry = IG;
@@ -589,8 +584,8 @@ void JumpScopeChecker::VerifyIndirectJumps() {
I = IndirectJumpTargets.begin(), E = IndirectJumpTargets.end();
I != E; ++I) {
LabelDecl *TheLabel = *I;
- assert(LabelAndGotoScopes.count(TheLabel->getStmt()) &&
- "Referenced label didn't get added to scopes?");
+ if (CHECK_PERMISSIVE(!LabelAndGotoScopes.count(TheLabel->getStmt())))
+ continue;
unsigned LabelScope = LabelAndGotoScopes[TheLabel->getStmt()];
LabelDecl *&Target = TargetScopes[LabelScope];
if (!Target) Target = TheLabel;
@@ -695,7 +690,8 @@ static void DiagnoseIndirectJumpStmt(Sema &S, IndirectGotoStmt *Jump,
/// Produce note diagnostics for a jump into a protected scope.
void JumpScopeChecker::NoteJumpIntoScopes(ArrayRef<unsigned> ToScopes) {
- assert(!ToScopes.empty());
+ if (CHECK_PERMISSIVE(ToScopes.empty()))
+ return;
for (unsigned I = 0, E = ToScopes.size(); I != E; ++I)
if (Scopes[ToScopes[I]].InDiag)
S.Diag(Scopes[ToScopes[I]].Loc, Scopes[ToScopes[I]].InDiag);
@@ -706,7 +702,8 @@ void JumpScopeChecker::DiagnoseIndirectJump(IndirectGotoStmt *Jump,
unsigned JumpScope,
LabelDecl *Target,
unsigned TargetScope) {
- assert(JumpScope != TargetScope);
+ if (CHECK_PERMISSIVE(JumpScope == TargetScope))
+ return;
unsigned Common = GetDeepestCommonScope(JumpScope, TargetScope);
bool Diagnosed = false;
@@ -743,10 +740,12 @@ void JumpScopeChecker::DiagnoseIndirectJump(IndirectGotoStmt *Jump,
void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc,
unsigned JumpDiagError, unsigned JumpDiagWarning,
unsigned JumpDiagCXX98Compat) {
- assert(LabelAndGotoScopes.count(From) && "Jump didn't get added to scopes?");
- unsigned FromScope = LabelAndGotoScopes[From];
+ if (CHECK_PERMISSIVE(!LabelAndGotoScopes.count(From)))
+ return;
+ if (CHECK_PERMISSIVE(!LabelAndGotoScopes.count(To)))
+ return;
- assert(LabelAndGotoScopes.count(To) && "Jump didn't get added to scopes?");
+ unsigned FromScope = LabelAndGotoScopes[From];
unsigned ToScope = LabelAndGotoScopes[To];
// Common case: exactly the same scope, which is fine.
@@ -762,7 +761,7 @@ void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc,
SmallVector<unsigned, 10> ToScopesError;
SmallVector<unsigned, 10> ToScopesWarning;
for (unsigned I = ToScope; I != CommonScope; I = Scopes[I].ParentScope) {
- if (S.getLangOpts().MicrosoftMode && JumpDiagWarning != 0 &&
+ if (S.getLangOpts().MSVCCompat && JumpDiagWarning != 0 &&
IsMicrosoftJumpWarning(JumpDiagError, Scopes[I].InDiag))
ToScopesWarning.push_back(I);
else if (IsCXX98CompatWarning(S, Scopes[I].InDiag))
diff --git a/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp
index ad7627a..97237db 100644
--- a/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp
@@ -46,7 +46,12 @@ Decl *MultiplexExternalSemaSource::GetExternalDecl(uint32_t ID) {
for(size_t i = 0; i < Sources.size(); ++i)
if (Decl *Result = Sources[i]->GetExternalDecl(ID))
return Result;
- return 0;
+ return nullptr;
+}
+
+void MultiplexExternalSemaSource::CompleteRedeclChain(const Decl *D) {
+ for (size_t i = 0; i < Sources.size(); ++i)
+ Sources[i]->CompleteRedeclChain(D);
}
Selector MultiplexExternalSemaSource::GetExternalSelector(uint32_t ID) {
@@ -70,7 +75,7 @@ Stmt *MultiplexExternalSemaSource::GetExternalDeclStmt(uint64_t Offset) {
for(size_t i = 0; i < Sources.size(); ++i)
if (Stmt *Result = Sources[i]->GetExternalDeclStmt(Offset))
return Result;
- return 0;
+ return nullptr;
}
CXXBaseSpecifier *MultiplexExternalSemaSource::GetExternalCXXBaseSpecifiers(
@@ -78,7 +83,7 @@ CXXBaseSpecifier *MultiplexExternalSemaSource::GetExternalCXXBaseSpecifiers(
for(size_t i = 0; i < Sources.size(); ++i)
if (CXXBaseSpecifier *R = Sources[i]->GetExternalCXXBaseSpecifiers(Offset))
return R;
- return 0;
+ return nullptr;
}
bool MultiplexExternalSemaSource::
diff --git a/contrib/llvm/tools/clang/lib/Sema/Scope.cpp b/contrib/llvm/tools/clang/lib/Sema/Scope.cpp
index 10f12ce..35e2075 100644
--- a/contrib/llvm/tools/clang/lib/Sema/Scope.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/Scope.cpp
@@ -13,6 +13,8 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/Scope.h"
+#include "clang/AST/Decl.h"
+#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -26,7 +28,7 @@ void Scope::Init(Scope *parent, unsigned flags) {
} else {
// Control scopes do not contain the contents of nested function scopes for
// control flow purposes.
- BreakParent = ContinueParent = 0;
+ BreakParent = ContinueParent = nullptr;
}
if (parent) {
@@ -36,16 +38,35 @@ void Scope::Init(Scope *parent, unsigned flags) {
FnParent = parent->FnParent;
BlockParent = parent->BlockParent;
TemplateParamParent = parent->TemplateParamParent;
+ MSLocalManglingParent = parent->MSLocalManglingParent;
+ SEHTryParent = parent->SEHTryParent;
+ if (parent->Flags & SEHTryScope)
+ SEHTryParent = parent;
+ if ((Flags & (FnScope | ClassScope | BlockScope | TemplateParamScope |
+ FunctionPrototypeScope | AtCatchScope | ObjCMethodScope)) ==
+ 0)
+ Flags |= parent->getFlags() & OpenMPSimdDirectiveScope;
} else {
Depth = 0;
PrototypeDepth = 0;
PrototypeIndex = 0;
- FnParent = BlockParent = 0;
- TemplateParamParent = 0;
+ SEHTryParent = MSLocalManglingParent = FnParent = BlockParent = nullptr;
+ TemplateParamParent = nullptr;
+ MSLocalManglingNumber = 1;
}
// If this scope is a function or contains breaks/continues, remember it.
if (flags & FnScope) FnParent = this;
+ SEHTryIndexPool = 0;
+ SEHTryIndex = -1;
+ if (flags & SEHTryScope)
+ SEHTryIndex = FnParent ? FnParent->SEHTryIndexPool++ : -1;
+ // The MS mangler uses the number of scopes that can hold declarations as
+ // part of an external name.
+ if (Flags & (ClassScope | FnScope)) {
+ MSLocalManglingNumber = getMSLocalManglingNumber();
+ MSLocalManglingParent = this;
+ }
if (flags & BreakScope) BreakParent = this;
if (flags & ContinueScope) ContinueParent = this;
if (flags & BlockScope) BlockParent = this;
@@ -54,10 +75,24 @@ void Scope::Init(Scope *parent, unsigned flags) {
// If this is a prototype scope, record that.
if (flags & FunctionPrototypeScope) PrototypeDepth++;
+ if (flags & DeclScope) {
+ if (flags & FunctionPrototypeScope)
+ ; // Prototype scopes are uninteresting.
+ else if ((flags & ClassScope) && getParent()->isClassScope())
+ ; // Nested class scopes aren't ambiguous.
+ else if ((flags & ClassScope) && getParent()->getFlags() == DeclScope)
+ ; // Classes inside of namespaces aren't ambiguous.
+ else if ((flags & EnumScope))
+ ; // Don't increment for enum scopes.
+ else
+ incrementMSLocalManglingNumber();
+ }
+
DeclsInScope.clear();
UsingDirectives.clear();
- Entity = 0;
+ Entity = nullptr;
ErrorTrap.reset();
+ NRVO.setPointerAndInt(nullptr, 0);
}
bool Scope::containedInPrototypeScope() const {
@@ -69,3 +104,121 @@ bool Scope::containedInPrototypeScope() const {
}
return false;
}
+
+void Scope::AddFlags(unsigned FlagsToSet) {
+ assert((FlagsToSet & ~(BreakScope | ContinueScope)) == 0 &&
+ "Unsupported scope flags");
+ if (FlagsToSet & BreakScope) {
+ assert((Flags & BreakScope) == 0 && "Already set");
+ BreakParent = this;
+ }
+ if (FlagsToSet & ContinueScope) {
+ assert((Flags & ContinueScope) == 0 && "Already set");
+ ContinueParent = this;
+ }
+ Flags |= FlagsToSet;
+}
+
+void Scope::mergeNRVOIntoParent() {
+ if (VarDecl *Candidate = NRVO.getPointer()) {
+ if (isDeclScope(Candidate))
+ Candidate->setNRVOVariable(true);
+ }
+
+ if (getEntity())
+ return;
+
+ if (NRVO.getInt())
+ getParent()->setNoNRVO();
+ else if (NRVO.getPointer())
+ getParent()->addNRVOCandidate(NRVO.getPointer());
+}
+
+void Scope::dump() const { dumpImpl(llvm::errs()); }
+
+void Scope::dumpImpl(raw_ostream &OS) const {
+ unsigned Flags = getFlags();
+ bool HasFlags = Flags != 0;
+
+ if (HasFlags)
+ OS << "Flags: ";
+
+ while (Flags) {
+ if (Flags & FnScope) {
+ OS << "FnScope";
+ Flags &= ~FnScope;
+ } else if (Flags & BreakScope) {
+ OS << "BreakScope";
+ Flags &= ~BreakScope;
+ } else if (Flags & ContinueScope) {
+ OS << "ContinueScope";
+ Flags &= ~ContinueScope;
+ } else if (Flags & DeclScope) {
+ OS << "DeclScope";
+ Flags &= ~DeclScope;
+ } else if (Flags & ControlScope) {
+ OS << "ControlScope";
+ Flags &= ~ControlScope;
+ } else if (Flags & ClassScope) {
+ OS << "ClassScope";
+ Flags &= ~ClassScope;
+ } else if (Flags & BlockScope) {
+ OS << "BlockScope";
+ Flags &= ~BlockScope;
+ } else if (Flags & TemplateParamScope) {
+ OS << "TemplateParamScope";
+ Flags &= ~TemplateParamScope;
+ } else if (Flags & FunctionPrototypeScope) {
+ OS << "FunctionPrototypeScope";
+ Flags &= ~FunctionPrototypeScope;
+ } else if (Flags & FunctionDeclarationScope) {
+ OS << "FunctionDeclarationScope";
+ Flags &= ~FunctionDeclarationScope;
+ } else if (Flags & AtCatchScope) {
+ OS << "AtCatchScope";
+ Flags &= ~AtCatchScope;
+ } else if (Flags & ObjCMethodScope) {
+ OS << "ObjCMethodScope";
+ Flags &= ~ObjCMethodScope;
+ } else if (Flags & SwitchScope) {
+ OS << "SwitchScope";
+ Flags &= ~SwitchScope;
+ } else if (Flags & TryScope) {
+ OS << "TryScope";
+ Flags &= ~TryScope;
+ } else if (Flags & FnTryCatchScope) {
+ OS << "FnTryCatchScope";
+ Flags &= ~FnTryCatchScope;
+ } else if (Flags & SEHTryScope) {
+ OS << "SEHTryScope";
+ Flags &= ~SEHTryScope;
+ } else if (Flags & OpenMPDirectiveScope) {
+ OS << "OpenMPDirectiveScope";
+ Flags &= ~OpenMPDirectiveScope;
+ } else if (Flags & OpenMPLoopDirectiveScope) {
+ OS << "OpenMPLoopDirectiveScope";
+ Flags &= ~OpenMPLoopDirectiveScope;
+ } else if (Flags & OpenMPSimdDirectiveScope) {
+ OS << "OpenMPSimdDirectiveScope";
+ Flags &= ~OpenMPSimdDirectiveScope;
+ }
+
+ if (Flags)
+ OS << " | ";
+ }
+ if (HasFlags)
+ OS << '\n';
+
+ if (const Scope *Parent = getParent())
+ OS << "Parent: (clang::Scope*)" << Parent << '\n';
+
+ OS << "Depth: " << Depth << '\n';
+ OS << "MSLocalManglingNumber: " << getMSLocalManglingNumber() << '\n';
+ if (const DeclContext *DC = getEntity())
+ OS << "Entity : (clang::DeclContext*)" << DC << '\n';
+
+ if (NRVO.getInt())
+ OS << "NRVO not allowed";
+ else if (NRVO.getPointer())
+ OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n';
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp b/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp
index 8b3493e..4d079e7 100644
--- a/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp
@@ -26,6 +26,12 @@ void FunctionScopeInfo::Clear() {
HasBranchProtectedScope = false;
HasBranchIntoScope = false;
HasIndirectGoto = false;
+ HasDroppedStmt = false;
+ ObjCShouldCallSuper = false;
+ ObjCIsDesignatedInit = false;
+ ObjCWarnForNoDesignatedInitChain = false;
+ ObjCIsSecondaryInit = false;
+ ObjCWarnForNoInitDelegation = false;
SwitchStack.clear();
Returns.clear();
@@ -45,7 +51,7 @@ FunctionScopeInfo::WeakObjectProfileTy::BaseInfoTy
FunctionScopeInfo::WeakObjectProfileTy::getBaseInfo(const Expr *E) {
E = E->IgnoreParenCasts();
- const NamedDecl *D = 0;
+ const NamedDecl *D = nullptr;
bool IsExact = false;
switch (E->getStmtClass()) {
@@ -87,10 +93,9 @@ FunctionScopeInfo::WeakObjectProfileTy::getBaseInfo(const Expr *E) {
return BaseInfoTy(D, IsExact);
}
-
FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
const ObjCPropertyRefExpr *PropE)
- : Base(0, true), Property(getBestPropertyDecl(PropE)) {
+ : Base(nullptr, true), Property(getBestPropertyDecl(PropE)) {
if (PropE->isObjectReceiver()) {
const OpaqueValueExpr *OVE = cast<OpaqueValueExpr>(PropE->getBase());
@@ -105,7 +110,7 @@ FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(const Expr *BaseE,
const ObjCPropertyDecl *Prop)
- : Base(0, true), Property(Prop) {
+ : Base(nullptr, true), Property(Prop) {
if (BaseE)
Base = getBaseInfo(BaseE);
// else, this is a message accessing a property on super.
@@ -113,7 +118,7 @@ FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(const Expr *BaseE,
FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
const DeclRefExpr *DRE)
- : Base(0, true), Property(DRE->getDecl()) {
+ : Base(nullptr, true), Property(DRE->getDecl()) {
assert(isa<VarDecl>(Property));
}
@@ -153,8 +158,14 @@ void FunctionScopeInfo::markSafeWeakUse(const Expr *E) {
// Has this weak object been seen before?
FunctionScopeInfo::WeakObjectUseMap::iterator Uses;
- if (const ObjCPropertyRefExpr *RefExpr = dyn_cast<ObjCPropertyRefExpr>(E))
- Uses = WeakObjectUses.find(WeakObjectProfileTy(RefExpr));
+ if (const ObjCPropertyRefExpr *RefExpr = dyn_cast<ObjCPropertyRefExpr>(E)) {
+ if (isa<OpaqueValueExpr>(RefExpr->getBase()))
+ Uses = WeakObjectUses.find(WeakObjectProfileTy(RefExpr));
+ else {
+ markSafeWeakUse(RefExpr->getBase());
+ return;
+ }
+ }
else if (const ObjCIvarRefExpr *IvarE = dyn_cast<ObjCIvarRefExpr>(E))
Uses = WeakObjectUses.find(WeakObjectProfileTy(IvarE));
else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
@@ -184,10 +195,11 @@ void FunctionScopeInfo::markSafeWeakUse(const Expr *E) {
ThisUse->markSafe();
}
-void LambdaScopeInfo::getPotentialVariableCapture(unsigned Idx, VarDecl *&VD, Expr *&E) {
+void LambdaScopeInfo::getPotentialVariableCapture(unsigned Idx, VarDecl *&VD,
+ Expr *&E) const {
assert(Idx < getNumPotentialVariableCaptures() &&
- "Index of potential capture must be within 0 to less than the "
- "number of captures!");
+ "Index of potential capture must be within 0 to less than the "
+ "number of captures!");
E = PotentiallyCapturingExprs[Idx];
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
VD = dyn_cast<VarDecl>(DRE->getFoundDecl());
diff --git a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
index 4d01fb0..2c65332 100644
--- a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
@@ -13,7 +13,6 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "TargetAttributesSema.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/DeclCXX.h"
@@ -22,6 +21,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
+#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
@@ -44,6 +44,12 @@
using namespace clang;
using namespace sema;
+SourceLocation Sema::getLocForEndOfToken(SourceLocation Loc, unsigned Offset) {
+ return Lexer::getLocForEndOfToken(Loc, Offset, SourceMgr, LangOpts);
+}
+
+ModuleLoader &Sema::getModuleLoader() const { return PP.getModuleLoader(); }
+
PrintingPolicy Sema::getPrintingPolicy(const ASTContext &Context,
const Preprocessor &PP) {
PrintingPolicy Policy = Context.getPrintingPolicy();
@@ -70,35 +76,41 @@ void Sema::ActOnTranslationUnitScope(Scope *S) {
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
TranslationUnitKind TUKind,
CodeCompleteConsumer *CodeCompleter)
- : TheTargetAttributesSema(0), ExternalSource(0),
+ : ExternalSource(nullptr),
isMultiplexExternalSource(false), FPFeatures(pp.getLangOpts()),
LangOpts(pp.getLangOpts()), PP(pp), Context(ctxt), Consumer(consumer),
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
CollectStats(false), CodeCompleter(CodeCompleter),
- CurContext(0), OriginalLexicalContext(0),
- PackContext(0), MSStructPragmaOn(false), VisContext(0),
+ CurContext(nullptr), OriginalLexicalContext(nullptr),
+ PackContext(nullptr), MSStructPragmaOn(false),
+ MSPointerToMemberRepresentationMethod(
+ LangOpts.getMSPointerToMemberRepresentationMethod()),
+ VtorDispModeStack(1, MSVtorDispAttr::Mode(LangOpts.VtorDispMode)),
+ DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr),
+ CodeSegStack(nullptr), CurInitSeg(nullptr), VisContext(nullptr),
IsBuildingRecoveryCallExpr(false),
- ExprNeedsCleanups(false), LateTemplateParser(0), OpaqueParser(0),
- IdResolver(pp), StdInitializerList(0), CXXTypeInfoDecl(0), MSVCGuidDecl(0),
- NSNumberDecl(0),
- NSStringDecl(0), StringWithUTF8StringMethod(0),
- NSArrayDecl(0), ArrayWithObjectsMethod(0),
- NSDictionaryDecl(0), DictionaryWithObjectsMethod(0),
+ ExprNeedsCleanups(false), LateTemplateParser(nullptr),
+ OpaqueParser(nullptr), IdResolver(pp), StdInitializerList(nullptr),
+ CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr),
+ NSNumberDecl(nullptr),
+ NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr),
+ NSArrayDecl(nullptr), ArrayWithObjectsMethod(nullptr),
+ NSDictionaryDecl(nullptr), DictionaryWithObjectsMethod(nullptr),
GlobalNewDeleteDeclared(false),
TUKind(TUKind),
- NumSFINAEErrors(0), InFunctionDeclarator(0),
+ NumSFINAEErrors(0),
AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false),
NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1),
- CurrentInstantiationScope(0), DisableTypoCorrection(false),
+ CurrentInstantiationScope(nullptr), DisableTypoCorrection(false),
TyposCorrected(0), AnalysisWarnings(*this),
- VarDataSharingAttributesStack(0), CurScope(0),
- Ident_super(0), Ident___float128(0)
+ VarDataSharingAttributesStack(nullptr), CurScope(nullptr),
+ Ident_super(nullptr), Ident___float128(nullptr)
{
- TUScope = 0;
+ TUScope = nullptr;
LoadedExternalKnownNamespaces = false;
for (unsigned I = 0; I != NSAPI::NumNSNumberLiteralMethods; ++I)
- NSNumberLiteralMethods[I] = 0;
+ NSNumberLiteralMethods[I] = nullptr;
if (getLangOpts().ObjC1)
NSAPIObj.reset(new NSAPI(Context));
@@ -112,7 +124,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
ExprEvalContexts.push_back(
ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0,
- false, 0, false));
+ false, nullptr, false));
FunctionScopes.push_back(new FunctionScopeInfo(Diags));
@@ -120,6 +132,12 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
InitDataSharingAttributesStack();
}
+void Sema::addImplicitTypedef(StringRef Name, QualType T) {
+ DeclarationName DN = &Context.Idents.get(Name);
+ if (IdResolver.begin(DN) == IdResolver.end())
+ PushOnScopeChains(Context.buildImplicitTypedef(T, Name), TUScope);
+}
+
void Sema::Initialize() {
// Tell the AST consumer about this Sema object.
Consumer.Initialize(Context);
@@ -134,7 +152,7 @@ void Sema::Initialize() {
ExternalSema->InitializeSema(*this);
// Initialize predefined 128-bit integer types, if needed.
- if (PP.getTargetInfo().hasInt128Type()) {
+ if (Context.getTargetInfo().hasInt128Type()) {
// If either of the 128-bit integer types are unavailable to name lookup,
// define them now.
DeclarationName Int128 = &Context.Idents.get("__int128_t");
@@ -172,20 +190,36 @@ void Sema::Initialize() {
PushOnScopeChains(Context.getObjCProtocolDecl(), TUScope);
}
+ // Initialize Microsoft "predefined C++ types".
+ if (PP.getLangOpts().MSVCCompat && PP.getLangOpts().CPlusPlus) {
+ if (IdResolver.begin(&Context.Idents.get("type_info")) == IdResolver.end())
+ PushOnScopeChains(Context.buildImplicitRecord("type_info", TTK_Class),
+ TUScope);
+
+ addImplicitTypedef("size_t", Context.getSizeType());
+ }
+
+ // Initialize predefined OpenCL types.
+ if (PP.getLangOpts().OpenCL) {
+ addImplicitTypedef("image1d_t", Context.OCLImage1dTy);
+ addImplicitTypedef("image1d_array_t", Context.OCLImage1dArrayTy);
+ addImplicitTypedef("image1d_buffer_t", Context.OCLImage1dBufferTy);
+ addImplicitTypedef("image2d_t", Context.OCLImage2dTy);
+ addImplicitTypedef("image2d_array_t", Context.OCLImage2dArrayTy);
+ addImplicitTypedef("image3d_t", Context.OCLImage3dTy);
+ addImplicitTypedef("sampler_t", Context.OCLSamplerTy);
+ addImplicitTypedef("event_t", Context.OCLEventTy);
+ }
+
DeclarationName BuiltinVaList = &Context.Idents.get("__builtin_va_list");
if (IdResolver.begin(BuiltinVaList) == IdResolver.end())
PushOnScopeChains(Context.getBuiltinVaListDecl(), TUScope);
}
Sema::~Sema() {
- for (LateParsedTemplateMapT::iterator I = LateParsedTemplateMap.begin(),
- E = LateParsedTemplateMap.end();
- I != E; ++I)
- delete I->second;
+ llvm::DeleteContainerSeconds(LateParsedTemplateMap);
if (PackContext) FreePackedContext();
if (VisContext) FreeVisContext();
- delete TheTargetAttributesSema;
- MSStructPragmaOn = false;
// Kill all the active scopes.
for (unsigned I = 1, E = FunctionScopes.size(); I != E; ++I)
delete FunctionScopes[I];
@@ -230,7 +264,7 @@ bool Sema::makeUnavailableInSystemHeader(SourceLocation loc,
// If the function is already unavailable, it's not an error.
if (fn->hasAttr<UnavailableAttr>()) return true;
- fn->addAttr(new (Context) UnavailableAttr(loc, Context, msg));
+ fn->addAttr(UnavailableAttr::CreateImplicit(Context, msg, loc));
return true;
}
@@ -279,7 +313,8 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
if (VK == VK_RValue && !E->isRValue()) {
switch (Kind) {
default:
- assert(0 && "can't implicitly cast lvalue to rvalue with this cast kind");
+ llvm_unreachable("can't implicitly cast lvalue to rvalue with this cast "
+ "kind");
case CK_LValueToRValue:
case CK_ArrayToPointerDecay:
case CK_FunctionToPointerDecay:
@@ -294,7 +329,7 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
QualType TypeTy = Context.getCanonicalType(Ty);
if (ExprTy == TypeTy)
- return Owned(E);
+ return E;
// If this is a derived-to-base cast to a through a virtual base, we
// need a vtable.
@@ -312,11 +347,11 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) {
ImpCast->setType(Ty);
ImpCast->setValueKind(VK);
- return Owned(E);
+ return E;
}
}
- return Owned(ImplicitCastExpr::Create(Context, Ty, Kind, E, BasePath, VK));
+ return ImplicitCastExpr::Create(Context, Ty, Kind, E, BasePath, VK);
}
/// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding
@@ -384,25 +419,6 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
return false;
}
-namespace {
- struct SortUndefinedButUsed {
- const SourceManager &SM;
- explicit SortUndefinedButUsed(SourceManager &SM) : SM(SM) {}
-
- bool operator()(const std::pair<NamedDecl *, SourceLocation> &l,
- const std::pair<NamedDecl *, SourceLocation> &r) const {
- if (l.second.isValid() && !r.second.isValid())
- return true;
- if (!l.second.isValid() && r.second.isValid())
- return false;
- if (l.second != r.second)
- return SM.isBeforeInTranslationUnit(l.second, r.second);
- return SM.isBeforeInTranslationUnit(l.first->getLocation(),
- r.first->getLocation());
- }
- };
-}
-
/// Obtains a sorted list of functions that are undefined but ODR-used.
void Sema::getUndefinedButUsed(
SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined) {
@@ -435,8 +451,19 @@ void Sema::getUndefinedButUsed(
// Sort (in order of use site) so that we're not dependent on the iteration
// order through an llvm::DenseMap.
+ SourceManager &SM = Context.getSourceManager();
std::sort(Undefined.begin(), Undefined.end(),
- SortUndefinedButUsed(Context.getSourceManager()));
+ [&SM](const std::pair<NamedDecl *, SourceLocation> &l,
+ const std::pair<NamedDecl *, SourceLocation> &r) {
+ if (l.second.isValid() && !r.second.isValid())
+ return true;
+ if (!l.second.isValid() && r.second.isValid())
+ return false;
+ if (l.second != r.second)
+ return SM.isBeforeInTranslationUnit(l.second, r.second);
+ return SM.isBeforeInTranslationUnit(l.first->getLocation(),
+ r.first->getLocation());
+ });
}
/// checkUndefinedButUsed - Check for undefined objects with internal linkage
@@ -453,6 +480,13 @@ static void checkUndefinedButUsed(Sema &S) {
I = Undefined.begin(), E = Undefined.end(); I != E; ++I) {
NamedDecl *ND = I->first;
+ if (ND->hasAttr<DLLImportAttr>() || ND->hasAttr<DLLExportAttr>()) {
+ // An exported function will always be emitted when defined, so even if
+ // the function is inline, it doesn't have to be emitted in this TU. An
+ // imported function implies that it has been exported somewhere else.
+ continue;
+ }
+
if (!ND->isExternallyVisible()) {
S.Diag(ND->getLocation(), diag::warn_undefined_internal)
<< isa<VarDecl>(ND) << ND;
@@ -561,7 +595,7 @@ static bool IsRecordFullyDefined(const CXXRecordDecl *RD,
/// translation unit when EOF is reached and all but the top-level scope is
/// popped.
void Sema::ActOnEndOfTranslationUnit() {
- assert(DelayedDiagnostics.getCurrentPool() == NULL
+ assert(DelayedDiagnostics.getCurrentPool() == nullptr
&& "reached end of translation unit with a pool attached?");
// If code completion is enabled, don't perform any end-of-translation-unit
@@ -582,8 +616,9 @@ void Sema::ActOnEndOfTranslationUnit() {
I != E; ++I) {
assert(!(*I)->isDependentType() &&
"Should not see dependent types here!");
- if (const CXXMethodDecl *KeyFunction = Context.getCurrentKeyFunction(*I)) {
- const FunctionDecl *Definition = 0;
+ if (const CXXMethodDecl *KeyFunction =
+ Context.getCurrentKeyFunction(*I)) {
+ const FunctionDecl *Definition = nullptr;
if (KeyFunction->hasBody(Definition))
MarkVTableUsed(Definition->getLocation(), *I, true);
}
@@ -603,7 +638,15 @@ void Sema::ActOnEndOfTranslationUnit() {
// so it will find some names that are not required to be found. This is
// valid, but we could do better by diagnosing if an instantiation uses a
// name that was not visible at its first point of instantiation.
+ if (ExternalSource) {
+ // Load pending instantiations from the external source.
+ SmallVector<PendingImplicitInstantiation, 4> Pending;
+ ExternalSource->ReadPendingInstantiations(Pending);
+ PendingInstantiations.insert(PendingInstantiations.begin(),
+ Pending.begin(), Pending.end());
+ }
PerformPendingInstantiations();
+
CheckDelayedMemberExceptionSpecs();
}
@@ -614,14 +657,14 @@ void Sema::ActOnEndOfTranslationUnit() {
// Remove file scoped decls that turned out to be used.
UnusedFileScopedDecls.erase(
- std::remove_if(UnusedFileScopedDecls.begin(0, true),
+ std::remove_if(UnusedFileScopedDecls.begin(nullptr, true),
UnusedFileScopedDecls.end(),
std::bind1st(std::ptr_fun(ShouldRemoveFromUnused), this)),
UnusedFileScopedDecls.end());
if (TUKind == TU_Prefix) {
// Translation unit prefixes don't need any of the checking below.
- TUScope = 0;
+ TUScope = nullptr;
return;
}
@@ -639,9 +682,7 @@ void Sema::ActOnEndOfTranslationUnit() {
}
if (LangOpts.CPlusPlus11 &&
- Diags.getDiagnosticLevel(diag::warn_delegating_ctor_cycle,
- SourceLocation())
- != DiagnosticsEngine::Ignored)
+ !Diags.isIgnored(diag::warn_delegating_ctor_cycle, SourceLocation()))
CheckDelegatingCtorCycles();
if (TUKind == TU_Module) {
@@ -673,7 +714,7 @@ void Sema::ActOnEndOfTranslationUnit() {
}
// Modules don't need any of the checking below.
- TUScope = 0;
+ TUScope = nullptr;
return;
}
@@ -699,7 +740,7 @@ void Sema::ActOnEndOfTranslationUnit() {
// If the tentative definition was completed, getActingDefinition() returns
// null. If we've already seen this variable before, insert()'s second
// return value is false.
- if (VD == 0 || VD->isInvalidDecl() || !Seen.insert(VD))
+ if (!VD || VD->isInvalidDecl() || !Seen.insert(VD))
continue;
if (const IncompleteArrayType *ArrayT
@@ -781,9 +822,7 @@ void Sema::ActOnEndOfTranslationUnit() {
checkUndefinedButUsed(*this);
}
- if (Diags.getDiagnosticLevel(diag::warn_unused_private_field,
- SourceLocation())
- != DiagnosticsEngine::Ignored) {
+ if (!Diags.isIgnored(diag::warn_unused_private_field, SourceLocation())) {
RecordCompleteMap RecordsComplete;
RecordCompleteMap MNCComplete;
for (NamedDeclSetType::iterator I = UnusedPrivateFields.begin(),
@@ -804,7 +843,7 @@ void Sema::ActOnEndOfTranslationUnit() {
assert(ParsingInitForAutoVars.empty() &&
"Didn't unmark var as having its initializer parsed");
- TUScope = 0;
+ TUScope = nullptr;
}
@@ -848,7 +887,7 @@ NamedDecl *Sema::getCurFunctionOrMethodDecl() {
DeclContext *DC = getFunctionLevelDeclContext();
if (isa<ObjCMethodDecl>(DC) || isa<FunctionDecl>(DC))
return cast<NamedDecl>(DC);
- return 0;
+ return nullptr;
}
void Sema::EmitCurrentDiagnostic(unsigned DiagID) {
@@ -996,7 +1035,7 @@ bool Sema::findMacroSpelling(SourceLocation &locref, StringRef name) {
Scope *Sema::getScopeForContext(DeclContext *Ctx) {
if (!Ctx)
- return 0;
+ return nullptr;
Ctx = Ctx->getPrimaryContext();
for (Scope *S = getCurScope(); S; S = S->getParent()) {
@@ -1008,7 +1047,7 @@ Scope *Sema::getScopeForContext(DeclContext *Ctx) {
return S;
}
- return 0;
+ return nullptr;
}
/// \brief Enter a new function scope
@@ -1052,19 +1091,12 @@ void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
// Issue any analysis-based warnings.
if (WP && D)
AnalysisWarnings.IssueWarnings(*WP, Scope, D, blkExpr);
- else {
- for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
- i = Scope->PossiblyUnreachableDiags.begin(),
- e = Scope->PossiblyUnreachableDiags.end();
- i != e; ++i) {
- const sema::PossiblyUnreachableDiag &D = *i;
- Diag(D.Loc, D.PD);
- }
- }
+ else
+ for (const auto &PUD : Scope->PossiblyUnreachableDiags)
+ Diag(PUD.Loc, PUD.PD);
- if (FunctionScopes.back() != Scope) {
+ if (FunctionScopes.back() != Scope)
delete Scope;
- }
}
void Sema::PushCompoundScope() {
@@ -1086,25 +1118,41 @@ bool Sema::hasAnyUnrecoverableErrorsInThisFunction() const {
BlockScopeInfo *Sema::getCurBlock() {
if (FunctionScopes.empty())
- return 0;
+ return nullptr;
+
+ auto CurBSI = dyn_cast<BlockScopeInfo>(FunctionScopes.back());
+ if (CurBSI && CurBSI->TheDecl &&
+ !CurBSI->TheDecl->Encloses(CurContext)) {
+ // We have switched contexts due to template instantiation.
+ assert(!ActiveTemplateInstantiations.empty());
+ return nullptr;
+ }
- return dyn_cast<BlockScopeInfo>(FunctionScopes.back());
+ return CurBSI;
}
LambdaScopeInfo *Sema::getCurLambda() {
if (FunctionScopes.empty())
- return 0;
+ return nullptr;
+
+ auto CurLSI = dyn_cast<LambdaScopeInfo>(FunctionScopes.back());
+ if (CurLSI && CurLSI->Lambda &&
+ !CurLSI->Lambda->Encloses(CurContext)) {
+ // We have switched contexts due to template instantiation.
+ assert(!ActiveTemplateInstantiations.empty());
+ return nullptr;
+ }
- return dyn_cast<LambdaScopeInfo>(FunctionScopes.back());
+ return CurLSI;
}
// We have a generic lambda if we parsed auto parameters, or we have
// an associated template parameter list.
LambdaScopeInfo *Sema::getCurGenericLambda() {
if (LambdaScopeInfo *LSI = getCurLambda()) {
return (LSI->AutoTemplateParams.size() ||
- LSI->GLTemplateParameterList) ? LSI : 0;
+ LSI->GLTemplateParameterList) ? LSI : nullptr;
}
- return 0;
+ return nullptr;
}
@@ -1182,7 +1230,7 @@ bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
ZeroArgCallReturnTy = QualType();
OverloadSet.clear();
- const OverloadExpr *Overloads = NULL;
+ const OverloadExpr *Overloads = nullptr;
bool IsMemExpr = false;
if (E.getType() == Context.OverloadTy) {
OverloadExpr::FindResult FR = OverloadExpr::find(const_cast<Expr*>(&E));
@@ -1215,7 +1263,7 @@ bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
ZeroArgCallReturnTy = QualType();
Ambiguous = true;
} else
- ZeroArgCallReturnTy = OverloadDecl->getResultType();
+ ZeroArgCallReturnTy = OverloadDecl->getReturnType();
}
}
}
@@ -1231,8 +1279,8 @@ bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
if (IsMemExpr && !E.isTypeDependent()) {
bool Suppress = getDiagnostics().getSuppressAllDiagnostics();
getDiagnostics().setSuppressAllDiagnostics(true);
- ExprResult R = BuildCallToMemberFunction(NULL, &E, SourceLocation(), None,
- SourceLocation());
+ ExprResult R = BuildCallToMemberFunction(nullptr, &E, SourceLocation(),
+ None, SourceLocation());
getDiagnostics().setSuppressAllDiagnostics(Suppress);
if (R.isUsable()) {
ZeroArgCallReturnTy = R.get()->getType();
@@ -1244,7 +1292,7 @@ bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
if (const DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E.IgnoreParens())) {
if (const FunctionDecl *Fun = dyn_cast<FunctionDecl>(DeclRef->getDecl())) {
if (Fun->getMinRequiredArguments() == 0)
- ZeroArgCallReturnTy = Fun->getResultType();
+ ZeroArgCallReturnTy = Fun->getReturnType();
return true;
}
}
@@ -1252,7 +1300,7 @@ bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
// We don't have an expression that's convenient to get a FunctionDecl from,
// but we can at least check if the type is "function of 0 arguments".
QualType ExprTy = E.getType();
- const FunctionType *FunTy = NULL;
+ const FunctionType *FunTy = nullptr;
QualType PointeeTy = ExprTy->getPointeeType();
if (!PointeeTy.isNull())
FunTy = PointeeTy->getAs<FunctionType>();
@@ -1261,8 +1309,8 @@ bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
if (const FunctionProtoType *FPT =
dyn_cast_or_null<FunctionProtoType>(FunTy)) {
- if (FPT->getNumArgs() == 0)
- ZeroArgCallReturnTy = FunTy->getResultType();
+ if (FPT->getNumParams() == 0)
+ ZeroArgCallReturnTy = FunTy->getReturnType();
return true;
}
return false;
@@ -1313,7 +1361,7 @@ static void notePlausibleOverloads(Sema &S, SourceLocation Loc,
for (OverloadExpr::decls_iterator It = Overloads.begin(),
DeclsEnd = Overloads.end(); It != DeclsEnd; ++It) {
const FunctionDecl *OverloadDecl = cast<FunctionDecl>(*It);
- QualType OverloadResultTy = OverloadDecl->getResultType();
+ QualType OverloadResultTy = OverloadDecl->getReturnType();
if (IsPlausibleResult(OverloadResultTy))
PlausibleOverloads.addDecl(It.getDecl());
}
@@ -1357,7 +1405,7 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
// FIXME: Try this before emitting the fixit, and suppress diagnostics
// while doing so.
- E = ActOnCallExpr(0, E.take(), Range.getEnd(), None,
+ E = ActOnCallExpr(nullptr, E.get(), Range.getEnd(), None,
Range.getEnd().getLocWithOffset(1));
return true;
}
@@ -1392,7 +1440,7 @@ void Sema::PushCapturedRegionScope(Scope *S, CapturedDecl *CD, RecordDecl *RD,
CapturedRegionScopeInfo *Sema::getCurCapturedRegion() {
if (FunctionScopes.empty())
- return 0;
+ return nullptr;
return dyn_cast<CapturedRegionScopeInfo>(FunctionScopes.back());
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp
index 61dc157..ffdb0aa 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp
@@ -78,7 +78,7 @@ static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) {
namespace {
struct EffectiveContext {
- EffectiveContext() : Inner(0), Dependent(false) {}
+ EffectiveContext() : Inner(nullptr), Dependent(false) {}
explicit EffectiveContext(DeclContext *DC)
: Inner(DC),
@@ -209,7 +209,8 @@ struct AccessTarget : public AccessedEntity {
CalculatedInstanceContext = true;
DeclContext *IC = S.computeDeclContext(getBaseObjectType());
- InstanceContext = (IC ? cast<CXXRecordDecl>(IC)->getCanonicalDecl() : 0);
+ InstanceContext = (IC ? cast<CXXRecordDecl>(IC)->getCanonicalDecl()
+ : nullptr);
return InstanceContext;
}
@@ -232,7 +233,7 @@ private:
!getBaseObjectType().isNull() &&
getTargetDecl()->isCXXInstanceMember());
CalculatedInstanceContext = false;
- InstanceContext = 0;
+ InstanceContext = nullptr;
if (isMemberAccess())
DeclaringClass = FindDeclaringClass(getTargetDecl());
@@ -288,12 +289,10 @@ static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived,
if (Derived->isDependentContext() && !Derived->hasDefinition())
return AR_dependent;
- for (CXXRecordDecl::base_class_const_iterator
- I = Derived->bases_begin(), E = Derived->bases_end(); I != E; ++I) {
-
+ for (const auto &I : Derived->bases()) {
const CXXRecordDecl *RD;
- QualType T = I->getType();
+ QualType T = I.getType();
if (const RecordType *RT = T->getAs<RecordType>()) {
RD = cast<CXXRecordDecl>(RT->getDecl());
} else if (const InjectedClassNameType *IT
@@ -376,18 +375,16 @@ static bool MightInstantiateTo(Sema &S,
if (FriendTy.getQualifiers() != ContextTy.getQualifiers())
return false;
- if (FriendTy->getNumArgs() != ContextTy->getNumArgs())
+ if (FriendTy->getNumParams() != ContextTy->getNumParams())
return false;
- if (!MightInstantiateTo(S,
- ContextTy->getResultType(),
- FriendTy->getResultType()))
+ if (!MightInstantiateTo(S, ContextTy->getReturnType(),
+ FriendTy->getReturnType()))
return false;
- for (unsigned I = 0, E = FriendTy->getNumArgs(); I != E; ++I)
- if (!MightInstantiateTo(S,
- ContextTy->getArgType(I),
- FriendTy->getArgType(I)))
+ for (unsigned I = 0, E = FriendTy->getNumParams(); I != E; ++I)
+ if (!MightInstantiateTo(S, ContextTy->getParamType(I),
+ FriendTy->getParamType(I)))
return false;
return true;
@@ -575,10 +572,7 @@ static AccessResult GetFriendKind(Sema &S,
AccessResult OnFailure = AR_inaccessible;
// Okay, check friends.
- for (CXXRecordDecl::friend_iterator I = Class->friend_begin(),
- E = Class->friend_end(); I != E; ++I) {
- FriendDecl *Friend = *I;
-
+ for (auto *Friend : Class->friends()) {
switch (MatchesFriend(S, EC, Friend)) {
case AR_accessible:
return AR_accessible;
@@ -648,18 +642,16 @@ struct ProtectedFriendContext {
EverDependent = true;
// Recurse into the base classes.
- for (CXXRecordDecl::base_class_const_iterator
- I = Cur->bases_begin(), E = Cur->bases_end(); I != E; ++I) {
-
+ for (const auto &I : Cur->bases()) {
// If this is private inheritance, then a public member of the
// base will not have any access in classes derived from Cur.
unsigned BasePrivateDepth = PrivateDepth;
- if (I->getAccessSpecifier() == AS_private)
+ if (I.getAccessSpecifier() == AS_private)
BasePrivateDepth = CurPath.size() - 1;
const CXXRecordDecl *RD;
- QualType T = I->getType();
+ QualType T = I.getType();
if (const RecordType *RT = T->getAs<RecordType>()) {
RD = cast<CXXRecordDecl>(RT->getDecl());
} else if (const InjectedClassNameType *IT
@@ -718,7 +710,7 @@ struct ProtectedFriendContext {
static AccessResult GetProtectedFriendKind(Sema &S, const EffectiveContext &EC,
const CXXRecordDecl *InstanceContext,
const CXXRecordDecl *NamingClass) {
- assert(InstanceContext == 0 ||
+ assert(InstanceContext == nullptr ||
InstanceContext->getCanonicalDecl() == InstanceContext);
assert(NamingClass->getCanonicalDecl() == NamingClass);
@@ -797,7 +789,7 @@ static AccessResult HasAccess(Sema &S,
// Emulate a MSVC bug where the creation of pointer-to-member
// to protected member of base class is allowed but only from
// static member functions.
- if (S.getLangOpts().MicrosoftMode && !EC.Functions.empty())
+ if (S.getLangOpts().MSVCCompat && !EC.Functions.empty())
if (CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(EC.Functions.front()))
if (MD->isStatic()) return AR_accessible;
@@ -851,7 +843,7 @@ static AccessResult HasAccess(Sema &S,
// and instead rely on whether any potential P is a friend.
if (Access == AS_protected && Target.isInstanceMember()) {
// Compute the instance context if possible.
- const CXXRecordDecl *InstanceContext = 0;
+ const CXXRecordDecl *InstanceContext = nullptr;
if (Target.hasInstanceContext()) {
InstanceContext = Target.resolveInstanceContext(S);
if (!InstanceContext) return AR_dependent;
@@ -946,7 +938,7 @@ static CXXBasePath *FindBestPath(Sema &S,
assert(isDerived && "derived class not actually derived from base");
(void) isDerived;
- CXXBasePath *BestPath = 0;
+ CXXBasePath *BestPath = nullptr;
assert(FinalAccess != AS_none && "forbidden access after declaring class");
@@ -995,7 +987,7 @@ static CXXBasePath *FindBestPath(Sema &S,
// Note that we modify the path's Access field to the
// friend-modified access.
- if (BestPath == 0 || PathAccess < BestPath->Access) {
+ if (BestPath == nullptr || PathAccess < BestPath->Access) {
BestPath = &*PI;
BestPath->Access = PathAccess;
@@ -1013,7 +1005,7 @@ static CXXBasePath *FindBestPath(Sema &S,
// We didn't find a public path, but at least one path was subject
// to dependent friendship, so delay the check.
if (AnyDependent)
- return 0;
+ return nullptr;
return BestPath;
}
@@ -1082,15 +1074,15 @@ static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC,
(isa<FunctionTemplateDecl>(D) &&
isa<CXXConstructorDecl>(
cast<FunctionTemplateDecl>(D)->getTemplatedDecl()))) {
- S.Diag(D->getLocation(), diag::note_access_protected_restricted_ctordtor)
- << isa<CXXDestructorDecl>(D);
- return true;
+ return S.Diag(D->getLocation(),
+ diag::note_access_protected_restricted_ctordtor)
+ << isa<CXXDestructorDecl>(D->getAsFunction());
}
// Otherwise, use the generic diagnostic.
- S.Diag(D->getLocation(), diag::note_access_protected_restricted_object)
- << S.Context.getTypeDeclType(ECRecord);
- return true;
+ return S.Diag(D->getLocation(),
+ diag::note_access_protected_restricted_object)
+ << S.Context.getTypeDeclType(ECRecord);
}
return false;
@@ -1110,7 +1102,7 @@ static void diagnoseBadDirectAccess(Sema &S,
// Find an original declaration.
while (D->isOutOfLine()) {
- NamedDecl *PrevDecl = 0;
+ NamedDecl *PrevDecl = nullptr;
if (VarDecl *VD = dyn_cast<VarDecl>(D))
PrevDecl = VD->getPreviousDecl();
else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
@@ -1140,11 +1132,9 @@ static void diagnoseBadDirectAccess(Sema &S,
// Check whether there's an AccessSpecDecl preceding this in the
// chain of the DeclContext.
bool isImplicit = true;
- for (CXXRecordDecl::decl_iterator
- I = DeclaringClass->decls_begin(), E = DeclaringClass->decls_end();
- I != E; ++I) {
- if (*I == ImmediateChild) break;
- if (isa<AccessSpecDecl>(*I)) {
+ for (const auto *I : DeclaringClass->decls()) {
+ if (I == ImmediateChild) break;
+ if (isa<AccessSpecDecl>(I)) {
isImplicit = false;
break;
}
@@ -1223,7 +1213,7 @@ static void DiagnoseAccessPath(Sema &S,
case AR_accessible:
accessSoFar = AS_public;
entity.suppressInstanceContext();
- constrainingBase = 0;
+ constrainingBase = nullptr;
break;
case AR_dependent:
llvm_unreachable("cannot diagnose dependent access");
@@ -1262,7 +1252,8 @@ static void DiagnoseAccessPath(Sema &S,
<< (base->getAccessSpecifierAsWritten() == AS_none);
if (entity.isMemberAccess())
- S.Diag(entity.getTargetDecl()->getLocation(), diag::note_field_decl);
+ S.Diag(entity.getTargetDecl()->getLocation(),
+ diag::note_member_declared_at);
}
static void DiagnoseBadAccess(Sema &S, SourceLocation Loc,
@@ -1270,7 +1261,7 @@ static void DiagnoseBadAccess(Sema &S, SourceLocation Loc,
AccessTarget &Entity) {
const CXXRecordDecl *NamingClass = Entity.getNamingClass();
const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
- NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0);
+ NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : nullptr);
S.Diag(Loc, Entity.getDiag())
<< (Entity.getAccess() == AS_protected)
@@ -1422,16 +1413,15 @@ static AccessResult CheckEffectiveAccess(Sema &S,
AccessTarget &Entity) {
assert(Entity.getAccess() != AS_public && "called for public access!");
- if (S.getLangOpts().MicrosoftMode &&
- IsMicrosoftUsingDeclarationAccessBug(S, Loc, Entity))
- return AR_accessible;
-
switch (IsAccessible(S, EC, Entity)) {
case AR_dependent:
DelayDependentAccess(S, EC, Loc, Entity);
return AR_dependent;
case AR_inaccessible:
+ if (S.getLangOpts().MSVCCompat &&
+ IsMicrosoftUsingDeclarationAccessBug(S, Loc, Entity))
+ return AR_accessible;
if (!Entity.isQuiet())
DiagnoseBadAccess(S, Loc, EC, Entity);
return AR_inaccessible;
@@ -1482,11 +1472,10 @@ void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *D) {
// However, this does not apply to local extern declarations.
DeclContext *DC = D->getDeclContext();
- if (FunctionDecl *FN = dyn_cast<FunctionDecl>(D)) {
- if (D->getLexicalDeclContext()->isFunctionOrMethod())
- DC = D->getLexicalDeclContext();
- else
- DC = FN;
+ if (D->isLocalExternDecl()) {
+ DC = D->getLexicalDeclContext();
+ } else if (FunctionDecl *FN = dyn_cast<FunctionDecl>(D)) {
+ DC = FN;
} else if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) {
DC = cast<DeclContext>(TD->getTemplatedDecl());
}
@@ -1750,10 +1739,7 @@ Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
/// Checks access to the target of a friend declaration.
Sema::AccessResult Sema::CheckFriendAccess(NamedDecl *target) {
- assert(isa<CXXMethodDecl>(target) ||
- (isa<FunctionTemplateDecl>(target) &&
- isa<CXXMethodDecl>(cast<FunctionTemplateDecl>(target)
- ->getTemplatedDecl())));
+ assert(isa<CXXMethodDecl>(target->getAsFunction()));
// Friendship lookup is a redeclaration lookup, so there's never an
// inheritance path modifying access.
@@ -1762,10 +1748,7 @@ Sema::AccessResult Sema::CheckFriendAccess(NamedDecl *target) {
if (!getLangOpts().AccessControl || access == AS_public)
return AR_accessible;
- CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(target);
- if (!method)
- method = cast<CXXMethodDecl>(
- cast<FunctionTemplateDecl>(target)->getTemplatedDecl());
+ CXXMethodDecl *method = cast<CXXMethodDecl>(target->getAsFunction());
assert(method->getQualifier());
AccessTarget entity(Context, AccessTarget::Member,
@@ -1891,7 +1874,7 @@ bool Sema::IsSimplyAccessible(NamedDecl *Decl, DeclContext *Ctx) {
// If we are inside a class or category implementation, determine the
// interface we're in.
- ObjCInterfaceDecl *ClassOfMethodDecl = 0;
+ ObjCInterfaceDecl *ClassOfMethodDecl = nullptr;
if (ObjCMethodDecl *MD = getCurMethodDecl())
ClassOfMethodDecl = MD->getClassInterface();
else if (FunctionDecl *FD = getCurFunctionDecl()) {
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp
index 8f9ab32..a7d606d 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp
@@ -109,7 +109,7 @@ bool PragmaPackStack::pop(IdentifierInfo *Name, bool IsReset) {
/// FreePackedContext - Deallocate and null out PackContext.
void Sema::FreePackedContext() {
delete static_cast<PragmaPackStack*>(PackContext);
- PackContext = 0;
+ PackContext = nullptr;
}
void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
@@ -122,23 +122,28 @@ void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
// Otherwise, check to see if we need a max field alignment attribute.
if (unsigned Alignment = Stack->getAlignment()) {
if (Alignment == PackStackEntry::kMac68kAlignmentSentinel)
- RD->addAttr(::new (Context) AlignMac68kAttr(SourceLocation(), Context));
+ RD->addAttr(AlignMac68kAttr::CreateImplicit(Context));
else
- RD->addAttr(::new (Context) MaxFieldAlignmentAttr(SourceLocation(),
- Context,
+ RD->addAttr(MaxFieldAlignmentAttr::CreateImplicit(Context,
Alignment * 8));
}
}
void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) {
- if (!MSStructPragmaOn)
- return;
- RD->addAttr(::new (Context) MsStructAttr(SourceLocation(), Context));
+ if (MSStructPragmaOn)
+ RD->addAttr(MsStructAttr::CreateImplicit(Context));
+
+ // FIXME: We should merge AddAlignmentAttributesForRecord with
+ // AddMsStructLayoutForRecord into AddPragmaAttributesForRecord, which takes
+ // all active pragmas and applies them as attributes to class definitions.
+ if (VtorDispModeStack.back() != getLangOpts().VtorDispMode)
+ RD->addAttr(
+ MSVtorDispAttr::CreateImplicit(Context, VtorDispModeStack.back()));
}
void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
SourceLocation PragmaLoc) {
- if (PackContext == 0)
+ if (!PackContext)
PackContext = new PragmaPackStack();
PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
@@ -150,31 +155,31 @@ void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
case POAK_Native:
case POAK_Power:
case POAK_Natural:
- Context->push(0);
+ Context->push(nullptr);
Context->setAlignment(0);
break;
// Note that '#pragma options align=packed' is not equivalent to attribute
// packed, it has a different precedence relative to attribute aligned.
case POAK_Packed:
- Context->push(0);
+ Context->push(nullptr);
Context->setAlignment(1);
break;
case POAK_Mac68k:
// Check if the target supports this.
- if (!PP.getTargetInfo().hasAlignMac68kSupport()) {
+ if (!this->Context.getTargetInfo().hasAlignMac68kSupport()) {
Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported);
return;
}
- Context->push(0);
+ Context->push(nullptr);
Context->setAlignment(PackStackEntry::kMac68kAlignmentSentinel);
break;
case POAK_Reset:
// Reset just pops the top of the stack, or resets the current alignment to
// default.
- if (!Context->pop(0, /*IsReset=*/true)) {
+ if (!Context->pop(nullptr, /*IsReset=*/true)) {
Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
<< "stack empty";
}
@@ -206,7 +211,7 @@ void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
AlignmentVal = (unsigned) Val.getZExtValue();
}
- if (PackContext == 0)
+ if (!PackContext)
PackContext = new PragmaPackStack();
PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
@@ -247,8 +252,8 @@ void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
// If a name was specified then failure indicates the name
// wasn't found. Otherwise failure indicates the stack was
// empty.
- Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed)
- << (Name ? "no record matching name" : "stack empty");
+ Diag(PragmaLoc, diag::warn_pragma_pop_failed)
+ << "pack" << (Name ? "no record matching name" : "stack empty");
// FIXME: Warn about popping named records as MSVC does.
} else {
@@ -288,12 +293,159 @@ void Sema::ActOnPragmaDetectMismatch(StringRef Name, StringRef Value) {
Consumer.HandleDetectMismatch(Name, Value);
}
+void Sema::ActOnPragmaMSPointersToMembers(
+ LangOptions::PragmaMSPointersToMembersKind RepresentationMethod,
+ SourceLocation PragmaLoc) {
+ MSPointerToMemberRepresentationMethod = RepresentationMethod;
+ ImplicitMSInheritanceAttrLoc = PragmaLoc;
+}
+
+void Sema::ActOnPragmaMSVtorDisp(PragmaVtorDispKind Kind,
+ SourceLocation PragmaLoc,
+ MSVtorDispAttr::Mode Mode) {
+ switch (Kind) {
+ case PVDK_Set:
+ VtorDispModeStack.back() = Mode;
+ break;
+ case PVDK_Push:
+ VtorDispModeStack.push_back(Mode);
+ break;
+ case PVDK_Reset:
+ VtorDispModeStack.clear();
+ VtorDispModeStack.push_back(MSVtorDispAttr::Mode(LangOpts.VtorDispMode));
+ break;
+ case PVDK_Pop:
+ VtorDispModeStack.pop_back();
+ if (VtorDispModeStack.empty()) {
+ Diag(PragmaLoc, diag::warn_pragma_pop_failed) << "vtordisp"
+ << "stack empty";
+ VtorDispModeStack.push_back(MSVtorDispAttr::Mode(LangOpts.VtorDispMode));
+ }
+ break;
+ }
+}
+
+template<typename ValueType>
+void Sema::PragmaStack<ValueType>::Act(SourceLocation PragmaLocation,
+ PragmaMsStackAction Action,
+ llvm::StringRef StackSlotLabel,
+ ValueType Value) {
+ if (Action == PSK_Reset) {
+ CurrentValue = nullptr;
+ return;
+ }
+ if (Action & PSK_Push)
+ Stack.push_back(Slot(StackSlotLabel, CurrentValue, CurrentPragmaLocation));
+ else if (Action & PSK_Pop) {
+ if (!StackSlotLabel.empty()) {
+ // If we've got a label, try to find it and jump there.
+ auto I = std::find_if(Stack.rbegin(), Stack.rend(),
+ [&](const Slot &x) { return x.StackSlotLabel == StackSlotLabel; });
+ // If we found the label so pop from there.
+ if (I != Stack.rend()) {
+ CurrentValue = I->Value;
+ CurrentPragmaLocation = I->PragmaLocation;
+ Stack.erase(std::prev(I.base()), Stack.end());
+ }
+ } else if (!Stack.empty()) {
+ // We don't have a label, just pop the last entry.
+ CurrentValue = Stack.back().Value;
+ CurrentPragmaLocation = Stack.back().PragmaLocation;
+ Stack.pop_back();
+ }
+ }
+ if (Action & PSK_Set) {
+ CurrentValue = Value;
+ CurrentPragmaLocation = PragmaLocation;
+ }
+}
+
+bool Sema::UnifySection(const StringRef &SectionName,
+ int SectionFlags,
+ DeclaratorDecl *Decl) {
+ auto Section = SectionInfos.find(SectionName);
+ if (Section == SectionInfos.end()) {
+ SectionInfos[SectionName] =
+ SectionInfo(Decl, SourceLocation(), SectionFlags);
+ return false;
+ }
+ // A pre-declared section takes precedence w/o diagnostic.
+ if (Section->second.SectionFlags == SectionFlags ||
+ !(Section->second.SectionFlags & PSF_Implicit))
+ return false;
+ auto OtherDecl = Section->second.Decl;
+ Diag(Decl->getLocation(), diag::err_section_conflict)
+ << Decl << OtherDecl;
+ Diag(OtherDecl->getLocation(), diag::note_declared_at)
+ << OtherDecl->getName();
+ if (auto A = Decl->getAttr<SectionAttr>())
+ if (A->isImplicit())
+ Diag(A->getLocation(), diag::note_pragma_entered_here);
+ if (auto A = OtherDecl->getAttr<SectionAttr>())
+ if (A->isImplicit())
+ Diag(A->getLocation(), diag::note_pragma_entered_here);
+ return false;
+}
+
+bool Sema::UnifySection(const StringRef &SectionName,
+ int SectionFlags,
+ SourceLocation PragmaSectionLocation) {
+ auto Section = SectionInfos.find(SectionName);
+ if (Section != SectionInfos.end()) {
+ if (Section->second.SectionFlags == SectionFlags)
+ return false;
+ if (!(Section->second.SectionFlags & PSF_Implicit)) {
+ Diag(PragmaSectionLocation, diag::err_section_conflict)
+ << "this" << "a prior #pragma section";
+ Diag(Section->second.PragmaSectionLocation,
+ diag::note_pragma_entered_here);
+ return true;
+ }
+ }
+ SectionInfos[SectionName] =
+ SectionInfo(nullptr, PragmaSectionLocation, SectionFlags);
+ return false;
+}
+
+/// \brief Called on well formed \#pragma bss_seg().
+void Sema::ActOnPragmaMSSeg(SourceLocation PragmaLocation,
+ PragmaMsStackAction Action,
+ llvm::StringRef StackSlotLabel,
+ StringLiteral *SegmentName,
+ llvm::StringRef PragmaName) {
+ PragmaStack<StringLiteral *> *Stack =
+ llvm::StringSwitch<PragmaStack<StringLiteral *> *>(PragmaName)
+ .Case("data_seg", &DataSegStack)
+ .Case("bss_seg", &BSSSegStack)
+ .Case("const_seg", &ConstSegStack)
+ .Case("code_seg", &CodeSegStack);
+ if (Action & PSK_Pop && Stack->Stack.empty())
+ Diag(PragmaLocation, diag::warn_pragma_pop_failed) << PragmaName
+ << "stack empty";
+ Stack->Act(PragmaLocation, Action, StackSlotLabel, SegmentName);
+}
+
+/// \brief Called on well formed \#pragma bss_seg().
+void Sema::ActOnPragmaMSSection(SourceLocation PragmaLocation,
+ int SectionFlags, StringLiteral *SegmentName) {
+ UnifySection(SegmentName->getString(), SectionFlags, PragmaLocation);
+}
+
+void Sema::ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,
+ StringLiteral *SegmentName) {
+ // There's no stack to maintain, so we just have a current section. When we
+ // see the default section, reset our current section back to null so we stop
+ // tacking on unnecessary attributes.
+ CurInitSeg = SegmentName->getString() == ".CRT$XCU" ? nullptr : SegmentName;
+ CurInitSegLoc = PragmaLocation;
+}
+
void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
SourceLocation PragmaLoc) {
IdentifierInfo *Name = IdTok.getIdentifierInfo();
LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName);
- LookupParsedName(Lookup, curScope, NULL, true);
+ LookupParsedName(Lookup, curScope, nullptr, true);
if (Lookup.empty()) {
Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
@@ -312,7 +464,7 @@ void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
if (VD->isUsed())
Diag(PragmaLoc, diag::warn_used_but_marked_unused) << Name;
- VD->addAttr(::new (Context) UnusedAttr(IdTok.getLocation(), Context));
+ VD->addAttr(UnusedAttr::CreateImplicit(Context, IdTok.getLocation()));
}
void Sema::AddCFAuditedAttribute(Decl *D) {
@@ -324,11 +476,39 @@ void Sema::AddCFAuditedAttribute(Decl *D) {
D->hasAttr<CFUnknownTransferAttr>())
return;
- D->addAttr(::new (Context) CFAuditedTransferAttr(Loc, Context));
+ D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Loc));
+}
+
+void Sema::ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc) {
+ if(On)
+ OptimizeOffPragmaLocation = SourceLocation();
+ else
+ OptimizeOffPragmaLocation = PragmaLoc;
+}
+
+void Sema::AddRangeBasedOptnone(FunctionDecl *FD) {
+ // In the future, check other pragmas if they're implemented (e.g. pragma
+ // optimize 0 will probably map to this functionality too).
+ if(OptimizeOffPragmaLocation.isValid())
+ AddOptnoneAttributeIfNoConflicts(FD, OptimizeOffPragmaLocation);
+}
+
+void Sema::AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD,
+ SourceLocation Loc) {
+ // Don't add a conflicting attribute. No diagnostic is needed.
+ if (FD->hasAttr<MinSizeAttr>() || FD->hasAttr<AlwaysInlineAttr>())
+ return;
+
+ // Add attributes only if required. Optnone requires noinline as well, but if
+ // either is already present then don't bother adding them.
+ if (!FD->hasAttr<OptimizeNoneAttr>())
+ FD->addAttr(OptimizeNoneAttr::CreateImplicit(Context, Loc));
+ if (!FD->hasAttr<NoInlineAttr>())
+ FD->addAttr(NoInlineAttr::CreateImplicit(Context, Loc));
}
typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack;
-enum { NoVisibility = (unsigned) -1 };
+enum : unsigned { NoVisibility = ~0U };
void Sema::AddPushedVisibilityAttribute(Decl *D) {
if (!VisContext)
@@ -346,13 +526,13 @@ void Sema::AddPushedVisibilityAttribute(Decl *D) {
= (VisibilityAttr::VisibilityType) rawType;
SourceLocation loc = Stack->back().second;
- D->addAttr(::new (Context) VisibilityAttr(loc, Context, type));
+ D->addAttr(VisibilityAttr::CreateImplicit(Context, type, loc));
}
/// FreeVisContext - Deallocate and null out VisContext.
void Sema::FreeVisContext() {
delete static_cast<VisStack*>(VisContext);
- VisContext = 0;
+ VisContext = nullptr;
}
static void PushPragmaVisibility(Sema &S, unsigned type, SourceLocation loc) {
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
index 554a114..a70aca2 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -29,7 +29,7 @@ using namespace clang;
static CXXRecordDecl *getCurrentInstantiationOf(QualType T,
DeclContext *CurContext) {
if (T.isNull())
- return 0;
+ return nullptr;
const Type *Ty = T->getCanonicalTypeInternal().getTypePtr();
if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
@@ -38,11 +38,11 @@ static CXXRecordDecl *getCurrentInstantiationOf(QualType T,
Record->isCurrentInstantiation(CurContext))
return Record;
- return 0;
+ return nullptr;
} else if (isa<InjectedClassNameType>(Ty))
return cast<InjectedClassNameType>(Ty)->getDecl();
else
- return 0;
+ return nullptr;
}
/// \brief Compute the DeclContext that is associated with the given type.
@@ -76,7 +76,7 @@ DeclContext *Sema::computeDeclContext(QualType T) {
DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
bool EnteringContext) {
if (!SS.isSet() || SS.isInvalid())
- return 0;
+ return nullptr;
NestedNameSpecifier *NNS = SS.getScopeRep();
if (NNS->isDependent()) {
@@ -88,7 +88,7 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
if (EnteringContext) {
const Type *NNSType = NNS->getAsType();
if (!NNSType) {
- return 0;
+ return nullptr;
}
// Look through type alias templates, per C++0x [temp.dep.type]p1.
@@ -126,7 +126,7 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
}
}
- return 0;
+ return nullptr;
}
switch (NNS->getKind()) {
@@ -170,7 +170,7 @@ CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier *NNS) {
assert(NNS->isDependent() && "Only dependent nested-name-specifier allowed");
if (!NNS->getAsType())
- return 0;
+ return nullptr;
QualType T = QualType(NNS->getAsType(), 0);
return ::getCurrentInstantiationOf(T, CurContext);
@@ -187,7 +187,7 @@ CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier *NNS) {
/// will attempt to instantiate that class template.
bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
DeclContext *DC) {
- assert(DC != 0 && "given null context");
+ assert(DC && "given null context");
TagDecl *tag = dyn_cast<TagDecl>(DC);
@@ -282,13 +282,13 @@ bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD) {
/// name lookup.
NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) {
if (!S || !NNS)
- return 0;
+ return nullptr;
while (NNS->getPrefix())
NNS = NNS->getPrefix();
if (NNS->getKind() != NestedNameSpecifier::Identifier)
- return 0;
+ return nullptr;
LookupResult Found(*this, NNS->getAsIdentifier(), SourceLocation(),
LookupNestedNameSpecifierName);
@@ -296,13 +296,13 @@ NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) {
assert(!Found.isAmbiguous() && "Cannot handle ambiguities here yet");
if (!Found.isSingleResult())
- return 0;
+ return nullptr;
NamedDecl *Result = Found.getFoundDecl();
if (isAcceptableNestedNameSpecifier(Result))
return Result;
- return 0;
+ return nullptr;
}
bool Sema::isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS,
@@ -313,7 +313,7 @@ bool Sema::isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS,
LookupResult Found(*this, &II, IdLoc, LookupNestedNameSpecifierName);
// Determine where to perform name lookup
- DeclContext *LookupCtx = 0;
+ DeclContext *LookupCtx = nullptr;
bool isDependent = false;
if (!ObjectType.isNull()) {
// This nested-name-specifier occurs in a member access expression, e.g.,
@@ -363,7 +363,7 @@ class NestedNameSpecifierValidatorCCC : public CorrectionCandidateCallback {
explicit NestedNameSpecifierValidatorCCC(Sema &SRef)
: SRef(SRef) {}
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
return SRef.isAcceptableNestedNameSpecifier(candidate.getCorrectionDecl());
}
@@ -377,6 +377,28 @@ class NestedNameSpecifierValidatorCCC : public CorrectionCandidateCallback {
/// by ActOnCXXNestedNameSpecifier.
///
/// This routine differs only slightly from ActOnCXXNestedNameSpecifier, in
+/// that it contains an extra parameter \p ScopeLookupResult.
+///
+/// \param S Scope in which the nested-name-specifier occurs.
+/// \param Identifier Identifier in the sequence "identifier" "::".
+/// \param IdentifierLoc Location of the \p Identifier.
+/// \param CCLoc Location of "::" following Identifier.
+/// \param ObjectType Type of postfix expression if the nested-name-specifier
+/// occurs in construct like: <tt>ptr->nns::f</tt>.
+/// \param EnteringContext If true, enter the context specified by the
+/// nested-name-specifier.
+/// \param SS Optional nested name specifier preceding the identifier.
+/// \param ScopeLookupResult Provides the result of name lookup within the
+/// scope of the nested-name-specifier that was computed at template
+/// definition time.
+/// \param ErrorRecoveryLookup Specifies if the method is called to improve
+/// error recovery and what kind of recovery is performed.
+/// \param IsCorrectedToColon If not null, suggestion of replace '::' -> ':'
+/// are allowed. The bool value pointed by this parameter is set to
+/// 'true' if the identifier is treated as if it was followed by ':',
+/// not '::'.
+///
+/// This routine differs only slightly from ActOnCXXNestedNameSpecifier, in
/// that it contains an extra parameter \p ScopeLookupResult, which provides
/// the result of name lookup within the scope of the nested-name-specifier
/// that was computed at template definition time.
@@ -395,13 +417,16 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
bool EnteringContext,
CXXScopeSpec &SS,
NamedDecl *ScopeLookupResult,
- bool ErrorRecoveryLookup) {
+ bool ErrorRecoveryLookup,
+ bool *IsCorrectedToColon) {
LookupResult Found(*this, &Identifier, IdentifierLoc,
LookupNestedNameSpecifierName);
// Determine where to perform name lookup
- DeclContext *LookupCtx = 0;
+ DeclContext *LookupCtx = nullptr;
bool isDependent = false;
+ if (IsCorrectedToColon)
+ *IsCorrectedToColon = 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.
@@ -416,7 +441,6 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
Found.setContextRange(SS.getRange());
}
-
bool ObjectTypeSearchedInScope = false;
if (LookupCtx) {
// Perform "qualified" name lookup into the declaration context we
@@ -473,18 +497,47 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
// Don't speculate if we're just trying to improve error recovery.
if (ErrorRecoveryLookup)
return true;
-
+
// We were not able to compute the declaration context for a dependent
// base object type or prior nested-name-specifier, so this
// nested-name-specifier refers to an unknown specialization. Just build
// a dependent nested-name-specifier.
SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc);
return false;
- }
-
+ }
+
// FIXME: Deal with ambiguities cleanly.
- if (Found.empty() && !ErrorRecoveryLookup && !getLangOpts().MicrosoftMode) {
+ if (Found.empty() && !ErrorRecoveryLookup) {
+ // If identifier is not found as class-name-or-namespace-name, but is found
+ // as other entity, don't look for typos.
+ LookupResult R(*this, Found.getLookupNameInfo(), LookupOrdinaryName);
+ if (LookupCtx)
+ LookupQualifiedName(R, LookupCtx);
+ else if (S && !isDependent)
+ LookupName(R, S);
+ if (!R.empty()) {
+ // The identifier is found in ordinary lookup. If correction to colon is
+ // allowed, suggest replacement to ':'.
+ if (IsCorrectedToColon) {
+ *IsCorrectedToColon = true;
+ Diag(CCLoc, diag::err_nested_name_spec_is_not_class)
+ << &Identifier << getLangOpts().CPlusPlus
+ << FixItHint::CreateReplacement(CCLoc, ":");
+ if (NamedDecl *ND = R.getAsSingle<NamedDecl>())
+ Diag(ND->getLocation(), diag::note_declared_at);
+ return true;
+ }
+ // Replacement '::' -> ':' is not allowed, just issue respective error.
+ Diag(R.getNameLoc(), diag::err_expected_class_or_namespace)
+ << &Identifier << getLangOpts().CPlusPlus;
+ if (NamedDecl *ND = R.getAsSingle<NamedDecl>())
+ Diag(ND->getLocation(), diag::note_entity_declared_at) << &Identifier;
+ return true;
+ }
+ }
+
+ if (Found.empty() && !ErrorRecoveryLookup && !getLangOpts().MSVCCompat) {
// We haven't found anything, and we're not recovering from a
// different kind of error, so look for typos.
DeclarationName Name = Found.getLookupName();
@@ -492,7 +545,8 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
Found.clear();
if (TypoCorrection Corrected =
CorrectTypo(Found.getLookupNameInfo(), Found.getLookupKind(), S,
- &SS, Validator, LookupCtx, EnteringContext)) {
+ &SS, Validator, CTK_ErrorRecovery, LookupCtx,
+ EnteringContext)) {
if (LookupCtx) {
bool DroppedSpecifier =
Corrected.WillReplaceSpecifier() &&
@@ -543,8 +597,8 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
!Context.hasSameType(
Context.getTypeDeclType(cast<TypeDecl>(OuterDecl)),
Context.getTypeDeclType(cast<TypeDecl>(SD))))) {
- if (ErrorRecoveryLookup)
- return true;
+ if (ErrorRecoveryLookup)
+ return true;
Diag(IdentifierLoc,
diag::err_nested_name_member_ref_lookup_ambiguous)
@@ -558,7 +612,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
}
}
- // If we're just performing this lookup for error-recovery purposes,
+ // If we're just performing this lookup for error-recovery purposes,
// don't extend the nested-name-specifier. Just return now.
if (ErrorRecoveryLookup)
return false;
@@ -646,7 +700,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
// public:
// void foo() { D::foo2(); }
// };
- if (getLangOpts().MicrosoftMode) {
+ if (getLangOpts().MSVCCompat) {
DeclContext *DC = LookupCtx ? LookupCtx : CurContext;
if (DC->isDependentContext() && DC->isFunctionOrMethod()) {
SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc);
@@ -654,20 +708,21 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
}
}
- unsigned DiagID;
- if (!Found.empty())
- DiagID = diag::err_expected_class_or_namespace;
- else if (SS.isSet()) {
- Diag(IdentifierLoc, diag::err_no_member)
- << &Identifier << LookupCtx << SS.getRange();
- return true;
- } else
- DiagID = diag::err_undeclared_var_use;
-
- if (SS.isSet())
- Diag(IdentifierLoc, DiagID) << &Identifier << SS.getRange();
+ if (!Found.empty()) {
+ if (TypeDecl *TD = Found.getAsSingle<TypeDecl>())
+ Diag(IdentifierLoc, diag::err_expected_class_or_namespace)
+ << QualType(TD->getTypeForDecl(), 0) << getLangOpts().CPlusPlus;
+ else {
+ Diag(IdentifierLoc, diag::err_expected_class_or_namespace)
+ << &Identifier << getLangOpts().CPlusPlus;
+ if (NamedDecl *ND = Found.getAsSingle<NamedDecl>())
+ Diag(ND->getLocation(), diag::note_entity_declared_at) << &Identifier;
+ }
+ } else if (SS.isSet())
+ Diag(IdentifierLoc, diag::err_no_member) << &Identifier << LookupCtx
+ << SS.getRange();
else
- Diag(IdentifierLoc, DiagID) << &Identifier;
+ Diag(IdentifierLoc, diag::err_undeclared_var_use) << &Identifier;
return true;
}
@@ -678,14 +733,17 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
SourceLocation CCLoc,
ParsedType ObjectType,
bool EnteringContext,
- CXXScopeSpec &SS) {
+ CXXScopeSpec &SS,
+ bool ErrorRecoveryLookup,
+ bool *IsCorrectedToColon) {
if (SS.isInvalid())
return true;
-
+
return BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, CCLoc,
GetTypeFromParser(ObjectType),
EnteringContext, SS,
- /*ScopeLookupResult=*/0, false);
+ /*ScopeLookupResult=*/nullptr, false,
+ IsCorrectedToColon);
}
bool Sema::ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS,
@@ -698,7 +756,7 @@ bool Sema::ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS,
QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
if (!T->isDependentType() && !T->getAs<TagType>()) {
- Diag(DS.getTypeSpecTypeLoc(), diag::err_expected_class)
+ Diag(DS.getTypeSpecTypeLoc(), diag::err_expected_class_or_namespace)
<< T << getLangOpts().CPlusPlus;
return true;
}
@@ -725,11 +783,11 @@ bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
bool EnteringContext) {
if (SS.isInvalid())
return false;
-
+
return !BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, ColonLoc,
GetTypeFromParser(ObjectType),
EnteringContext, SS,
- /*ScopeLookupResult=*/0, true);
+ /*ScopeLookupResult=*/nullptr, true);
}
bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
@@ -749,7 +807,8 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
translateTemplateArguments(TemplateArgsIn, TemplateArgs);
- if (DependentTemplateName *DTN = Template.get().getAsDependentTemplateName()){
+ DependentTemplateName *DTN = Template.get().getAsDependentTemplateName();
+ if (DTN && DTN->isIdentifier()) {
// Handle a dependent template specialization for which we cannot resolve
// the template name.
assert(DTN->getQualifier() == SS.getScopeRep());
@@ -775,20 +834,20 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
CCLoc);
return false;
}
-
-
- if (Template.get().getAsOverloadedTemplate() ||
- isa<FunctionTemplateDecl>(Template.get().getAsTemplateDecl())) {
+
+ TemplateDecl *TD = Template.get().getAsTemplateDecl();
+ if (Template.get().getAsOverloadedTemplate() || DTN ||
+ isa<FunctionTemplateDecl>(TD) || isa<VarTemplateDecl>(TD)) {
SourceRange R(TemplateNameLoc, RAngleLoc);
if (SS.getRange().isValid())
R.setBegin(SS.getRange().getBegin());
-
+
Diag(CCLoc, diag::err_non_type_template_in_nested_name_specifier)
- << Template.get() << R;
+ << (TD && isa<VarTemplateDecl>(TD)) << Template.get() << R;
NoteAllFoundTemplates(Template.get());
return true;
}
-
+
// We were able to resolve the template name to an actual template.
// Build an appropriate nested-name-specifier.
QualType T = CheckTemplateIdType(Template.get(), TemplateNameLoc,
@@ -831,8 +890,8 @@ namespace {
void *Sema::SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS) {
if (SS.isEmpty() || SS.isInvalid())
- return 0;
-
+ return nullptr;
+
void *Mem = Context.Allocate((sizeof(NestedNameSpecifierAnnotation) +
SS.location_size()),
llvm::alignOf<NestedNameSpecifierAnnotation>());
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
index ba00b71..ae5436c 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
@@ -21,6 +21,7 @@
#include "clang/AST/ExprObjC.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/Initialization.h"
#include "llvm/ADT/SmallVector.h"
#include <set>
@@ -89,10 +90,10 @@ namespace {
if (IsARCUnbridgedCast) {
castExpr = ImplicitCastExpr::Create(Self.Context,
Self.Context.ARCUnbridgedCastTy,
- CK_Dependent, castExpr, 0,
+ CK_Dependent, castExpr, nullptr,
castExpr->getValueKind());
}
- return Self.Owned(castExpr);
+ return castExpr;
}
// Internal convenience methods.
@@ -133,7 +134,7 @@ namespace {
if (!isPlaceholder() || isPlaceholder(BuiltinType::Overload))
return;
- SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.take());
+ SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.get());
if (SrcExpr.isInvalid())
return;
PlaceholderKind = (BuiltinType::Kind) 0;
@@ -238,7 +239,7 @@ ExprResult
Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
TypeSourceInfo *DestTInfo, Expr *E,
SourceRange AngleBrackets, SourceRange Parens) {
- ExprResult Ex = Owned(E);
+ ExprResult Ex = E;
QualType DestType = DestTInfo->getType();
// If the type is dependent, we won't do the semantic analysis now.
@@ -261,7 +262,7 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
return ExprError();
}
return Op.complete(CXXConstCastExpr::Create(Context, Op.ResultType,
- Op.ValueKind, Op.SrcExpr.take(), DestTInfo,
+ Op.ValueKind, Op.SrcExpr.get(), DestTInfo,
OpLoc, Parens.getEnd(),
AngleBrackets));
@@ -272,7 +273,7 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
return ExprError();
}
return Op.complete(CXXDynamicCastExpr::Create(Context, Op.ResultType,
- Op.ValueKind, Op.Kind, Op.SrcExpr.take(),
+ Op.ValueKind, Op.Kind, Op.SrcExpr.get(),
&Op.BasePath, DestTInfo,
OpLoc, Parens.getEnd(),
AngleBrackets));
@@ -284,8 +285,8 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
return ExprError();
}
return Op.complete(CXXReinterpretCastExpr::Create(Context, Op.ResultType,
- Op.ValueKind, Op.Kind, Op.SrcExpr.take(),
- 0, DestTInfo, OpLoc,
+ Op.ValueKind, Op.Kind, Op.SrcExpr.get(),
+ nullptr, DestTInfo, OpLoc,
Parens.getEnd(),
AngleBrackets));
}
@@ -297,7 +298,7 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
}
return Op.complete(CXXStaticCastExpr::Create(Context, Op.ResultType,
- Op.ValueKind, Op.Kind, Op.SrcExpr.take(),
+ Op.ValueKind, Op.Kind, Op.SrcExpr.get(),
&Op.BasePath, DestTInfo,
OpLoc, Parens.getEnd(),
AngleBrackets));
@@ -534,9 +535,9 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
/// checked downcasts in class hierarchies.
void CastOperation::CheckDynamicCast() {
if (ValueKind == VK_RValue)
- SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
+ SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get());
else if (isPlaceholder())
- SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.take());
+ SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.get());
if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
return;
@@ -548,7 +549,7 @@ void CastOperation::CheckDynamicCast() {
QualType DestPointee;
const PointerType *DestPointer = DestType->getAs<PointerType>();
- const ReferenceType *DestReference = 0;
+ const ReferenceType *DestReference = nullptr;
if (DestPointer) {
DestPointee = DestPointer->getPointeeType();
} else if ((DestReference = DestType->getAs<ReferenceType>())) {
@@ -599,6 +600,11 @@ void CastOperation::CheckDynamicCast() {
}
SrcPointee = SrcType;
} else {
+ // If we're dynamic_casting from a prvalue to an rvalue reference, we need
+ // to materialize the prvalue before we bind the reference to it.
+ if (SrcExpr.get()->isRValue())
+ SrcExpr = new (Self.Context) MaterializeTemporaryExpr(
+ SrcType, SrcExpr.get(), /*IsLValueReference*/false);
SrcPointee = SrcType;
}
@@ -647,7 +653,7 @@ void CastOperation::CheckDynamicCast() {
SrcExpr = ExprError();
return;
}
-
+
Kind = CK_DerivedToBase;
// If we are casting to or through a virtual base class, we need a
@@ -689,9 +695,9 @@ void CastOperation::CheckDynamicCast() {
/// legacy_function(const_cast\<char*\>(str));
void CastOperation::CheckConstCast() {
if (ValueKind == VK_RValue)
- SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
+ SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get());
else if (isPlaceholder())
- SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.take());
+ SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.get());
if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
return;
@@ -804,7 +810,7 @@ static void DiagnoseReinterpretUpDownCast(Sema &Self, const Expr *SrcExpr,
/// char *bytes = reinterpret_cast\<char*\>(int_ptr);
void CastOperation::CheckReinterpretCast() {
if (ValueKind == VK_RValue && !isPlaceholder(BuiltinType::Overload))
- SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
+ SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get());
else
checkNonOverloadPlaceholders();
if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
@@ -863,13 +869,13 @@ void CastOperation::CheckStaticCast() {
return;
}
- SrcExpr = Self.IgnoredValueConversions(SrcExpr.take());
+ SrcExpr = Self.IgnoredValueConversions(SrcExpr.get());
return;
}
if (ValueKind == VK_RValue && !DestType->isRecordType() &&
!isPlaceholder(BuiltinType::Overload)) {
- SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
+ SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get());
if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
return;
}
@@ -1066,6 +1072,11 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
Kind = CK_BitCast;
return TC_Success;
}
+ // Allow ns-pointer to cf-pointer conversion in either direction
+ // with static casts.
+ if (!CStyle &&
+ Self.CheckTollFreeBridgeStaticCast(DestType, SrcExpr.get(), Kind))
+ return TC_Success;
// We tried everything. Everything! Nothing works! :-(
return TC_NotApplicable;
@@ -1150,6 +1161,9 @@ TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType,
QualType DestPointee = DestReference->getPointeeType();
+ // FIXME: If the source is a prvalue, we should issue a warning (because the
+ // cast always has undefined behavior), and for AST consistency, we should
+ // materialize a temporary.
return TryStaticDowncast(Self,
Self.Context.getCanonicalType(SrcExpr->getType()),
Self.Context.getCanonicalType(DestPointee), CStyle,
@@ -1271,7 +1285,7 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
return TC_Failed;
}
- if (Paths.getDetectedVirtual() != 0) {
+ if (Paths.getDetectedVirtual() != nullptr) {
QualType VirtualBase(Paths.getDetectedVirtual(), 0);
Self.Diag(OpRange.getBegin(), diag::err_static_downcast_via_virtual)
<< OrigSrcType << OrigDestType << VirtualBase << OpRange;
@@ -1346,7 +1360,8 @@ TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
QualType DestClass(DestMemPtr->getClass(), 0);
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/true);
- if (!Self.IsDerivedFrom(SrcClass, DestClass, Paths)) {
+ if (Self.RequireCompleteType(OpRange.getBegin(), SrcClass, 0) ||
+ !Self.IsDerivedFrom(SrcClass, DestClass, Paths)) {
return TC_NotApplicable;
}
@@ -1431,6 +1446,10 @@ TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
msg = 0;
return TC_Failed;
}
+ } else if (DestType->isMemberPointerType()) {
+ if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ Self.RequireCompleteType(OpRange.getBegin(), DestType, 0);
+ }
}
InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType);
@@ -1578,8 +1597,7 @@ static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr,
// This is a const_cast from a class prvalue to an rvalue reference type.
// Materialize a temporary to store the result of the conversion.
SrcExpr = new (Self.Context) MaterializeTemporaryExpr(
- SrcType, SrcExpr.take(), /*IsLValueReference*/ false,
- /*ExtendingDecl*/ 0);
+ SrcType, SrcExpr.get(), /*IsLValueReference*/ false);
return TC_Success;
}
@@ -1596,10 +1614,8 @@ void Sema::CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType,
diag::warn_pointer_indirection_from_incompatible_type :
diag::warn_undefined_reinterpret_cast;
- if (Diags.getDiagnosticLevel(DiagID, Range.getBegin()) ==
- DiagnosticsEngine::Ignored) {
+ if (Diags.isIgnored(DiagID, Range.getBegin()))
return;
- }
QualType SrcTy, DestTy;
if (IsDereference) {
@@ -1729,7 +1745,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
// same effect as the conversion *reinterpret_cast<T*>(&x) with the
// built-in & and * operators.
- const char *inappropriate = 0;
+ const char *inappropriate = nullptr;
switch (SrcExpr.get()->getObjectKind()) {
case OK_Ordinary:
break;
@@ -1778,6 +1794,13 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
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.
+ Self.RequireCompleteType(OpRange.getBegin(), SrcType, 0);
+ Self.RequireCompleteType(OpRange.getBegin(), DestType, 0);
+ }
+
// Don't allow casting between member pointers of different sizes.
if (Self.Context.getTypeSize(DestMemPtr) !=
Self.Context.getTypeSize(SrcMemPtr)) {
@@ -2007,7 +2030,7 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
return;
}
- SrcExpr = Self.IgnoredValueConversions(SrcExpr.take());
+ SrcExpr = Self.IgnoredValueConversions(SrcExpr.get());
return;
}
@@ -2020,7 +2043,7 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
if (ValueKind == VK_RValue && !DestType->isRecordType() &&
!isPlaceholder(BuiltinType::Overload)) {
- SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
+ SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get());
if (SrcExpr.isInvalid())
return;
}
@@ -2082,10 +2105,16 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
DestType,
/*Complain*/ true,
Found);
-
- assert(!Fn && "cast failed but able to resolve overload expression!!");
- (void)Fn;
-
+ if (Fn) {
+ // If DestType is a function type (not to be confused with the function
+ // pointer type), it will be possible to resolve the function address,
+ // but the type cast should be considered as failure.
+ OverloadExpr *OE = OverloadExpr::find(SrcExpr.get()).Expression;
+ Self.Diag(OpRange.getBegin(), diag::err_bad_cstyle_cast_overload)
+ << OE->getName() << DestType << OpRange
+ << OE->getQualifierLoc().getSourceRange();
+ Self.NoteAllOverloadCandidates(SrcExpr.get());
+ }
} else {
diagnoseBadCast(Self, msg, (FunctionalStyle ? CT_Functional : CT_CStyle),
OpRange, SrcExpr.get(), DestType, ListInitialization);
@@ -2104,9 +2133,8 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
/// pointer; etc. Cast to 'void' is an exception.
static void DiagnoseBadFunctionCast(Sema &Self, const ExprResult &SrcExpr,
QualType DestType) {
- if (Self.Diags.getDiagnosticLevel(diag::warn_bad_function_cast,
- SrcExpr.get()->getExprLoc())
- == DiagnosticsEngine::Ignored)
+ if (Self.Diags.isIgnored(diag::warn_bad_function_cast,
+ SrcExpr.get()->getExprLoc()))
return;
if (!isa<CallExpr>(SrcExpr.get()))
@@ -2152,7 +2180,7 @@ void CastOperation::CheckCStyleCast() {
// type needs to be scalar.
if (DestType->isVoidType()) {
// We don't necessarily do lvalue-to-rvalue conversions on this.
- SrcExpr = Self.IgnoredValueConversions(SrcExpr.take());
+ SrcExpr = Self.IgnoredValueConversions(SrcExpr.get());
if (SrcExpr.isInvalid())
return;
@@ -2161,13 +2189,28 @@ void CastOperation::CheckCStyleCast() {
return;
}
- SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
+ SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get());
if (SrcExpr.isInvalid())
return;
QualType SrcType = SrcExpr.get()->getType();
assert(!SrcType->isPlaceholderType());
+ // OpenCL v1 s6.5: Casting a pointer to address space A to a pointer to
+ // address space B is illegal.
+ if (Self.getLangOpts().OpenCL && DestType->isPointerType() &&
+ SrcType->isPointerType()) {
+ if (DestType->getPointeeType().getAddressSpace() !=
+ SrcType->getPointeeType().getAddressSpace()) {
+ Self.Diag(OpRange.getBegin(),
+ diag::err_typecheck_incompatible_address_space)
+ << SrcType << DestType << Sema::AA_Casting
+ << SrcExpr.get()->getSourceRange();
+ SrcExpr = ExprError();
+ return;
+ }
+ }
+
if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
diag::err_typecheck_cast_to_incomplete)) {
SrcExpr = ExprError();
@@ -2227,7 +2270,7 @@ void CastOperation::CheckCStyleCast() {
}
if (DestType->isExtVectorType()) {
- SrcExpr = Self.CheckExtVectorCast(OpRange, DestType, SrcExpr.take(), Kind);
+ SrcExpr = Self.CheckExtVectorCast(OpRange, DestType, SrcExpr.get(), Kind);
return;
}
@@ -2319,6 +2362,7 @@ void CastOperation::CheckCStyleCast() {
return;
}
}
+
DiagnoseCastOfObjCSEL(Self, SrcExpr, DestType);
DiagnoseBadFunctionCast(Self, SrcExpr, DestType);
Kind = Self.PrepareScalarCast(SrcExpr, DestType);
@@ -2348,7 +2392,7 @@ ExprResult Sema::BuildCStyleCastExpr(SourceLocation LPLoc,
return ExprError();
return Op.complete(CStyleCastExpr::Create(Context, Op.ResultType,
- Op.ValueKind, Op.Kind, Op.SrcExpr.take(),
+ Op.ValueKind, Op.Kind, Op.SrcExpr.get(),
&Op.BasePath, CastTypeInfo, LPLoc, RPLoc));
}
@@ -2370,5 +2414,5 @@ ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo,
return Op.complete(CXXFunctionalCastExpr::Create(Context, Op.ResultType,
Op.ValueKind, CastTypeInfo, Op.Kind,
- Op.SrcExpr.take(), &Op.BasePath, LPLoc, RPLoc));
+ Op.SrcExpr.get(), &Op.BasePath, LPLoc, RPLoc));
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
index 0530a04..420aff3 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
@@ -27,14 +27,14 @@
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/Lexer.h" // TODO: Extract static functions to fix layering.
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/Sema.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/raw_ostream.h"
#include <limits>
@@ -43,8 +43,8 @@ using namespace sema;
SourceLocation Sema::getLocationOfStringLiteralByte(const StringLiteral *SL,
unsigned ByteNo) const {
- return SL->getLocationOfByte(ByteNo, PP.getSourceManager(),
- PP.getLangOpts(), PP.getTargetInfo());
+ return SL->getLocationOfByte(ByteNo, getSourceManager(), LangOpts,
+ Context.getTargetInfo());
}
/// Checks that a call expression's argument count is the desired number.
@@ -101,19 +101,19 @@ static bool SemaBuiltinAddressof(Sema &S, CallExpr *TheCall) {
if (checkArgCount(S, TheCall, 1))
return true;
- ExprResult Arg(S.Owned(TheCall->getArg(0)));
+ ExprResult Arg(TheCall->getArg(0));
QualType ResultType = S.CheckAddressOfOperand(Arg, TheCall->getLocStart());
if (ResultType.isNull())
return true;
- TheCall->setArg(0, Arg.take());
+ TheCall->setArg(0, Arg.get());
TheCall->setType(ResultType);
return false;
}
ExprResult
Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
- ExprResult TheCallResult(Owned(TheCall));
+ ExprResult TheCallResult(TheCall);
// Find out if any arguments are required to be integer constant expressions.
unsigned ICEArguments = 0;
@@ -145,6 +145,20 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
if (SemaBuiltinVAStart(TheCall))
return ExprError();
break;
+ case Builtin::BI__va_start: {
+ switch (Context.getTargetInfo().getTriple().getArch()) {
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ if (SemaBuiltinVAStartARM(TheCall))
+ return ExprError();
+ break;
+ default:
+ if (SemaBuiltinVAStart(TheCall))
+ return ExprError();
+ break;
+ }
+ break;
+ }
case Builtin::BI__builtin_isgreater:
case Builtin::BI__builtin_isgreaterequal:
case Builtin::BI__builtin_isless:
@@ -174,8 +188,12 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
if (SemaBuiltinPrefetch(TheCall))
return ExprError();
break;
+ case Builtin::BI__assume:
+ if (SemaBuiltinAssume(TheCall))
+ return ExprError();
+ break;
case Builtin::BI__builtin_object_size:
- if (SemaBuiltinObjectSize(TheCall))
+ if (SemaBuiltinConstantArgRange(TheCall, 1, 0, 3))
return ExprError();
break;
case Builtin::BI__builtin_longjmp:
@@ -295,18 +313,37 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
if (SemaBuiltinAddressof(*this, TheCall))
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++";
+ return ExprError();
+ }
+ // CodeGen assumes it can find the global new and delete to call,
+ // so ensure that they are declared.
+ DeclareGlobalNewDelete();
+ break;
}
-
+
// Since the target specific builtins for each arch overlap, only check those
// of the arch we are compiling for.
if (BuiltinID >= Builtin::FirstTSBuiltin) {
switch (Context.getTargetInfo().getTriple().getArch()) {
case llvm::Triple::arm:
+ case llvm::Triple::armeb:
case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
if (CheckARMBuiltinFunctionCall(BuiltinID, TheCall))
return ExprError();
break;
case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_be:
+ case llvm::Triple::arm64:
+ case llvm::Triple::arm64_be:
if (CheckAArch64BuiltinFunctionCall(BuiltinID, TheCall))
return ExprError();
break;
@@ -317,6 +354,11 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
if (CheckMipsBuiltinFunctionCall(BuiltinID, TheCall))
return ExprError();
break;
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ if (CheckX86BuiltinFunctionCall(BuiltinID, TheCall))
+ return ExprError();
+ break;
default:
break;
}
@@ -326,9 +368,9 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
}
// Get the valid immediate range for the specified NEON type code.
-static unsigned RFT(unsigned t, bool shift = false) {
+static unsigned RFT(unsigned t, bool shift = false, bool ForceQuad = false) {
NeonTypeFlags Type(t);
- int IsQuad = Type.isQuad();
+ int IsQuad = ForceQuad ? true : Type.isQuad();
switch (Type.getEltType()) {
case NeonTypeFlags::Int8:
case NeonTypeFlags::Poly8:
@@ -341,6 +383,8 @@ static unsigned RFT(unsigned t, bool shift = false) {
case NeonTypeFlags::Int64:
case NeonTypeFlags::Poly64:
return shift ? 63 : (1 << IsQuad) - 1;
+ case NeonTypeFlags::Poly128:
+ return shift ? 127 : (1 << IsQuad) - 1;
case NeonTypeFlags::Float16:
assert(!shift && "cannot shift float types!");
return (4 << IsQuad) - 1;
@@ -358,7 +402,7 @@ static unsigned RFT(unsigned t, bool shift = false) {
/// the vector type specified by the NeonTypeFlags. This is used to check
/// the pointer arguments for Neon load/store intrinsics.
static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context,
- bool IsAArch64) {
+ bool IsPolyUnsigned, bool IsInt64Long) {
switch (Flags.getEltType()) {
case NeonTypeFlags::Int8:
return Flags.isUnsigned() ? Context.UnsignedCharTy : Context.SignedCharTy;
@@ -367,13 +411,19 @@ static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context,
case NeonTypeFlags::Int32:
return Flags.isUnsigned() ? Context.UnsignedIntTy : Context.IntTy;
case NeonTypeFlags::Int64:
- return Flags.isUnsigned() ? Context.UnsignedLongLongTy : Context.LongLongTy;
+ if (IsInt64Long)
+ return Flags.isUnsigned() ? Context.UnsignedLongTy : Context.LongTy;
+ else
+ return Flags.isUnsigned() ? Context.UnsignedLongLongTy
+ : Context.LongLongTy;
case NeonTypeFlags::Poly8:
- return IsAArch64 ? Context.UnsignedCharTy : Context.SignedCharTy;
+ return IsPolyUnsigned ? Context.UnsignedCharTy : Context.SignedCharTy;
case NeonTypeFlags::Poly16:
- return IsAArch64 ? Context.UnsignedShortTy : Context.ShortTy;
+ return IsPolyUnsigned ? Context.UnsignedShortTy : Context.ShortTy;
case NeonTypeFlags::Poly64:
- return Context.UnsignedLongLongTy;
+ return Context.UnsignedLongTy;
+ case NeonTypeFlags::Poly128:
+ break;
case NeonTypeFlags::Float16:
return Context.HalfTy;
case NeonTypeFlags::Float32:
@@ -384,24 +434,21 @@ static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context,
llvm_unreachable("Invalid NeonTypeFlag!");
}
-bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID,
- CallExpr *TheCall) {
-
+bool Sema::CheckNeonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
llvm::APSInt Result;
-
uint64_t mask = 0;
unsigned TV = 0;
int PtrArgNum = -1;
bool HasConstPtr = false;
switch (BuiltinID) {
-#define GET_NEON_AARCH64_OVERLOAD_CHECK
+#define GET_NEON_OVERLOAD_CHECK
#include "clang/Basic/arm_neon.inc"
-#undef GET_NEON_AARCH64_OVERLOAD_CHECK
+#undef GET_NEON_OVERLOAD_CHECK
}
// For NEON intrinsics which are overloaded on vector element type, validate
// the immediate which specifies which variant to emit.
- unsigned ImmArg = TheCall->getNumArgs() - 1;
+ unsigned ImmArg = TheCall->getNumArgs()-1;
if (mask) {
if (SemaBuiltinConstantArg(TheCall, ImmArg, Result))
return true;
@@ -409,7 +456,7 @@ bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID,
TV = Result.getLimitedValue(64);
if ((TV > 63) || (mask & (1ULL << TV)) == 0)
return Diag(TheCall->getLocStart(), diag::err_invalid_neon_type_code)
- << TheCall->getArg(ImmArg)->getSourceRange();
+ << TheCall->getArg(ImmArg)->getSourceRange();
}
if (PtrArgNum >= 0) {
@@ -419,7 +466,14 @@ bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID,
Arg = ICE->getSubExpr();
ExprResult RHS = DefaultFunctionArrayLvalueConversion(Arg);
QualType RHSTy = RHS.get()->getType();
- QualType EltTy = getNeonEltType(NeonTypeFlags(TV), Context, true);
+
+ llvm::Triple::ArchType Arch = Context.getTargetInfo().getTriple().getArch();
+ bool IsPolyUnsigned =
+ Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::arm64;
+ bool IsInt64Long =
+ Context.getTargetInfo().getInt64Type() == TargetInfo::SignedLong;
+ QualType EltTy =
+ getNeonEltType(NeonTypeFlags(TV), Context, IsPolyUnsigned, IsInt64Long);
if (HasConstPtr)
EltTy = EltTy.withConst();
QualType LHSTy = Context.getPointerType(EltTy);
@@ -438,35 +492,29 @@ bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID,
switch (BuiltinID) {
default:
return false;
-#define GET_NEON_AARCH64_IMMEDIATE_CHECK
+#define GET_NEON_IMMEDIATE_CHECK
#include "clang/Basic/arm_neon.inc"
-#undef GET_NEON_AARCH64_IMMEDIATE_CHECK
+#undef GET_NEON_IMMEDIATE_CHECK
}
- ;
- // We can't check the value of a dependent argument.
- if (TheCall->getArg(i)->isTypeDependent() ||
- TheCall->getArg(i)->isValueDependent())
- return false;
-
- // Check that the immediate argument is actually a constant.
- if (SemaBuiltinConstantArg(TheCall, i, Result))
- return true;
-
- // Range check against the upper/lower values for this isntruction.
- unsigned Val = Result.getZExtValue();
- if (Val < l || Val > (u + l))
- return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
- << l << u + l << TheCall->getArg(i)->getSourceRange();
-
- return false;
+ return SemaBuiltinConstantArgRange(TheCall, i, l, u + l);
}
-bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall) {
+bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall,
+ unsigned MaxWidth) {
assert((BuiltinID == ARM::BI__builtin_arm_ldrex ||
- BuiltinID == ARM::BI__builtin_arm_strex) &&
+ BuiltinID == ARM::BI__builtin_arm_ldaex ||
+ BuiltinID == ARM::BI__builtin_arm_strex ||
+ BuiltinID == ARM::BI__builtin_arm_stlex ||
+ BuiltinID == AArch64::BI__builtin_arm_ldrex ||
+ BuiltinID == AArch64::BI__builtin_arm_ldaex ||
+ BuiltinID == AArch64::BI__builtin_arm_strex ||
+ BuiltinID == AArch64::BI__builtin_arm_stlex) &&
"unexpected ARM builtin");
- bool IsLdrex = BuiltinID == ARM::BI__builtin_arm_ldrex;
+ bool IsLdrex = BuiltinID == ARM::BI__builtin_arm_ldrex ||
+ BuiltinID == ARM::BI__builtin_arm_ldaex ||
+ BuiltinID == AArch64::BI__builtin_arm_ldrex ||
+ BuiltinID == AArch64::BI__builtin_arm_ldaex;
DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
@@ -482,7 +530,7 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall) {
ExprResult PointerArgRes = DefaultFunctionArrayLvalueConversion(PointerArg);
if (PointerArgRes.isInvalid())
return true;
- PointerArg = PointerArgRes.take();
+ PointerArg = PointerArgRes.get();
const PointerType *pointerType = PointerArg->getType()->getAs<PointerType>();
if (!pointerType) {
@@ -514,7 +562,7 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall) {
PointerArgRes = ImpCastExprToType(PointerArg, AddrType, CastNeeded);
if (PointerArgRes.isInvalid())
return true;
- PointerArg = PointerArgRes.take();
+ PointerArg = PointerArgRes.get();
TheCall->setArg(IsLdrex ? 0 : 1, PointerArg);
@@ -527,7 +575,8 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall) {
}
// But ARM doesn't have instructions to deal with 128-bit versions.
- if (Context.getTypeSize(ValType) > 64) {
+ if (Context.getTypeSize(ValType) > MaxWidth) {
+ assert(MaxWidth == 64 && "Diagnostic unexpectedly inaccurate");
Diag(DRE->getLocStart(), diag::err_atomic_exclusive_builtin_pointer_size)
<< PointerArg->getType() << PointerArg->getSourceRange();
return true;
@@ -572,55 +621,17 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
llvm::APSInt Result;
if (BuiltinID == ARM::BI__builtin_arm_ldrex ||
- BuiltinID == ARM::BI__builtin_arm_strex) {
- return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall);
+ BuiltinID == ARM::BI__builtin_arm_ldaex ||
+ BuiltinID == ARM::BI__builtin_arm_strex ||
+ BuiltinID == ARM::BI__builtin_arm_stlex) {
+ return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall, 64);
}
- uint64_t mask = 0;
- unsigned TV = 0;
- int PtrArgNum = -1;
- bool HasConstPtr = false;
- switch (BuiltinID) {
-#define GET_NEON_OVERLOAD_CHECK
-#include "clang/Basic/arm_neon.inc"
-#undef GET_NEON_OVERLOAD_CHECK
- }
-
- // For NEON intrinsics which are overloaded on vector element type, validate
- // the immediate which specifies which variant to emit.
- unsigned ImmArg = TheCall->getNumArgs()-1;
- if (mask) {
- if (SemaBuiltinConstantArg(TheCall, ImmArg, Result))
- return true;
-
- TV = Result.getLimitedValue(64);
- if ((TV > 63) || (mask & (1ULL << TV)) == 0)
- return Diag(TheCall->getLocStart(), diag::err_invalid_neon_type_code)
- << TheCall->getArg(ImmArg)->getSourceRange();
- }
+ if (CheckNeonBuiltinFunctionCall(BuiltinID, TheCall))
+ return true;
- if (PtrArgNum >= 0) {
- // Check that pointer arguments have the specified type.
- Expr *Arg = TheCall->getArg(PtrArgNum);
- if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg))
- Arg = ICE->getSubExpr();
- ExprResult RHS = DefaultFunctionArrayLvalueConversion(Arg);
- QualType RHSTy = RHS.get()->getType();
- QualType EltTy = getNeonEltType(NeonTypeFlags(TV), Context, false);
- if (HasConstPtr)
- EltTy = EltTy.withConst();
- QualType LHSTy = Context.getPointerType(EltTy);
- AssignConvertType ConvTy;
- ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS);
- if (RHS.isInvalid())
- return true;
- if (DiagnoseAssignmentResult(ConvTy, Arg->getLocStart(), LHSTy, RHSTy,
- RHS.get(), AA_Assigning))
- return true;
- }
-
- // For NEON intrinsics which take an immediate value as part of the
- // instruction, range check them here.
+ // For intrinsics which take an immediate value as part of the instruction,
+ // range check them here.
unsigned i = 0, l = 0, u = 0;
switch (BuiltinID) {
default: return false;
@@ -629,29 +640,40 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case ARM::BI__builtin_arm_vcvtr_f:
case ARM::BI__builtin_arm_vcvtr_d: i = 1; u = 1; break;
case ARM::BI__builtin_arm_dmb:
- case ARM::BI__builtin_arm_dsb: l = 0; u = 15; break;
-#define GET_NEON_IMMEDIATE_CHECK
-#include "clang/Basic/arm_neon.inc"
-#undef GET_NEON_IMMEDIATE_CHECK
- };
+ case ARM::BI__builtin_arm_dsb:
+ case ARM::BI__builtin_arm_isb: l = 0; u = 15; break;
+ }
- // We can't check the value of a dependent argument.
- if (TheCall->getArg(i)->isTypeDependent() ||
- TheCall->getArg(i)->isValueDependent())
- return false;
+ // FIXME: VFP Intrinsics should error if VFP not present.
+ return SemaBuiltinConstantArgRange(TheCall, i, l, u + l);
+}
+
+bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID,
+ CallExpr *TheCall) {
+ llvm::APSInt Result;
+
+ if (BuiltinID == AArch64::BI__builtin_arm_ldrex ||
+ BuiltinID == AArch64::BI__builtin_arm_ldaex ||
+ BuiltinID == AArch64::BI__builtin_arm_strex ||
+ BuiltinID == AArch64::BI__builtin_arm_stlex) {
+ return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall, 128);
+ }
- // Check that the immediate argument is actually a constant.
- if (SemaBuiltinConstantArg(TheCall, i, Result))
+ if (CheckNeonBuiltinFunctionCall(BuiltinID, TheCall))
return true;
- // Range check against the upper/lower values for this isntruction.
- unsigned Val = Result.getZExtValue();
- if (Val < l || Val > (u + l))
- return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
- << l << u+l << TheCall->getArg(i)->getSourceRange();
+ // For intrinsics which take an immediate value as part of the instruction,
+ // range check them here.
+ unsigned i = 0, l = 0, u = 0;
+ switch (BuiltinID) {
+ default: return false;
+ case AArch64::BI__builtin_arm_dmb:
+ case AArch64::BI__builtin_arm_dsb:
+ case AArch64::BI__builtin_arm_isb: l = 0; u = 15; break;
+ }
// FIXME: VFP Intrinsics should error if VFP not present.
- return false;
+ return SemaBuiltinConstantArgRange(TheCall, i, l, u + l);
}
bool Sema::CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
@@ -665,24 +687,17 @@ bool Sema::CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case Mips::BI__builtin_mips_precr_sra_ph_w: i = 2; l = 0; u = 31; break;
case Mips::BI__builtin_mips_precr_sra_r_ph_w: i = 2; l = 0; u = 31; break;
case Mips::BI__builtin_mips_prepend: i = 2; l = 0; u = 31; break;
- };
-
- // We can't check the value of a dependent argument.
- if (TheCall->getArg(i)->isTypeDependent() ||
- TheCall->getArg(i)->isValueDependent())
- return false;
-
- // Check that the immediate argument is actually a constant.
- llvm::APSInt Result;
- if (SemaBuiltinConstantArg(TheCall, i, Result))
- return true;
+ }
- // Range check against the upper/lower values for this instruction.
- unsigned Val = Result.getZExtValue();
- if (Val < l || Val > u)
- return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
- << l << u << TheCall->getArg(i)->getSourceRange();
+ return SemaBuiltinConstantArgRange(TheCall, i, l, u);
+}
+bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
+ switch (BuiltinID) {
+ case X86::BI_mm_prefetch:
+ // This is declared to take (const char*, int)
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 3);
+ }
return false;
}
@@ -709,14 +724,66 @@ bool Sema::getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
return true;
}
+/// Checks if a the given expression evaluates to null.
+///
+/// \brief Returns true if the value evaluates to null.
+static bool CheckNonNullExpr(Sema &S,
+ const Expr *Expr) {
+ // As a special case, transparent unions initialized with zero are
+ // considered null for the purposes of the nonnull attribute.
+ if (const RecordType *UT = Expr->getType()->getAsUnionType()) {
+ if (UT->getDecl()->hasAttr<TransparentUnionAttr>())
+ if (const CompoundLiteralExpr *CLE =
+ dyn_cast<CompoundLiteralExpr>(Expr))
+ if (const InitListExpr *ILE =
+ dyn_cast<InitListExpr>(CLE->getInitializer()))
+ Expr = ILE->getInit(0);
+ }
+
+ bool Result;
+ return (!Expr->isValueDependent() &&
+ Expr->EvaluateAsBooleanCondition(Result, S.Context) &&
+ !Result);
+}
+
+static void CheckNonNullArgument(Sema &S,
+ const Expr *ArgExpr,
+ SourceLocation CallSiteLoc) {
+ if (CheckNonNullExpr(S, ArgExpr))
+ S.Diag(CallSiteLoc, diag::warn_null_arg) << ArgExpr->getSourceRange();
+}
+
+static void CheckNonNullArguments(Sema &S,
+ const NamedDecl *FDecl,
+ const Expr * const *ExprArgs,
+ SourceLocation CallSiteLoc) {
+ // Check the attributes attached to the method/function itself.
+ for (const auto *NonNull : FDecl->specific_attrs<NonNullAttr>()) {
+ for (const auto &Val : NonNull->args())
+ CheckNonNullArgument(S, ExprArgs[Val], CallSiteLoc);
+ }
+
+ // Check the attributes on the parameters.
+ ArrayRef<ParmVarDecl*> parms;
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(FDecl))
+ parms = FD->parameters();
+ else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(FDecl))
+ parms = MD->parameters();
+
+ unsigned argIndex = 0;
+ for (ArrayRef<ParmVarDecl*>::iterator I = parms.begin(), E = parms.end();
+ I != E; ++I, ++argIndex) {
+ const ParmVarDecl *PVD = *I;
+ if (PVD->hasAttr<NonNullAttr>())
+ CheckNonNullArgument(S, ExprArgs[argIndex], CallSiteLoc);
+ }
+}
+
/// Handles the checks for format strings, non-POD arguments to vararg
/// functions, and NULL arguments passed to non-NULL parameters.
-void Sema::checkCall(NamedDecl *FDecl,
- ArrayRef<const Expr *> Args,
- unsigned NumProtoArgs,
- bool IsMemberFunction,
- SourceLocation Loc,
- SourceRange Range,
+void Sema::checkCall(NamedDecl *FDecl, ArrayRef<const Expr *> Args,
+ unsigned NumParams, bool IsMemberFunction,
+ SourceLocation Loc, SourceRange Range,
VariadicCallType CallType) {
// FIXME: We should check as much as we can in the template definition.
if (CurContext->isDependentContext())
@@ -725,14 +792,11 @@ void Sema::checkCall(NamedDecl *FDecl,
// Printf and scanf checking.
llvm::SmallBitVector CheckedVarArgs;
if (FDecl) {
- for (specific_attr_iterator<FormatAttr>
- I = FDecl->specific_attr_begin<FormatAttr>(),
- E = FDecl->specific_attr_end<FormatAttr>();
- I != E; ++I) {
+ for (const auto *I : FDecl->specific_attrs<FormatAttr>()) {
// Only create vector if there are format attributes.
CheckedVarArgs.resize(Args.size());
- CheckFormatArguments(*I, Args, IsMemberFunction, CallType, Loc, Range,
+ CheckFormatArguments(I, Args, IsMemberFunction, CallType, Loc, Range,
CheckedVarArgs);
}
}
@@ -740,7 +804,7 @@ void Sema::checkCall(NamedDecl *FDecl,
// Refuse POD arguments that weren't caught by the format string
// checks above.
if (CallType != VariadicDoesNotApply) {
- for (unsigned ArgIdx = NumProtoArgs; ArgIdx < Args.size(); ++ArgIdx) {
+ for (unsigned ArgIdx = NumParams; ArgIdx < Args.size(); ++ArgIdx) {
// Args[ArgIdx] can be null in malformed code.
if (const Expr *Arg = Args[ArgIdx]) {
if (CheckedVarArgs.empty() || !CheckedVarArgs[ArgIdx])
@@ -750,18 +814,11 @@ void Sema::checkCall(NamedDecl *FDecl,
}
if (FDecl) {
- for (specific_attr_iterator<NonNullAttr>
- I = FDecl->specific_attr_begin<NonNullAttr>(),
- E = FDecl->specific_attr_end<NonNullAttr>(); I != E; ++I)
- CheckNonNullArguments(*I, Args.data(), Loc);
+ CheckNonNullArguments(*this, FDecl, Args.data(), Loc);
// Type safety checking.
- for (specific_attr_iterator<ArgumentWithTypeTagAttr>
- i = FDecl->specific_attr_begin<ArgumentWithTypeTagAttr>(),
- e = FDecl->specific_attr_end<ArgumentWithTypeTagAttr>();
- i != e; ++i) {
- CheckArgumentWithTypeTag(*i, Args.data());
- }
+ for (const auto *I : FDecl->specific_attrs<ArgumentWithTypeTagAttr>())
+ CheckArgumentWithTypeTag(I, Args.data());
}
}
@@ -773,7 +830,7 @@ void Sema::CheckConstructorCall(FunctionDecl *FDecl,
SourceLocation Loc) {
VariadicCallType CallType =
Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply;
- checkCall(FDecl, Args, Proto->getNumArgs(),
+ checkCall(FDecl, Args, Proto->getNumParams(),
/*IsMemberFunction=*/true, Loc, SourceRange(), CallType);
}
@@ -787,7 +844,7 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
IsMemberOperatorCall;
VariadicCallType CallType = getVariadicCallType(FDecl, Proto,
TheCall->getCallee());
- unsigned NumProtoArgs = Proto ? Proto->getNumArgs() : 0;
+ unsigned NumParams = Proto ? Proto->getNumParams() : 0;
Expr** Args = TheCall->getArgs();
unsigned NumArgs = TheCall->getNumArgs();
if (IsMemberOperatorCall) {
@@ -797,8 +854,7 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
++Args;
--NumArgs;
}
- checkCall(FDecl, llvm::makeArrayRef<const Expr *>(Args, NumArgs),
- NumProtoArgs,
+ checkCall(FDecl, llvm::makeArrayRef<const Expr *>(Args, NumArgs), NumParams,
IsMemberFunction, TheCall->getRParenLoc(),
TheCall->getCallee()->getSourceRange(), CallType);
@@ -808,6 +864,8 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
if (!FnInfo)
return false;
+ CheckAbsoluteValueFunction(TheCall, FDecl, FnInfo);
+
unsigned CMId = FDecl->getMemoryFunctionKind();
if (CMId == 0)
return false;
@@ -853,35 +911,59 @@ bool Sema::CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall,
} else { // Ty->isFunctionPointerType()
CallType = VariadicFunction;
}
- unsigned NumProtoArgs = Proto ? Proto->getNumArgs() : 0;
+ unsigned NumParams = Proto ? Proto->getNumParams() : 0;
- checkCall(NDecl,
- llvm::makeArrayRef<const Expr *>(TheCall->getArgs(),
- TheCall->getNumArgs()),
- NumProtoArgs, /*IsMemberFunction=*/false,
- TheCall->getRParenLoc(),
+ checkCall(NDecl, llvm::makeArrayRef<const Expr *>(TheCall->getArgs(),
+ TheCall->getNumArgs()),
+ NumParams, /*IsMemberFunction=*/false, TheCall->getRParenLoc(),
TheCall->getCallee()->getSourceRange(), CallType);
-
+
return false;
}
/// Checks function calls when a FunctionDecl or a NamedDecl is not available,
/// such as function pointers returned from functions.
bool Sema::CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto) {
- VariadicCallType CallType = getVariadicCallType(/*FDecl=*/0, Proto,
+ VariadicCallType CallType = getVariadicCallType(/*FDecl=*/nullptr, Proto,
TheCall->getCallee());
- unsigned NumProtoArgs = Proto ? Proto->getNumArgs() : 0;
+ unsigned NumParams = Proto ? Proto->getNumParams() : 0;
- checkCall(/*FDecl=*/0,
+ checkCall(/*FDecl=*/nullptr,
llvm::makeArrayRef<const Expr *>(TheCall->getArgs(),
TheCall->getNumArgs()),
- NumProtoArgs, /*IsMemberFunction=*/false,
- TheCall->getRParenLoc(),
+ NumParams, /*IsMemberFunction=*/false, TheCall->getRParenLoc(),
TheCall->getCallee()->getSourceRange(), CallType);
return false;
}
+static bool isValidOrderingForOp(int64_t Ordering, AtomicExpr::AtomicOp Op) {
+ if (Ordering < AtomicExpr::AO_ABI_memory_order_relaxed ||
+ Ordering > AtomicExpr::AO_ABI_memory_order_seq_cst)
+ return false;
+
+ switch (Op) {
+ case AtomicExpr::AO__c11_atomic_init:
+ llvm_unreachable("There is no ordering argument for an init");
+
+ case AtomicExpr::AO__c11_atomic_load:
+ case AtomicExpr::AO__atomic_load_n:
+ case AtomicExpr::AO__atomic_load:
+ return Ordering != AtomicExpr::AO_ABI_memory_order_release &&
+ Ordering != AtomicExpr::AO_ABI_memory_order_acq_rel;
+
+ case AtomicExpr::AO__c11_atomic_store:
+ case AtomicExpr::AO__atomic_store:
+ case AtomicExpr::AO__atomic_store_n:
+ return Ordering != AtomicExpr::AO_ABI_memory_order_consume &&
+ Ordering != AtomicExpr::AO_ABI_memory_order_acquire &&
+ Ordering != AtomicExpr::AO_ABI_memory_order_acq_rel;
+
+ default:
+ return true;
+ }
+}
+
ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
AtomicExpr::AtomicOp Op) {
CallExpr *TheCall = cast<CallExpr>(TheCallResult.get());
@@ -1170,7 +1252,16 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
SubExprs.push_back(TheCall->getArg(3)); // Weak
break;
}
-
+
+ if (SubExprs.size() >= 2 && Form != Init) {
+ llvm::APSInt Result(32);
+ if (SubExprs[1]->isIntegerConstantExpr(Result, Context) &&
+ !isValidOrderingForOp(Result.getSExtValue(), Op))
+ Diag(SubExprs[1]->getLocStart(),
+ diag::warn_atomic_op_has_invalid_memory_order)
+ << SubExprs[1]->getSourceRange();
+ }
+
AtomicExpr *AE = new (Context) AtomicExpr(TheCall->getCallee()->getLocStart(),
SubExprs, ResultType, Op,
TheCall->getRParenLoc());
@@ -1181,7 +1272,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
Diag(AE->getLocStart(), diag::err_atomic_load_store_uses_lib) <<
((Op == AtomicExpr::AO__c11_atomic_load) ? 0 : 1);
- return Owned(AE);
+ return AE;
}
@@ -1205,7 +1296,7 @@ static bool checkBuiltinArgument(Sema &S, CallExpr *E, unsigned ArgIndex) {
if (Arg.isInvalid())
return true;
- E->setArg(ArgIndex, Arg.take());
+ E->setArg(ArgIndex, Arg.get());
return false;
}
@@ -1240,7 +1331,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
ExprResult FirstArgResult = DefaultFunctionArrayLvalueConversion(FirstArg);
if (FirstArgResult.isInvalid())
return ExprError();
- FirstArg = FirstArgResult.take();
+ FirstArg = FirstArgResult.get();
TheCall->setArg(0, FirstArg);
const PointerType *pointerType = FirstArg->getType()->getAs<PointerType>();
@@ -1493,7 +1584,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
LookupName(Res, TUScope, /*AllowBuiltinCreation=*/true);
assert(Res.getFoundDecl());
NewBuiltinDecl = dyn_cast<FunctionDecl>(Res.getFoundDecl());
- if (NewBuiltinDecl == 0)
+ if (!NewBuiltinDecl)
return ExprError();
}
@@ -1518,7 +1609,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
// pass in 42. The 42 gets converted to char. This is even more strange
// for things like 45.123 -> char, etc.
// FIXME: Do this check.
- TheCall->setArg(i+1, Arg.take());
+ TheCall->setArg(i+1, Arg.get());
}
ASTContext& Context = this->getASTContext();
@@ -1539,7 +1630,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
QualType CalleePtrTy = Context.getPointerType(NewBuiltinDecl->getType());
ExprResult PromotedCall = ImpCastExprToType(NewDRE, CalleePtrTy,
CK_BuiltinFnToFnPtr);
- TheCall->setCallee(PromotedCall.take());
+ TheCall->setCallee(PromotedCall.get());
// Change the result type of the call to match the original value type. This
// is arbitrary, but the codegen for these builtins ins design to handle it
@@ -1661,6 +1752,58 @@ bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) {
return false;
}
+bool Sema::SemaBuiltinVAStartARM(CallExpr *Call) {
+ // void __va_start(va_list *ap, const char *named_addr, size_t slot_size,
+ // const char *named_addr);
+
+ Expr *Func = Call->getCallee();
+
+ if (Call->getNumArgs() < 3)
+ return Diag(Call->getLocEnd(),
+ diag::err_typecheck_call_too_few_args_at_least)
+ << 0 /*function call*/ << 3 << Call->getNumArgs();
+
+ // Determine whether the current function is variadic or not.
+ bool IsVariadic;
+ if (BlockScopeInfo *CurBlock = getCurBlock())
+ IsVariadic = CurBlock->TheDecl->isVariadic();
+ else if (FunctionDecl *FD = getCurFunctionDecl())
+ IsVariadic = FD->isVariadic();
+ else if (ObjCMethodDecl *MD = getCurMethodDecl())
+ IsVariadic = MD->isVariadic();
+ else
+ llvm_unreachable("unexpected statement type");
+
+ if (!IsVariadic) {
+ Diag(Func->getLocStart(), diag::err_va_start_used_in_non_variadic_function);
+ return true;
+ }
+
+ // Type-check the first argument normally.
+ if (checkBuiltinArgument(*this, Call, 0))
+ return true;
+
+ static const struct {
+ unsigned ArgNo;
+ QualType Type;
+ } ArgumentTypes[] = {
+ { 1, Context.getPointerType(Context.CharTy.withConst()) },
+ { 2, Context.getSizeType() },
+ };
+
+ for (const auto &AT : ArgumentTypes) {
+ const Expr *Arg = Call->getArg(AT.ArgNo)->IgnoreParens();
+ if (Arg->getType().getCanonicalType() == AT.Type.getCanonicalType())
+ continue;
+ Diag(Arg->getLocStart(), diag::err_typecheck_convert_incompatible)
+ << Arg->getType() << AT.Type << 1 /* different class */
+ << 0 /* qualifier difference */ << 3 /* parameter mismatch */
+ << AT.ArgNo + 1 << Arg->getType() << AT.Type;
+ }
+
+ return false;
+}
+
/// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isgreater and
/// friends. This is declared to take (...), so we have to check everything.
bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) {
@@ -1735,7 +1878,7 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) {
if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Float)) {
assert(Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) &&
"promotion from float to double is the only expected cast here");
- Cast->setSubExpr(0);
+ Cast->setSubExpr(nullptr);
TheCall->setArg(NumArgs-1, CastArg);
}
}
@@ -1820,12 +1963,12 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; i++) {
exprs.push_back(TheCall->getArg(i));
- TheCall->setArg(i, 0);
+ TheCall->setArg(i, nullptr);
}
- return Owned(new (Context) ShuffleVectorExpr(Context, exprs, resType,
- TheCall->getCallee()->getLocStart(),
- TheCall->getRParenLoc()));
+ return new (Context) ShuffleVectorExpr(Context, exprs, resType,
+ TheCall->getCallee()->getLocStart(),
+ TheCall->getRParenLoc());
}
/// SemaConvertVectorExpr - Handle __builtin_convertvector
@@ -1854,9 +1997,8 @@ ExprResult Sema::SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
<< E->getSourceRange());
}
- return Owned(new (Context) ConvertVectorExpr(E, TInfo, DstTy, VK, OK,
- BuiltinLoc, RParenLoc));
-
+ return new (Context)
+ ConvertVectorExpr(E, TInfo, DstTy, VK, OK, BuiltinLoc, RParenLoc);
}
/// SemaBuiltinPrefetch - Handle __builtin_prefetch.
@@ -1873,30 +2015,23 @@ bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) {
// Argument 0 is checked for us and the remaining arguments must be
// constant integers.
- for (unsigned i = 1; i != NumArgs; ++i) {
- Expr *Arg = TheCall->getArg(i);
+ for (unsigned i = 1; i != NumArgs; ++i)
+ if (SemaBuiltinConstantArgRange(TheCall, i, 0, i == 1 ? 1 : 3))
+ return true;
- // We can't check the value of a dependent argument.
- if (Arg->isTypeDependent() || Arg->isValueDependent())
- continue;
+ return false;
+}
- llvm::APSInt Result;
- if (SemaBuiltinConstantArg(TheCall, i, Result))
- return true;
+/// SemaBuiltinAssume - Handle __assume (MS Extension).
+// __assume does not evaluate its arguments, and should warn if its argument
+// has side effects.
+bool Sema::SemaBuiltinAssume(CallExpr *TheCall) {
+ Expr *Arg = TheCall->getArg(0);
+ if (Arg->isInstantiationDependent()) return false;
- // FIXME: gcc issues a warning and rewrites these to 0. These
- // seems especially odd for the third argument since the default
- // is 3.
- if (i == 1) {
- if (Result.getLimitedValue() > 1)
- return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
- << "0" << "1" << Arg->getSourceRange();
- } else {
- if (Result.getLimitedValue() > 3)
- return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
- << "0" << "3" << Arg->getSourceRange();
- }
- }
+ if (Arg->HasSideEffects(Context))
+ return Diag(Arg->getLocStart(), diag::warn_assume_side_effects)
+ << Arg->getSourceRange();
return false;
}
@@ -1918,27 +2053,24 @@ bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum,
return false;
}
-/// SemaBuiltinObjectSize - Handle __builtin_object_size(void *ptr,
-/// int type). This simply type checks that type is one of the defined
-/// constants (0-3).
-// For compatibility check 0-3, llvm only handles 0 and 2.
-bool Sema::SemaBuiltinObjectSize(CallExpr *TheCall) {
+/// 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) {
llvm::APSInt Result;
// We can't check the value of a dependent argument.
- if (TheCall->getArg(1)->isTypeDependent() ||
- TheCall->getArg(1)->isValueDependent())
+ Expr *Arg = TheCall->getArg(ArgNum);
+ if (Arg->isTypeDependent() || Arg->isValueDependent())
return false;
// Check constant-ness first.
- if (SemaBuiltinConstantArg(TheCall, 1, Result))
+ if (SemaBuiltinConstantArg(TheCall, ArgNum, Result))
return true;
- Expr *Arg = TheCall->getArg(1);
- if (Result.getSExtValue() < 0 || Result.getSExtValue() > 3) {
+ if (Result.getSExtValue() < Low || Result.getSExtValue() > High)
return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
- << "0" << "3" << SourceRange(Arg->getLocStart(), Arg->getLocEnd());
- }
+ << Low << High << Arg->getSourceRange();
return false;
}
@@ -2081,10 +2213,7 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(VD)) {
if (const NamedDecl *ND = dyn_cast<NamedDecl>(PV->getDeclContext())) {
int PVIndex = PV->getFunctionScopeIndex() + 1;
- for (specific_attr_iterator<FormatAttr>
- i = ND->specific_attr_begin<FormatAttr>(),
- e = ND->specific_attr_end<FormatAttr>(); i != e ; ++i) {
- FormatAttr *PVFormat = *i;
+ for (const auto *PVFormat : ND->specific_attrs<FormatAttr>()) {
// adjust for implicit parameter
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND))
if (MD->isInstance())
@@ -2133,30 +2262,9 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
return SLCT_NotALiteral;
}
-
- case Stmt::ObjCMessageExprClass: {
- const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(E);
- if (const ObjCMethodDecl *MDecl = ME->getMethodDecl()) {
- if (const NamedDecl *ND = dyn_cast<NamedDecl>(MDecl)) {
- if (const FormatArgAttr *FA = ND->getAttr<FormatArgAttr>()) {
- unsigned ArgIndex = FA->getFormatIdx();
- if (ArgIndex <= ME->getNumArgs()) {
- const Expr *Arg = ME->getArg(ArgIndex-1);
- return checkFormatStringExpr(S, Arg, Args,
- HasVAListArg, format_idx,
- firstDataArg, Type, CallType,
- InFunctionCall, CheckedVarArgs);
- }
- }
- }
- }
-
- return SLCT_NotALiteral;
- }
-
case Stmt::ObjCStringLiteralClass:
case Stmt::StringLiteralClass: {
- const StringLiteral *StrE = NULL;
+ const StringLiteral *StrE = nullptr;
if (const ObjCStringLiteral *ObjCFExpr = dyn_cast<ObjCStringLiteral>(E))
StrE = ObjCFExpr->getString();
@@ -2177,32 +2285,6 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
}
}
-void
-Sema::CheckNonNullArguments(const NonNullAttr *NonNull,
- const Expr * const *ExprArgs,
- SourceLocation CallSiteLoc) {
- for (NonNullAttr::args_iterator i = NonNull->args_begin(),
- e = NonNull->args_end();
- i != e; ++i) {
- const Expr *ArgExpr = ExprArgs[*i];
-
- // As a special case, transparent unions initialized with zero are
- // considered null for the purposes of the nonnull attribute.
- if (const RecordType *UT = ArgExpr->getType()->getAsUnionType()) {
- if (UT->getDecl()->hasAttr<TransparentUnionAttr>())
- if (const CompoundLiteralExpr *CLE =
- dyn_cast<CompoundLiteralExpr>(ArgExpr))
- if (const InitListExpr *ILE =
- dyn_cast<InitListExpr>(CLE->getInitializer()))
- ArgExpr = ILE->getInit(0);
- }
-
- bool Result;
- if (ArgExpr->EvaluateAsBooleanCondition(Result, Context) && !Result)
- Diag(CallSiteLoc, diag::warn_null_arg) << ArgExpr->getSourceRange();
- }
-}
-
Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) {
return llvm::StringSwitch<FormatStringType>(Format->getType()->getName())
.Case("scanf", FST_Scanf)
@@ -2331,30 +2413,31 @@ public:
void DoneProcessing();
void HandleIncompleteSpecifier(const char *startSpecifier,
- unsigned specifierLen);
+ unsigned specifierLen) override;
void HandleInvalidLengthModifier(
- const analyze_format_string::FormatSpecifier &FS,
- const analyze_format_string::ConversionSpecifier &CS,
- const char *startSpecifier, unsigned specifierLen, unsigned DiagID);
+ const analyze_format_string::FormatSpecifier &FS,
+ const analyze_format_string::ConversionSpecifier &CS,
+ const char *startSpecifier, unsigned specifierLen,
+ unsigned DiagID);
void HandleNonStandardLengthModifier(
- const analyze_format_string::FormatSpecifier &FS,
- const char *startSpecifier, unsigned specifierLen);
+ const analyze_format_string::FormatSpecifier &FS,
+ const char *startSpecifier, unsigned specifierLen);
void HandleNonStandardConversionSpecifier(
- const analyze_format_string::ConversionSpecifier &CS,
- const char *startSpecifier, unsigned specifierLen);
+ const analyze_format_string::ConversionSpecifier &CS,
+ const char *startSpecifier, unsigned specifierLen);
- virtual void HandlePosition(const char *startPos, unsigned posLen);
+ void HandlePosition(const char *startPos, unsigned posLen) override;
- virtual void HandleInvalidPosition(const char *startSpecifier,
- unsigned specifierLen,
- analyze_format_string::PositionContext p);
+ void HandleInvalidPosition(const char *startSpecifier,
+ unsigned specifierLen,
+ analyze_format_string::PositionContext p) override;
- virtual void HandleZeroPosition(const char *startPos, unsigned posLen);
+ void HandleZeroPosition(const char *startPos, unsigned posLen) override;
- void HandleNullChar(const char *nullCharacter);
+ void HandleNullChar(const char *nullCharacter) override;
template <typename Range>
static void EmitFormatDiagnostic(Sema &S, bool inFunctionCall,
@@ -2390,9 +2473,6 @@ protected:
void EmitFormatDiagnostic(PartialDiagnostic PDiag, SourceLocation StringLoc,
bool IsStringLocation, Range StringRange,
ArrayRef<FixItHint> Fixit = None);
-
- void CheckPositionalAndNonpositionalArgs(
- const analyze_format_string::FormatSpecifier *FS);
};
}
@@ -2723,15 +2803,15 @@ public:
ObjCContext(isObjC)
{}
-
+
bool HandleInvalidPrintfConversionSpecifier(
const analyze_printf::PrintfSpecifier &FS,
const char *startSpecifier,
- unsigned specifierLen);
-
+ unsigned specifierLen) override;
+
bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
const char *startSpecifier,
- unsigned specifierLen);
+ unsigned specifierLen) override;
bool checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
const char *StartSpecifier,
unsigned SpecifierLen,
@@ -2751,7 +2831,7 @@ public:
const analyze_printf::OptionalFlag &flag,
const char *startSpecifier, unsigned specifierLen);
bool checkForCStrMembers(const analyze_printf::ArgType &AT,
- const Expr *E, const CharSourceRange &CSR);
+ const Expr *E);
};
}
@@ -2885,11 +2965,12 @@ CXXRecordMembersNamed(StringRef Name, Sema &S, QualType Ty) {
if (!RT)
return Results;
const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
- if (!RD)
+ if (!RD || !RD->getDefinition())
return Results;
- LookupResult R(S, &S.PP.getIdentifierTable().get(Name), SourceLocation(),
+ LookupResult R(S, &S.Context.Idents.get(Name), SourceLocation(),
Sema::LookupMemberName);
+ R.suppressDiagnostics();
// We just need to include all members of the right kind turned up by the
// filter, at this point.
@@ -2902,12 +2983,26 @@ CXXRecordMembersNamed(StringRef Name, Sema &S, QualType Ty) {
return Results;
}
+/// Check if we could call '.c_str()' on an object.
+///
+/// FIXME: This returns the wrong results in some cases (if cv-qualifiers don't
+/// allow the call, or if it would be ambiguous).
+bool Sema::hasCStrMethod(const Expr *E) {
+ typedef llvm::SmallPtrSet<CXXMethodDecl*, 1> MethodSet;
+ MethodSet Results =
+ CXXRecordMembersNamed<CXXMethodDecl>("c_str", *this, E->getType());
+ for (MethodSet::iterator MI = Results.begin(), ME = Results.end();
+ MI != ME; ++MI)
+ if ((*MI)->getMinRequiredArguments() == 0)
+ return true;
+ return false;
+}
+
// Check if a (w)string was passed when a (w)char* was needed, and offer a
// better diagnostic if so. AT is assumed to be valid.
// Returns true when a c_str() conversion method is found.
bool CheckPrintfHandler::checkForCStrMembers(
- const analyze_printf::ArgType &AT, const Expr *E,
- const CharSourceRange &CSR) {
+ const analyze_printf::ArgType &AT, const Expr *E) {
typedef llvm::SmallPtrSet<CXXMethodDecl*, 1> MethodSet;
MethodSet Results =
@@ -2916,11 +3011,10 @@ bool CheckPrintfHandler::checkForCStrMembers(
for (MethodSet::iterator MI = Results.begin(), ME = Results.end();
MI != ME; ++MI) {
const CXXMethodDecl *Method = *MI;
- if (Method->getNumParams() == 0 &&
- AT.matchesType(S.Context, Method->getResultType())) {
+ if (Method->getMinRequiredArguments() == 0 &&
+ AT.matchesType(S.Context, Method->getReturnType())) {
// FIXME: Suggest parens if the expression needs them.
- SourceLocation EndLoc =
- S.getPreprocessor().getLocForEndOfToken(E->getLocEnd());
+ SourceLocation EndLoc = S.getLocForEndOfToken(E->getLocEnd());
S.Diag(E->getLocStart(), diag::note_printf_c_str)
<< "c_str()"
<< FixItHint::CreateInsertion(EndLoc, ".c_str()");
@@ -2994,7 +3088,7 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier
ArgType(S.Context.IntTy) : ArgType::CStrTy;
if (AT.isValid() && !AT.matchesType(S.Context, Ex->getType()))
S.Diag(getLocationOfByte(CS.getStart()),
- diag::warn_printf_conversion_argument_type_mismatch)
+ diag::warn_format_conversion_argument_type_mismatch)
<< AT.getRepresentativeType(S.Context) << Ex->getType()
<< getSpecifierRange(startSpecifier, specifierLen)
<< Ex->getSourceRange();
@@ -3005,7 +3099,7 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier
const analyze_printf::ArgType &AT2 = ArgType::CStrTy;
if (AT2.isValid() && !AT2.matchesType(S.Context, Ex->getType()))
S.Diag(getLocationOfByte(CS.getStart()),
- diag::warn_printf_conversion_argument_type_mismatch)
+ diag::warn_format_conversion_argument_type_mismatch)
<< AT2.getRepresentativeType(S.Context) << Ex->getType()
<< getSpecifierRange(startSpecifier, specifierLen)
<< Ex->getSourceRange();
@@ -3169,6 +3263,13 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
ExprTy = S.Context.CharTy;
}
+ // Look through enums to their underlying type.
+ bool IsEnum = false;
+ if (auto EnumTy = ExprTy->getAs<EnumType>()) {
+ ExprTy = EnumTy->getDecl()->getIntegerType();
+ IsEnum = true;
+ }
+
// %C in an Objective-C context prints a unichar, not a wchar_t.
// If the argument is an integer of some kind, believe the %C and suggest
// a cast instead of changing the conversion specifier.
@@ -3241,8 +3342,8 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
// In this case, the specifier is wrong and should be changed to match
// the argument.
EmitFormatDiagnostic(
- S.PDiag(diag::warn_printf_conversion_argument_type_mismatch)
- << AT.getRepresentativeTypeName(S.Context) << IntendedTy
+ S.PDiag(diag::warn_format_conversion_argument_type_mismatch)
+ << AT.getRepresentativeTypeName(S.Context) << IntendedTy << IsEnum
<< E->getSourceRange(),
E->getLocStart(),
/*IsStringLocation*/false,
@@ -3283,7 +3384,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
Hints.push_back(FixItHint::CreateInsertion(E->getLocStart(),
CastFix.str()));
- SourceLocation After = S.PP.getLocForEndOfToken(E->getLocEnd());
+ SourceLocation After = S.getLocForEndOfToken(E->getLocEnd());
Hints.push_back(FixItHint::CreateInsertion(After, ")"));
}
@@ -3294,7 +3395,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
StringRef Name = cast<TypedefType>(ExprTy)->getDecl()->getName();
EmitFormatDiagnostic(S.PDiag(diag::warn_format_argument_needs_cast)
- << Name << IntendedTy
+ << Name << IntendedTy << IsEnum
<< E->getSourceRange(),
E->getLocStart(), /*IsStringLocation=*/false,
SpecRange, Hints);
@@ -3303,8 +3404,8 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
// specifier, but we've decided that the specifier is probably correct
// and we should cast instead. Just use the normal warning message.
EmitFormatDiagnostic(
- S.PDiag(diag::warn_printf_conversion_argument_type_mismatch)
- << AT.getRepresentativeTypeName(S.Context) << ExprTy
+ S.PDiag(diag::warn_format_conversion_argument_type_mismatch)
+ << AT.getRepresentativeTypeName(S.Context) << ExprTy << IsEnum
<< E->getSourceRange(),
E->getLocStart(), /*IsStringLocation*/false,
SpecRange, Hints);
@@ -3320,8 +3421,8 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
case Sema::VAK_Valid:
case Sema::VAK_ValidInCXX11:
EmitFormatDiagnostic(
- S.PDiag(diag::warn_printf_conversion_argument_type_mismatch)
- << AT.getRepresentativeTypeName(S.Context) << ExprTy
+ S.PDiag(diag::warn_format_conversion_argument_type_mismatch)
+ << AT.getRepresentativeTypeName(S.Context) << ExprTy << IsEnum
<< CSR
<< E->getSourceRange(),
E->getLocStart(), /*IsStringLocation*/false, CSR);
@@ -3337,7 +3438,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
<< CSR
<< E->getSourceRange(),
E->getLocStart(), /*IsStringLocation*/false, CSR);
- checkForCStrMembers(AT, E, CSR);
+ checkForCStrMembers(AT, E);
break;
case Sema::VAK_Invalid:
@@ -3389,14 +3490,14 @@ public:
bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
const char *startSpecifier,
- unsigned specifierLen);
+ unsigned specifierLen) override;
bool HandleInvalidScanfConversionSpecifier(
const analyze_scanf::ScanfSpecifier &FS,
const char *startSpecifier,
- unsigned specifierLen);
+ unsigned specifierLen) override;
- void HandleIncompleteScanList(const char *start, const char *end);
+ void HandleIncompleteScanList(const char *start, const char *end) override;
};
}
@@ -3501,8 +3602,9 @@ bool CheckScanfHandler::HandleScanfSpecifier(
const analyze_format_string::ArgType &AT = FS.getArgType(S.Context);
if (AT.isValid() && !AT.matchesType(S.Context, Ex->getType())) {
ScanfSpecifier fixedFS = FS;
- bool success = fixedFS.fixType(Ex->getType(), S.getLangOpts(),
- S.Context);
+ bool success = fixedFS.fixType(Ex->getType(),
+ Ex->IgnoreImpCasts()->getType(),
+ S.getLangOpts(), S.Context);
if (success) {
// Get the fix string from the fixed format specifier.
@@ -3511,8 +3613,8 @@ bool CheckScanfHandler::HandleScanfSpecifier(
fixedFS.toString(os);
EmitFormatDiagnostic(
- S.PDiag(diag::warn_printf_conversion_argument_type_mismatch)
- << AT.getRepresentativeTypeName(S.Context) << Ex->getType()
+ S.PDiag(diag::warn_format_conversion_argument_type_mismatch)
+ << AT.getRepresentativeTypeName(S.Context) << Ex->getType() << false
<< Ex->getSourceRange(),
Ex->getLocStart(),
/*IsStringLocation*/false,
@@ -3522,8 +3624,8 @@ bool CheckScanfHandler::HandleScanfSpecifier(
os.str()));
} else {
EmitFormatDiagnostic(
- S.PDiag(diag::warn_printf_conversion_argument_type_mismatch)
- << AT.getRepresentativeTypeName(S.Context) << Ex->getType()
+ S.PDiag(diag::warn_format_conversion_argument_type_mismatch)
+ << AT.getRepresentativeTypeName(S.Context) << Ex->getType() << false
<< Ex->getSourceRange(),
Ex->getLocStart(),
/*IsStringLocation*/false,
@@ -3554,9 +3656,25 @@ void Sema::CheckFormatString(const StringLiteral *FExpr,
// Str - The format string. NOTE: this is NOT null-terminated!
StringRef StrRef = FExpr->getString();
const char *Str = StrRef.data();
- unsigned StrLen = StrRef.size();
+ // Account for cases where the string literal is truncated in a declaration.
+ const ConstantArrayType *T = Context.getAsConstantArrayType(FExpr->getType());
+ assert(T && "String literal not of constant array type!");
+ size_t TypeSize = T->getSize().getZExtValue();
+ size_t StrLen = std::min(std::max(TypeSize, size_t(1)) - 1, StrRef.size());
const unsigned numDataArgs = Args.size() - firstDataArg;
-
+
+ // Emit a warning if the string literal is truncated and does not contain an
+ // embedded null character.
+ if (TypeSize <= StrRef.size() &&
+ StrRef.substr(0, TypeSize).find('\0') == StringRef::npos) {
+ CheckFormatHandler::EmitFormatDiagnostic(
+ *this, inFunctionCall, Args[format_idx],
+ PDiag(diag::warn_printf_format_string_not_null_terminated),
+ FExpr->getLocStart(),
+ /*IsStringLocation=*/true, OrigFormatExpr->getSourceRange());
+ return;
+ }
+
// CHECK: empty format string?
if (StrLen == 0 && numDataArgs > 0) {
CheckFormatHandler::EmitFormatDiagnostic(
@@ -3588,17 +3706,452 @@ void Sema::CheckFormatString(const StringLiteral *FExpr,
} // TODO: handle other formats
}
+//===--- CHECK: Warn on use of wrong absolute value function. -------------===//
+
+// Returns the related absolute value function that is larger, of 0 if one
+// does not exist.
+static unsigned getLargerAbsoluteValueFunction(unsigned AbsFunction) {
+ switch (AbsFunction) {
+ default:
+ return 0;
+
+ case Builtin::BI__builtin_abs:
+ return Builtin::BI__builtin_labs;
+ case Builtin::BI__builtin_labs:
+ return Builtin::BI__builtin_llabs;
+ case Builtin::BI__builtin_llabs:
+ return 0;
+
+ case Builtin::BI__builtin_fabsf:
+ return Builtin::BI__builtin_fabs;
+ case Builtin::BI__builtin_fabs:
+ return Builtin::BI__builtin_fabsl;
+ case Builtin::BI__builtin_fabsl:
+ return 0;
+
+ case Builtin::BI__builtin_cabsf:
+ return Builtin::BI__builtin_cabs;
+ case Builtin::BI__builtin_cabs:
+ return Builtin::BI__builtin_cabsl;
+ case Builtin::BI__builtin_cabsl:
+ return 0;
+
+ case Builtin::BIabs:
+ return Builtin::BIlabs;
+ case Builtin::BIlabs:
+ return Builtin::BIllabs;
+ case Builtin::BIllabs:
+ return 0;
+
+ case Builtin::BIfabsf:
+ return Builtin::BIfabs;
+ case Builtin::BIfabs:
+ return Builtin::BIfabsl;
+ case Builtin::BIfabsl:
+ return 0;
+
+ case Builtin::BIcabsf:
+ return Builtin::BIcabs;
+ case Builtin::BIcabs:
+ return Builtin::BIcabsl;
+ case Builtin::BIcabsl:
+ return 0;
+ }
+}
+
+// Returns the argument type of the absolute value function.
+static QualType getAbsoluteValueArgumentType(ASTContext &Context,
+ unsigned AbsType) {
+ if (AbsType == 0)
+ return QualType();
+
+ ASTContext::GetBuiltinTypeError Error = ASTContext::GE_None;
+ QualType BuiltinType = Context.GetBuiltinType(AbsType, Error);
+ if (Error != ASTContext::GE_None)
+ return QualType();
+
+ const FunctionProtoType *FT = BuiltinType->getAs<FunctionProtoType>();
+ if (!FT)
+ return QualType();
+
+ if (FT->getNumParams() != 1)
+ return QualType();
+
+ return FT->getParamType(0);
+}
+
+// Returns the best absolute value function, or zero, based on type and
+// current absolute value function.
+static unsigned getBestAbsFunction(ASTContext &Context, QualType ArgType,
+ unsigned AbsFunctionKind) {
+ unsigned BestKind = 0;
+ uint64_t ArgSize = Context.getTypeSize(ArgType);
+ for (unsigned Kind = AbsFunctionKind; Kind != 0;
+ Kind = getLargerAbsoluteValueFunction(Kind)) {
+ QualType ParamType = getAbsoluteValueArgumentType(Context, Kind);
+ if (Context.getTypeSize(ParamType) >= ArgSize) {
+ if (BestKind == 0)
+ BestKind = Kind;
+ else if (Context.hasSameType(ParamType, ArgType)) {
+ BestKind = Kind;
+ break;
+ }
+ }
+ }
+ return BestKind;
+}
+
+enum AbsoluteValueKind {
+ AVK_Integer,
+ AVK_Floating,
+ AVK_Complex
+};
+
+static AbsoluteValueKind getAbsoluteValueKind(QualType T) {
+ if (T->isIntegralOrEnumerationType())
+ return AVK_Integer;
+ if (T->isRealFloatingType())
+ return AVK_Floating;
+ if (T->isAnyComplexType())
+ return AVK_Complex;
+
+ llvm_unreachable("Type not integer, floating, or complex");
+}
+
+// Changes the absolute value function to a different type. Preserves whether
+// the function is a builtin.
+static unsigned changeAbsFunction(unsigned AbsKind,
+ AbsoluteValueKind ValueKind) {
+ switch (ValueKind) {
+ case AVK_Integer:
+ switch (AbsKind) {
+ default:
+ return 0;
+ case Builtin::BI__builtin_fabsf:
+ case Builtin::BI__builtin_fabs:
+ case Builtin::BI__builtin_fabsl:
+ case Builtin::BI__builtin_cabsf:
+ case Builtin::BI__builtin_cabs:
+ case Builtin::BI__builtin_cabsl:
+ return Builtin::BI__builtin_abs;
+ case Builtin::BIfabsf:
+ case Builtin::BIfabs:
+ case Builtin::BIfabsl:
+ case Builtin::BIcabsf:
+ case Builtin::BIcabs:
+ case Builtin::BIcabsl:
+ return Builtin::BIabs;
+ }
+ case AVK_Floating:
+ switch (AbsKind) {
+ default:
+ return 0;
+ case Builtin::BI__builtin_abs:
+ case Builtin::BI__builtin_labs:
+ case Builtin::BI__builtin_llabs:
+ case Builtin::BI__builtin_cabsf:
+ case Builtin::BI__builtin_cabs:
+ case Builtin::BI__builtin_cabsl:
+ return Builtin::BI__builtin_fabsf;
+ case Builtin::BIabs:
+ case Builtin::BIlabs:
+ case Builtin::BIllabs:
+ case Builtin::BIcabsf:
+ case Builtin::BIcabs:
+ case Builtin::BIcabsl:
+ return Builtin::BIfabsf;
+ }
+ case AVK_Complex:
+ switch (AbsKind) {
+ default:
+ return 0;
+ case Builtin::BI__builtin_abs:
+ case Builtin::BI__builtin_labs:
+ case Builtin::BI__builtin_llabs:
+ case Builtin::BI__builtin_fabsf:
+ case Builtin::BI__builtin_fabs:
+ case Builtin::BI__builtin_fabsl:
+ return Builtin::BI__builtin_cabsf;
+ case Builtin::BIabs:
+ case Builtin::BIlabs:
+ case Builtin::BIllabs:
+ case Builtin::BIfabsf:
+ case Builtin::BIfabs:
+ case Builtin::BIfabsl:
+ return Builtin::BIcabsf;
+ }
+ }
+ llvm_unreachable("Unable to convert function");
+}
+
+static unsigned getAbsoluteValueFunctionKind(const FunctionDecl *FDecl) {
+ const IdentifierInfo *FnInfo = FDecl->getIdentifier();
+ if (!FnInfo)
+ return 0;
+
+ switch (FDecl->getBuiltinID()) {
+ default:
+ return 0;
+ case Builtin::BI__builtin_abs:
+ case Builtin::BI__builtin_fabs:
+ case Builtin::BI__builtin_fabsf:
+ case Builtin::BI__builtin_fabsl:
+ case Builtin::BI__builtin_labs:
+ case Builtin::BI__builtin_llabs:
+ case Builtin::BI__builtin_cabs:
+ case Builtin::BI__builtin_cabsf:
+ case Builtin::BI__builtin_cabsl:
+ case Builtin::BIabs:
+ case Builtin::BIlabs:
+ case Builtin::BIllabs:
+ case Builtin::BIfabs:
+ case Builtin::BIfabsf:
+ case Builtin::BIfabsl:
+ case Builtin::BIcabs:
+ case Builtin::BIcabsf:
+ case Builtin::BIcabsl:
+ return FDecl->getBuiltinID();
+ }
+ llvm_unreachable("Unknown Builtin type");
+}
+
+// If the replacement is valid, emit a note with replacement function.
+// Additionally, suggest including the proper header if not already included.
+static void emitReplacement(Sema &S, SourceLocation Loc, SourceRange Range,
+ unsigned AbsKind, QualType ArgType) {
+ bool EmitHeaderHint = true;
+ const char *HeaderName = nullptr;
+ const char *FunctionName = nullptr;
+ if (S.getLangOpts().CPlusPlus && !ArgType->isAnyComplexType()) {
+ FunctionName = "std::abs";
+ if (ArgType->isIntegralOrEnumerationType()) {
+ HeaderName = "cstdlib";
+ } else if (ArgType->isRealFloatingType()) {
+ HeaderName = "cmath";
+ } else {
+ llvm_unreachable("Invalid Type");
+ }
+
+ // Lookup all std::abs
+ if (NamespaceDecl *Std = S.getStdNamespace()) {
+ LookupResult R(S, &S.Context.Idents.get("abs"), Loc, Sema::LookupAnyName);
+ R.suppressDiagnostics();
+ S.LookupQualifiedName(R, Std);
+
+ for (const auto *I : R) {
+ const FunctionDecl *FDecl = nullptr;
+ if (const UsingShadowDecl *UsingD = dyn_cast<UsingShadowDecl>(I)) {
+ FDecl = dyn_cast<FunctionDecl>(UsingD->getTargetDecl());
+ } else {
+ FDecl = dyn_cast<FunctionDecl>(I);
+ }
+ if (!FDecl)
+ continue;
+
+ // Found std::abs(), check that they are the right ones.
+ if (FDecl->getNumParams() != 1)
+ continue;
+
+ // Check that the parameter type can handle the argument.
+ QualType ParamType = FDecl->getParamDecl(0)->getType();
+ if (getAbsoluteValueKind(ArgType) == getAbsoluteValueKind(ParamType) &&
+ S.Context.getTypeSize(ArgType) <=
+ S.Context.getTypeSize(ParamType)) {
+ // Found a function, don't need the header hint.
+ EmitHeaderHint = false;
+ break;
+ }
+ }
+ }
+ } else {
+ FunctionName = S.Context.BuiltinInfo.GetName(AbsKind);
+ HeaderName = S.Context.BuiltinInfo.getHeaderName(AbsKind);
+
+ if (HeaderName) {
+ DeclarationName DN(&S.Context.Idents.get(FunctionName));
+ LookupResult R(S, DN, Loc, Sema::LookupAnyName);
+ R.suppressDiagnostics();
+ S.LookupName(R, S.getCurScope());
+
+ if (R.isSingleResult()) {
+ FunctionDecl *FD = dyn_cast<FunctionDecl>(R.getFoundDecl());
+ if (FD && FD->getBuiltinID() == AbsKind) {
+ EmitHeaderHint = false;
+ } else {
+ return;
+ }
+ } else if (!R.empty()) {
+ return;
+ }
+ }
+ }
+
+ S.Diag(Loc, diag::note_replace_abs_function)
+ << FunctionName << FixItHint::CreateReplacement(Range, FunctionName);
+
+ if (!HeaderName)
+ return;
+
+ if (!EmitHeaderHint)
+ return;
+
+ S.Diag(Loc, diag::note_include_header_or_declare) << HeaderName
+ << FunctionName;
+}
+
+static bool IsFunctionStdAbs(const FunctionDecl *FDecl) {
+ if (!FDecl)
+ return false;
+
+ if (!FDecl->getIdentifier() || !FDecl->getIdentifier()->isStr("abs"))
+ return false;
+
+ const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(FDecl->getDeclContext());
+
+ while (ND && ND->isInlineNamespace()) {
+ ND = dyn_cast<NamespaceDecl>(ND->getDeclContext());
+ }
+
+ if (!ND || !ND->getIdentifier() || !ND->getIdentifier()->isStr("std"))
+ return false;
+
+ if (!isa<TranslationUnitDecl>(ND->getDeclContext()))
+ return false;
+
+ return true;
+}
+
+// Warn when using the wrong abs() function.
+void Sema::CheckAbsoluteValueFunction(const CallExpr *Call,
+ const FunctionDecl *FDecl,
+ IdentifierInfo *FnInfo) {
+ if (Call->getNumArgs() != 1)
+ return;
+
+ unsigned AbsKind = getAbsoluteValueFunctionKind(FDecl);
+ bool IsStdAbs = IsFunctionStdAbs(FDecl);
+ if (AbsKind == 0 && !IsStdAbs)
+ return;
+
+ QualType ArgType = Call->getArg(0)->IgnoreParenImpCasts()->getType();
+ QualType ParamType = Call->getArg(0)->getType();
+
+ // Unsigned types cannot be negative. Suggest removing the absolute value
+ // function call.
+ if (ArgType->isUnsignedIntegerType()) {
+ const char *FunctionName =
+ IsStdAbs ? "std::abs" : Context.BuiltinInfo.GetName(AbsKind);
+ Diag(Call->getExprLoc(), diag::warn_unsigned_abs) << ArgType << ParamType;
+ Diag(Call->getExprLoc(), diag::note_remove_abs)
+ << FunctionName
+ << FixItHint::CreateRemoval(Call->getCallee()->getSourceRange());
+ return;
+ }
+
+ // std::abs has overloads which prevent most of the absolute value problems
+ // from occurring.
+ if (IsStdAbs)
+ return;
+
+ AbsoluteValueKind ArgValueKind = getAbsoluteValueKind(ArgType);
+ AbsoluteValueKind ParamValueKind = getAbsoluteValueKind(ParamType);
+
+ // The argument and parameter are the same kind. Check if they are the right
+ // size.
+ if (ArgValueKind == ParamValueKind) {
+ if (Context.getTypeSize(ArgType) <= Context.getTypeSize(ParamType))
+ return;
+
+ unsigned NewAbsKind = getBestAbsFunction(Context, ArgType, AbsKind);
+ Diag(Call->getExprLoc(), diag::warn_abs_too_small)
+ << FDecl << ArgType << ParamType;
+
+ if (NewAbsKind == 0)
+ return;
+
+ emitReplacement(*this, Call->getExprLoc(),
+ Call->getCallee()->getSourceRange(), NewAbsKind, ArgType);
+ return;
+ }
+
+ // ArgValueKind != ParamValueKind
+ // The wrong type of absolute value function was used. Attempt to find the
+ // proper one.
+ unsigned NewAbsKind = changeAbsFunction(AbsKind, ArgValueKind);
+ NewAbsKind = getBestAbsFunction(Context, ArgType, NewAbsKind);
+ if (NewAbsKind == 0)
+ return;
+
+ Diag(Call->getExprLoc(), diag::warn_wrong_absolute_value_type)
+ << FDecl << ParamValueKind << ArgValueKind;
+
+ emitReplacement(*this, Call->getExprLoc(),
+ Call->getCallee()->getSourceRange(), NewAbsKind, ArgType);
+ return;
+}
+
//===--- CHECK: Standard memory functions ---------------------------------===//
-/// \brief Determine whether the given type is a dynamic class type (e.g.,
-/// whether it has a vtable).
-static bool isDynamicClassType(QualType T) {
- if (CXXRecordDecl *Record = T->getAsCXXRecordDecl())
- if (CXXRecordDecl *Definition = Record->getDefinition())
- if (Definition->isDynamicClass())
- return true;
-
- return false;
+/// \brief 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))`.
+static bool CheckMemorySizeofForComparison(Sema &S, const Expr *E,
+ IdentifierInfo *FnName,
+ SourceLocation FnLoc,
+ SourceLocation RParenLoc) {
+ const BinaryOperator *Size = dyn_cast<BinaryOperator>(E);
+ if (!Size)
+ return false;
+
+ // if E is binop and op is >, <, >=, <=, ==, &&, ||:
+ if (!Size->isComparisonOp() && !Size->isEqualityOp() && !Size->isLogicalOp())
+ return false;
+
+ SourceRange SizeRange = Size->getSourceRange();
+ S.Diag(Size->getOperatorLoc(), diag::warn_memsize_comparison)
+ << SizeRange << FnName;
+ S.Diag(FnLoc, diag::note_memsize_comparison_paren)
+ << FnName << FixItHint::CreateInsertion(
+ S.getLocForEndOfToken(Size->getLHS()->getLocEnd()), ")")
+ << FixItHint::CreateRemoval(RParenLoc);
+ S.Diag(SizeRange.getBegin(), diag::note_memsize_comparison_cast_silence)
+ << FixItHint::CreateInsertion(SizeRange.getBegin(), "(size_t)(")
+ << FixItHint::CreateInsertion(S.getLocForEndOfToken(SizeRange.getEnd()),
+ ")");
+
+ return true;
+}
+
+/// \brief 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) {
+ // Look through array types while ignoring qualifiers.
+ const Type *Ty = T->getBaseElementTypeUnsafe();
+ IsContained = false;
+
+ const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
+ RD = RD ? RD->getDefinition() : nullptr;
+ if (!RD)
+ return nullptr;
+
+ if (RD->isDynamicClass())
+ return RD;
+
+ // Check all the fields. If any bases were dynamic, the class is dynamic.
+ // It's impossible for a class to transitively contain itself by value, so
+ // infinite recursion is impossible.
+ for (auto *FD : RD->fields()) {
+ bool SubContained;
+ if (const CXXRecordDecl *ContainedRD =
+ getContainedDynamicClass(FD->getType(), SubContained)) {
+ IsContained = true;
+ return ContainedRD;
+ }
+ }
+
+ return nullptr;
}
/// \brief If E is a sizeof expression, returns its argument expression,
@@ -3609,7 +4162,7 @@ static const Expr *getSizeOfExprArg(const Expr* E) {
if (SizeOf->getKind() == clang::UETT_SizeOf && !SizeOf->isArgumentType())
return SizeOf->getArgumentExpr()->IgnoreParenImpCasts();
- return 0;
+ return nullptr;
}
/// \brief If E is a sizeof expression, returns its argument type.
@@ -3645,6 +4198,10 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
unsigned LenArg = (BId == Builtin::BIstrndup ? 1 : 2);
const Expr *LenExpr = Call->getArg(LenArg)->IgnoreParenImpCasts();
+ if (CheckMemorySizeofForComparison(*this, LenExpr, FnName,
+ Call->getLocStart(), Call->getRParenLoc()))
+ return;
+
// We have special checking when the length is a sizeof expression.
QualType SizeOfArgTy = getSizeOfArgType(LenExpr);
const Expr *SizeOfArg = getSizeOfExprArg(LenExpr);
@@ -3668,8 +4225,8 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
// expression IDs can be expensive, we only do this if the diagnostic is
// enabled.
if (SizeOfArg &&
- Diags.getDiagnosticLevel(diag::warn_sizeof_pointer_expr_memaccess,
- SizeOfArg->getExprLoc())) {
+ !Diags.isIgnored(diag::warn_sizeof_pointer_expr_memaccess,
+ SizeOfArg->getExprLoc())) {
// We only compute IDs for expressions if the warning is enabled, and
// cache the sizeof arg's ID.
if (SizeOfArgID == llvm::FoldingSetNodeID())
@@ -3695,7 +4252,7 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
SourceLocation SL = SizeOfArg->getExprLoc();
SourceRange DSR = Dest->getSourceRange();
SourceRange SSR = SizeOfArg->getSourceRange();
- SourceManager &SM = PP.getSourceManager();
+ SourceManager &SM = getSourceManager();
if (SM.isMacroArgExpansion(SL)) {
ReadableName = Lexer::getImmediateMacroName(SL, SM, LangOpts);
@@ -3738,7 +4295,9 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
}
// Always complain about dynamic classes.
- if (isDynamicClassType(PointeeTy)) {
+ bool IsContained;
+ if (const CXXRecordDecl *ContainedRD =
+ getContainedDynamicClass(PointeeTy, IsContained)) {
unsigned OperationType = 0;
// "overwritten" if we're warning about the destination for any call
@@ -3756,8 +4315,7 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
Dest->getExprLoc(), Dest,
PDiag(diag::warn_dyn_class_memaccess)
<< (BId == Builtin::BImemcmp ? ArgIdx + 2 : ArgIdx)
- << FnName << PointeeTy
- << OperationType
+ << FnName << IsContained << ContainedRD << OperationType
<< Call->getCallee()->getSourceRange());
} else if (PointeeTy.hasNonTrivialObjCLifetime() &&
BId != Builtin::BImemset)
@@ -3827,7 +4385,11 @@ void Sema::CheckStrlcpycatArguments(const CallExpr *Call,
const Expr *SrcArg = ignoreLiteralAdditions(Call->getArg(1), Context);
const Expr *SizeArg = ignoreLiteralAdditions(Call->getArg(2), Context);
- const Expr *CompareWithSrc = NULL;
+ const Expr *CompareWithSrc = nullptr;
+
+ if (CheckMemorySizeofForComparison(*this, SizeArg, FnName,
+ Call->getLocStart(), Call->getRParenLoc()))
+ return;
// Look for 'strlcpy(dst, x, sizeof(x))'
if (const Expr *Ex = getSizeOfExprArg(SizeArg))
@@ -3835,8 +4397,8 @@ void Sema::CheckStrlcpycatArguments(const CallExpr *Call,
else {
// Look for 'strlcpy(dst, x, strlen(x))'
if (const CallExpr *SizeCall = dyn_cast<CallExpr>(SizeArg)) {
- if (SizeCall->isBuiltinCall() == Builtin::BIstrlen
- && SizeCall->getNumArgs() == 1)
+ if (SizeCall->getBuiltinCallee() == Builtin::BIstrlen &&
+ SizeCall->getNumArgs() == 1)
CompareWithSrc = ignoreLiteralAdditions(SizeCall->getArg(0), Context);
}
}
@@ -3872,7 +4434,7 @@ void Sema::CheckStrlcpycatArguments(const CallExpr *Call,
SmallString<128> sizeString;
llvm::raw_svector_ostream OS(sizeString);
OS << "sizeof(";
- DstArg->printPretty(OS, 0, getPrintingPolicy());
+ DstArg->printPretty(OS, nullptr, getPrintingPolicy());
OS << ")";
Diag(OriginalSizeArg->getLocStart(), diag::note_strlcpycat_wrong_size)
@@ -3892,10 +4454,10 @@ static const Expr *getStrlenExprArg(const Expr *E) {
if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
const FunctionDecl *FD = CE->getDirectCallee();
if (!FD || FD->getMemoryFunctionKind() != Builtin::BIstrlen)
- return 0;
+ return nullptr;
return CE->getArg(0)->IgnoreParenCasts();
}
- return 0;
+ return nullptr;
}
// Warn on anti-patterns as the 'size' argument to strncat.
@@ -3910,6 +4472,10 @@ void Sema::CheckStrncatArguments(const CallExpr *CE,
const Expr *SrcArg = CE->getArg(1)->IgnoreParenCasts();
const Expr *LenArg = CE->getArg(2)->IgnoreParenCasts();
+ if (CheckMemorySizeofForComparison(*this, LenArg, FnName, CE->getLocStart(),
+ CE->getRParenLoc()))
+ return;
+
// Identify common expressions, which are wrongly used as the size argument
// to strncat and may lead to buffer overflows.
unsigned PatternType = 0;
@@ -3940,7 +4506,7 @@ void Sema::CheckStrncatArguments(const CallExpr *CE,
// Generate the diagnostic.
SourceLocation SL = LenArg->getLocStart();
SourceRange SR = LenArg->getSourceRange();
- SourceManager &SM = PP.getSourceManager();
+ SourceManager &SM = getSourceManager();
// If the function is defined as a builtin macro, do not show macro expansion.
if (SM.isMacroArgExpansion(SL)) {
@@ -3969,10 +4535,10 @@ void Sema::CheckStrncatArguments(const CallExpr *CE,
SmallString<128> sizeString;
llvm::raw_svector_ostream OS(sizeString);
OS << "sizeof(";
- DstArg->printPretty(OS, 0, getPrintingPolicy());
+ DstArg->printPretty(OS, nullptr, getPrintingPolicy());
OS << ") - ";
OS << "strlen(";
- DstArg->printPretty(OS, 0, getPrintingPolicy());
+ DstArg->printPretty(OS, nullptr, getPrintingPolicy());
OS << ") - 1";
Diag(SL, diag::note_strncat_wrong_size)
@@ -3988,23 +4554,23 @@ static Expr *EvalAddr(Expr* E, SmallVectorImpl<DeclRefExpr *> &refVars,
/// CheckReturnStackAddr - Check if a return statement returns the address
/// of a stack variable.
-void
-Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
- SourceLocation ReturnLoc) {
+static void
+CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType,
+ SourceLocation ReturnLoc) {
- Expr *stackE = 0;
+ Expr *stackE = nullptr;
SmallVector<DeclRefExpr *, 8> refVars;
// Perform checking for returned stack addresses, local blocks,
// label addresses or references to temporaries.
if (lhsType->isPointerType() ||
- (!getLangOpts().ObjCAutoRefCount && lhsType->isBlockPointerType())) {
- stackE = EvalAddr(RetValExp, refVars, /*ParentDecl=*/0);
+ (!S.getLangOpts().ObjCAutoRefCount && lhsType->isBlockPointerType())) {
+ stackE = EvalAddr(RetValExp, refVars, /*ParentDecl=*/nullptr);
} else if (lhsType->isReferenceType()) {
- stackE = EvalVal(RetValExp, refVars, /*ParentDecl=*/0);
+ stackE = EvalVal(RetValExp, refVars, /*ParentDecl=*/nullptr);
}
- if (stackE == 0)
+ if (!stackE)
return; // Nothing suspicious was found.
SourceLocation diagLoc;
@@ -4022,16 +4588,16 @@ Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
}
if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(stackE)) { //address of local var.
- Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_stack_ref
+ S.Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_stack_ref
: diag::warn_ret_stack_addr)
<< DR->getDecl()->getDeclName() << diagRange;
} else if (isa<BlockExpr>(stackE)) { // local block.
- Diag(diagLoc, diag::err_ret_local_block) << diagRange;
+ S.Diag(diagLoc, diag::err_ret_local_block) << diagRange;
} else if (isa<AddrLabelExpr>(stackE)) { // address of label.
- Diag(diagLoc, diag::warn_ret_addr_label) << diagRange;
+ S.Diag(diagLoc, diag::warn_ret_addr_label) << diagRange;
} else { // local temporary.
- Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_local_temp_ref
- : diag::warn_ret_local_temp_addr)
+ S.Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_local_temp_ref
+ : diag::warn_ret_local_temp_addr)
<< diagRange;
}
@@ -4044,8 +4610,8 @@ Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
// show the range of the expression.
SourceRange range = (i < e-1) ? refVars[i+1]->getSourceRange()
: stackE->getSourceRange();
- Diag(VD->getLocation(), diag::note_ref_var_local_bind)
- << VD->getDeclName() << range;
+ S.Diag(VD->getLocation(), diag::note_ref_var_local_bind)
+ << VD->getDeclName() << range;
}
}
@@ -4078,7 +4644,7 @@ Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
Decl *ParentDecl) {
if (E->isTypeDependent())
- return NULL;
+ return nullptr;
// We should only be called for evaluating pointer expressions.
assert((E->getType()->isAnyPointerType() ||
@@ -4095,6 +4661,10 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
case Stmt::DeclRefExprClass: {
DeclRefExpr *DR = cast<DeclRefExpr>(E);
+ // If we leave the immediate function, the lifetime isn't about to end.
+ if (DR->refersToEnclosingLocal())
+ return nullptr;
+
if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl()))
// If this is a reference variable, follow through to the expression that
// it points to.
@@ -4105,7 +4675,7 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
return EvalAddr(V->getInit(), refVars, ParentDecl);
}
- return NULL;
+ return nullptr;
}
case Stmt::UnaryOperatorClass: {
@@ -4116,7 +4686,7 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
if (U->getOpcode() == UO_AddrOf)
return EvalVal(U->getSubExpr(), refVars, ParentDecl);
else
- return NULL;
+ return nullptr;
}
case Stmt::BinaryOperatorClass: {
@@ -4126,7 +4696,7 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
BinaryOperatorKind op = B->getOpcode();
if (op != BO_Add && op != BO_Sub)
- return NULL;
+ return nullptr;
Expr *Base = B->getLHS();
@@ -4144,24 +4714,25 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
ConditionalOperator *C = cast<ConditionalOperator>(E);
// Handle the GNU extension for missing LHS.
- if (Expr *lhsExpr = C->getLHS()) {
- // In C++, we can have a throw-expression, which has 'void' type.
- if (!lhsExpr->getType()->isVoidType())
- if (Expr* LHS = EvalAddr(lhsExpr, refVars, ParentDecl))
+ // FIXME: That isn't a ConditionalOperator, so doesn't get here.
+ if (Expr *LHSExpr = C->getLHS()) {
+ // In C++, we can have a throw-expression, which has 'void' type.
+ if (!LHSExpr->getType()->isVoidType())
+ if (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 NULL;
+ return nullptr;
return EvalAddr(C->getRHS(), refVars, ParentDecl);
}
-
+
case Stmt::BlockExprClass:
if (cast<BlockExpr>(E)->getBlockDecl()->hasCaptures())
return E; // local block.
- return NULL;
+ return nullptr;
case Stmt::AddrLabelExprClass:
return E; // address of label.
@@ -4182,7 +4753,6 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
case Stmt::CXXReinterpretCastExprClass: {
Expr* SubExpr = cast<CastExpr>(E)->getSubExpr();
switch (cast<CastExpr>(E)->getCastKind()) {
- case CK_BitCast:
case CK_LValueToRValue:
case CK_NoOp:
case CK_BaseToDerived:
@@ -4197,8 +4767,16 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
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 0;
+ return nullptr;
}
}
@@ -4212,7 +4790,7 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
// Everything else: we simply don't reason about them.
default:
- return NULL;
+ return nullptr;
}
}
@@ -4238,7 +4816,7 @@ do {
E = IE->getSubExpr();
continue;
}
- return NULL;
+ return nullptr;
}
case Stmt::ExprWithCleanupsClass:
@@ -4250,6 +4828,10 @@ do {
// local storage within the function, and if so, return the expression.
DeclRefExpr *DR = cast<DeclRefExpr>(E);
+ // If we leave the immediate function, the lifetime isn't about to end.
+ if (DR->refersToEnclosingLocal())
+ return nullptr;
+
if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl())) {
// Check if it refers to itself, e.g. "int& i = i;".
if (V == ParentDecl)
@@ -4269,7 +4851,7 @@ do {
}
}
- return NULL;
+ return nullptr;
}
case Stmt::UnaryOperatorClass: {
@@ -4281,7 +4863,7 @@ do {
if (U->getOpcode() == UO_Deref)
return EvalAddr(U->getSubExpr(), refVars, ParentDecl);
- return NULL;
+ return nullptr;
}
case Stmt::ArraySubscriptExprClass: {
@@ -4297,9 +4879,16 @@ do {
ConditionalOperator *C = cast<ConditionalOperator>(E);
// Handle the GNU extension for missing LHS.
- if (Expr *lhsExpr = C->getLHS())
- if (Expr *LHS = EvalVal(lhsExpr, refVars, ParentDecl))
- return LHS;
+ if (Expr *LHSExpr = C->getLHS()) {
+ // In C++, we can have a throw-expression, which has 'void' type.
+ if (!LHSExpr->getType()->isVoidType())
+ if (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);
}
@@ -4310,12 +4899,12 @@ do {
// Check for indirect access. We only want direct field accesses.
if (M->isArrow())
- return NULL;
+ 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 NULL;
+ return nullptr;
return EvalVal(M->getBase(), refVars, ParentDecl);
}
@@ -4335,11 +4924,43 @@ do {
return E;
// Everything else: we simply don't reason about them.
- return NULL;
+ 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) &&
+ CheckNonNullExpr(*this, RetValExp))
+ Diag(ReturnLoc, diag::warn_null_ret)
+ << (isObjCMethod ? 1 : 0) << RetValExp->getSourceRange();
+
+ // C++11 [basic.stc.dynamic.allocation]p4:
+ // If an allocation function declared with a non-throwing
+ // exception-specification fails to allocate storage, it shall return
+ // a null pointer. Any other allocation function that fails to allocate
+ // storage shall indicate failure only by throwing an exception [...]
+ if (FD) {
+ OverloadedOperatorKind Op = FD->getOverloadedOperator();
+ if (Op == OO_New || Op == OO_Array_New) {
+ const FunctionProtoType *Proto
+ = FD->getType()->castAs<FunctionProtoType>();
+ if (!Proto->isNothrow(Context, /*ResultIfDependent*/true) &&
+ CheckNonNullExpr(*this, RetValExp))
+ Diag(ReturnLoc, diag::warn_operator_new_returns_null)
+ << FD << getLangOpts().CPlusPlus11;
+ }
+ }
+}
+
//===--- CHECK: Floating-Point comparisons (-Wfloat-equal) ---------------===//
/// Check for comparisons of floating point operands using != and ==.
@@ -4372,11 +4993,11 @@ void Sema::CheckFloatComparison(SourceLocation Loc, Expr* LHS, Expr *RHS) {
// Check for comparisons with builtin types.
if (CallExpr* CL = dyn_cast<CallExpr>(LeftExprSansParen))
- if (CL->isBuiltinCall())
+ if (CL->getBuiltinCallee())
return;
if (CallExpr* CR = dyn_cast<CallExpr>(RightExprSansParen))
- if (CR->isBuiltinCall())
+ if (CR->getBuiltinCallee())
return;
// Emit the diagnostic.
@@ -4421,6 +5042,8 @@ struct IntRange {
T = VT->getElementType().getTypePtr();
if (const ComplexType *CT = dyn_cast<ComplexType>(T))
T = CT->getElementType().getTypePtr();
+ if (const AtomicType *AT = dyn_cast<AtomicType>(T))
+ T = AT->getValueType().getTypePtr();
// For enum types, use the known bit width of the enumerators.
if (const EnumType *ET = dyn_cast<EnumType>(T)) {
@@ -4456,6 +5079,8 @@ struct IntRange {
T = VT->getElementType().getTypePtr();
if (const ComplexType *CT = dyn_cast<ComplexType>(T))
T = CT->getElementType().getTypePtr();
+ if (const AtomicType *AT = dyn_cast<AtomicType>(T))
+ T = AT->getValueType().getTypePtr();
if (const EnumType *ET = dyn_cast<EnumType>(T))
T = C.getCanonicalType(ET->getDecl()->getIntegerType()).getTypePtr();
@@ -4855,95 +5480,189 @@ static void DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E,
if (!S.ActiveTemplateInstantiations.empty())
return;
+ // TODO: Investigate using GetExprRange() to get tighter bounds
+ // on the bit ranges.
+ QualType OtherT = Other->getType();
+ if (const AtomicType *AT = dyn_cast<AtomicType>(OtherT))
+ OtherT = AT->getValueType();
+ IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT);
+ unsigned OtherWidth = OtherRange.Width;
+
+ bool OtherIsBooleanType = Other->isKnownToHaveBooleanValue();
+
// 0 values are handled later by CheckTrivialUnsignedComparison().
- if (Value == 0)
+ if ((Value == 0) && (!OtherIsBooleanType))
return;
BinaryOperatorKind op = E->getOpcode();
- QualType OtherT = Other->getType();
- QualType ConstantT = Constant->getType();
- QualType CommonT = E->getLHS()->getType();
- if (S.Context.hasSameUnqualifiedType(OtherT, ConstantT))
- return;
- assert((OtherT->isIntegerType() && ConstantT->isIntegerType())
- && "comparison with non-integer type");
+ bool IsTrue = true;
+
+ // Used for diagnostic printout.
+ enum {
+ LiteralConstant = 0,
+ CXXBoolLiteralTrue,
+ CXXBoolLiteralFalse
+ } LiteralOrBoolConstant = LiteralConstant;
- bool ConstantSigned = ConstantT->isSignedIntegerType();
- bool CommonSigned = CommonT->isSignedIntegerType();
+ if (!OtherIsBooleanType) {
+ QualType ConstantT = Constant->getType();
+ QualType CommonT = E->getLHS()->getType();
- bool EqualityOnly = false;
+ if (S.Context.hasSameUnqualifiedType(OtherT, ConstantT))
+ return;
+ assert((OtherT->isIntegerType() && ConstantT->isIntegerType()) &&
+ "comparison with non-integer type");
- // TODO: Investigate using GetExprRange() to get tighter bounds on
- // on the bit ranges.
- IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT);
- unsigned OtherWidth = OtherRange.Width;
-
- if (CommonSigned) {
- // The common type is signed, therefore no signed to unsigned conversion.
- if (!OtherRange.NonNegative) {
- // Check that the constant is representable in type OtherT.
- if (ConstantSigned) {
- if (OtherWidth >= Value.getMinSignedBits())
- return;
- } else { // !ConstantSigned
- if (OtherWidth >= Value.getActiveBits() + 1)
- return;
+ bool ConstantSigned = ConstantT->isSignedIntegerType();
+ bool CommonSigned = CommonT->isSignedIntegerType();
+
+ bool EqualityOnly = false;
+
+ if (CommonSigned) {
+ // The common type is signed, therefore no signed to unsigned conversion.
+ if (!OtherRange.NonNegative) {
+ // Check that the constant is representable in type OtherT.
+ if (ConstantSigned) {
+ if (OtherWidth >= Value.getMinSignedBits())
+ return;
+ } else { // !ConstantSigned
+ if (OtherWidth >= Value.getActiveBits() + 1)
+ return;
+ }
+ } else { // !OtherSigned
+ // Check that the constant is representable in type OtherT.
+ // Negative values are out of range.
+ if (ConstantSigned) {
+ if (Value.isNonNegative() && OtherWidth >= Value.getActiveBits())
+ return;
+ } else { // !ConstantSigned
+ if (OtherWidth >= Value.getActiveBits())
+ return;
+ }
}
- } else { // !OtherSigned
- // Check that the constant is representable in type OtherT.
- // Negative values are out of range.
- if (ConstantSigned) {
- if (Value.isNonNegative() && OtherWidth >= Value.getActiveBits())
- return;
- } else { // !ConstantSigned
+ } else { // !CommonSigned
+ if (OtherRange.NonNegative) {
if (OtherWidth >= Value.getActiveBits())
return;
+ } else { // OtherSigned
+ assert(!ConstantSigned &&
+ "Two signed types converted to unsigned types.");
+ // Check to see if the constant is representable in OtherT.
+ if (OtherWidth > Value.getActiveBits())
+ return;
+ // Check to see if the constant is equivalent to a negative value
+ // cast to CommonT.
+ if (S.Context.getIntWidth(ConstantT) ==
+ S.Context.getIntWidth(CommonT) &&
+ Value.isNegative() && Value.getMinSignedBits() <= OtherWidth)
+ return;
+ // The constant value rests between values that OtherT can represent
+ // after conversion. Relational comparison still works, but equality
+ // comparisons will be tautological.
+ EqualityOnly = true;
}
}
- } else { // !CommonSigned
- if (OtherRange.NonNegative) {
- if (OtherWidth >= Value.getActiveBits())
- return;
- } else if (!OtherRange.NonNegative && !ConstantSigned) {
- // Check to see if the constant is representable in OtherT.
- if (OtherWidth > Value.getActiveBits())
- return;
- // Check to see if the constant is equivalent to a negative value
- // cast to CommonT.
- if (S.Context.getIntWidth(ConstantT) == S.Context.getIntWidth(CommonT) &&
- Value.isNegative() && Value.getMinSignedBits() <= OtherWidth)
- return;
- // The constant value rests between values that OtherT can represent after
- // conversion. Relational comparison still works, but equality
- // comparisons will be tautological.
- EqualityOnly = true;
- } else { // OtherSigned && ConstantSigned
- assert(0 && "Two signed types converted to unsigned types.");
- }
- }
- bool PositiveConstant = !ConstantSigned || Value.isNonNegative();
+ bool PositiveConstant = !ConstantSigned || Value.isNonNegative();
- bool IsTrue = true;
- if (op == BO_EQ || op == BO_NE) {
- IsTrue = op == BO_NE;
- } else if (EqualityOnly) {
- return;
- } else if (RhsConstant) {
- if (op == BO_GT || op == BO_GE)
- IsTrue = !PositiveConstant;
- else // op == BO_LT || op == BO_LE
- IsTrue = PositiveConstant;
+ if (op == BO_EQ || op == BO_NE) {
+ IsTrue = op == BO_NE;
+ } else if (EqualityOnly) {
+ return;
+ } else if (RhsConstant) {
+ if (op == BO_GT || op == BO_GE)
+ IsTrue = !PositiveConstant;
+ else // op == BO_LT || op == BO_LE
+ IsTrue = PositiveConstant;
+ } else {
+ if (op == BO_LT || op == BO_LE)
+ IsTrue = !PositiveConstant;
+ else // op == BO_GT || op == BO_GE
+ IsTrue = PositiveConstant;
+ }
} else {
- if (op == BO_LT || op == BO_LE)
- IsTrue = !PositiveConstant;
- else // op == BO_GT || op == BO_GE
- IsTrue = PositiveConstant;
+ // Other isKnownToHaveBooleanValue
+ enum CompareBoolWithConstantResult { AFals, ATrue, Unkwn };
+ enum ConstantValue { LT_Zero, Zero, One, GT_One, SizeOfConstVal };
+ enum ConstantSide { Lhs, Rhs, SizeOfConstSides };
+
+ static const struct LinkedConditions {
+ CompareBoolWithConstantResult BO_LT_OP[SizeOfConstSides][SizeOfConstVal];
+ CompareBoolWithConstantResult BO_GT_OP[SizeOfConstSides][SizeOfConstVal];
+ CompareBoolWithConstantResult BO_LE_OP[SizeOfConstSides][SizeOfConstVal];
+ CompareBoolWithConstantResult BO_GE_OP[SizeOfConstSides][SizeOfConstVal];
+ CompareBoolWithConstantResult BO_EQ_OP[SizeOfConstSides][SizeOfConstVal];
+ CompareBoolWithConstantResult BO_NE_OP[SizeOfConstSides][SizeOfConstVal];
+
+ } TruthTable = {
+ // Constant on LHS. | Constant on RHS. |
+ // LT_Zero| Zero | One |GT_One| LT_Zero| Zero | One |GT_One|
+ { { ATrue, Unkwn, AFals, AFals }, { AFals, AFals, Unkwn, ATrue } },
+ { { AFals, AFals, Unkwn, ATrue }, { ATrue, Unkwn, AFals, AFals } },
+ { { ATrue, ATrue, Unkwn, AFals }, { AFals, Unkwn, ATrue, ATrue } },
+ { { AFals, Unkwn, ATrue, ATrue }, { ATrue, ATrue, Unkwn, AFals } },
+ { { AFals, Unkwn, Unkwn, AFals }, { AFals, Unkwn, Unkwn, AFals } },
+ { { ATrue, Unkwn, Unkwn, ATrue }, { ATrue, Unkwn, Unkwn, ATrue } }
+ };
+
+ bool ConstantIsBoolLiteral = isa<CXXBoolLiteralExpr>(Constant);
+
+ enum ConstantValue ConstVal = Zero;
+ if (Value.isUnsigned() || Value.isNonNegative()) {
+ if (Value == 0) {
+ LiteralOrBoolConstant =
+ ConstantIsBoolLiteral ? CXXBoolLiteralFalse : LiteralConstant;
+ ConstVal = Zero;
+ } else if (Value == 1) {
+ LiteralOrBoolConstant =
+ ConstantIsBoolLiteral ? CXXBoolLiteralTrue : LiteralConstant;
+ ConstVal = One;
+ } else {
+ LiteralOrBoolConstant = LiteralConstant;
+ ConstVal = GT_One;
+ }
+ } else {
+ ConstVal = LT_Zero;
+ }
+
+ CompareBoolWithConstantResult CmpRes;
+
+ switch (op) {
+ case BO_LT:
+ CmpRes = TruthTable.BO_LT_OP[RhsConstant][ConstVal];
+ break;
+ case BO_GT:
+ CmpRes = TruthTable.BO_GT_OP[RhsConstant][ConstVal];
+ break;
+ case BO_LE:
+ CmpRes = TruthTable.BO_LE_OP[RhsConstant][ConstVal];
+ break;
+ case BO_GE:
+ CmpRes = TruthTable.BO_GE_OP[RhsConstant][ConstVal];
+ break;
+ case BO_EQ:
+ CmpRes = TruthTable.BO_EQ_OP[RhsConstant][ConstVal];
+ break;
+ case BO_NE:
+ CmpRes = TruthTable.BO_NE_OP[RhsConstant][ConstVal];
+ break;
+ default:
+ CmpRes = Unkwn;
+ break;
+ }
+
+ if (CmpRes == AFals) {
+ IsTrue = false;
+ } else if (CmpRes == ATrue) {
+ IsTrue = true;
+ } else {
+ return;
+ }
}
// If this is a comparison to an enum constant, include that
// constant in the diagnostic.
- const EnumConstantDecl *ED = 0;
+ const EnumConstantDecl *ED = nullptr;
if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Constant))
ED = dyn_cast<EnumConstantDecl>(DR->getDecl());
@@ -4954,9 +5673,12 @@ static void DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E,
else
OS << Value;
- S.Diag(E->getOperatorLoc(), diag::warn_out_of_range_compare)
- << OS.str() << OtherT << IsTrue
- << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
+ S.DiagRuntimeBehavior(
+ E->getOperatorLoc(), E,
+ S.PDiag(diag::warn_out_of_range_compare)
+ << OS.str() << LiteralOrBoolConstant
+ << OtherT << (OtherIsBooleanType && !OtherT->isBooleanType()) << IsTrue
+ << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange());
}
/// Analyze the operands of the given comparison. Implements the
@@ -5245,7 +5967,7 @@ void CheckImplicitArgumentConversions(Sema &S, CallExpr *TheCall,
}
void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
- SourceLocation CC, bool *ICContext = 0) {
+ SourceLocation CC, bool *ICContext = nullptr) {
if (E->isTypeDependent() || E->isValueDependent()) return;
const Type *Source = S.Context.getCanonicalType(E->getType()).getTypePtr();
@@ -5265,39 +5987,21 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
if (Target->isSpecificBuiltinType(BuiltinType::Bool)) {
if (isa<StringLiteral>(E))
// Warn on string literal to bool. Checks for string literals in logical
- // expressions, for instances, assert(0 && "error here"), is prevented
- // by a check in AnalyzeImplicitConversions().
+ // and expressions, for instance, assert(0 && "error here"), are
+ // prevented by a check in AnalyzeImplicitConversions().
return DiagnoseImpCast(S, E, T, CC,
diag::warn_impcast_string_literal_to_bool);
- if (Source->isFunctionType()) {
- // Warn on function to bool. Checks free functions and static member
- // functions. Weakly imported functions are excluded from the check,
- // since it's common to test their value to check whether the linker
- // found a definition for them.
- ValueDecl *D = 0;
- if (DeclRefExpr* R = dyn_cast<DeclRefExpr>(E)) {
- D = R->getDecl();
- } else if (MemberExpr *M = dyn_cast<MemberExpr>(E)) {
- D = M->getMemberDecl();
- }
-
- if (D && !D->isWeak()) {
- if (FunctionDecl* F = dyn_cast<FunctionDecl>(D)) {
- S.Diag(E->getExprLoc(), diag::warn_impcast_function_to_bool)
- << F << E->getSourceRange() << SourceRange(CC);
- S.Diag(E->getExprLoc(), diag::note_function_to_bool_silence)
- << FixItHint::CreateInsertion(E->getExprLoc(), "&");
- QualType ReturnType;
- UnresolvedSet<4> NonTemplateOverloads;
- S.tryExprAsCall(*E, ReturnType, NonTemplateOverloads);
- if (!ReturnType.isNull()
- && ReturnType->isSpecificBuiltinType(BuiltinType::Bool))
- S.Diag(E->getExprLoc(), diag::note_function_to_bool_call)
- << FixItHint::CreateInsertion(
- S.getPreprocessor().getLocForEndOfToken(E->getLocEnd()), "()");
- return;
- }
- }
+ if (isa<ObjCStringLiteral>(E) || isa<ObjCArrayLiteral>(E) ||
+ isa<ObjCDictionaryLiteral>(E) || isa<ObjCBoxedExpr>(E)) {
+ // This covers the literal expressions that evaluate to Objective-C
+ // objects.
+ return DiagnoseImpCast(S, E, T, CC,
+ diag::warn_impcast_objective_c_literal_to_bool);
+ }
+ if (Source->isPointerType() || Source->canDecayToPointerType()) {
+ // Warn on pointer to bool conversion that is always true.
+ S.DiagnoseAlwaysNonNullPointer(E, Expr::NPCK_NotNull, /*IsEqual*/ false,
+ SourceRange(CC));
}
}
@@ -5317,6 +6021,8 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
Source = cast<VectorType>(Source)->getElementType().getTypePtr();
Target = cast<VectorType>(Target)->getElementType().getTypePtr();
}
+ if (auto VecTy = dyn_cast<VectorType>(Target))
+ Target = VecTy->getElementType().getTypePtr();
// Strip complex types.
if (isa<ComplexType>(Source)) {
@@ -5535,8 +6241,7 @@ void CheckConditionalOperator(Sema &S, ConditionalOperator *E,
if (!Suspicious) return;
// ...but it's currently ignored...
- if (S.Diags.getDiagnosticLevel(diag::warn_impcast_integer_sign_conditional,
- CC))
+ if (!S.Diags.isIgnored(diag::warn_impcast_integer_sign_conditional, CC))
return;
// ...then check whether it would have warned about either of the
@@ -5560,7 +6265,7 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) {
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)) {
@@ -5617,15 +6322,16 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) {
// Now just recurse over the expression's children.
CC = E->getExprLoc();
BinaryOperator *BO = dyn_cast<BinaryOperator>(E);
- bool IsLogicalOperator = BO && BO->isLogicalOp();
+ bool IsLogicalAndOperator = BO && BO->getOpcode() == BO_LAnd;
for (Stmt::child_range I = E->children(); I; ++I) {
Expr *ChildExpr = dyn_cast_or_null<Expr>(*I);
if (!ChildExpr)
continue;
- if (IsLogicalOperator &&
+ if (IsLogicalAndOperator &&
isa<StringLiteral>(ChildExpr->IgnoreParenImpCasts()))
- // Ignore checking string literals that are in logical operators.
+ // Ignore checking string literals that are in logical and operators.
+ // This is a common pattern for asserts.
continue;
AnalyzeImplicitConversions(S, ChildExpr, CC);
}
@@ -5633,6 +6339,172 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) {
} // end anonymous namespace
+enum {
+ AddressOf,
+ FunctionPointer,
+ ArrayPointer
+};
+
+// Helper function for Sema::DiagnoseAlwaysNonNullPointer.
+// Returns true when emitting a warning about taking the address of a reference.
+static bool CheckForReference(Sema &SemaRef, const Expr *E,
+ PartialDiagnostic PD) {
+ E = E->IgnoreParenImpCasts();
+
+ const FunctionDecl *FD = nullptr;
+
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+ if (!DRE->getDecl()->getType()->isReferenceType())
+ return false;
+ } else if (const MemberExpr *M = dyn_cast<MemberExpr>(E)) {
+ if (!M->getMemberDecl()->getType()->isReferenceType())
+ return false;
+ } else if (const CallExpr *Call = dyn_cast<CallExpr>(E)) {
+ if (!Call->getCallReturnType()->isReferenceType())
+ return false;
+ FD = Call->getDirectCallee();
+ } else {
+ return false;
+ }
+
+ SemaRef.Diag(E->getExprLoc(), PD);
+
+ // If possible, point to location of function.
+ if (FD) {
+ SemaRef.Diag(FD->getLocation(), diag::note_reference_is_return_value) << FD;
+ }
+
+ return true;
+}
+
+/// \brief 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
+/// \param IsEqual True when the comparison is equal to a null pointer
+/// \param Range Extra SourceRange to highlight in the diagnostic
+void Sema::DiagnoseAlwaysNonNullPointer(Expr *E,
+ Expr::NullPointerConstantKind NullKind,
+ bool IsEqual, SourceRange Range) {
+ if (!E)
+ return;
+
+ // Don't warn inside macros.
+ if (E->getExprLoc().isMacroID())
+ return;
+ E = E->IgnoreImpCasts();
+
+ const bool IsCompare = NullKind != Expr::NPCK_NotNull;
+
+ if (isa<CXXThisExpr>(E)) {
+ unsigned DiagID = IsCompare ? diag::warn_this_null_compare
+ : diag::warn_this_bool_conversion;
+ Diag(E->getExprLoc(), DiagID) << E->getSourceRange() << Range << IsEqual;
+ return;
+ }
+
+ bool IsAddressOf = false;
+
+ if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
+ if (UO->getOpcode() != UO_AddrOf)
+ return;
+ IsAddressOf = true;
+ E = UO->getSubExpr();
+ }
+
+ if (IsAddressOf) {
+ unsigned DiagID = IsCompare
+ ? diag::warn_address_of_reference_null_compare
+ : diag::warn_address_of_reference_bool_conversion;
+ PartialDiagnostic PD = PDiag(DiagID) << E->getSourceRange() << Range
+ << IsEqual;
+ if (CheckForReference(*this, E, PD)) {
+ return;
+ }
+ }
+
+ // Expect to find a single Decl. Skip anything more complicated.
+ ValueDecl *D = nullptr;
+ if (DeclRefExpr *R = dyn_cast<DeclRefExpr>(E)) {
+ D = R->getDecl();
+ } else if (MemberExpr *M = dyn_cast<MemberExpr>(E)) {
+ D = M->getMemberDecl();
+ }
+
+ // Weak Decls can be null.
+ if (!D || D->isWeak())
+ return;
+
+ QualType T = D->getType();
+ const bool IsArray = T->isArrayType();
+ const bool IsFunction = T->isFunctionType();
+
+ // Address of function is used to silence the function warning.
+ if (IsAddressOf && IsFunction) {
+ return;
+ }
+
+ // Found nothing.
+ if (!IsAddressOf && !IsFunction && !IsArray)
+ return;
+
+ // Pretty print the expression for the diagnostic.
+ std::string Str;
+ llvm::raw_string_ostream S(Str);
+ E->printPretty(S, nullptr, getPrintingPolicy());
+
+ unsigned DiagID = IsCompare ? diag::warn_null_pointer_compare
+ : diag::warn_impcast_pointer_to_bool;
+ unsigned DiagType;
+ if (IsAddressOf)
+ DiagType = AddressOf;
+ else if (IsFunction)
+ DiagType = FunctionPointer;
+ else if (IsArray)
+ DiagType = ArrayPointer;
+ else
+ llvm_unreachable("Could not determine diagnostic.");
+ Diag(E->getExprLoc(), DiagID) << DiagType << S.str() << E->getSourceRange()
+ << Range << IsEqual;
+
+ if (!IsFunction)
+ return;
+
+ // Suggest '&' to silence the function warning.
+ Diag(E->getExprLoc(), diag::note_function_warning_silence)
+ << FixItHint::CreateInsertion(E->getLocStart(), "&");
+
+ // Check to see if '()' fixit should be emitted.
+ QualType ReturnType;
+ UnresolvedSet<4> NonTemplateOverloads;
+ tryExprAsCall(*E, ReturnType, NonTemplateOverloads);
+ if (ReturnType.isNull())
+ return;
+
+ if (IsCompare) {
+ // There are two cases here. If there is null constant, the only suggest
+ // for a pointer return type. If the null is 0, then suggest if the return
+ // type is a pointer or an integer type.
+ if (!ReturnType->isPointerType()) {
+ if (NullKind == Expr::NPCK_ZeroExpression ||
+ NullKind == Expr::NPCK_ZeroLiteral) {
+ if (!ReturnType->isIntegerType())
+ return;
+ } else {
+ return;
+ }
+ }
+ } else { // !IsCompare
+ // For function to bool, only suggest if the function pointer has bool
+ // return type.
+ if (!ReturnType->isSpecificBuiltinType(BuiltinType::Bool))
+ return;
+ }
+ Diag(E->getExprLoc(), diag::note_function_to_function_call)
+ << FixItHint::CreateInsertion(getLocForEndOfToken(E->getLocEnd()), "()");
+}
+
+
/// Diagnoses "dangerous" implicit conversions within the given
/// expression (which is a full expression). Implements -Wconversion
/// and -Wsign-compare.
@@ -5754,7 +6626,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
};
struct Usage {
- Usage() : Use(0), Seq() {}
+ Usage() : Use(nullptr), Seq() {}
Expr *Use;
SequenceTree::Seq Seq;
};
@@ -5854,7 +6726,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
} else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
// FIXME: If this is a reference, map through to its value.
return DRE->getDecl();
- return 0;
+ return nullptr;
}
/// \brief Note that an object was modified or used by an expression.
@@ -5914,8 +6786,8 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
public:
SequenceChecker(Sema &S, Expr *E, SmallVectorImpl<Expr *> &WorkList)
- : Base(S.Context), SemaRef(S), Region(Tree.root()), ModAsSideEffect(0),
- WorkList(WorkList), EvalTracker(0) {
+ : Base(S.Context), SemaRef(S), Region(Tree.root()),
+ ModAsSideEffect(nullptr), WorkList(WorkList), EvalTracker(nullptr) {
Visit(E);
}
@@ -6200,7 +7072,7 @@ bool Sema::CheckParmsForFunctionDef(ParmVarDecl *const *P,
// C99 6.9.1p5: If the declarator includes a parameter type list, the
// declaration of each parameter shall include an identifier.
if (CheckParameterNames &&
- Param->getIdentifier() == 0 &&
+ Param->getIdentifier() == nullptr &&
!Param->isImplicit() &&
!getLangOpts().CPlusPlus)
Diag(Param->getLocation(), diag::err_parameter_name_omitted);
@@ -6223,11 +7095,23 @@ bool Sema::CheckParmsForFunctionDef(ParmVarDecl *const *P,
// 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.
- if (getLangOpts().CPlusPlus &&
- Context.getTargetInfo().getCXXABI().isArgumentDestroyedByCallee()) {
- if (const RecordType *RT = Param->getType()->getAs<RecordType>())
- FinalizeVarWithDestructor(Param, RT);
+ // 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());
+ }
+ }
+ }
}
}
@@ -6239,9 +7123,7 @@ bool Sema::CheckParmsForFunctionDef(ParmVarDecl *const *P,
void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) {
// This is actually a lot of work to potentially be doing on every
// cast; don't do it if we're ignoring -Wcast_align (as is the default).
- if (getDiagnostics().getDiagnosticLevel(diag::warn_cast_align,
- TRange.getBegin())
- == DiagnosticsEngine::Ignored)
+ if (getDiagnostics().isIgnored(diag::warn_cast_align, TRange.getBegin()))
return;
// Ignore dependent types.
@@ -6355,7 +7237,7 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
if (IndexNegated)
index = -index;
- const NamedDecl *ND = NULL;
+ const NamedDecl *ND = nullptr;
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
ND = dyn_cast<NamedDecl>(DRE->getDecl());
if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr))
@@ -6498,7 +7380,7 @@ void Sema::CheckArrayAccess(const Expr *expr) {
namespace {
struct RetainCycleOwner {
- RetainCycleOwner() : Variable(0), Indirect(false) {}
+ RetainCycleOwner() : Variable(nullptr), Indirect(false) {}
VarDecl *Variable;
SourceRange Range;
SourceLocation Loc;
@@ -6609,10 +7491,12 @@ namespace {
struct FindCaptureVisitor : EvaluatedExprVisitor<FindCaptureVisitor> {
FindCaptureVisitor(ASTContext &Context, VarDecl *variable)
: EvaluatedExprVisitor<FindCaptureVisitor>(Context),
- Variable(variable), Capturer(0) {}
-
+ Context(Context), Variable(variable), Capturer(nullptr),
+ VarWillBeReased(false) {}
+ ASTContext &Context;
VarDecl *Variable;
Expr *Capturer;
+ bool VarWillBeReased;
void VisitDeclRefExpr(DeclRefExpr *ref) {
if (ref->getDecl() == Variable && !Capturer)
@@ -6637,6 +7521,21 @@ namespace {
if (OVE->getSourceExpr())
Visit(OVE->getSourceExpr());
}
+ void VisitBinaryOperator(BinaryOperator *BinOp) {
+ if (!Variable || VarWillBeReased || BinOp->getOpcode() != BO_Assign)
+ return;
+ Expr *LHS = BinOp->getLHS();
+ if (const DeclRefExpr *DRE = dyn_cast_or_null<DeclRefExpr>(LHS)) {
+ if (DRE->getDecl() != Variable)
+ return;
+ if (Expr *RHS = BinOp->getRHS()) {
+ RHS = RHS->IgnoreParenCasts();
+ llvm::APSInt Value;
+ VarWillBeReased =
+ (RHS && RHS->isIntegerConstantExpr(Value, Context) && Value == 0);
+ }
+ }
+ }
};
}
@@ -6653,7 +7552,7 @@ static Expr *findCapturingExpr(Sema &S, Expr *e, RetainCycleOwner &owner) {
if (Cmd.isUnarySelector() && Cmd.getNameForSlot(0) == "copy") {
e = ME->getInstanceReceiver();
if (!e)
- return 0;
+ return nullptr;
e = e->IgnoreParenCasts();
}
} else if (CallExpr *CE = dyn_cast<CallExpr>(e)) {
@@ -6670,11 +7569,11 @@ static Expr *findCapturingExpr(Sema &S, Expr *e, RetainCycleOwner &owner) {
BlockExpr *block = dyn_cast<BlockExpr>(e);
if (!block || !block->getBlockDecl()->capturesVariable(owner.Variable))
- return 0;
+ return nullptr;
FindCaptureVisitor visitor(S.Context, owner.Variable);
visitor.Visit(block->getBlockDecl()->getBody());
- return visitor.Capturer;
+ return visitor.VarWillBeReased ? nullptr : visitor.Capturer;
}
static void diagnoseRetainCycle(Sema &S, Expr *capturer,
@@ -6746,7 +7645,7 @@ void Sema::checkRetainCycles(Expr *receiver, Expr *argument) {
void Sema::checkRetainCycles(VarDecl *Var, Expr *Init) {
RetainCycleOwner Owner;
- if (!considerVariable(Var, /*DeclRefExpr=*/0, Owner))
+ if (!considerVariable(Var, /*DeclRefExpr=*/nullptr, Owner))
return;
// Because we don't have an expression for the variable, we have to set the
@@ -6818,7 +7717,7 @@ void Sema::checkUnsafeExprAssigns(SourceLocation Loc,
Expr *LHS, Expr *RHS) {
QualType LHSType;
// PropertyRef on LHS type need be directly obtained from
- // its declaration as it has a PsuedoType.
+ // its declaration as it has a PseudoType.
ObjCPropertyRefExpr *PRE
= dyn_cast<ObjCPropertyRefExpr>(LHS->IgnoreParens());
if (PRE && !PRE->isImplicitProperty()) {
@@ -6833,9 +7732,7 @@ void Sema::checkUnsafeExprAssigns(SourceLocation Loc,
Qualifiers::ObjCLifetime LT = LHSType.getObjCLifetime();
if (LT == Qualifiers::OCL_Weak) {
- DiagnosticsEngine::Level Level =
- Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, Loc);
- if (Level != DiagnosticsEngine::Ignored)
+ if (!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc))
getCurFunction()->markSafeWeakUse(LHS);
}
@@ -6960,8 +7857,7 @@ void Sema::DiagnoseEmptyLoopBody(const Stmt *S,
return;
// Skip expensive checks if diagnostic is disabled.
- if (Diags.getDiagnosticLevel(DiagID, NBody->getSemiLoc()) ==
- DiagnosticsEngine::Ignored)
+ if (Diags.isIgnored(DiagID, NBody->getSemiLoc()))
return;
// Do the usual checks.
@@ -7091,21 +7987,16 @@ bool isLayoutCompatibleUnion(ASTContext &C,
RecordDecl *RD1,
RecordDecl *RD2) {
llvm::SmallPtrSet<FieldDecl *, 8> UnmatchedFields;
- for (RecordDecl::field_iterator Field2 = RD2->field_begin(),
- Field2End = RD2->field_end();
- Field2 != Field2End; ++Field2) {
- UnmatchedFields.insert(*Field2);
- }
+ for (auto *Field2 : RD2->fields())
+ UnmatchedFields.insert(Field2);
- for (RecordDecl::field_iterator Field1 = RD1->field_begin(),
- Field1End = RD1->field_end();
- Field1 != Field1End; ++Field1) {
+ for (auto *Field1 : RD1->fields()) {
llvm::SmallPtrSet<FieldDecl *, 8>::iterator
I = UnmatchedFields.begin(),
E = UnmatchedFields.end();
for ( ; I != E; ++I) {
- if (isLayoutCompatible(C, *Field1, *I)) {
+ if (isLayoutCompatible(C, Field1, *I)) {
bool Result = UnmatchedFields.erase(*I);
(void) Result;
assert(Result);
@@ -7262,7 +8153,7 @@ bool GetMatchingCType(
FoundWrongKind = false;
// Variable declaration that has type_tag_for_datatype attribute.
- const ValueDecl *VD = NULL;
+ const ValueDecl *VD = nullptr;
uint64_t MagicValue;
@@ -7270,10 +8161,7 @@ bool GetMatchingCType(
return false;
if (VD) {
- for (specific_attr_iterator<TypeTagForDatatypeAttr>
- I = VD->specific_attr_begin<TypeTagForDatatypeAttr>(),
- E = VD->specific_attr_end<TypeTagForDatatypeAttr>();
- I != E; ++I) {
+ if (TypeTagForDatatypeAttr *I = VD->getAttr<TypeTagForDatatypeAttr>()) {
if (I->getArgumentKind() != ArgumentKind) {
FoundWrongKind = true;
return false;
@@ -7406,8 +8294,9 @@ void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr,
if (mismatch)
Diag(ArgumentExpr->getExprLoc(), diag::warn_type_safety_type_mismatch)
- << ArgumentType << ArgumentKind->getName()
+ << ArgumentType << ArgumentKind
<< TypeInfo.LayoutCompatible << RequiredType
<< ArgumentExpr->getSourceRange()
<< TypeTagExpr->getSourceRange();
}
+
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
index 7a1b36b..3d250e3 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
@@ -104,7 +104,7 @@ namespace {
if (DeclIndexPairVector *Vec
= DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
delete Vec;
- DeclOrVector = ((NamedDecl *)0);
+ DeclOrVector = ((NamedDecl *)nullptr);
}
}
@@ -172,12 +172,12 @@ namespace {
explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
CodeCompletionTUInfo &CCTUInfo,
const CodeCompletionContext &CompletionContext,
- LookupFilter Filter = 0)
+ LookupFilter Filter = nullptr)
: SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
Filter(Filter),
AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
CompletionContext(CompletionContext),
- ObjCImplementation(0)
+ ObjCImplementation(nullptr)
{
// If this is an Objective-C instance method definition, dig out the
// corresponding implementation.
@@ -212,8 +212,8 @@ namespace {
void setFilter(LookupFilter Filter) {
this->Filter = Filter;
}
-
- Result *data() { return Results.empty()? 0 : &Results.front(); }
+
+ Result *data() { return Results.empty()? nullptr : &Results.front(); }
unsigned size() const { return Results.size(); }
bool empty() const { return Results.empty(); }
@@ -289,8 +289,8 @@ namespace {
/// \param R the result to add (if it is unique).
///
/// \param CurContext the context in which this result will be named.
- void MaybeAddResult(Result R, DeclContext *CurContext = 0);
-
+ void MaybeAddResult(Result R, DeclContext *CurContext = nullptr);
+
/// \brief Add a new result to this result set, where we already know
/// the hiding declation (if any).
///
@@ -364,8 +364,8 @@ public:
return &Value;
}
};
-
- iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { }
+
+ iterator() : DeclOrIterator((NamedDecl *)nullptr), SingleDeclIndex(0) {}
iterator(const NamedDecl *SingleDecl, unsigned Index)
: DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
@@ -375,7 +375,7 @@ public:
iterator &operator++() {
if (DeclOrIterator.is<const NamedDecl *>()) {
- DeclOrIterator = (NamedDecl *)0;
+ DeclOrIterator = (NamedDecl *)nullptr;
SingleDeclIndex = 0;
return *this;
}
@@ -461,8 +461,8 @@ getRequiredQualification(ASTContext &Context,
TargetParents.push_back(CommonAncestor);
}
-
- NestedNameSpecifier *Result = 0;
+
+ NestedNameSpecifier *Result = nullptr;
while (!TargetParents.empty()) {
const DeclContext *Parent = TargetParents.pop_back_val();
@@ -480,6 +480,16 @@ getRequiredQualification(ASTContext &Context,
return Result;
}
+/// Determine whether \p Id is a name reserved for the implementation (C99
+/// 7.1.3, C++ [lib.global.names]).
+static bool isReservedName(const IdentifierInfo *Id) {
+ if (Id->getLength() < 2)
+ return false;
+ const char *Name = Id->getNameStart();
+ return Name[0] == '_' &&
+ (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z'));
+}
+
bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
bool &AsNestedNameSpecifier) const {
AsNestedNameSpecifier = false;
@@ -506,31 +516,21 @@ bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
return false;
// Some declarations have reserved names that we don't want to ever show.
- if (const IdentifierInfo *Id = ND->getIdentifier()) {
- // __va_list_tag is a freak of nature. Find it and skip it.
- if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list"))
- return false;
-
- // Filter out names reserved for the implementation (C99 7.1.3,
- // C++ [lib.global.names]) if they come from a system header.
- //
- // FIXME: Add predicate for this.
- if (Id->getLength() >= 2) {
- const char *Name = Id->getNameStart();
- if (Name[0] == '_' &&
- (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')) &&
- (ND->getLocation().isInvalid() ||
- SemaRef.SourceMgr.isInSystemHeader(
- SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))))
+ // Filter out names reserved for the implementation if they come from a
+ // system header.
+ // TODO: Add a predicate for this.
+ if (const IdentifierInfo *Id = ND->getIdentifier())
+ if (isReservedName(Id) &&
+ (ND->getLocation().isInvalid() ||
+ SemaRef.SourceMgr.isInSystemHeader(
+ SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))))
return false;
- }
- }
if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
Filter != &ResultBuilder::IsNamespace &&
Filter != &ResultBuilder::IsNamespaceOrAlias &&
- Filter != 0))
+ Filter != nullptr))
AsNestedNameSpecifier = true;
// Filter out any unwanted results.
@@ -660,13 +660,10 @@ QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
return C.getObjCInterfaceType(Iface);
QualType T;
- if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
+ if (const FunctionDecl *Function = ND->getAsFunction())
T = Function->getCallResultType();
else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
T = Method->getSendResultType();
- else if (const FunctionTemplateDecl *FunTmpl =
- dyn_cast<FunctionTemplateDecl>(ND))
- T = FunTmpl->getTemplatedDecl()->getCallResultType();
else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
@@ -700,7 +697,7 @@ QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
}
if (const FunctionType *Function = T->getAs<FunctionType>()) {
- T = Function->getResultType();
+ T = Function->getReturnType();
continue;
}
@@ -782,7 +779,7 @@ void ResultBuilder::MaybeAddConstructorResults(Result R) {
ASTContext &Context = SemaRef.Context;
const NamedDecl *D = R.Declaration;
- const CXXRecordDecl *Record = 0;
+ const CXXRecordDecl *Record = nullptr;
if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
Record = ClassTemplate->getTemplatedDecl();
else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
@@ -913,10 +910,11 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
!R.StartsNestedNameSpecifier) {
const DeclContext *Ctx = R.Declaration->getDeclContext();
if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
- R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
+ R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
+ Namespace);
else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
- R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
- SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
+ R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
+ false, SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
else
R.QualifierIsInformative = false;
}
@@ -978,9 +976,10 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
!R.StartsNestedNameSpecifier) {
const DeclContext *Ctx = R.Declaration->getDeclContext();
if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
- R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
+ R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
+ Namespace);
else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
- R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
+ R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr, false,
SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
else
R.QualifierIsInformative = false;
@@ -1256,15 +1255,15 @@ namespace {
public:
CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
: Results(Results), CurContext(CurContext) { }
-
- virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
- bool InBaseClass) {
+
+ void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
+ bool InBaseClass) override {
bool Accessible = true;
if (Ctx)
Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
-
- ResultBuilder::Result Result(ND, Results.getBasePriority(ND), 0, false,
- Accessible);
+
+ ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
+ false, Accessible);
Results.AddResult(Result, CurContext, Hiding, InBaseClass);
}
};
@@ -1784,10 +1783,10 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
// know the function is void or not.
bool isVoid = false;
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
- isVoid = Function->getResultType()->isVoidType();
+ isVoid = Function->getReturnType()->isVoidType();
else if (ObjCMethodDecl *Method
= dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
- isVoid = Method->getResultType()->isVoidType();
+ isVoid = Method->getReturnType()->isVoidType();
else if (SemaRef.getCurBlock() &&
!SemaRef.getCurBlock()->ReturnType.isNull())
isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
@@ -2066,14 +2065,11 @@ static void AddResultTypeChunk(ASTContext &Context,
return;
// Determine the type of the declaration (if it has a type).
- QualType T;
- if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
- T = Function->getResultType();
+ QualType T;
+ if (const FunctionDecl *Function = ND->getAsFunction())
+ T = Function->getReturnType();
else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
- T = Method->getResultType();
- else if (const FunctionTemplateDecl *FunTmpl =
- dyn_cast<FunctionTemplateDecl>(ND))
- T = FunTmpl->getTemplatedDecl()->getResultType();
+ T = Method->getReturnType();
else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
else if (isa<UnresolvedUsingValueDecl>(ND)) {
@@ -2206,26 +2202,26 @@ static std::string FormatFunctionParameter(ASTContext &Context,
// We have the function prototype behind the block pointer type, as it was
// written in the source.
std::string Result;
- QualType ResultType = Block.getTypePtr()->getResultType();
+ QualType ResultType = Block.getTypePtr()->getReturnType();
if (!ResultType->isVoidType() || SuppressBlock)
ResultType.getAsStringInternal(Result, Policy);
// Format the parameter list.
std::string Params;
- if (!BlockProto || Block.getNumArgs() == 0) {
+ if (!BlockProto || Block.getNumParams() == 0) {
if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Params = "(...)";
else
Params = "(void)";
} else {
Params += "(";
- for (unsigned I = 0, N = Block.getNumArgs(); I != N; ++I) {
+ for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
if (I)
Params += ", ";
- Params += FormatFunctionParameter(Context, Policy, Block.getArg(I),
- /*SuppressName=*/false,
+ Params += FormatFunctionParameter(Context, Policy, Block.getParam(I),
+ /*SuppressName=*/false,
/*SuppressBlock=*/true);
-
+
if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Params += ", ...";
}
@@ -2297,7 +2293,7 @@ static void AddFunctionParameterChunks(ASTContext &Context,
if (const FunctionProtoType *Proto
= Function->getType()->getAs<FunctionProtoType>())
if (Proto->isVariadic()) {
- if (Proto->getNumArgs() == 0)
+ if (Proto->getNumParams() == 0)
Result.AddPlaceholderChunk("...");
MaybeAddSentinel(Context, Function, Result);
@@ -2450,7 +2446,7 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
switch (Name.getNameKind()) {
case DeclarationName::CXXOperatorName: {
- const char *OperatorName = 0;
+ const char *OperatorName = nullptr;
switch (Name.getCXXOverloadedOperator()) {
case OO_None:
case OO_Conditional:
@@ -2489,7 +2485,7 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
break;
case DeclarationName::CXXConstructorName: {
- CXXRecordDecl *Record = 0;
+ CXXRecordDecl *Record = nullptr;
QualType Ty = Name.getCXXNameType();
if (const RecordType *RecordTy = Ty->getAs<RecordType>())
Record = cast<CXXRecordDecl>(RecordTy->getDecl());
@@ -2644,12 +2640,9 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
return Result.TakeString();
}
- for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) {
- if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) {
- Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation()));
- }
- }
-
+ for (const auto *I : ND->specific_attrs<AnnotateAttr>())
+ Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
+
AddResultTypeChunk(Ctx, Policy, ND, Result);
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
@@ -2836,9 +2829,8 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
// Function without a prototype. Just give the return type and a
// highlighted ellipsis.
const FunctionType *FT = getFunctionType();
- Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
- S.Context, Policy,
- Result.getAllocator()));
+ Result.AddTextChunk(GetCompletionTypeString(FT->getReturnType(), S.Context,
+ Policy, Result.getAllocator()));
Result.AddChunk(CodeCompletionString::CK_LeftParen);
Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
Result.AddChunk(CodeCompletionString::CK_RightParen);
@@ -2849,12 +2841,11 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Result.AddTextChunk(
Result.getAllocator().CopyString(FDecl->getNameAsString()));
else
- Result.AddTextChunk(
- Result.getAllocator().CopyString(
- Proto->getResultType().getAsString(Policy)));
-
+ Result.AddTextChunk(Result.getAllocator().CopyString(
+ Proto->getReturnType().getAsString(Policy)));
+
Result.AddChunk(CodeCompletionString::CK_LeftParen);
- unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
+ unsigned NumParams = FDecl ? FDecl->getNumParams() : Proto->getNumParams();
for (unsigned I = 0; I != NumParams; ++I) {
if (I)
Result.AddChunk(CodeCompletionString::CK_Comma);
@@ -2866,7 +2857,7 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
ArgString = FDecl->getParamDecl(I)->getNameAsString();
ArgType = FDecl->getParamDecl(I)->getOriginalType();
} else {
- ArgType = Proto->getArgType(I);
+ ArgType = Proto->getParamType(I);
}
ArgType.getAsStringInternal(ArgString, Policy);
@@ -2998,11 +2989,16 @@ static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
for (Preprocessor::macro_iterator M = PP.macro_begin(),
MEnd = PP.macro_end();
M != MEnd; ++M) {
- if (IncludeUndefined || M->first->hasMacroDefinition())
+ if (IncludeUndefined || M->first->hasMacroDefinition()) {
+ if (MacroInfo *MI = M->second->getMacroInfo())
+ if (MI->isUsedForHeaderGuard())
+ continue;
+
Results.AddResult(Result(M->first,
getMacroUsagePriority(M->first->getName(),
PP.getLangOpts(),
TargetTypeIsPointer)));
+ }
}
Results.ExitScope();
@@ -3109,13 +3105,9 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
// We need to have names for all of the parameters, if we're going to
// generate a forwarding call.
- for (CXXMethodDecl::param_iterator P = Method->param_begin(),
- PEnd = Method->param_end();
- P != PEnd;
- ++P) {
- if (!(*P)->getDeclName())
+ for (auto P : Method->params())
+ if (!P->getDeclName())
return;
- }
PrintingPolicy Policy = getCompletionPrintingPolicy(S);
for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
@@ -3145,16 +3137,14 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
Overridden->getNameAsString()));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
bool FirstParam = true;
- for (CXXMethodDecl::param_iterator P = Method->param_begin(),
- PEnd = Method->param_end();
- P != PEnd; ++P) {
+ for (auto P : Method->params()) {
if (FirstParam)
FirstParam = false;
else
Builder.AddChunk(CodeCompletionString::CK_Comma);
- Builder.AddPlaceholderChunk(Results.getAllocator().CopyString(
- (*P)->getIdentifier()->getName()));
+ Builder.AddPlaceholderChunk(
+ Results.getAllocator().CopyString(P->getIdentifier()->getName()));
}
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(CodeCompletionResult(Builder.TakeString(),
@@ -3252,7 +3242,7 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
if (getLangOpts().CPlusPlus)
- MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
+ MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
break;
case PCC_RecoveryInFunction:
@@ -3340,7 +3330,7 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
CodeCompleter->includeGlobals());
- Results.setFilter(0);
+ Results.setFilter(nullptr);
}
}
Results.ExitScope();
@@ -3438,7 +3428,7 @@ void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
if (E.isInvalid())
CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
else if (getLangOpts().ObjC1)
- CodeCompleteObjCInstanceMessage(S, E.take(), None, false);
+ CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
}
/// \brief The set of properties that have already been added, referenced by
@@ -3475,32 +3465,26 @@ static void AddObjCProperties(ObjCContainerDecl *Container,
Container = getContainerDef(Container);
// Add properties in this container.
- for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
- PEnd = Container->prop_end();
- P != PEnd;
- ++P) {
+ for (const auto *P : Container->properties())
if (AddedProperties.insert(P->getIdentifier()))
- Results.MaybeAddResult(Result(*P, Results.getBasePriority(*P), 0),
+ Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
CurContext);
- }
-
+
// Add nullary methods
if (AllowNullaryMethods) {
ASTContext &Context = Container->getASTContext();
PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
- for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
- MEnd = Container->meth_end();
- M != MEnd; ++M) {
+ for (auto *M : Container->methods()) {
if (M->getSelector().isUnarySelector())
if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
if (AddedProperties.insert(Name)) {
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
- AddResultTypeChunk(Context, Policy, *M, Builder);
+ AddResultTypeChunk(Context, Policy, M, Builder);
Builder.AddTypedTextChunk(
Results.getAllocator().CopyString(Name->getName()));
- Results.MaybeAddResult(Result(Builder.TakeString(), *M,
+ Results.MaybeAddResult(Result(Builder.TakeString(), M,
CCP_MemberDeclaration + CCD_MethodAsProperty),
CurContext);
}
@@ -3510,27 +3494,20 @@ static void AddObjCProperties(ObjCContainerDecl *Container,
// Add properties in referenced protocols.
if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
- for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
- PEnd = Protocol->protocol_end();
- P != PEnd; ++P)
- AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
+ for (auto *P : Protocol->protocols())
+ AddObjCProperties(P, AllowCategories, AllowNullaryMethods, CurContext,
AddedProperties, Results);
} else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
if (AllowCategories) {
// Look through categories.
- for (ObjCInterfaceDecl::known_categories_iterator
- Cat = IFace->known_categories_begin(),
- CatEnd = IFace->known_categories_end();
- Cat != CatEnd; ++Cat)
- AddObjCProperties(*Cat, AllowCategories, AllowNullaryMethods,
- CurContext, AddedProperties, Results);
+ for (auto *Cat : IFace->known_categories())
+ AddObjCProperties(Cat, AllowCategories, AllowNullaryMethods, CurContext,
+ AddedProperties, Results);
}
-
+
// Look through protocols.
- for (ObjCInterfaceDecl::all_protocol_iterator
- I = IFace->all_referenced_protocol_begin(),
- E = IFace->all_referenced_protocol_end(); I != E; ++I)
- AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext,
+ for (auto *I : IFace->all_referenced_protocols())
+ AddObjCProperties(I, AllowCategories, AllowNullaryMethods, CurContext,
AddedProperties, Results);
// Look in the superclass.
@@ -3541,10 +3518,8 @@ static void AddObjCProperties(ObjCContainerDecl *Container,
} else if (const ObjCCategoryDecl *Category
= dyn_cast<ObjCCategoryDecl>(Container)) {
// Look through protocols.
- for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
- PEnd = Category->protocol_end();
- P != PEnd; ++P)
- AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
+ for (auto *P : Category->protocols())
+ AddObjCProperties(P, AllowCategories, AllowNullaryMethods, CurContext,
AddedProperties, Results);
}
}
@@ -3636,15 +3611,13 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
AddedProperties, Results);
// Add properties from the protocols in a qualified interface.
- for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
- E = ObjCPtr->qual_end();
- I != E; ++I)
- AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext,
+ for (auto *I : ObjCPtr->quals())
+ AddObjCProperties(I, true, /*AllowNullaryMethods=*/true, CurContext,
AddedProperties, Results);
} else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
(!IsArrow && BaseType->isObjCObjectType())) {
// Objective-C instance variable access.
- ObjCInterfaceDecl *Class = 0;
+ ObjCInterfaceDecl *Class = nullptr;
if (const ObjCObjectPointerType *ObjCPtr
= BaseType->getAs<ObjCObjectPointerType>())
Class = ObjCPtr->getInterfaceDecl();
@@ -3673,8 +3646,8 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
if (!CodeCompleter)
return;
-
- ResultBuilder::LookupFilter Filter = 0;
+
+ ResultBuilder::LookupFilter Filter = nullptr;
enum CodeCompletionContext::Kind ContextKind
= CodeCompletionContext::CCC_Other;
switch ((DeclSpec::TST)TagSpec) {
@@ -3763,7 +3736,7 @@ void Sema::CodeCompleteCase(Scope *S) {
// 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 = 0;
+ NestedNameSpecifier *Qualifier = nullptr;
for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
SC = SC->getNextSwitchCase()) {
CaseStmt *Case = dyn_cast<CaseStmt>(SC);
@@ -3809,14 +3782,12 @@ void Sema::CodeCompleteCase(Scope *S) {
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Expression);
Results.EnterNewScope();
- for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
- EEnd = Enum->enumerator_end();
- E != EEnd; ++E) {
- if (EnumeratorsSeen.count(*E))
+ for (auto *E : Enum->enumerators()) {
+ if (EnumeratorsSeen.count(E))
continue;
- CodeCompletionResult R(*E, CCP_EnumInCase, Qualifier);
- Results.AddResult(R, CurContext, 0, false);
+ CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
+ Results.AddResult(R, CurContext, nullptr, false);
}
Results.ExitScope();
@@ -3833,22 +3804,6 @@ void Sema::CodeCompleteCase(Scope *S) {
Results.data(),Results.size());
}
-namespace {
- struct IsBetterOverloadCandidate {
- Sema &S;
- SourceLocation Loc;
-
- public:
- explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
- : S(S), Loc(Loc) { }
-
- bool
- operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
- return isBetterOverloadCandidate(S, X, Y, Loc);
- }
- };
-}
-
static bool anyNullArguments(ArrayRef<Expr *> Args) {
if (Args.size() && !Args.data())
return true;
@@ -3880,7 +3835,7 @@ void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, ArrayRef<Expr *> Args) {
// Build an overload candidate set based on the functions we find.
SourceLocation Loc = Fn->getExprLoc();
- OverloadCandidateSet CandidateSet(Loc);
+ OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
// FIXME: What if we're calling something that isn't a function declaration?
// FIXME: What if we're calling a pseudo-destructor?
@@ -3910,9 +3865,12 @@ void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, ArrayRef<Expr *> Args) {
if (!CandidateSet.empty()) {
// Sort the overload candidate set by placing the best overloads first.
- std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
- IsBetterOverloadCandidate(*this, Loc));
-
+ std::stable_sort(
+ CandidateSet.begin(), CandidateSet.end(),
+ [&](const OverloadCandidate &X, const OverloadCandidate &Y) {
+ return isBetterOverloadCandidate(*this, X, Y, Loc);
+ });
+
// Add the remaining viable overload candidates as code-completion reslults.
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
CandEnd = CandidateSet.end();
@@ -3925,12 +3883,13 @@ void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, ArrayRef<Expr *> Args) {
for (unsigned I = 0, N = Results.size(); I != N; ++I) {
if (const FunctionType *FType = Results[I].getFunctionType())
if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
- if (Args.size() < Proto->getNumArgs()) {
+ if (Args.size() < Proto->getNumParams()) {
if (ParamType.isNull())
- ParamType = Proto->getArgType(Args.size());
+ ParamType = Proto->getParamType(Args.size());
else if (!Context.hasSameUnqualifiedType(
- ParamType.getNonReferenceType(),
- Proto->getArgType(Args.size()).getNonReferenceType())) {
+ ParamType.getNonReferenceType(),
+ Proto->getParamType(Args.size())
+ .getNonReferenceType())) {
ParamType = QualType();
break;
}
@@ -3951,8 +3910,8 @@ void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, ArrayRef<Expr *> Args) {
if (const FunctionProtoType *Proto
= FunctionType->getAs<FunctionProtoType>()) {
- if (Args.size() < Proto->getNumArgs())
- ParamType = Proto->getArgType(Args.size());
+ if (Args.size() < Proto->getNumParams())
+ ParamType = Proto->getParamType(Args.size());
}
}
@@ -3982,10 +3941,10 @@ void Sema::CodeCompleteReturn(Scope *S) {
if (BlockScopeInfo *BSI = getCurBlock())
ResultType = BSI->ReturnType;
} else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
- ResultType = Function->getResultType();
+ ResultType = Function->getReturnType();
else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
- ResultType = Method->getResultType();
-
+ ResultType = Method->getReturnType();
+
if (ResultType.isNull())
CodeCompleteOrdinaryName(S, PCC_Expression);
else
@@ -4080,7 +4039,7 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
// The "template" keyword can follow "::" in the grammar, but only
// put it into the grammar if the nested-name-specifier is dependent.
- NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
+ NestedNameSpecifier *NNS = SS.getScopeRep();
if (!Results.empty() && NNS->isDependent())
Results.AddResult("template");
@@ -4184,8 +4143,9 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) {
NSEnd = OrigToLatest.end();
NS != NSEnd; ++NS)
Results.AddResult(CodeCompletionResult(
- NS->second, Results.getBasePriority(NS->second), 0),
- CurContext, 0, false);
+ NS->second, Results.getBasePriority(NS->second),
+ nullptr),
+ CurContext, nullptr, false);
Results.ExitScope();
}
@@ -4274,21 +4234,19 @@ void Sema::CodeCompleteConstructorInitializer(
Results.getCodeCompletionTUInfo());
bool SawLastInitializer = Initializers.empty();
CXXRecordDecl *ClassDecl = Constructor->getParent();
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
- BaseEnd = ClassDecl->bases_end();
- Base != BaseEnd; ++Base) {
- if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
+ for (const auto &Base : ClassDecl->bases()) {
+ if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))) {
SawLastInitializer
= !Initializers.empty() &&
Initializers.back()->isBaseInitializer() &&
- Context.hasSameUnqualifiedType(Base->getType(),
+ Context.hasSameUnqualifiedType(Base.getType(),
QualType(Initializers.back()->getBaseClass(), 0));
continue;
}
Builder.AddTypedTextChunk(
Results.getAllocator().CopyString(
- Base->getType().getAsString(Policy)));
+ Base.getType().getAsString(Policy)));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("args");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
@@ -4299,21 +4257,19 @@ void Sema::CodeCompleteConstructorInitializer(
}
// Add completions for virtual base classes.
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
- BaseEnd = ClassDecl->vbases_end();
- Base != BaseEnd; ++Base) {
- if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
+ for (const auto &Base : ClassDecl->vbases()) {
+ if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))) {
SawLastInitializer
= !Initializers.empty() &&
Initializers.back()->isBaseInitializer() &&
- Context.hasSameUnqualifiedType(Base->getType(),
+ Context.hasSameUnqualifiedType(Base.getType(),
QualType(Initializers.back()->getBaseClass(), 0));
continue;
}
Builder.AddTypedTextChunk(
Builder.getAllocator().CopyString(
- Base->getType().getAsString(Policy)));
+ Base.getType().getAsString(Policy)));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("args");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
@@ -4324,14 +4280,12 @@ void Sema::CodeCompleteConstructorInitializer(
}
// Add completions for members.
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- FieldEnd = ClassDecl->field_end();
- Field != FieldEnd; ++Field) {
+ for (auto *Field : ClassDecl->fields()) {
if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
SawLastInitializer
= !Initializers.empty() &&
Initializers.back()->isAnyMemberInitializer() &&
- Initializers.back()->getAnyMember() == *Field;
+ Initializers.back()->getAnyMember() == Field;
continue;
}
@@ -4348,7 +4302,7 @@ void Sema::CodeCompleteConstructorInitializer(
: CCP_MemberDeclaration,
CXCursor_MemberRef,
CXAvailability_Available,
- *Field));
+ Field));
SawLastInitializer = false;
}
Results.ExitScope();
@@ -4376,22 +4330,19 @@ void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
// Note what has already been captured.
llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
bool IncludedThis = false;
- for (SmallVectorImpl<LambdaCapture>::iterator C = Intro.Captures.begin(),
- CEnd = Intro.Captures.end();
- C != CEnd; ++C) {
- if (C->Kind == LCK_This) {
+ for (const auto &C : Intro.Captures) {
+ if (C.Kind == LCK_This) {
IncludedThis = true;
continue;
}
- Known.insert(C->Id);
+ Known.insert(C.Id);
}
// Look for other capturable variables.
for (; S && !isNamespaceScope(S); S = S->getParent()) {
- for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
- D != DEnd; ++D) {
- VarDecl *Var = dyn_cast<VarDecl>(*D);
+ for (const auto *D : S->decls()) {
+ const auto *Var = dyn_cast<VarDecl>(D);
if (!Var ||
!Var->hasLocalStorage() ||
Var->hasAttr<BlocksAttr>())
@@ -4399,7 +4350,7 @@ void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
if (Known.insert(Var->getIdentifier()))
Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
- CurContext, 0, false);
+ CurContext, nullptr, false);
}
}
@@ -4759,7 +4710,7 @@ void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
CodeCompletionBuilder Setter(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
Setter.AddTypedTextChunk("setter");
- Setter.AddTextChunk(" = ");
+ Setter.AddTextChunk("=");
Setter.AddPlaceholderChunk("method");
Results.AddResult(CodeCompletionResult(Setter.TakeString()));
}
@@ -4767,7 +4718,7 @@ void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
CodeCompletionBuilder Getter(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
Getter.AddTypedTextChunk("getter");
- Getter.AddTextChunk(" = ");
+ Getter.AddTextChunk("=");
Getter.AddPlaceholderChunk("method");
Results.AddResult(CodeCompletionResult(Getter.TakeString()));
}
@@ -4856,22 +4807,20 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
Container = getContainerDef(Container);
ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
bool isRootClass = IFace && !IFace->getSuperClass();
- for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
- MEnd = Container->meth_end();
- M != MEnd; ++M) {
+ for (auto *M : Container->methods()) {
// The instance methods on the root class can be messaged via the
// metaclass.
if (M->isInstanceMethod() == WantInstanceMethods ||
(isRootClass && !WantInstanceMethods)) {
// 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))
+ if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
continue;
if (!Selectors.insert(M->getSelector()))
continue;
-
- Result R = Result(*M, Results.getBasePriority(*M), 0);
+
+ Result R = Result(M, Results.getBasePriority(M), nullptr);
R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = (WantKind != MK_Any);
if (!InOriginalClass)
@@ -4897,19 +4846,12 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
return;
// Add methods in protocols.
- for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
- E = IFace->protocol_end();
- I != E; ++I)
- AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
+ for (auto *I : IFace->protocols())
+ AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents,
CurContext, Selectors, AllowSameLength, Results, false);
// Add methods in categories.
- for (ObjCInterfaceDecl::known_categories_iterator
- Cat = IFace->known_categories_begin(),
- CatEnd = IFace->known_categories_end();
- Cat != CatEnd; ++Cat) {
- ObjCCategoryDecl *CatDecl = *Cat;
-
+ for (auto *CatDecl : IFace->known_categories()) {
AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
CurContext, Selectors, AllowSameLength,
Results, InOriginalClass);
@@ -5080,22 +5022,22 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
if (!Msg)
- return 0;
+ return nullptr;
Selector Sel = Msg->getSelector();
if (Sel.isNull())
- return 0;
+ return nullptr;
IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
if (!Id)
- return 0;
+ return nullptr;
ObjCMethodDecl *Method = Msg->getMethodDecl();
if (!Method)
- return 0;
+ return nullptr;
// Determine the class that we're sending the message to.
- ObjCInterfaceDecl *IFace = 0;
+ ObjCInterfaceDecl *IFace = nullptr;
switch (Msg->getReceiverKind()) {
case ObjCMessageExpr::Class:
if (const ObjCObjectType *ObjType
@@ -5116,7 +5058,7 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
}
if (!IFace)
- return 0;
+ return nullptr;
ObjCInterfaceDecl *Super = IFace->getSuperClass();
if (Method->isInstanceMethod())
@@ -5133,7 +5075,7 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
.Case("class", IFace)
.Case("classForCoder", IFace)
.Case("superclass", Super)
- .Default(0);
+ .Default(nullptr);
return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
.Case("new", IFace)
@@ -5141,7 +5083,7 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
.Case("allocWithZone", IFace)
.Case("class", IFace)
.Case("superclass", Super)
- .Default(0);
+ .Default(nullptr);
}
// Add a special completion for a message send to "super", which fills in the
@@ -5166,14 +5108,14 @@ static ObjCMethodDecl *AddSuperSendCompletion(
ResultBuilder &Results) {
ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
if (!CurMethod)
- return 0;
-
+ return nullptr;
+
ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
if (!Class)
- return 0;
-
+ return nullptr;
+
// Try to find a superclass method with the same selector.
- ObjCMethodDecl *SuperMethod = 0;
+ ObjCMethodDecl *SuperMethod = nullptr;
while ((Class = Class->getSuperClass()) && !SuperMethod) {
// Check in the class
SuperMethod = Class->getMethod(CurMethod->getSelector(),
@@ -5181,10 +5123,7 @@ static ObjCMethodDecl *AddSuperSendCompletion(
// Check in categories or class extensions.
if (!SuperMethod) {
- for (ObjCInterfaceDecl::known_categories_iterator
- Cat = Class->known_categories_begin(),
- CatEnd = Class->known_categories_end();
- Cat != CatEnd; ++Cat) {
+ for (const auto *Cat : Class->known_categories()) {
if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
CurMethod->isInstanceMethod())))
break;
@@ -5193,13 +5132,13 @@ static ObjCMethodDecl *AddSuperSendCompletion(
}
if (!SuperMethod)
- return 0;
-
+ return nullptr;
+
// Check whether the superclass method has the same signature.
if (CurMethod->param_size() != SuperMethod->param_size() ||
CurMethod->isVariadic() != SuperMethod->isVariadic())
- return 0;
-
+ return nullptr;
+
for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
CurPEnd = CurMethod->param_end(),
SuperP = SuperMethod->param_begin();
@@ -5207,11 +5146,11 @@ static ObjCMethodDecl *AddSuperSendCompletion(
// Make sure the parameter types are compatible.
if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
(*SuperP)->getType()))
- return 0;
-
+ return nullptr;
+
// Make sure we have a parameter name to forward!
if (!(*CurP)->getIdentifier())
- return 0;
+ return nullptr;
}
// We have a superclass method. Now, form the send-to-super completion.
@@ -5306,7 +5245,7 @@ void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
ArrayRef<IdentifierInfo *> SelIdents,
bool AtArgumentExpression) {
- ObjCInterfaceDecl *CDecl = 0;
+ ObjCInterfaceDecl *CDecl = nullptr;
if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
// Figure out which interface we're in.
CDecl = CurMethod->getClassInterface();
@@ -5322,7 +5261,7 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
// We are inside an instance method, which means that the message
// send [super ...] is actually calling an instance method on the
// current object.
- return CodeCompleteObjCInstanceMessage(S, 0, SelIdents,
+ return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
AtArgumentExpression,
CDecl);
}
@@ -5383,7 +5322,7 @@ static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
if (R.Priority <= BestPriority) {
const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
if (NumSelIdents <= Method->param_size()) {
- QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
+ QualType MyPreferredType = Method->parameters()[NumSelIdents - 1]
->getType();
if (R.Priority < BestPriority || PreferredType.isNull()) {
BestPriority = R.Priority;
@@ -5407,12 +5346,12 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
bool IsSuper,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
- ObjCInterfaceDecl *CDecl = 0;
-
+ ObjCInterfaceDecl *CDecl = nullptr;
+
// If the given name refers to an interface type, retrieve the
// corresponding declaration.
if (Receiver) {
- QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
+ QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
if (!T.isNull())
if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
CDecl = Interface->getInterface();
@@ -5465,8 +5404,9 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
MethList = MethList->getNext()) {
if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents))
continue;
-
- Result R(MethList->Method, Results.getBasePriority(MethList->Method),0);
+
+ Result R(MethList->Method, Results.getBasePriority(MethList->Method),
+ nullptr);
R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = false;
Results.MaybeAddResult(R, SemaRef.CurContext);
@@ -5526,7 +5466,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
if (Conv.isInvalid()) // conversion failed. bail.
return;
- RecExpr = Conv.take();
+ RecExpr = Conv.get();
}
QualType ReceiverType = RecExpr? RecExpr->getType()
: Super? Context.getObjCObjectPointerType(
@@ -5536,7 +5476,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
// 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 (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
if (ReceiverType->isObjCClassType())
return CodeCompleteObjCClassMessage(S,
@@ -5547,6 +5487,13 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
ReceiverType = Context.getObjCObjectPointerType(
Context.getObjCInterfaceType(IFace));
}
+ } else if (RecExpr && getLangOpts().CPlusPlus) {
+ ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
+ if (Conv.isUsable()) {
+ RecExpr = Conv.get();
+ ReceiverType = RecExpr->getType();
+ }
+ }
// Build the set of methods we can see.
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
@@ -5587,10 +5534,8 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
else if (const ObjCObjectPointerType *QualID
= ReceiverType->getAsObjCQualifiedIdType()) {
// Search protocols for instance methods.
- for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
- E = QualID->qual_end();
- I != E; ++I)
- AddObjCMethods(*I, true, MK_Any, SelIdents, CurContext,
+ for (auto *I : QualID->quals())
+ AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Selectors, AtArgumentExpression, Results);
}
// Handle messages to a pointer to interface type.
@@ -5602,10 +5547,8 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Results);
// Search protocols for instance methods.
- for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
- E = IFacePtr->qual_end();
- I != E; ++I)
- AddObjCMethods(*I, true, MK_Any, SelIdents, CurContext,
+ for (auto *I : IFacePtr->quals())
+ AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Selectors, AtArgumentExpression, Results);
}
// Handle messages to "id".
@@ -5637,8 +5580,9 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
if (!Selectors.insert(MethList->Method->getSelector()))
continue;
-
- Result R(MethList->Method, Results.getBasePriority(MethList->Method),0);
+
+ Result R(MethList->Method, Results.getBasePriority(MethList->Method),
+ nullptr);
R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = false;
Results.MaybeAddResult(R, CurContext);
@@ -5750,14 +5694,12 @@ static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
- for (DeclContext::decl_iterator D = Ctx->decls_begin(),
- DEnd = Ctx->decls_end();
- D != DEnd; ++D) {
+ for (const auto *D : Ctx->decls()) {
// Record any protocols we find.
- if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
+ if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
if (!OnlyForwardDeclarations || !Proto->hasDefinition())
- Results.AddResult(Result(Proto, Results.getBasePriority(Proto), 0),
- CurContext, 0, false);
+ Results.AddResult(Result(Proto, Results.getBasePriority(Proto),nullptr),
+ CurContext, nullptr, false);
}
}
@@ -5818,15 +5760,13 @@ static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
- for (DeclContext::decl_iterator D = Ctx->decls_begin(),
- DEnd = Ctx->decls_end();
- D != DEnd; ++D) {
+ for (const auto *D : Ctx->decls()) {
// Record any interfaces we find.
- if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
+ if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
(!OnlyUnimplemented || !Class->getImplementation()))
- Results.AddResult(Result(Class, Results.getBasePriority(Class), 0),
- CurContext, 0, false);
+ Results.AddResult(Result(Class, Results.getBasePriority(Class),nullptr),
+ CurContext, nullptr, false);
}
}
@@ -5909,24 +5849,19 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
NamedDecl *CurClass
= LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){
- for (ObjCInterfaceDecl::visible_categories_iterator
- Cat = Class->visible_categories_begin(),
- CatEnd = Class->visible_categories_end();
- Cat != CatEnd; ++Cat) {
+ for (const auto *Cat : Class->visible_categories())
CategoryNames.insert(Cat->getIdentifier());
- }
}
// Add all of the categories we know about.
Results.EnterNewScope();
TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
- for (DeclContext::decl_iterator D = TU->decls_begin(),
- DEnd = TU->decls_end();
- D != DEnd; ++D)
- if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
+ for (const auto *D : TU->decls())
+ if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
if (CategoryNames.insert(Category->getIdentifier()))
- Results.AddResult(Result(Category, Results.getBasePriority(Category),0),
- CurContext, 0, false);
+ Results.AddResult(Result(Category, Results.getBasePriority(Category),
+ nullptr),
+ CurContext, nullptr, false);
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter,
@@ -5959,14 +5894,11 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Results.EnterNewScope();
bool IgnoreImplemented = true;
while (Class) {
- for (ObjCInterfaceDecl::visible_categories_iterator
- Cat = Class->visible_categories_begin(),
- CatEnd = Class->visible_categories_end();
- Cat != CatEnd; ++Cat) {
+ for (const auto *Cat : Class->visible_categories()) {
if ((!IgnoreImplemented || !Cat->getImplementation()) &&
CategoryNames.insert(Cat->getIdentifier()))
- Results.AddResult(Result(*Cat, Results.getBasePriority(*Cat), 0),
- CurContext, 0, false);
+ Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
+ CurContext, nullptr, false);
}
Class = Class->getSuperClass();
@@ -5994,10 +5926,8 @@ void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
// Ignore any properties that have already been implemented.
Container = getContainerDef(Container);
- for (DeclContext::decl_iterator D = Container->decls_begin(),
- DEnd = Container->decls_end();
- D != DEnd; ++D)
- if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
+ for (const auto *D : Container->decls())
+ if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Results.Ignore(PropertyImpl->getPropertyDecl());
// Add any properties that we find.
@@ -6035,7 +5965,7 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
return;
// Figure out which interface we're looking into.
- ObjCInterfaceDecl *Class = 0;
+ ObjCInterfaceDecl *Class = nullptr;
if (ObjCImplementationDecl *ClassImpl
= dyn_cast<ObjCImplementationDecl>(Container))
Class = ClassImpl->getClassInterface();
@@ -6067,9 +5997,9 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
for(; Class; Class = Class->getSuperClass()) {
for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
Ivar = Ivar->getNextIvar()) {
- Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), 0),
- CurContext, 0, false);
-
+ Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
+ CurContext, nullptr, false);
+
// Determine whether we've seen an ivar with a name similar to the
// property.
if ((PropertyName == Ivar->getIdentifier() ||
@@ -6144,11 +6074,8 @@ static void FindImplementableMethods(ASTContext &Context,
KnownMethods, InOriginalClass);
// Add methods from any class extensions and categories.
- for (ObjCInterfaceDecl::visible_categories_iterator
- Cat = IFace->visible_categories_begin(),
- CatEnd = IFace->visible_categories_end();
- Cat != CatEnd; ++Cat) {
- FindImplementableMethods(Context, *Cat, WantInstanceMethods, ReturnType,
+ for (auto *Cat : IFace->visible_categories()) {
+ FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
KnownMethods, false);
}
@@ -6196,16 +6123,14 @@ static void FindImplementableMethods(ASTContext &Context,
// Add methods in this container. This operation occurs last because
// we want the methods from this container to override any methods
// we've previously seen with the same selector.
- for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
- MEnd = Container->meth_end();
- M != MEnd; ++M) {
+ for (auto *M : Container->methods()) {
if (M->isInstanceMethod() == WantInstanceMethods) {
if (!ReturnType.isNull() &&
- !Context.hasSameUnqualifiedType(ReturnType, M->getResultType()))
+ !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
continue;
KnownMethods[M->getSelector()] =
- KnownMethodsMap::mapped_type(*M, InOriginalClass);
+ KnownMethodsMap::mapped_type(M, InOriginalClass);
}
}
}
@@ -6267,10 +6192,10 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
CodeCompletionAllocator &Allocator;
StringRef Key;
const char *CopiedKey;
-
+
KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
- : Allocator(Allocator), Key(Key), CopiedKey(0) { }
-
+ : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
+
operator const char *() {
if (CopiedKey)
return CopiedKey;
@@ -6872,13 +6797,13 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
// Determine the return type of the method we're declaring, if
// provided.
QualType ReturnType = GetTypeFromParser(ReturnTy);
- Decl *IDecl = 0;
+ Decl *IDecl = nullptr;
if (CurContext->isObjCContainer()) {
ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
IDecl = cast<Decl>(OCD);
}
// Determine where we should start searching for methods.
- ObjCContainerDecl *SearchDecl = 0;
+ ObjCContainerDecl *SearchDecl = nullptr;
bool IsInImplementation = false;
if (Decl *D = IDecl) {
if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
@@ -6900,7 +6825,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
if (!SearchDecl) {
HandleCodeCompleteResults(this, CodeCompleter,
CodeCompletionContext::CCC_Other,
- 0, 0);
+ nullptr, 0);
return;
}
@@ -6926,10 +6851,9 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
// If the result type was not already provided, add it to the
// pattern as (type).
if (ReturnType.isNull())
- AddObjCPassingTypeChunk(Method->getResultType(),
- Method->getObjCDeclQualifier(),
- Context, Policy,
- Builder);
+ AddObjCPassingTypeChunk(Method->getReturnType(),
+ Method->getObjCDeclQualifier(), Context, Policy,
+ Builder);
Selector Sel = Method->getSelector();
@@ -6973,7 +6897,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
- if (!Method->getResultType()->isVoidType()) {
+ if (!Method->getReturnType()->isVoidType()) {
// If the result type is not void, add a return clause.
Builder.AddTextChunk("return");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -7011,23 +6935,14 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
IFace = Category->getClassInterface();
- if (IFace) {
- for (ObjCInterfaceDecl::visible_categories_iterator
- Cat = IFace->visible_categories_begin(),
- CatEnd = IFace->visible_categories_end();
- Cat != CatEnd; ++Cat) {
- Containers.push_back(*Cat);
- }
- }
+ if (IFace)
+ for (auto *Cat : IFace->visible_categories())
+ Containers.push_back(Cat);
- for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
- for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
- PEnd = Containers[I]->prop_end();
- P != PEnd; ++P) {
- AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
+ for (unsigned I = 0, N = Containers.size(); I != N; ++I)
+ for (auto *P : Containers[I]->properties())
+ AddObjCKeyValueCompletions(P, IsInstanceMethod, ReturnType, Context,
KnownSelectors, Results);
- }
- }
}
Results.ExitScope();
@@ -7079,7 +6994,7 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
// Suggest parameter names we've seen before.
unsigned NumSelIdents = SelIdents.size();
if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
- ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
+ ParmVarDecl *Param = MethList->Method->parameters()[NumSelIdents-1];
if (Param->getIdentifier()) {
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
@@ -7091,8 +7006,9 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
continue;
}
-
- Result R(MethList->Method, Results.getBasePriority(MethList->Method), 0);
+
+ Result R(MethList->Method, Results.getBasePriority(MethList->Method),
+ nullptr);
R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = false;
R.DeclaringEntity = true;
@@ -7338,7 +7254,7 @@ void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
void Sema::CodeCompleteNaturalLanguage() {
HandleCodeCompleteResults(this, CodeCompleter,
CodeCompletionContext::CCC_NaturalLanguage,
- 0, 0);
+ nullptr, 0);
}
void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
index 328ce70..bbe6930 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
@@ -25,12 +25,14 @@
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
+#include "clang/Basic/Builtins.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Lex/HeaderSearch.h" // FIXME: Sema shouldn't depend on Lex
-#include "clang/Lex/ModuleLoader.h" // FIXME: Sema shouldn't depend on Lex
-#include "clang/Lex/Preprocessor.h" // FIXME: Sema shouldn't depend on Lex
+#include "clang/Lex/HeaderSearch.h" // TODO: Sema shouldn't depend on Lex
+#include "clang/Lex/Lexer.h" // TODO: Extract static functions to fix layering.
+#include "clang/Lex/ModuleLoader.h" // TODO: Sema shouldn't depend on Lex
+#include "clang/Lex/Preprocessor.h" // Included for isCodeCompletionEnabled()
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/CXXFieldCollector.h"
#include "clang/Sema/DeclSpec.h"
@@ -62,24 +64,29 @@ namespace {
class TypeNameValidatorCCC : public CorrectionCandidateCallback {
public:
- TypeNameValidatorCCC(bool AllowInvalid, bool WantClass=false)
- : AllowInvalidDecl(AllowInvalid), WantClassName(WantClass) {
+ TypeNameValidatorCCC(bool AllowInvalid, bool WantClass=false,
+ bool AllowTemplates=false)
+ : AllowInvalidDecl(AllowInvalid), WantClassName(WantClass),
+ AllowClassTemplates(AllowTemplates) {
WantExpressionKeywords = false;
WantCXXNamedCasts = false;
WantRemainingKeywords = false;
}
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
- if (NamedDecl *ND = candidate.getCorrectionDecl())
- return (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
- (AllowInvalidDecl || !ND->isInvalidDecl());
- else
- return !WantClassName && candidate.isKeyword();
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
+ if (NamedDecl *ND = candidate.getCorrectionDecl()) {
+ bool IsType = isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
+ bool AllowedTemplate = AllowClassTemplates && isa<ClassTemplateDecl>(ND);
+ return (IsType || AllowedTemplate) &&
+ (AllowInvalidDecl || !ND->isInvalidDecl());
+ }
+ return !WantClassName && candidate.isKeyword();
}
private:
bool AllowInvalidDecl;
bool WantClassName;
+ bool AllowClassTemplates;
};
}
@@ -121,6 +128,65 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const {
return false;
}
+static ParsedType recoverFromTypeInKnownDependentBase(Sema &S,
+ const IdentifierInfo &II,
+ SourceLocation NameLoc) {
+ // Find the first parent class template context, if any.
+ // FIXME: Perform the lookup in all enclosing class templates.
+ const CXXRecordDecl *RD = nullptr;
+ for (DeclContext *DC = S.CurContext; DC; DC = DC->getParent()) {
+ RD = dyn_cast<CXXRecordDecl>(DC);
+ if (RD && RD->getDescribedClassTemplate())
+ break;
+ }
+ if (!RD)
+ return ParsedType();
+
+ // Look for type decls in dependent base classes that have known primary
+ // templates.
+ bool FoundTypeDecl = false;
+ for (const auto &Base : RD->bases()) {
+ auto *TST = Base.getType()->getAs<TemplateSpecializationType>();
+ if (!TST || !TST->isDependentType())
+ continue;
+ auto *TD = TST->getTemplateName().getAsTemplateDecl();
+ if (!TD)
+ continue;
+ auto *BasePrimaryTemplate = cast<CXXRecordDecl>(TD->getTemplatedDecl());
+ // FIXME: Allow lookup into non-dependent bases of dependent bases, possibly
+ // by calling or integrating with the main LookupQualifiedName mechanism.
+ for (NamedDecl *ND : BasePrimaryTemplate->lookup(&II)) {
+ if (FoundTypeDecl)
+ return ParsedType();
+ FoundTypeDecl = isa<TypeDecl>(ND);
+ if (!FoundTypeDecl)
+ return ParsedType();
+ }
+ }
+ if (!FoundTypeDecl)
+ return ParsedType();
+
+ // We found some types in dependent base classes. Recover as if the user
+ // wrote 'typename MyClass::II' instead of 'II'. We'll fully resolve the
+ // lookup during template instantiation.
+ S.Diag(NameLoc, diag::ext_found_via_dependent_bases_lookup) << &II;
+
+ ASTContext &Context = S.Context;
+ auto *NNS = NestedNameSpecifier::Create(Context, nullptr, false,
+ cast<Type>(Context.getRecordType(RD)));
+ QualType T = Context.getDependentNameType(ETK_Typename, NNS, &II);
+
+ CXXScopeSpec SS;
+ SS.MakeTrivial(Context, NNS, SourceRange(NameLoc));
+
+ TypeLocBuilder Builder;
+ DependentNameTypeLoc DepTL = Builder.push<DependentNameTypeLoc>(T);
+ DepTL.setNameLoc(NameLoc);
+ DepTL.setElaboratedKeywordLoc(SourceLocation());
+ DepTL.setQualifierLoc(SS.getWithLocInContext(Context));
+ return S.CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
+}
+
/// \brief If the identifier refers to a type name within this scope,
/// return the declaration of that type.
///
@@ -137,7 +203,7 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
bool WantNontrivialTypeSourceInfo,
IdentifierInfo **CorrectedII) {
// Determine where we will perform name lookup.
- DeclContext *LookupCtx = 0;
+ DeclContext *LookupCtx = nullptr;
if (ObjectTypePtr) {
QualType ObjectType = ObjectTypePtr.get();
if (ObjectType->isRecordType())
@@ -165,11 +231,9 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
return ActOnTypenameType(S, SourceLocation(), *SS, II, NameLoc).get();
NestedNameSpecifierLoc QualifierLoc = SS->getWithLocInContext(Context);
- QualType T =
- CheckTypenameType(ETK_None, SourceLocation(), QualifierLoc,
- II, NameLoc);
-
- return ParsedType::make(T);
+ QualType T = CheckTypenameType(ETK_None, SourceLocation(), QualifierLoc,
+ II, NameLoc);
+ return ParsedType::make(T);
}
return ParsedType();
@@ -204,16 +268,25 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
} else {
// Perform unqualified name lookup.
LookupName(Result, S);
+
+ // For unqualified lookup in a class template in MSVC mode, look into
+ // dependent base classes where the primary class template is known.
+ if (Result.empty() && getLangOpts().MSVCCompat && (!SS || SS->isEmpty())) {
+ if (ParsedType TypeInBase =
+ recoverFromTypeInKnownDependentBase(*this, II, NameLoc))
+ return TypeInBase;
+ }
}
-
- NamedDecl *IIDecl = 0;
+
+ NamedDecl *IIDecl = nullptr;
switch (Result.getResultKind()) {
case LookupResult::NotFound:
case LookupResult::NotFoundInCurrentInstantiation:
if (CorrectedII) {
TypeNameValidatorCCC Validator(true, isClassName);
TypoCorrection Correction = CorrectTypo(Result.getLookupNameInfo(),
- Kind, S, SS, Validator);
+ Kind, S, SS, Validator,
+ CTK_ErrorRecovery);
IdentifierInfo *NewII = Correction.getCorrectionAsIdentifierInfo();
TemplateTy Template;
bool MemberOfUnknownSpecialization;
@@ -303,8 +376,7 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) {
DiagnoseUseOfDecl(IIDecl, NameLoc);
- if (T.isNull())
- T = Context.getTypeDeclType(TD);
+ T = Context.getTypeDeclType(TD);
// NOTE: avoid constructing an ElaboratedType(Loc) if this is a
// constructor or destructor name (in such a case, the scope specifier
@@ -338,6 +410,50 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
return ParsedType::make(T);
}
+// Builds a fake NNS for the given decl context.
+static NestedNameSpecifier *
+synthesizeCurrentNestedNameSpecifier(ASTContext &Context, DeclContext *DC) {
+ for (;; DC = DC->getLookupParent()) {
+ DC = DC->getPrimaryContext();
+ auto *ND = dyn_cast<NamespaceDecl>(DC);
+ if (ND && !ND->isInline() && !ND->isAnonymousNamespace())
+ return NestedNameSpecifier::Create(Context, nullptr, ND);
+ else if (auto *RD = dyn_cast<CXXRecordDecl>(DC))
+ return NestedNameSpecifier::Create(Context, nullptr, RD->isTemplateDecl(),
+ RD->getTypeForDecl());
+ else if (isa<TranslationUnitDecl>(DC))
+ return NestedNameSpecifier::GlobalSpecifier(Context);
+ }
+ llvm_unreachable("something isn't in TU scope?");
+}
+
+ParsedType Sema::ActOnDelayedDefaultTemplateArg(const IdentifierInfo &II,
+ SourceLocation NameLoc) {
+ // Accepting an undeclared identifier as a default argument for a template
+ // type parameter is a Microsoft extension.
+ Diag(NameLoc, diag::ext_ms_delayed_template_argument) << &II;
+
+ // Build a fake DependentNameType that will perform lookup into CurContext at
+ // instantiation time. The name specifier isn't dependent, so template
+ // instantiation won't transform it. It will retry the lookup, however.
+ NestedNameSpecifier *NNS =
+ synthesizeCurrentNestedNameSpecifier(Context, CurContext);
+ QualType T = Context.getDependentNameType(ETK_None, NNS, &II);
+
+ // Build type location information. We synthesized the qualifier, so we have
+ // to build a fake NestedNameSpecifierLoc.
+ NestedNameSpecifierLocBuilder NNSLocBuilder;
+ NNSLocBuilder.MakeTrivial(Context, NNS, SourceRange(NameLoc));
+ NestedNameSpecifierLoc QualifierLoc = NNSLocBuilder.getWithLocInContext(Context);
+
+ TypeLocBuilder Builder;
+ DependentNameTypeLoc DepTL = Builder.push<DependentNameTypeLoc>(T);
+ DepTL.setNameLoc(NameLoc);
+ DepTL.setElaboratedKeywordLoc(SourceLocation());
+ DepTL.setQualifierLoc(QualifierLoc);
+ return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
+}
+
/// isTagName() - This method is called *for error recovery purposes only*
/// to determine if the specified name is a valid tag name ("struct foo"). If
/// so, this returns the TST for the tag corresponding to it (TST_enum,
@@ -381,29 +497,29 @@ bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S) {
const Type *Ty = SS->getScopeRep()->getAsType();
CXXRecordDecl *RD = cast<CXXRecordDecl>(CurContext);
- for (CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin(),
- BaseEnd = RD->bases_end(); Base != BaseEnd; ++Base)
- if (Context.hasSameUnqualifiedType(QualType(Ty, 1), Base->getType()))
+ for (const auto &Base : RD->bases())
+ if (Context.hasSameUnqualifiedType(QualType(Ty, 1), Base.getType()))
return true;
return S->isFunctionPrototypeScope();
}
return CurContext->isFunctionOrMethod() || S->isFunctionPrototypeScope();
}
-bool Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
+void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
SourceLocation IILoc,
Scope *S,
CXXScopeSpec *SS,
- ParsedType &SuggestedType) {
+ ParsedType &SuggestedType,
+ bool AllowClassTemplates) {
// We don't have anything to suggest (yet).
SuggestedType = ParsedType();
// There may have been a typo in the name of the type. Look up typo
// results, in case we have something that we can suggest.
- TypeNameValidatorCCC Validator(false);
+ TypeNameValidatorCCC Validator(false, false, AllowClassTemplates);
if (TypoCorrection Corrected = CorrectTypo(DeclarationNameInfo(II, IILoc),
LookupOrdinaryName, S, SS,
- Validator)) {
+ Validator, CTK_ErrorRecovery)) {
if (Corrected.isKeyword()) {
// We corrected to a keyword.
diagnoseTypo(Corrected, PDiag(diag::err_unknown_typename_suggest) << II);
@@ -434,7 +550,7 @@ bool Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
/*IsCtorOrDtorName=*/false,
/*NonTrivialTypeSourceInfo=*/true);
}
- return true;
+ return;
}
if (getLangOpts().CPlusPlus) {
@@ -453,7 +569,7 @@ bool Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
Diag(TplDecl->getLocation(), diag::note_template_decl_here)
<< TplDecl->getTemplateParameters()->getSourceRange();
}
- return true;
+ return;
}
}
@@ -467,11 +583,11 @@ bool Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
<< II << DC << SS->getRange();
else if (isDependentScopeSpecifier(*SS)) {
unsigned DiagID = diag::err_typename_missing;
- if (getLangOpts().MicrosoftMode && isMicrosoftMissingTypename(SS, S))
- DiagID = diag::warn_typename_missing;
+ if (getLangOpts().MSVCCompat && isMicrosoftMissingTypename(SS, S))
+ DiagID = diag::ext_typename_missing;
Diag(SS->getRange().getBegin(), DiagID)
- << (NestedNameSpecifier *)SS->getScopeRep() << II->getName()
+ << SS->getScopeRep() << II->getName()
<< SourceRange(SS->getRange().getBegin(), IILoc)
<< FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename ");
SuggestedType = ActOnTypenameType(S, SourceLocation(),
@@ -480,8 +596,6 @@ bool Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
assert(SS && SS->isInvalid() &&
"Invalid scope specifier has already been diagnosed");
}
-
- return true;
}
/// \brief Determine whether the given result set contains either a type name
@@ -508,35 +622,30 @@ static bool isTagTypeWithMissingTag(Sema &SemaRef, LookupResult &Result,
LookupResult R(SemaRef, Name, NameLoc, Sema::LookupTagName);
SemaRef.LookupParsedName(R, S, &SS);
if (TagDecl *Tag = R.getAsSingle<TagDecl>()) {
- const char *TagName = 0;
- const char *FixItTagName = 0;
+ StringRef FixItTagName;
switch (Tag->getTagKind()) {
case TTK_Class:
- TagName = "class";
FixItTagName = "class ";
break;
case TTK_Enum:
- TagName = "enum";
FixItTagName = "enum ";
break;
case TTK_Struct:
- TagName = "struct";
FixItTagName = "struct ";
break;
case TTK_Interface:
- TagName = "__interface";
FixItTagName = "__interface ";
break;
case TTK_Union:
- TagName = "union";
FixItTagName = "union ";
break;
}
+ StringRef TagName = FixItTagName.drop_back();
SemaRef.Diag(NameLoc, diag::err_use_of_tag_name_without_tag)
<< Name << TagName << SemaRef.getLangOpts().CPlusPlus
<< FixItHint::CreateInsertion(NameLoc, FixItTagName);
@@ -579,16 +688,23 @@ Sema::NameClassification Sema::ClassifyName(Scope *S,
CorrectionCandidateCallback *CCC) {
DeclarationNameInfo NameInfo(Name, NameLoc);
ObjCMethodDecl *CurMethod = getCurMethodDecl();
-
+
if (NextToken.is(tok::coloncolon)) {
BuildCXXNestedNameSpecifier(S, *Name, NameLoc, NextToken.getLocation(),
- QualType(), false, SS, 0, false);
-
+ QualType(), false, SS, nullptr, false);
}
-
+
LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName);
LookupParsedName(Result, S, &SS, !CurMethod);
-
+
+ // For unqualified lookup in a class template in MSVC mode, look into
+ // dependent base classes where the primary class template is known.
+ if (Result.empty() && SS.isEmpty() && getLangOpts().MSVCCompat) {
+ if (ParsedType TypeInBase =
+ recoverFromTypeInKnownDependentBase(*this, *Name, NameLoc))
+ return TypeInBase;
+ }
+
// Perform lookup for Objective-C instance variables (including automatically
// synthesized instance variables), if we're in an Objective-C method.
// FIXME: This lookup really, really needs to be folded in to the normal
@@ -646,13 +762,14 @@ Corrected:
SecondTry = true;
if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(),
Result.getLookupKind(), S,
- &SS, *CCC)) {
+ &SS, *CCC,
+ CTK_ErrorRecovery)) {
unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest;
unsigned QualifiedDiag = diag::err_no_member_suggest;
NamedDecl *FirstDecl = Corrected.getCorrectionDecl();
NamedDecl *UnderlyingFirstDecl
- = FirstDecl? FirstDecl->getUnderlyingDecl() : 0;
+ = FirstDecl? FirstDecl->getUnderlyingDecl() : nullptr;
if (getLangOpts().CPlusPlus && NextToken.is(tok::less) &&
UnderlyingFirstDecl && isa<TemplateDecl>(UnderlyingFirstDecl)) {
UnqualifiedDiag = diag::err_no_template_suggest;
@@ -725,7 +842,7 @@ Corrected:
// keyword here.
return ActOnDependentIdExpression(SS, /*TemplateKWLoc=*/SourceLocation(),
NameInfo, IsAddressOfOperand,
- /*TemplateArgs=*/0);
+ /*TemplateArgs=*/nullptr);
}
case LookupResult::Found:
@@ -817,8 +934,8 @@ Corrected:
ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(FirstDecl);
if (!Class) {
// FIXME: It's unfortunate that we don't have a Type node for handling this.
- if (ObjCCompatibleAliasDecl *Alias
- = dyn_cast<ObjCCompatibleAliasDecl>(FirstDecl))
+ if (ObjCCompatibleAliasDecl *Alias =
+ dyn_cast<ObjCCompatibleAliasDecl>(FirstDecl))
Class = Alias->getClassInterface();
}
@@ -845,7 +962,8 @@ Corrected:
// seems likely a type is wanted instead of the non-type that was found.
bool NextIsOp = NextToken.is(tok::amp) || NextToken.is(tok::star);
if ((NextToken.is(tok::identifier) ||
- (NextIsOp && FirstDecl->isFunctionOrFunctionTemplate())) &&
+ (NextIsOp &&
+ FirstDecl->getUnderlyingDecl()->isFunctionOrFunctionTemplate())) &&
isTagTypeWithMissingTag(*this, Result, S, SS, Name, NameLoc)) {
TypeDecl *Type = Result.getAsSingle<TypeDecl>();
DiagnoseUseOfDecl(Type, NameLoc);
@@ -856,7 +974,8 @@ Corrected:
}
if (FirstDecl->isCXXClassMember())
- return BuildPossibleImplicitMemberExpr(SS, SourceLocation(), Result, 0);
+ return BuildPossibleImplicitMemberExpr(SS, SourceLocation(), Result,
+ nullptr);
bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren));
return BuildDeclarationNameExpr(SS, Result, ADL);
@@ -962,12 +1081,9 @@ void Sema::ExitDeclaratorContext(Scope *S) {
void Sema::ActOnReenterFunctionContext(Scope* S, Decl *D) {
- FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
- if (FunctionTemplateDecl *TFD = dyn_cast_or_null<FunctionTemplateDecl>(D)) {
- // We assume that the caller has already called
- // ActOnReenterTemplateScope
- FD = TFD->getTemplatedDecl();
- }
+ // We assume that the caller has already called
+ // ActOnReenterTemplateScope so getTemplatedDecl() works.
+ FunctionDecl *FD = D->getAsFunction();
if (!FD)
return;
@@ -1086,9 +1202,8 @@ void Sema::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) {
}
bool Sema::isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S,
- bool ExplicitInstantiationOrSpecialization) {
- return IdResolver.isDeclInScope(D, Ctx, S,
- ExplicitInstantiationOrSpecialization);
+ bool AllowInlineNamespace) {
+ return IdResolver.isDeclInScope(D, Ctx, S, AllowInlineNamespace);
}
Scope *Sema::getScopeForDeclContext(Scope *S, DeclContext *DC) {
@@ -1099,7 +1214,7 @@ Scope *Sema::getScopeForDeclContext(Scope *S, DeclContext *DC) {
return S;
} while ((S = S->getParent()));
- return 0;
+ return nullptr;
}
static bool isOutOfScopePreviousDeclaration(NamedDecl *,
@@ -1108,21 +1223,19 @@ static bool isOutOfScopePreviousDeclaration(NamedDecl *,
/// Filters out lookup results that don't fall within the given scope
/// as determined by isDeclInScope.
-void Sema::FilterLookupForScope(LookupResult &R,
- DeclContext *Ctx, Scope *S,
+void Sema::FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S,
bool ConsiderLinkage,
- bool ExplicitInstantiationOrSpecialization) {
+ bool AllowInlineNamespace) {
LookupResult::Filter F = R.makeFilter();
while (F.hasNext()) {
NamedDecl *D = F.next();
- if (isDeclInScope(D, Ctx, S, ExplicitInstantiationOrSpecialization))
+ if (isDeclInScope(D, Ctx, S, AllowInlineNamespace))
continue;
- if (ConsiderLinkage &&
- isOutOfScopePreviousDeclaration(D, Ctx, Context))
+ if (ConsiderLinkage && isOutOfScopePreviousDeclaration(D, Ctx, Context))
continue;
-
+
F.erase();
}
@@ -1173,8 +1286,8 @@ static bool IsDisallowedCopyOrAssign(const CXXMethodDecl *D) {
//
// When we see foo we don't know if after the typedef we will get 'A' or '*A'
// for example. If 'A', foo will have external linkage. If we have '*A',
-// foo will have no linkage. Since we can't know untill we get to the end
-// of the typedef, this function finds out if D might have non external linkage.
+// foo will have no linkage. Since we can't know until we get to the end
+// of the typedef, this function finds out if D might have non-external linkage.
// Callers should verify at the end of the TU if it D has external linkage or
// not.
bool Sema::mightHaveNonExternalLinkage(const DeclaratorDecl *D) {
@@ -1204,7 +1317,8 @@ bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const {
if (D->isInvalidDecl() || D->isUsed() || D->hasAttr<UnusedAttr>())
return false;
- // Ignore class templates.
+ // Ignore all entities declared within templates, and out-of-line definitions
+ // of members of class templates.
if (D->getDeclContext()->isDependentContext() ||
D->getLexicalDeclContext()->isDependentContext())
return false;
@@ -1218,8 +1332,7 @@ bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const {
return false;
} else {
// 'static inline' functions are defined in headers; don't warn.
- if (FD->isInlineSpecified() &&
- !isMainFileLoc(*this, FD->getLocation()))
+ if (FD->isInlined() && !isMainFileLoc(*this, FD->getLocation()))
return false;
}
@@ -1244,6 +1357,8 @@ bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const {
}
// Only warn for unused decls internal to the translation unit.
+ // FIXME: This seems like a bogus check; it suppresses -Wunused-function
+ // for inline functions defined in the main source file, for instance.
return mightHaveNonExternalLinkage(D);
}
@@ -1271,7 +1386,8 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
if (D->isInvalidDecl())
return false;
- if (D->isReferenced() || D->isUsed() || D->hasAttr<UnusedAttr>())
+ if (D->isReferenced() || D->isUsed() || D->hasAttr<UnusedAttr>() ||
+ D->hasAttr<ObjCPreciseLifetimeAttr>())
return false;
if (isa<LabelDecl>(D))
@@ -1309,7 +1425,8 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
return false;
if (const Expr *Init = VD->getInit()) {
- if (const ExprWithCleanups *Cleanups = dyn_cast<ExprWithCleanups>(Init))
+ if (const ExprWithCleanups *Cleanups =
+ dyn_cast<ExprWithCleanups>(Init))
Init = Cleanups->getSubExpr();
const CXXConstructExpr *Construct =
dyn_cast<CXXConstructExpr>(Init);
@@ -1344,10 +1461,10 @@ static void GenerateFixForUnusedDecl(const NamedDecl *D, ASTContext &Ctx,
/// DiagnoseUnusedDecl - Emit warnings about declarations that are not used
/// unless they are marked attr(unused).
void Sema::DiagnoseUnusedDecl(const NamedDecl *D) {
- FixItHint Hint;
if (!ShouldDiagnoseUnusedDecl(D))
return;
+ FixItHint Hint;
GenerateFixForUnusedDecl(D, Context, Hint);
unsigned DiagID;
@@ -1365,18 +1482,18 @@ static void CheckPoppedLabel(LabelDecl *L, Sema &S) {
// Verify that we have no forward references left. If so, there was a goto
// or address of a label taken, but no definition of it. Label fwd
// definitions are indicated with a null substmt.
- if (L->getStmt() == 0)
+ if (L->getStmt() == nullptr)
S.Diag(L->getLocation(), diag::err_undeclared_label_use) <<L->getDeclName();
}
void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
+ S->mergeNRVOIntoParent();
+
if (S->decl_empty()) return;
assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) &&
"Scope shouldn't contain decls!");
- for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
- I != E; ++I) {
- Decl *TmpD = (*I);
+ for (auto *TmpD : S->decls()) {
assert(TmpD && "This decl didn't get pushed??");
assert(isa<NamedDecl>(TmpD) && "Decl isn't NamedDecl?");
@@ -1395,16 +1512,6 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
// Remove this name from our lexical scope.
IdResolver.RemoveDecl(D);
}
- DiagnoseUnusedBackingIvarInAccessor(S);
-}
-
-void Sema::ActOnStartFunctionDeclarator() {
- ++InFunctionDeclarator;
-}
-
-void Sema::ActOnEndFunctionDeclarator() {
- assert(InFunctionDeclarator);
- --InFunctionDeclarator;
}
/// \brief Look for an Objective-C class in the translation unit.
@@ -1432,8 +1539,8 @@ ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id,
// find an Objective-C class name.
DeclFilterCCC<ObjCInterfaceDecl> Validator;
if (TypoCorrection C = CorrectTypo(DeclarationNameInfo(Id, IdLoc),
- LookupOrdinaryName, TUScope, NULL,
- Validator)) {
+ LookupOrdinaryName, TUScope, nullptr,
+ Validator, CTK_ErrorRecovery)) {
diagnoseTypo(C, PDiag(diag::err_undef_interface_suggest) << Id);
IDecl = C.getCorrectionDeclAs<ObjCInterfaceDecl>();
Id = IDecl->getIdentifier();
@@ -1495,6 +1602,20 @@ static void LookupPredefedObjCSuperType(Sema &ThisSema, Scope *S,
Context.setObjCSuperType(Context.getTagDeclType(TD));
}
+static StringRef getHeaderName(ASTContext::GetBuiltinTypeError Error) {
+ switch (Error) {
+ case ASTContext::GE_None:
+ return "";
+ case ASTContext::GE_Missing_stdio:
+ return "stdio.h";
+ case ASTContext::GE_Missing_setjmp:
+ return "setjmp.h";
+ case ASTContext::GE_Missing_ucontext:
+ return "ucontext.h";
+ }
+ llvm_unreachable("unhandled error kind");
+}
+
/// LazilyCreateBuiltin - The specified Builtin-ID was first used at
/// file scope. lazily create a decl for it. ForRedeclaration is true
/// if we're creating this built-in in anticipation of redeclaring the
@@ -1508,28 +1629,12 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
ASTContext::GetBuiltinTypeError Error;
QualType R = Context.GetBuiltinType(BID, Error);
- switch (Error) {
- case ASTContext::GE_None:
- // Okay
- break;
-
- case ASTContext::GE_Missing_stdio:
+ if (Error) {
if (ForRedeclaration)
- Diag(Loc, diag::warn_implicit_decl_requires_stdio)
- << Context.BuiltinInfo.GetName(BID);
- return 0;
-
- case ASTContext::GE_Missing_setjmp:
- if (ForRedeclaration)
- Diag(Loc, diag::warn_implicit_decl_requires_setjmp)
- << Context.BuiltinInfo.GetName(BID);
- return 0;
-
- case ASTContext::GE_Missing_ucontext:
- if (ForRedeclaration)
- Diag(Loc, diag::warn_implicit_decl_requires_ucontext)
- << Context.BuiltinInfo.GetName(BID);
- return 0;
+ Diag(Loc, diag::warn_implicit_decl_requires_sysheader)
+ << getHeaderName(Error)
+ << Context.BuiltinInfo.GetName(BID);
+ return nullptr;
}
if (!ForRedeclaration && Context.BuiltinInfo.isPredefinedLibFunction(BID)) {
@@ -1537,11 +1642,10 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
<< Context.BuiltinInfo.GetName(BID)
<< R;
if (Context.BuiltinInfo.getHeaderName(BID) &&
- Diags.getDiagnosticLevel(diag::ext_implicit_lib_function_decl, Loc)
- != DiagnosticsEngine::Ignored)
- Diag(Loc, diag::note_please_include_header)
- << Context.BuiltinInfo.getHeaderName(BID)
- << Context.BuiltinInfo.GetName(BID);
+ !Diags.isIgnored(diag::ext_implicit_lib_function_decl, Loc))
+ Diag(Loc, diag::note_include_header_or_declare)
+ << Context.BuiltinInfo.getHeaderName(BID)
+ << Context.BuiltinInfo.GetName(BID);
}
DeclContext *Parent = Context.getTranslationUnitDecl();
@@ -1549,13 +1653,14 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
LinkageSpecDecl *CLinkageDecl =
LinkageSpecDecl::Create(Context, Parent, Loc, Loc,
LinkageSpecDecl::lang_c, false);
+ CLinkageDecl->setImplicit();
Parent->addDecl(CLinkageDecl);
Parent = CLinkageDecl;
}
FunctionDecl *New = FunctionDecl::Create(Context,
Parent,
- Loc, Loc, II, R, /*TInfo=*/0,
+ Loc, Loc, II, R, /*TInfo=*/nullptr,
SC_Extern,
false,
/*hasPrototype=*/true);
@@ -1565,12 +1670,11 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
// FunctionDecl.
if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(R)) {
SmallVector<ParmVarDecl*, 16> Params;
- for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) {
+ for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
ParmVarDecl *parm =
- ParmVarDecl::Create(Context, New, SourceLocation(),
- SourceLocation(), 0,
- FT->getArgType(i), /*TInfo=*/0,
- SC_None, 0);
+ ParmVarDecl::Create(Context, New, SourceLocation(), SourceLocation(),
+ nullptr, FT->getParamType(i), /*TInfo=*/nullptr,
+ SC_None, nullptr);
parm->setScopeInfo(0, i);
Params.push_back(parm);
}
@@ -1789,7 +1893,7 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) {
Context.getSourceManager().isInSystemHeader(New->getLocation())))
return;
- Diag(New->getLocation(), diag::warn_redefinition_of_typedef)
+ Diag(New->getLocation(), diag::ext_redefinition_of_typedef)
<< New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
return;
@@ -1797,46 +1901,19 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) {
/// DeclhasAttr - returns true if decl Declaration already has the target
/// attribute.
-static bool
-DeclHasAttr(const Decl *D, const Attr *A) {
- // There can be multiple AvailabilityAttr in a Decl. Make sure we copy
- // all of them. It is mergeAvailabilityAttr in SemaDeclAttr.cpp that is
- // responsible for making sure they are consistent.
- const AvailabilityAttr *AA = dyn_cast<AvailabilityAttr>(A);
- if (AA)
- return false;
-
- // The following thread safety attributes can also be duplicated.
- switch (A->getKind()) {
- case attr::ExclusiveLocksRequired:
- case attr::SharedLocksRequired:
- case attr::LocksExcluded:
- case attr::ExclusiveLockFunction:
- case attr::SharedLockFunction:
- case attr::UnlockFunction:
- case attr::ExclusiveTrylockFunction:
- case attr::SharedTrylockFunction:
- case attr::GuardedBy:
- case attr::PtGuardedBy:
- case attr::AcquiredBefore:
- case attr::AcquiredAfter:
- return false;
- default:
- ;
- }
-
+static bool DeclHasAttr(const Decl *D, const Attr *A) {
const OwnershipAttr *OA = dyn_cast<OwnershipAttr>(A);
const AnnotateAttr *Ann = dyn_cast<AnnotateAttr>(A);
- for (Decl::attr_iterator i = D->attr_begin(), e = D->attr_end(); i != e; ++i)
- if ((*i)->getKind() == A->getKind()) {
+ for (const auto *i : D->attrs())
+ if (i->getKind() == A->getKind()) {
if (Ann) {
- if (Ann->getAnnotation() == cast<AnnotateAttr>(*i)->getAnnotation())
+ if (Ann->getAnnotation() == cast<AnnotateAttr>(i)->getAnnotation())
return true;
continue;
}
// FIXME: Don't hardcode this check
- if (OA && isa<OwnershipAttr>(*i))
- return OA->getOwnKind() == cast<OwnershipAttr>(*i)->getOwnKind();
+ if (OA && isa<OwnershipAttr>(i))
+ return OA->getOwnKind() == cast<OwnershipAttr>(i)->getOwnKind();
return true;
}
@@ -1858,12 +1935,10 @@ static bool isAttributeTargetADefinition(Decl *D) {
static bool mergeAlignedAttrs(Sema &S, NamedDecl *New, Decl *Old) {
// Look for alignas attributes on Old, and pick out whichever attribute
// specifies the strictest alignment requirement.
- AlignedAttr *OldAlignasAttr = 0;
- AlignedAttr *OldStrictestAlignAttr = 0;
+ AlignedAttr *OldAlignasAttr = nullptr;
+ AlignedAttr *OldStrictestAlignAttr = nullptr;
unsigned OldAlign = 0;
- for (specific_attr_iterator<AlignedAttr>
- I = Old->specific_attr_begin<AlignedAttr>(),
- E = Old->specific_attr_end<AlignedAttr>(); I != E; ++I) {
+ for (auto *I : Old->specific_attrs<AlignedAttr>()) {
// FIXME: We have no way of representing inherited dependent alignments
// in a case like:
// template<int A, int B> struct alignas(A) X;
@@ -1874,26 +1949,24 @@ static bool mergeAlignedAttrs(Sema &S, NamedDecl *New, Decl *Old) {
return false;
if (I->isAlignas())
- OldAlignasAttr = *I;
+ OldAlignasAttr = I;
unsigned Align = I->getAlignment(S.Context);
if (Align > OldAlign) {
OldAlign = Align;
- OldStrictestAlignAttr = *I;
+ OldStrictestAlignAttr = I;
}
}
// Look for alignas attributes on New.
- AlignedAttr *NewAlignasAttr = 0;
+ AlignedAttr *NewAlignasAttr = nullptr;
unsigned NewAlign = 0;
- for (specific_attr_iterator<AlignedAttr>
- I = New->specific_attr_begin<AlignedAttr>(),
- E = New->specific_attr_end<AlignedAttr>(); I != E; ++I) {
+ for (auto *I : New->specific_attrs<AlignedAttr>()) {
if (I->isAlignmentDependent())
return false;
if (I->isAlignas())
- NewAlignasAttr = *I;
+ NewAlignasAttr = I;
unsigned Align = I->getAlignment(S.Context);
if (Align > NewAlign)
@@ -1939,9 +2012,9 @@ static bool mergeAlignedAttrs(Sema &S, NamedDecl *New, Decl *Old) {
// specifier, any other declaration of that object shall also
// have no alignment specifier.
S.Diag(New->getLocation(), diag::err_alignas_missing_on_definition)
- << OldAlignasAttr->isC11();
+ << OldAlignasAttr;
S.Diag(OldAlignasAttr->getLocation(), diag::note_alignas_on_declaration)
- << OldAlignasAttr->isC11();
+ << OldAlignasAttr;
}
bool AnyAdded = false;
@@ -1966,40 +2039,46 @@ static bool mergeAlignedAttrs(Sema &S, NamedDecl *New, Decl *Old) {
return AnyAdded;
}
-static bool mergeDeclAttribute(Sema &S, NamedDecl *D, InheritableAttr *Attr,
- bool Override) {
- InheritableAttr *NewAttr = NULL;
+static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
+ const InheritableAttr *Attr, bool Override) {
+ InheritableAttr *NewAttr = nullptr;
unsigned AttrSpellingListIndex = Attr->getSpellingListIndex();
- if (AvailabilityAttr *AA = dyn_cast<AvailabilityAttr>(Attr))
+ if (const auto *AA = dyn_cast<AvailabilityAttr>(Attr))
NewAttr = S.mergeAvailabilityAttr(D, AA->getRange(), AA->getPlatform(),
AA->getIntroduced(), AA->getDeprecated(),
AA->getObsoleted(), AA->getUnavailable(),
AA->getMessage(), Override,
AttrSpellingListIndex);
- else if (VisibilityAttr *VA = dyn_cast<VisibilityAttr>(Attr))
+ else if (const auto *VA = dyn_cast<VisibilityAttr>(Attr))
NewAttr = S.mergeVisibilityAttr(D, VA->getRange(), VA->getVisibility(),
AttrSpellingListIndex);
- else if (TypeVisibilityAttr *VA = dyn_cast<TypeVisibilityAttr>(Attr))
+ else if (const auto *VA = dyn_cast<TypeVisibilityAttr>(Attr))
NewAttr = S.mergeTypeVisibilityAttr(D, VA->getRange(), VA->getVisibility(),
AttrSpellingListIndex);
- else if (DLLImportAttr *ImportA = dyn_cast<DLLImportAttr>(Attr))
+ else if (const auto *ImportA = dyn_cast<DLLImportAttr>(Attr))
NewAttr = S.mergeDLLImportAttr(D, ImportA->getRange(),
AttrSpellingListIndex);
- else if (DLLExportAttr *ExportA = dyn_cast<DLLExportAttr>(Attr))
+ else if (const auto *ExportA = dyn_cast<DLLExportAttr>(Attr))
NewAttr = S.mergeDLLExportAttr(D, ExportA->getRange(),
AttrSpellingListIndex);
- else if (FormatAttr *FA = dyn_cast<FormatAttr>(Attr))
+ else if (const auto *FA = dyn_cast<FormatAttr>(Attr))
NewAttr = S.mergeFormatAttr(D, FA->getRange(), FA->getType(),
FA->getFormatIdx(), FA->getFirstArg(),
AttrSpellingListIndex);
- else if (SectionAttr *SA = dyn_cast<SectionAttr>(Attr))
+ else if (const auto *SA = dyn_cast<SectionAttr>(Attr))
NewAttr = S.mergeSectionAttr(D, SA->getRange(), SA->getName(),
AttrSpellingListIndex);
+ else if (const auto *IA = dyn_cast<MSInheritanceAttr>(Attr))
+ NewAttr = S.mergeMSInheritanceAttr(D, IA->getRange(), IA->getBestCase(),
+ AttrSpellingListIndex,
+ IA->getSemanticSpelling());
else if (isa<AlignedAttr>(Attr))
// AlignedAttrs are handled separately, because we need to handle all
// such attributes on a declaration at the same time.
- NewAttr = 0;
- else if (!DeclHasAttr(D, Attr))
+ NewAttr = nullptr;
+ else if (isa<DeprecatedAttr>(Attr) && Override)
+ NewAttr = nullptr;
+ else if (Attr->duplicatesAllowed() || !DeclHasAttr(D, Attr))
NewAttr = cast<InheritableAttr>(Attr->clone(S.Context));
if (NewAttr) {
@@ -2025,16 +2104,13 @@ static const Decl *getDefinition(const Decl *D) {
if (FD->isDefined(Def))
return Def;
}
- return NULL;
+ return nullptr;
}
static bool hasAttribute(const Decl *D, attr::Kind Kind) {
- for (Decl::attr_iterator I = D->attr_begin(), E = D->attr_end();
- I != E; ++I) {
- Attr *Attribute = *I;
+ for (const auto *Attribute : D->attrs())
if (Attribute->getKind() == Kind)
return true;
- }
return false;
}
@@ -2097,9 +2173,9 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {
// specifier, any other declaration of that object shall also
// have no alignment specifier.
S.Diag(Def->getLocation(), diag::err_alignas_missing_on_definition)
- << AA->isC11();
+ << AA;
S.Diag(NewAttribute->getLocation(), diag::note_alignas_on_declaration)
- << AA->isC11();
+ << AA;
NewAttributes.erase(NewAttributes.begin() + I);
--E;
continue;
@@ -2138,15 +2214,12 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
// we process them.
if (!foundAny) New->setAttrs(AttrVec());
- for (specific_attr_iterator<InheritableAttr>
- i = Old->specific_attr_begin<InheritableAttr>(),
- e = Old->specific_attr_end<InheritableAttr>();
- i != e; ++i) {
+ for (auto *I : Old->specific_attrs<InheritableAttr>()) {
bool Override = false;
// Ignore deprecated/unavailable/availability attributes if requested.
- if (isa<DeprecatedAttr>(*i) ||
- isa<UnavailableAttr>(*i) ||
- isa<AvailabilityAttr>(*i)) {
+ if (isa<DeprecatedAttr>(I) ||
+ isa<UnavailableAttr>(I) ||
+ isa<AvailabilityAttr>(I)) {
switch (AMK) {
case AMK_None:
continue;
@@ -2161,10 +2234,10 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
}
// Already handled.
- if (isa<UsedAttr>(*i))
+ if (isa<UsedAttr>(I))
continue;
- if (mergeDeclAttribute(*this, New, *i, Override))
+ if (mergeDeclAttribute(*this, New, I, Override))
foundAny = true;
}
@@ -2183,9 +2256,9 @@ static void mergeParamDeclAttributes(ParmVarDecl *newDecl,
// The first declaration of a function shall specify the
// carries_dependency attribute for its declarator-id if any declaration
// of the function specifies the carries_dependency attribute.
- if (newDecl->hasAttr<CarriesDependencyAttr>() &&
- !oldDecl->hasAttr<CarriesDependencyAttr>()) {
- S.Diag(newDecl->getAttr<CarriesDependencyAttr>()->getLocation(),
+ const CarriesDependencyAttr *CDA = newDecl->getAttr<CarriesDependencyAttr>();
+ if (CDA && !oldDecl->hasAttr<CarriesDependencyAttr>()) {
+ S.Diag(CDA->getLocation(),
diag::err_carries_dependency_missing_on_first_decl) << 1/*Param*/;
// Find the first declaration of the parameter.
// FIXME: Should we build redeclaration chains for function parameters?
@@ -2206,12 +2279,10 @@ static void mergeParamDeclAttributes(ParmVarDecl *newDecl,
// done before we process them.
if (!foundAny) newDecl->setAttrs(AttrVec());
- for (specific_attr_iterator<InheritableParamAttr>
- i = oldDecl->specific_attr_begin<InheritableParamAttr>(),
- e = oldDecl->specific_attr_end<InheritableParamAttr>(); i != e; ++i) {
- if (!DeclHasAttr(newDecl, *i)) {
+ for (const auto *I : oldDecl->specific_attrs<InheritableParamAttr>()) {
+ if (!DeclHasAttr(newDecl, I)) {
InheritableAttr *newAttr =
- cast<InheritableParamAttr>((*i)->clone(S.Context));
+ cast<InheritableParamAttr>(I->clone(S.Context));
newAttr->setInherited(true);
newDecl->addAttr(newAttr);
foundAny = true;
@@ -2255,6 +2326,24 @@ Sema::CXXSpecialMember Sema::getSpecialMember(const CXXMethodDecl *MD) {
return Sema::CXXInvalid;
}
+// Determine whether the previous declaration was a definition, implicit
+// declaration, or a declaration.
+template <typename T>
+static std::pair<diag::kind, SourceLocation>
+getNoteDiagForInvalidRedeclaration(const T *Old, const T *New) {
+ diag::kind PrevDiag;
+ SourceLocation OldLocation = Old->getLocation();
+ if (Old->isThisDeclarationADefinition())
+ PrevDiag = diag::note_previous_definition;
+ else if (Old->isImplicit()) {
+ PrevDiag = diag::note_previous_implicit_declaration;
+ if (OldLocation.isInvalid())
+ OldLocation = New->getLocation();
+ } else
+ PrevDiag = diag::note_previous_declaration;
+ return std::make_pair(PrevDiag, OldLocation);
+}
+
/// canRedefineFunction - checks if a function can be redefined. Currently,
/// only extern inline functions can be redefined, and even then only in
/// GNU89 mode.
@@ -2298,15 +2387,10 @@ static bool haveIncompatibleLanguageLinkages(const T *Old, const T *New) {
/// merged with.
///
/// Returns true if there was an error, false otherwise.
-bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S,
- bool MergeTypeWithOld) {
+bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
+ Scope *S, bool MergeTypeWithOld) {
// Verify the old decl was also a function.
- FunctionDecl *Old = 0;
- if (FunctionTemplateDecl *OldFunctionTemplate
- = dyn_cast<FunctionTemplateDecl>(OldD))
- Old = OldFunctionTemplate->getTemplatedDecl();
- else
- Old = dyn_cast<FunctionDecl>(OldD);
+ FunctionDecl *Old = OldD->getAsFunction();
if (!Old) {
if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(OldD)) {
if (New->getFriendObjectKind()) {
@@ -2318,33 +2402,44 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S,
return true;
}
- Diag(New->getLocation(), diag::err_using_decl_conflict_reverse);
- Diag(Shadow->getTargetDecl()->getLocation(),
- diag::note_using_decl_target);
- Diag(Shadow->getUsingDecl()->getLocation(),
- diag::note_using_decl) << 0;
+ // C++11 [namespace.udecl]p14:
+ // If a function declaration in namespace scope or block scope has the
+ // same name and the same parameter-type-list as a function introduced
+ // by a using-declaration, and the declarations do not declare the same
+ // function, the program is ill-formed.
+
+ // Check whether the two declarations might declare the same function.
+ Old = dyn_cast<FunctionDecl>(Shadow->getTargetDecl());
+ if (Old &&
+ !Old->getDeclContext()->getRedeclContext()->Equals(
+ New->getDeclContext()->getRedeclContext()) &&
+ !(Old->isExternC() && New->isExternC()))
+ Old = nullptr;
+
+ if (!Old) {
+ Diag(New->getLocation(), diag::err_using_decl_conflict_reverse);
+ Diag(Shadow->getTargetDecl()->getLocation(),
+ diag::note_using_decl_target);
+ Diag(Shadow->getUsingDecl()->getLocation(), diag::note_using_decl) << 0;
+ return true;
+ }
+ OldD = Old;
+ } else {
+ Diag(New->getLocation(), diag::err_redefinition_different_kind)
+ << New->getDeclName();
+ Diag(OldD->getLocation(), diag::note_previous_definition);
return true;
}
-
- Diag(New->getLocation(), diag::err_redefinition_different_kind)
- << New->getDeclName();
- Diag(OldD->getLocation(), diag::note_previous_definition);
- return true;
}
// If the old declaration is invalid, just give up here.
if (Old->isInvalidDecl())
return true;
- // Determine whether the previous declaration was a definition,
- // implicit declaration, or a declaration.
diag::kind PrevDiag;
- if (Old->isThisDeclarationADefinition())
- PrevDiag = diag::note_previous_definition;
- else if (Old->isImplicit())
- PrevDiag = diag::note_previous_implicit_declaration;
- else
- PrevDiag = diag::note_previous_declaration;
+ SourceLocation OldLocation;
+ std::tie(PrevDiag, OldLocation) =
+ getNoteDiagForInvalidRedeclaration(Old, New);
// Don't complain about this if we're in GNU89 mode and the old function
// is an extern inline function.
@@ -2356,11 +2451,11 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S,
!New->getTemplateSpecializationInfo() &&
!canRedefineFunction(Old, getLangOpts())) {
if (getLangOpts().MicrosoftExt) {
- Diag(New->getLocation(), diag::warn_static_non_static) << New;
- Diag(Old->getLocation(), PrevDiag);
+ Diag(New->getLocation(), diag::ext_static_non_static) << New;
+ Diag(OldLocation, PrevDiag);
} else {
Diag(New->getLocation(), diag::err_static_non_static) << New;
- Diag(Old->getLocation(), PrevDiag);
+ Diag(OldLocation, PrevDiag);
return true;
}
}
@@ -2426,7 +2521,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S,
Diag(New->getLocation(), diag::err_regparm_mismatch)
<< NewType->getRegParmType()
<< OldType->getRegParmType();
- Diag(Old->getLocation(), diag::note_previous_declaration);
+ Diag(OldLocation, diag::note_previous_declaration);
return true;
}
@@ -2438,7 +2533,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S,
if (OldTypeInfo.getProducesResult() != NewTypeInfo.getProducesResult()) {
if (NewTypeInfo.getProducesResult()) {
Diag(New->getLocation(), diag::err_returns_retained_mismatch);
- Diag(Old->getLocation(), diag::note_previous_declaration);
+ Diag(OldLocation, diag::note_previous_declaration);
return true;
}
@@ -2482,12 +2577,14 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S,
// Redeclarations or specializations of a function or function template
// with a declared return type that uses a placeholder type shall also
// use that placeholder, not a deduced type.
- QualType OldDeclaredReturnType = (Old->getTypeSourceInfo()
- ? Old->getTypeSourceInfo()->getType()->castAs<FunctionType>()
- : OldType)->getResultType();
- QualType NewDeclaredReturnType = (New->getTypeSourceInfo()
- ? New->getTypeSourceInfo()->getType()->castAs<FunctionType>()
- : NewType)->getResultType();
+ QualType OldDeclaredReturnType =
+ (Old->getTypeSourceInfo()
+ ? Old->getTypeSourceInfo()->getType()->castAs<FunctionType>()
+ : OldType)->getReturnType();
+ QualType NewDeclaredReturnType =
+ (New->getTypeSourceInfo()
+ ? New->getTypeSourceInfo()->getType()->castAs<FunctionType>()
+ : NewType)->getReturnType();
QualType ResQT;
if (!Context.hasSameType(OldDeclaredReturnType, NewDeclaredReturnType) &&
!((NewQType->isDependentType() || OldQType->isDependentType()) &&
@@ -2497,23 +2594,25 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S,
ResQT = Context.mergeObjCGCQualifiers(NewQType, OldQType);
if (ResQT.isNull()) {
if (New->isCXXClassMember() && New->isOutOfLine())
- Diag(New->getLocation(),
- diag::err_member_def_does_not_match_ret_type) << New;
+ Diag(New->getLocation(), diag::err_member_def_does_not_match_ret_type)
+ << New << New->getReturnTypeSourceRange();
else
- Diag(New->getLocation(), diag::err_ovl_diff_return_type);
- Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
+ Diag(New->getLocation(), diag::err_ovl_diff_return_type)
+ << New->getReturnTypeSourceRange();
+ Diag(OldLocation, PrevDiag) << Old << Old->getType()
+ << Old->getReturnTypeSourceRange();
return true;
}
else
NewQType = ResQT;
}
- QualType OldReturnType = OldType->getResultType();
- QualType NewReturnType = cast<FunctionType>(NewQType)->getResultType();
+ QualType OldReturnType = OldType->getReturnType();
+ QualType NewReturnType = cast<FunctionType>(NewQType)->getReturnType();
if (OldReturnType != NewReturnType) {
// If this function has a deduced return type and has already been
// defined, copy the deduced value from the old declaration.
- AutoType *OldAT = Old->getResultType()->getContainedAutoType();
+ AutoType *OldAT = Old->getReturnType()->getContainedAutoType();
if (OldAT && OldAT->isDeduced()) {
New->setType(
SubstAutoType(New->getType(),
@@ -2533,8 +2632,8 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S,
NewMethod->setTrivial(OldMethod->isTrivial());
// MSVC allows explicit template specialization at class scope:
- // 2 CXMethodDecls referring to the same function will be injected.
- // We don't want a redeclartion error.
+ // 2 CXXMethodDecls referring to the same function will be injected.
+ // We don't want a redeclaration error.
bool IsClassScopeExplicitSpecialization =
OldMethod->isFunctionTemplateSpecialization() &&
NewMethod->isFunctionTemplateSpecialization();
@@ -2547,7 +2646,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S,
// is a static member function declaration.
if (OldMethod->isStatic() != NewMethod->isStatic()) {
Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member);
- Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
+ Diag(OldLocation, PrevDiag) << Old << Old->getType();
return true;
}
@@ -2571,7 +2670,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S,
Diag(New->getLocation(), diag::err_member_redeclared_in_instantiation)
<< New << New->getType();
}
- Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
+ Diag(OldLocation, PrevDiag) << Old << Old->getType();
// Complain if this is an explicit declaration of a special
// member that was initially declared implicitly.
@@ -2599,10 +2698,9 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S,
// The first declaration of a function shall specify the noreturn
// attribute if any declaration of that function specifies the noreturn
// attribute.
- if (New->hasAttr<CXX11NoReturnAttr>() &&
- !Old->hasAttr<CXX11NoReturnAttr>()) {
- Diag(New->getAttr<CXX11NoReturnAttr>()->getLocation(),
- diag::err_noreturn_missing_on_first_decl);
+ const CXX11NoReturnAttr *NRA = New->getAttr<CXX11NoReturnAttr>();
+ if (NRA && !Old->hasAttr<CXX11NoReturnAttr>()) {
+ Diag(NRA->getLocation(), diag::err_noreturn_missing_on_first_decl);
Diag(Old->getFirstDecl()->getLocation(),
diag::note_noreturn_missing_first_decl);
}
@@ -2611,9 +2709,9 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S,
// The first declaration of a function shall specify the
// carries_dependency attribute for its declarator-id if any declaration
// of the function specifies the carries_dependency attribute.
- if (New->hasAttr<CarriesDependencyAttr>() &&
- !Old->hasAttr<CarriesDependencyAttr>()) {
- Diag(New->getAttr<CarriesDependencyAttr>()->getLocation(),
+ const CarriesDependencyAttr *CDA = New->getAttr<CarriesDependencyAttr>();
+ if (CDA && !Old->hasAttr<CarriesDependencyAttr>()) {
+ Diag(CDA->getLocation(),
diag::err_carries_dependency_missing_on_first_decl) << 0/*Function*/;
Diag(Old->getFirstDecl()->getLocation(),
diag::note_carries_dependency_missing_first_decl) << 0/*Function*/;
@@ -2645,10 +2743,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S,
// Check cautiously as the friend object kind isn't yet complete.
if (New->getFriendObjectKind() != Decl::FOK_None) {
Diag(New->getLocation(), diag::ext_retained_language_linkage) << New;
- Diag(Old->getLocation(), PrevDiag);
+ Diag(OldLocation, PrevDiag);
} else {
Diag(New->getLocation(), diag::err_different_language_linkage) << New;
- Diag(Old->getLocation(), PrevDiag);
+ Diag(OldLocation, PrevDiag);
return true;
}
}
@@ -2673,32 +2771,26 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S,
Context.typesAreCompatible(OldQType, NewQType)) {
const FunctionType *OldFuncType = OldQType->getAs<FunctionType>();
const FunctionType *NewFuncType = NewQType->getAs<FunctionType>();
- const FunctionProtoType *OldProto = 0;
+ const FunctionProtoType *OldProto = nullptr;
if (MergeTypeWithOld && isa<FunctionNoProtoType>(NewFuncType) &&
(OldProto = dyn_cast<FunctionProtoType>(OldFuncType))) {
// The old declaration provided a function prototype, but the
// new declaration does not. Merge in the prototype.
assert(!OldProto->hasExceptionSpec() && "Exception spec in C");
- SmallVector<QualType, 16> ParamTypes(OldProto->arg_type_begin(),
- OldProto->arg_type_end());
- NewQType = Context.getFunctionType(NewFuncType->getResultType(),
- ParamTypes,
- OldProto->getExtProtoInfo());
+ SmallVector<QualType, 16> ParamTypes(OldProto->param_types());
+ NewQType =
+ Context.getFunctionType(NewFuncType->getReturnType(), ParamTypes,
+ OldProto->getExtProtoInfo());
New->setType(NewQType);
New->setHasInheritedPrototype();
- // Synthesize a parameter for each argument type.
+ // Synthesize parameters with the same types.
SmallVector<ParmVarDecl*, 16> Params;
- for (FunctionProtoType::arg_type_iterator
- ParamType = OldProto->arg_type_begin(),
- ParamEnd = OldProto->arg_type_end();
- ParamType != ParamEnd; ++ParamType) {
- ParmVarDecl *Param = ParmVarDecl::Create(Context, New,
- SourceLocation(),
- SourceLocation(), 0,
- *ParamType, /*TInfo=*/0,
- SC_None,
- 0);
+ for (const auto &ParamType : OldProto->param_types()) {
+ ParmVarDecl *Param = ParmVarDecl::Create(Context, New, SourceLocation(),
+ SourceLocation(), nullptr,
+ ParamType, /*TInfo=*/nullptr,
+ SC_None, nullptr);
Param->setScopeInfo(0, Params.size());
Param->setImplicit();
Params.push_back(Param);
@@ -2733,21 +2825,21 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S,
= New->getType()->getAs<FunctionProtoType>();
// Determine whether this is the GNU C extension.
- QualType MergedReturn = Context.mergeTypes(OldProto->getResultType(),
- NewProto->getResultType());
+ QualType MergedReturn = Context.mergeTypes(OldProto->getReturnType(),
+ NewProto->getReturnType());
bool LooseCompatible = !MergedReturn.isNull();
for (unsigned Idx = 0, End = Old->getNumParams();
LooseCompatible && Idx != End; ++Idx) {
ParmVarDecl *OldParm = Old->getParamDecl(Idx);
ParmVarDecl *NewParm = New->getParamDecl(Idx);
if (Context.typesAreCompatible(OldParm->getType(),
- NewProto->getArgType(Idx))) {
+ NewProto->getParamType(Idx))) {
ArgTypes.push_back(NewParm->getType());
} else if (Context.typesAreCompatible(OldParm->getType(),
NewParm->getType(),
/*CompareUnqualified=*/true)) {
- GNUCompatibleParamWarning Warn
- = { OldParm, NewParm, NewProto->getArgType(Idx) };
+ GNUCompatibleParamWarning Warn = { OldParm, NewParm,
+ NewProto->getParamType(Idx) };
Warnings.push_back(Warn);
ArgTypes.push_back(NewParm->getType());
} else
@@ -2785,7 +2877,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S,
// or 'printf', just warn about the incompatible redeclaration.
if (Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) {
Diag(New->getLocation(), diag::warn_redecl_library_builtin) << New;
- Diag(Old->getLocation(), diag::note_previous_builtin_declaration)
+ Diag(OldLocation, diag::note_previous_builtin_declaration)
<< Old << Old->getType();
// If this is a global redeclaration, just forget hereafter
@@ -2806,7 +2898,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S,
}
Diag(New->getLocation(), diag::err_conflicting_types) << New->getDeclName();
- Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
+ Diag(OldLocation, PrevDiag) << Old << Old->getType();
return true;
}
@@ -3003,14 +3095,17 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
if (New->isInvalidDecl())
return;
+ VarTemplateDecl *NewTemplate = New->getDescribedVarTemplate();
+
// Verify the old decl was also a variable or variable template.
- VarDecl *Old = 0;
- if (Previous.isSingleResult() &&
- (Old = dyn_cast<VarDecl>(Previous.getFoundDecl()))) {
- if (New->getDescribedVarTemplate())
- Old = Old->getDescribedVarTemplate() ? Old : 0;
- else
- Old = Old->getDescribedVarTemplate() ? 0 : Old;
+ VarDecl *Old = nullptr;
+ VarTemplateDecl *OldTemplate = nullptr;
+ if (Previous.isSingleResult()) {
+ if (NewTemplate) {
+ OldTemplate = dyn_cast<VarTemplateDecl>(Previous.getFoundDecl());
+ Old = OldTemplate ? OldTemplate->getTemplatedDecl() : nullptr;
+ } else
+ Old = dyn_cast<VarDecl>(Previous.getFoundDecl());
}
if (!Old) {
Diag(New->getLocation(), diag::err_redefinition_different_kind)
@@ -3023,6 +3118,13 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
if (!shouldLinkPossiblyHiddenDecl(Old, New))
return;
+ // Ensure the template parameters are compatible.
+ if (NewTemplate &&
+ !TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
+ OldTemplate->getTemplateParameters(),
+ /*Complain=*/true, TPL_TemplateMatch))
+ return;
+
// C++ [class.mem]p1:
// A member shall not be declared twice in the member-specification [...]
//
@@ -3037,9 +3139,9 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
mergeDeclAttributes(New, Old);
// Warn if an already-declared variable is made a weak_import in a subsequent
// declaration
- if (New->getAttr<WeakImportAttr>() &&
+ if (New->hasAttr<WeakImportAttr>() &&
Old->getStorageClass() == SC_None &&
- !Old->getAttr<WeakImportAttr>()) {
+ !Old->hasAttr<WeakImportAttr>()) {
Diag(New->getLocation(), diag::warn_weak_import) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
// Remove weak_import attribute on new declaration.
@@ -3052,13 +3154,25 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
if (New->isInvalidDecl())
return;
+ diag::kind PrevDiag;
+ SourceLocation OldLocation;
+ std::tie(PrevDiag, OldLocation) =
+ getNoteDiagForInvalidRedeclaration(Old, New);
+
// [dcl.stc]p8: Check if we have a non-static decl followed by a static.
if (New->getStorageClass() == SC_Static &&
!New->isStaticDataMember() &&
Old->hasExternalFormalLinkage()) {
- Diag(New->getLocation(), diag::err_static_non_static) << New->getDeclName();
- Diag(Old->getLocation(), diag::note_previous_definition);
- return New->setInvalidDecl();
+ if (getLangOpts().MicrosoftExt) {
+ Diag(New->getLocation(), diag::ext_static_non_static)
+ << New->getDeclName();
+ Diag(OldLocation, PrevDiag);
+ } else {
+ Diag(New->getLocation(), diag::err_static_non_static)
+ << New->getDeclName();
+ Diag(OldLocation, PrevDiag);
+ return New->setInvalidDecl();
+ }
}
// C99 6.2.2p4:
// For an identifier declared with the storage-class specifier
@@ -3075,7 +3189,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
!New->isStaticDataMember() &&
Old->getCanonicalDecl()->getStorageClass() == SC_Static) {
Diag(New->getLocation(), diag::err_non_static_static) << New->getDeclName();
- Diag(Old->getLocation(), diag::note_previous_definition);
+ Diag(OldLocation, PrevDiag);
return New->setInvalidDecl();
}
@@ -3083,13 +3197,13 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
if (New->hasExternalStorage() &&
!Old->hasLinkage() && Old->isLocalVarDecl()) {
Diag(New->getLocation(), diag::err_extern_non_extern) << New->getDeclName();
- Diag(Old->getLocation(), diag::note_previous_definition);
+ Diag(OldLocation, PrevDiag);
return New->setInvalidDecl();
}
if (Old->hasLinkage() && New->isLocalVarDecl() &&
!New->hasExternalStorage()) {
Diag(New->getLocation(), diag::err_non_extern_extern) << New->getDeclName();
- Diag(Old->getLocation(), diag::note_previous_definition);
+ Diag(OldLocation, PrevDiag);
return New->setInvalidDecl();
}
@@ -3102,17 +3216,17 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
!(Old->getLexicalDeclContext()->isRecord() &&
!New->getLexicalDeclContext()->isRecord())) {
Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName();
- Diag(Old->getLocation(), diag::note_previous_definition);
+ Diag(OldLocation, PrevDiag);
return New->setInvalidDecl();
}
if (New->getTLSKind() != Old->getTLSKind()) {
if (!Old->getTLSKind()) {
Diag(New->getLocation(), diag::err_thread_non_thread) << New->getDeclName();
- Diag(Old->getLocation(), diag::note_previous_declaration);
+ Diag(OldLocation, PrevDiag);
} else if (!New->getTLSKind()) {
Diag(New->getLocation(), diag::err_non_thread_thread) << New->getDeclName();
- Diag(Old->getLocation(), diag::note_previous_declaration);
+ Diag(OldLocation, PrevDiag);
} else {
// Do not allow redeclaration to change the variable between requiring
// static and dynamic initialization.
@@ -3120,7 +3234,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
// declaration to determine the kind. Do we need to be compatible here?
Diag(New->getLocation(), diag::err_thread_thread_different_kind)
<< New->getDeclName() << (New->getTLSKind() == VarDecl::TLS_Dynamic);
- Diag(Old->getLocation(), diag::note_previous_declaration);
+ Diag(OldLocation, PrevDiag);
}
}
@@ -3137,7 +3251,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
if (haveIncompatibleLanguageLinkages(Old, New)) {
Diag(New->getLocation(), diag::err_different_language_linkage) << New;
- Diag(Old->getLocation(), diag::note_previous_definition);
+ Diag(OldLocation, PrevDiag);
New->setInvalidDecl();
return;
}
@@ -3148,14 +3262,13 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
// Keep a chain of previous declarations.
New->setPreviousDecl(Old);
+ if (NewTemplate)
+ NewTemplate->setPreviousDecl(OldTemplate);
// Inherit access appropriately.
New->setAccess(Old->getAccess());
-
- if (VarTemplateDecl *VTD = New->getDescribedVarTemplate()) {
- if (New->isStaticDataMember() && New->isOutOfLine())
- VTD->setAccess(New->getAccess());
- }
+ if (NewTemplate)
+ NewTemplate->setAccess(New->getAccess());
}
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
@@ -3165,7 +3278,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
return ParsedFreeStandingDeclSpec(S, AS, DS, MultiTemplateParamsArg());
}
-static void HandleTagNumbering(Sema &S, const TagDecl *Tag) {
+static void HandleTagNumbering(Sema &S, const TagDecl *Tag, Scope *TagScope) {
if (!S.Context.getLangOpts().CPlusPlus)
return;
@@ -3176,7 +3289,8 @@ static void HandleTagNumbering(Sema &S, const TagDecl *Tag) {
return;
MangleNumberingContext &MCtx =
S.Context.getManglingNumberContext(Tag->getParent());
- S.Context.setManglingNumber(Tag, MCtx.getManglingNumber(Tag));
+ S.Context.setManglingNumber(
+ Tag, MCtx.getManglingNumber(Tag, TagScope->getMSLocalManglingNumber()));
return;
}
@@ -3185,7 +3299,9 @@ static void HandleTagNumbering(Sema &S, const TagDecl *Tag) {
if (MangleNumberingContext *MCtx =
S.getCurrentMangleNumberContext(Tag->getDeclContext(),
ManglingContextDecl)) {
- S.Context.setManglingNumber(Tag, MCtx->getManglingNumber(Tag));
+ S.Context.setManglingNumber(
+ Tag,
+ MCtx->getManglingNumber(Tag, TagScope->getMSLocalManglingNumber()));
}
}
@@ -3196,8 +3312,8 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
DeclSpec &DS,
MultiTemplateParamsArg TemplateParams,
bool IsExplicitInstantiation) {
- Decl *TagD = 0;
- TagDecl *Tag = 0;
+ Decl *TagD = nullptr;
+ TagDecl *Tag = nullptr;
if (DS.getTypeSpecType() == DeclSpec::TST_class ||
DS.getTypeSpecType() == DeclSpec::TST_struct ||
DS.getTypeSpecType() == DeclSpec::TST_interface ||
@@ -3206,7 +3322,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
TagD = DS.getRepAsDecl();
if (!TagD) // We probably had an error
- return 0;
+ return nullptr;
// Note that the above type specs guarantee that the
// type rep is a Decl, whereas in many of the others
@@ -3218,7 +3334,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
}
if (Tag) {
- HandleTagNumbering(*this, Tag);
+ HandleTagNumbering(*this, Tag, S);
Tag->setFreeStanding();
if (Tag->isInvalidDecl())
return Tag;
@@ -3254,7 +3370,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
// If we're dealing with a decl but not a TagDecl, assume that
// whatever routines created it handled the friendship aspect.
if (TagD && !Tag)
- return 0;
+ return nullptr;
return ActOnFriendTypeDecl(S, DS, TemplateParams);
}
@@ -3273,7 +3389,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
DS.getTypeSpecType() == DeclSpec::TST_interface ? 2 :
DS.getTypeSpecType() == DeclSpec::TST_union ? 3 : 4)
<< SS.getRange();
- return 0;
+ return nullptr;
}
// Track whether this decl-specifier declares anything.
@@ -3285,7 +3401,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
DS.getStorageClassSpec() != DeclSpec::SCS_typedef) {
if (getLangOpts().CPlusPlus ||
Record->getDeclContext()->isRecord())
- return BuildAnonymousStructOrUnion(S, DS, AS, Record);
+ return BuildAnonymousStructOrUnion(S, DS, AS, Record, Context.getPrintingPolicy());
DeclaresAnything = false;
}
@@ -3368,10 +3484,15 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
// Note that a linkage-specification sets a storage class, but
// 'extern "C" struct foo;' is actually valid and not theoretically
// useless.
- if (DeclSpec::SCS SCS = DS.getStorageClassSpec())
- if (!DS.isExternInLinkageSpec() && SCS != DeclSpec::SCS_typedef)
+ if (DeclSpec::SCS SCS = DS.getStorageClassSpec()) {
+ if (SCS == DeclSpec::SCS_mutable)
+ // Since mutable is not a viable storage class specifier in C, there is
+ // no reason to treat it as an extension. Instead, diagnose as an error.
+ Diag(DS.getStorageClassSpecLoc(), diag::err_mutable_nonmember);
+ else if (!DS.isExternInLinkageSpec() && SCS != DeclSpec::SCS_typedef)
Diag(DS.getStorageClassSpecLoc(), DiagID)
<< DeclSpec::getSpecifierName(SCS);
+ }
if (DeclSpec::TSCS TSCS = DS.getThreadStorageClassSpec())
Diag(DS.getThreadStorageClassSpecLoc(), DiagID)
@@ -3471,12 +3592,10 @@ static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S,
bool Invalid = false;
// Look every FieldDecl and IndirectFieldDecl with a name.
- for (RecordDecl::decl_iterator D = AnonRecord->decls_begin(),
- DEnd = AnonRecord->decls_end();
- D != DEnd; ++D) {
- if ((isa<FieldDecl>(*D) || isa<IndirectFieldDecl>(*D)) &&
- cast<NamedDecl>(*D)->getDeclName()) {
- ValueDecl *VD = cast<ValueDecl>(*D);
+ for (auto *D : AnonRecord->decls()) {
+ if ((isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D)) &&
+ cast<NamedDecl>(D)->getDeclName()) {
+ ValueDecl *VD = cast<ValueDecl>(D);
if (CheckAnonMemberRedeclaration(SemaRef, S, Owner, VD->getDeclName(),
VD->getLocation(), diagKind)) {
// C++ [class.union]p2:
@@ -3492,9 +3611,8 @@ static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S,
// anonymous union is declared.
unsigned OldChainingSize = Chaining.size();
if (IndirectFieldDecl *IF = dyn_cast<IndirectFieldDecl>(VD))
- for (IndirectFieldDecl::chain_iterator PI = IF->chain_begin(),
- PE = IF->chain_end(); PI != PE; ++PI)
- Chaining.push_back(*PI);
+ for (auto *PI : IF->chain())
+ Chaining.push_back(PI);
else
Chaining.push_back(VD);
@@ -3549,13 +3667,45 @@ StorageClassSpecToVarDeclStorageClass(const DeclSpec &DS) {
llvm_unreachable("unknown storage class specifier");
}
+static SourceLocation findDefaultInitializer(const CXXRecordDecl *Record) {
+ assert(Record->hasInClassInitializer());
+
+ for (const auto *I : Record->decls()) {
+ const auto *FD = dyn_cast<FieldDecl>(I);
+ if (const auto *IFD = dyn_cast<IndirectFieldDecl>(I))
+ FD = IFD->getAnonField();
+ if (FD && FD->hasInClassInitializer())
+ return FD->getLocation();
+ }
+
+ llvm_unreachable("couldn't find in-class initializer");
+}
+
+static void checkDuplicateDefaultInit(Sema &S, CXXRecordDecl *Parent,
+ SourceLocation DefaultInitLoc) {
+ if (!Parent->isUnion() || !Parent->hasInClassInitializer())
+ return;
+
+ S.Diag(DefaultInitLoc, diag::err_multiple_mem_union_initialization);
+ S.Diag(findDefaultInitializer(Parent), diag::note_previous_initializer) << 0;
+}
+
+static void checkDuplicateDefaultInit(Sema &S, CXXRecordDecl *Parent,
+ CXXRecordDecl *AnonUnion) {
+ if (!Parent->isUnion() || !Parent->hasInClassInitializer())
+ return;
+
+ checkDuplicateDefaultInit(S, Parent, findDefaultInitializer(AnonUnion));
+}
+
/// BuildAnonymousStructOrUnion - Handle the declaration of an
/// anonymous structure or union. Anonymous unions are a C++ feature
/// (C++ [class.union]) and a C11 feature; anonymous structures
/// are a C11 feature and GNU C++ extension.
Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
- AccessSpecifier AS,
- RecordDecl *Record) {
+ AccessSpecifier AS,
+ RecordDecl *Record,
+ const PrintingPolicy &Policy) {
DeclContext *Owner = Record->getDeclContext();
// Diagnose whether this anonymous struct/union is an extension.
@@ -3570,7 +3720,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
// structs/unions.
bool Invalid = false;
if (getLangOpts().CPlusPlus) {
- const char* PrevSpec = 0;
+ const char *PrevSpec = nullptr;
unsigned DiagID;
if (Record->isUnion()) {
// C++ [class.union]p6:
@@ -3585,7 +3735,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
// Recover by adding 'static'.
DS.SetStorageClassSpec(*this, DeclSpec::SCS_static, SourceLocation(),
- PrevSpec, DiagID);
+ PrevSpec, DiagID, Policy);
}
// C++ [class.union]p6:
// A storage class is not allowed in a declaration of an
@@ -3599,7 +3749,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
// Recover by removing the storage specifier.
DS.SetStorageClassSpec(*this, DeclSpec::SCS_unspecified,
SourceLocation(),
- PrevSpec, DiagID);
+ PrevSpec, DiagID, Context.getPrintingPolicy());
}
}
@@ -3632,10 +3782,8 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
// The member-specification of an anonymous union shall only
// define non-static data members. [Note: nested types and
// functions cannot be declared within an anonymous union. ]
- for (DeclContext::decl_iterator Mem = Record->decls_begin(),
- MemEnd = Record->decls_end();
- Mem != MemEnd; ++Mem) {
- if (FieldDecl *FD = dyn_cast<FieldDecl>(*Mem)) {
+ for (auto *Mem : Record->decls()) {
+ if (auto *FD = dyn_cast<FieldDecl>(Mem)) {
// C++ [class.union]p3:
// An anonymous union shall not have private or protected
// members (clause 11).
@@ -3653,14 +3801,14 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
// array of such objects.
if (CheckNontrivialField(FD))
Invalid = true;
- } else if ((*Mem)->isImplicit()) {
+ } else if (Mem->isImplicit()) {
// Any implicit members are fine.
- } else if (isa<TagDecl>(*Mem) && (*Mem)->getDeclContext() != Record) {
+ } else if (isa<TagDecl>(Mem) && Mem->getDeclContext() != Record) {
// This is a type that showed up in an
// elaborated-type-specifier inside the anonymous struct or
// union, but which actually declares a type outside of the
// anonymous struct or union. It's okay.
- } else if (RecordDecl *MemRecord = dyn_cast<RecordDecl>(*Mem)) {
+ } else if (auto *MemRecord = dyn_cast<RecordDecl>(Mem)) {
if (!MemRecord->isAnonymousStructOrUnion() &&
MemRecord->getDeclName()) {
// Visual C++ allows type definition in anonymous struct or union.
@@ -3681,31 +3829,41 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
diag::ext_anonymous_record_with_anonymous_type)
<< (int)Record->isUnion();
}
- } else if (isa<AccessSpecDecl>(*Mem)) {
+ } else if (isa<AccessSpecDecl>(Mem)) {
// Any access specifier is fine.
+ } else if (isa<StaticAssertDecl>(Mem)) {
+ // In C++1z, static_assert declarations are also fine.
} else {
// We have something that isn't a non-static data
// member. Complain about it.
unsigned DK = diag::err_anonymous_record_bad_member;
- if (isa<TypeDecl>(*Mem))
+ if (isa<TypeDecl>(Mem))
DK = diag::err_anonymous_record_with_type;
- else if (isa<FunctionDecl>(*Mem))
+ else if (isa<FunctionDecl>(Mem))
DK = diag::err_anonymous_record_with_function;
- else if (isa<VarDecl>(*Mem))
+ else if (isa<VarDecl>(Mem))
DK = diag::err_anonymous_record_with_static;
// Visual C++ allows type definition in anonymous struct or union.
if (getLangOpts().MicrosoftExt &&
DK == diag::err_anonymous_record_with_type)
- Diag((*Mem)->getLocation(), diag::ext_anonymous_record_with_type)
+ Diag(Mem->getLocation(), diag::ext_anonymous_record_with_type)
<< (int)Record->isUnion();
else {
- Diag((*Mem)->getLocation(), DK)
+ Diag(Mem->getLocation(), DK)
<< (int)Record->isUnion();
Invalid = true;
}
}
}
+
+ // C++11 [class.union]p8 (DR1460):
+ // At most one variant member of a union may have a
+ // brace-or-equal-initializer.
+ if (cast<CXXRecordDecl>(Record)->hasInClassInitializer() &&
+ Owner->isRecord())
+ checkDuplicateDefaultInit(*this, cast<CXXRecordDecl>(Owner),
+ cast<CXXRecordDecl>(Record));
}
if (!Record->isUnion() && !Owner->isRecord()) {
@@ -3720,15 +3878,15 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
assert(TInfo && "couldn't build declarator info for anonymous struct/union");
// Create a declaration for this anonymous struct/union.
- NamedDecl *Anon = 0;
+ NamedDecl *Anon = nullptr;
if (RecordDecl *OwningClass = dyn_cast<RecordDecl>(Owner)) {
Anon = FieldDecl::Create(Context, OwningClass,
DS.getLocStart(),
Record->getLocation(),
- /*IdentifierInfo=*/0,
+ /*IdentifierInfo=*/nullptr,
Context.getTypeDeclType(Record),
TInfo,
- /*BitWidth=*/0, /*Mutable=*/false,
+ /*BitWidth=*/nullptr, /*Mutable=*/false,
/*InitStyle=*/ICIS_NoInit);
Anon->setAccess(AS);
if (getLangOpts().CPlusPlus)
@@ -3746,7 +3904,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
Anon = VarDecl::Create(Context, Owner,
DS.getLocStart(),
- Record->getLocation(), /*IdentifierInfo=*/0,
+ Record->getLocation(), /*IdentifierInfo=*/nullptr,
Context.getTypeDeclType(Record),
TInfo, SC);
@@ -3758,11 +3916,14 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
}
Anon->setImplicit();
+ // Mark this as an anonymous struct/union type.
+ Record->setAnonymousStructOrUnion(true);
+
// Add the anonymous struct/union object to the current
// context. We'll be referencing this object when we refer to one of
// its members.
Owner->addDecl(Anon);
-
+
// Inject the members of the anonymous struct/union into the owning
// context and into the identifier resolver chain for name lookup
// purposes.
@@ -3773,13 +3934,17 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
Chain, false))
Invalid = true;
- // Mark this as an anonymous struct/union type. Note that we do not
- // do this until after we have already checked and injected the
- // members of this anonymous struct/union type, because otherwise
- // the members could be injected twice: once by DeclContext when it
- // builds its lookup table, and once by
- // InjectAnonymousStructOrUnionMembers.
- Record->setAnonymousStructOrUnion(true);
+ if (VarDecl *NewVD = dyn_cast<VarDecl>(Anon)) {
+ if (getLangOpts().CPlusPlus && NewVD->isStaticLocal()) {
+ Decl *ManglingContextDecl;
+ if (MangleNumberingContext *MCtx =
+ getCurrentMangleNumberContext(NewVD->getDeclContext(),
+ ManglingContextDecl)) {
+ Context.setManglingNumber(NewVD, MCtx->getManglingNumber(NewVD, S->getMSLocalManglingNumber()));
+ Context.setStaticLocalNumber(NewVD, MCtx->getStaticLocalNumber(NewVD));
+ }
+ }
+ }
if (Invalid)
Anon->setInvalidDecl();
@@ -3813,14 +3978,14 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
assert(TInfo && "couldn't build declarator info for anonymous struct");
// Create a declaration for this anonymous struct.
- NamedDecl* Anon = FieldDecl::Create(Context,
+ NamedDecl *Anon = FieldDecl::Create(Context,
cast<RecordDecl>(CurContext),
DS.getLocStart(),
DS.getLocStart(),
- /*IdentifierInfo=*/0,
+ /*IdentifierInfo=*/nullptr,
Context.getTypeDeclType(Record),
TInfo,
- /*BitWidth=*/0, /*Mutable=*/false,
+ /*BitWidth=*/nullptr, /*Mutable=*/false,
/*InitStyle=*/ICIS_NoInit);
Anon->setImplicit();
@@ -3922,7 +4087,7 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
Context.getCanonicalType(CurClassType)));
NameInfo.setLoc(Name.StartLocation);
// FIXME: should we retrieve TypeSourceInfo?
- NameInfo.setNamedTypeInfo(0);
+ NameInfo.setNamedTypeInfo(nullptr);
return NameInfo;
}
@@ -4018,7 +4183,7 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,
case DeclSpec::TST_underlyingType:
case DeclSpec::TST_atomic: {
// Grab the type from the parser.
- TypeSourceInfo *TSI = 0;
+ TypeSourceInfo *TSI = nullptr;
QualType T = S.GetTypeFromParser(DS.getRepAsType(), &TSI);
if (T.isNull() || !T->isDependentType()) break;
@@ -4117,33 +4282,31 @@ bool Sema::DiagnoseClassNameShadow(DeclContext *DC,
/// \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) {
DeclContext *Cur = CurContext;
while (isa<LinkageSpecDecl>(Cur) || isa<CapturedDecl>(Cur))
Cur = Cur->getParent();
-
- // C++ [dcl.meaning]p1:
- // A declarator-id shall not be qualified except for the definition
- // of a member function (9.3) or static data member (9.4) outside of
- // its class, the definition or explicit instantiation of a function
- // or variable member of a namespace outside of its namespace, or the
- // definition of an explicit specialization outside of its namespace,
- // or the declaration of a friend function that is a member of
- // another class or namespace (11.3). [...]
-
- // The user provided a superfluous scope specifier that refers back to the
- // class or namespaces in which the entity is already declared.
+
+ // If the user provided a superfluous scope specifier that refers back to the
+ // class in which the entity is already declared, diagnose and ignore it.
//
// class X {
// void X::f();
// };
+ //
+ // Note, it was once ill-formed to give redundant qualification in all
+ // contexts, but that rule was removed by DR482.
if (Cur->Equals(DC)) {
- Diag(Loc, LangOpts.MicrosoftExt? diag::warn_member_extra_qualification
- : diag::err_member_extra_qualification)
- << Name << FixItHint::CreateRemoval(SS.getRange());
- SS.clear();
+ if (Cur->isRecord()) {
+ Diag(Loc, LangOpts.MicrosoftExt ? diag::warn_member_extra_qualification
+ : diag::err_member_extra_qualification)
+ << Name << FixItHint::CreateRemoval(SS.getRange());
+ SS.clear();
+ } else {
+ Diag(Loc, diag::warn_namespace_member_extra_qualification) << Name;
+ }
return false;
- }
+ }
// Check whether the qualifying scope encloses the scope of the original
// declaration.
@@ -4212,9 +4375,9 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
Diag(D.getDeclSpec().getLocStart(),
diag::err_declarator_need_ident)
<< D.getDeclSpec().getSourceRange() << D.getSourceRange();
- return 0;
+ return nullptr;
} else if (DiagnoseUnexpandedParameterPack(NameInfo, UPPC_DeclarationType))
- return 0;
+ return nullptr;
// The scope passed in may not be a decl scope. Zip up the scope tree until
// we find one that is.
@@ -4228,7 +4391,7 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
else if (D.getCXXScopeSpec().isSet()) {
if (DiagnoseUnexpandedParameterPack(D.getCXXScopeSpec(),
UPPC_DeclarationQualifier))
- return 0;
+ return nullptr;
bool EnteringContext = !D.getDeclSpec().isFriendSpecified();
DC = computeDeclContext(D.getCXXScopeSpec(), EnteringContext);
@@ -4239,15 +4402,15 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
// and return early, to avoid the coming semantic disaster.
Diag(D.getIdentifierLoc(),
diag::err_template_qualified_declarator_no_match)
- << (NestedNameSpecifier*)D.getCXXScopeSpec().getScopeRep()
+ << D.getCXXScopeSpec().getScopeRep()
<< D.getCXXScopeSpec().getRange();
- return 0;
+ return nullptr;
}
bool IsDependentContext = DC->isDependentContext();
if (!IsDependentContext &&
RequireCompleteDeclContext(D.getCXXScopeSpec(), DC))
- return 0;
+ return nullptr;
if (isa<CXXRecordDecl>(DC) && !cast<CXXRecordDecl>(DC)->hasDefinition()) {
Diag(D.getIdentifierLoc(),
@@ -4258,8 +4421,8 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
if (diagnoseQualifiedDeclaration(D.getCXXScopeSpec(), DC,
Name, D.getIdentifierLoc())) {
if (DC->isRecord())
- return 0;
-
+ return nullptr;
+
D.setInvalidType();
}
}
@@ -4278,8 +4441,8 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
// If this is a typedef, we'll end up spewing multiple diagnostics.
// Just return early; it's safer.
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
- return 0;
-
+ return nullptr;
+
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType R = TInfo->getType();
@@ -4380,7 +4543,7 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
if (TemplateParamLists.size()) {
Diag(D.getIdentifierLoc(), diag::err_template_typedef);
- return 0;
+ return nullptr;
}
New = ActOnTypedefDeclarator(S, D, DC, TInfo, Previous);
@@ -4393,8 +4556,8 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
AddToScope);
}
- if (New == 0)
- return 0;
+ if (!New)
+ return nullptr;
// If this has an identifier and is not an invalid redeclaration or
// function template specialization, add it to the scope stack.
@@ -4521,7 +4684,7 @@ TryToFixInvalidVariablyModifiedTypeSourceInfo(TypeSourceInfo *TInfo,
= TryToFixInvalidVariablyModifiedType(TInfo->getType(), Context,
SizeIsNegative, Oversized);
if (FixedTy.isNull())
- return 0;
+ return nullptr;
TypeSourceInfo *FixedTInfo = Context.getTrivialTypeSourceInfo(FixedTy);
FixInvalidVariablyModifiedTypeLoc(TInfo->getTypeLoc(),
FixedTInfo->getTypeLoc());
@@ -4560,7 +4723,7 @@ NamedDecl *Sema::findLocallyScopedExternCDecl(DeclarationName Name) {
}
NamedDecl *D = LocallyScopedExternCDecls.lookup(Name);
- return D ? D->getMostRecentDecl() : 0;
+ return D ? D->getMostRecentDecl() : nullptr;
}
/// \brief Diagnose function specifiers on a declaration of an identifier that
@@ -4607,11 +4770,11 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (D.getName().Kind != UnqualifiedId::IK_Identifier) {
Diag(D.getName().StartLocation, diag::err_typedef_not_identifier)
<< D.getName().getSourceRange();
- return 0;
+ return nullptr;
}
TypedefDecl *NewTD = ParseTypedefDecl(S, D, TInfo->getType(), TInfo);
- if (!NewTD) return 0;
+ if (!NewTD) return nullptr;
// Handle attributes prior to checking for duplicates in MergeVarDecl
ProcessDeclAttributes(S, NewTD, D);
@@ -4635,7 +4798,7 @@ Sema::CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *NewTD) {
if (T->isVariablyModifiedType()) {
getCurFunction()->setHasBranchProtectedScope();
- if (S->getFnParent() == 0) {
+ if (S->getFnParent() == nullptr) {
bool SizeIsNegative;
llvm::APSInt Oversized;
TypeSourceInfo *FixedTInfo =
@@ -4670,8 +4833,8 @@ Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD,
LookupResult &Previous, bool &Redeclaration) {
// Merge the decl with the existing one if appropriate. If the decl is
// in an outer scope, it isn't the same thing.
- FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage*/ false,
- /*ExplicitInstantiationOrSpecialization=*/false);
+ FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage*/false,
+ /*AllowInlineNamespace*/false);
filterNonConflictingPreviousDecls(Context, NewTD, Previous);
if (!Previous.empty()) {
Redeclaration = true;
@@ -4804,6 +4967,10 @@ bool Sema::inferObjCARCLifetime(ValueDecl *decl) {
}
static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
+ // Ensure that an auto decl is deduced otherwise the checks below might cache
+ // the wrong linkage.
+ assert(S.ParsingInitForAutoVars.count(&ND) == 0);
+
// 'weak' only applies to declarations with external linkage.
if (WeakAttr *Attr = ND.getAttr<WeakAttr>()) {
if (!ND.isExternallyVisible()) {
@@ -4826,6 +4993,79 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
ND.dropAttr<SelectAnyAttr>();
}
}
+
+ // dll attributes require external linkage.
+ if (const DLLImportAttr *Attr = ND.getAttr<DLLImportAttr>()) {
+ if (!ND.isExternallyVisible()) {
+ S.Diag(ND.getLocation(), diag::err_attribute_dll_not_extern)
+ << &ND << Attr;
+ ND.setInvalidDecl();
+ }
+ }
+ if (const DLLExportAttr *Attr = ND.getAttr<DLLExportAttr>()) {
+ if (!ND.isExternallyVisible()) {
+ S.Diag(ND.getLocation(), diag::err_attribute_dll_not_extern)
+ << &ND << Attr;
+ ND.setInvalidDecl();
+ }
+ }
+}
+
+static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
+ NamedDecl *NewDecl,
+ bool IsSpecialization) {
+ if (TemplateDecl *OldTD = dyn_cast<TemplateDecl>(OldDecl))
+ OldDecl = OldTD->getTemplatedDecl();
+ if (TemplateDecl *NewTD = dyn_cast<TemplateDecl>(NewDecl))
+ NewDecl = NewTD->getTemplatedDecl();
+
+ if (!OldDecl || !NewDecl)
+ return;
+
+ const DLLImportAttr *OldImportAttr = OldDecl->getAttr<DLLImportAttr>();
+ const DLLExportAttr *OldExportAttr = OldDecl->getAttr<DLLExportAttr>();
+ const DLLImportAttr *NewImportAttr = NewDecl->getAttr<DLLImportAttr>();
+ const DLLExportAttr *NewExportAttr = NewDecl->getAttr<DLLExportAttr>();
+
+ // dllimport and dllexport are inheritable attributes so we have to exclude
+ // inherited attribute instances.
+ bool HasNewAttr = (NewImportAttr && !NewImportAttr->isInherited()) ||
+ (NewExportAttr && !NewExportAttr->isInherited());
+
+ // A redeclaration is not allowed to add a dllimport or dllexport attribute,
+ // the only exception being explicit specializations.
+ // Implicitly generated declarations are also excluded for now because there
+ // is no other way to switch these to use dllimport or dllexport.
+ bool AddsAttr = !(OldImportAttr || OldExportAttr) && HasNewAttr;
+ if (AddsAttr && !IsSpecialization && !OldDecl->isImplicit()) {
+ S.Diag(NewDecl->getLocation(), diag::err_attribute_dll_redeclaration)
+ << NewDecl
+ << (NewImportAttr ? (const Attr *)NewImportAttr : NewExportAttr);
+ S.Diag(OldDecl->getLocation(), diag::note_previous_declaration);
+ NewDecl->setInvalidDecl();
+ return;
+ }
+
+ // A redeclaration is not allowed to drop a dllimport attribute, the only
+ // exception being inline function definitions.
+ // NB: MSVC converts such a declaration to dllexport.
+ bool IsInline = false, IsStaticDataMember = false;
+ if (const auto *VD = dyn_cast<VarDecl>(NewDecl))
+ // Ignore static data because out-of-line definitions are diagnosed
+ // separately.
+ IsStaticDataMember = VD->isStaticDataMember();
+ else if (const auto *FD = dyn_cast<FunctionDecl>(NewDecl))
+ IsInline = FD->isInlined();
+
+ if (OldImportAttr && !HasNewAttr && !IsInline && !IsStaticDataMember) {
+ S.Diag(NewDecl->getLocation(),
+ diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
+ << NewDecl << OldImportAttr;
+ S.Diag(OldDecl->getLocation(), diag::note_previous_declaration);
+ S.Diag(OldImportAttr->getLocation(), diag::note_previous_attribute);
+ OldDecl->dropAttr<DLLImportAttr>();
+ NewDecl->dropAttr<DLLImportAttr>();
+ }
}
/// Given that we are within the definition of the given function,
@@ -4851,7 +5091,8 @@ static bool isFunctionDefinitionDiscarded(Sema &S, FunctionDecl *FD) {
FD->setLazyBody(1);
#endif
- bool isC99Inline = (S.Context.GetGVALinkageForFunction(FD) == GVA_C99Inline);
+ bool isC99Inline =
+ S.Context.GetGVALinkageForFunction(FD) == GVA_AvailableExternally;
#ifndef NDEBUG
FD->setLazyBody(0);
@@ -4906,6 +5147,31 @@ 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) {
+ // Check decl attributes on the DeclSpec.
+ if (hasParsedAttr(S, PD.getDeclSpec().getAttributes().getList(), 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))
+ return true;
+ }
+
+ // Finally, check attributes on the decl itself.
+ return hasParsedAttr(S, PD.getAttributes(), Kind);
+}
+
/// Adjust the \c DeclContext for a function or variable that might be a
/// function-local external declaration.
bool Sema::adjustContextForLocalExternDecl(DeclContext *&DC) {
@@ -4942,16 +5208,36 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
VarDecl::StorageClass SC =
StorageClassSpecToVarDeclStorageClass(D.getDeclSpec());
+ // 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))
+ SC = SC_Extern;
+
DeclContext *OriginalDC = DC;
bool IsLocalExternDecl = SC == SC_Extern &&
adjustContextForLocalExternDecl(DC);
- if (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp16) {
- // OpenCL v1.2 s6.1.1.1: reject declaring variables of the half and
- // half array type (unless the cl_khr_fp16 extension is enabled).
- if (Context.getBaseElementType(R)->isHalfType()) {
- Diag(D.getIdentifierLoc(), diag::err_opencl_half_declaration) << R;
- D.setInvalidType();
+ if (getLangOpts().OpenCL) {
+ // OpenCL v1.0 s6.8.a.3: Pointers to functions are not allowed.
+ QualType NR = R;
+ while (NR->isPointerType()) {
+ if (NR->isFunctionPointerType()) {
+ Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer_variable);
+ D.setInvalidType();
+ break;
+ }
+ NR = NR->getPointeeType();
+ }
+
+ if (!getOpenCLOptions().cl_khr_fp16) {
+ // OpenCL v1.2 s6.1.1.1: reject declaring variables of the half and
+ // half array type (unless the cl_khr_fp16 extension is enabled).
+ if (Context.getBaseElementType(R)->isHalfType()) {
+ Diag(D.getIdentifierLoc(), diag::err_opencl_half_declaration) << R;
+ D.setInvalidType();
+ }
}
}
@@ -4978,21 +5264,17 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (!II) {
Diag(D.getIdentifierLoc(), diag::err_bad_variable_name)
<< Name;
- return 0;
+ return nullptr;
}
DiagnoseFunctionSpecifiers(D.getDeclSpec());
- if (!DC->isRecord() && S->getFnParent() == 0) {
+ if (!DC->isRecord() && S->getFnParent() == nullptr) {
// C99 6.9p2: The storage-class specifiers auto and register shall not
// appear in the declaration specifiers in an external declaration.
- if (SC == SC_Auto || SC == SC_Register) {
- // If this is a register variable with an asm label specified, then this
- // is a GNU extension.
- if (SC == SC_Register && D.getAsmLabel())
- Diag(D.getIdentifierLoc(), diag::err_unsupported_global_register);
- else
- Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope);
+ // Global Register+Asm is a GNU extension we support.
+ if (SC == SC_Auto || (SC == SC_Register && !D.getAsmLabel())) {
+ Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope);
D.setInvalidType();
}
}
@@ -5017,7 +5299,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// The event type cannot be used with the __local, __constant and __global
// address space qualifiers.
if (R->isEventT()) {
- if (S->getParent() == 0) {
+ if (S->getParent() == nullptr) {
Diag(D.getLocStart(), diag::err_event_t_global_var);
D.setInvalidType();
}
@@ -5033,9 +5315,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
bool IsVariableTemplateSpecialization = false;
bool IsPartialSpecialization = false;
bool IsVariableTemplate = false;
- VarTemplateDecl *PrevVarTemplate = 0;
- VarDecl *NewVD = 0;
- VarTemplateDecl *NewTemplate = 0;
+ VarDecl *NewVD = nullptr;
+ VarTemplateDecl *NewTemplate = nullptr;
+ TemplateParameterList *TemplateParams = nullptr;
if (!getLangOpts().CPlusPlus) {
NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
D.getIdentifierLoc(), II,
@@ -5097,18 +5379,17 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
}
- NamedDecl *PrevDecl = 0;
- if (Previous.begin() != Previous.end())
- PrevDecl = (*Previous.begin())->getUnderlyingDecl();
- PrevVarTemplate = dyn_cast_or_null<VarTemplateDecl>(PrevDecl);
-
// Match up the template parameter lists with the scope specifier, then
// determine whether we have a template or a template specialization.
- TemplateParameterList *TemplateParams =
- MatchTemplateParametersToScopeSpecifier(
- D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
- D.getCXXScopeSpec(), TemplateParamLists,
- /*never a friend*/ false, IsExplicitSpecialization, Invalid);
+ TemplateParams = MatchTemplateParametersToScopeSpecifier(
+ D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
+ D.getCXXScopeSpec(),
+ D.getName().getKind() == UnqualifiedId::IK_TemplateId
+ ? D.getName().TemplateId
+ : nullptr,
+ TemplateParamLists,
+ /*never a friend*/ false, IsExplicitSpecialization, Invalid);
+
if (TemplateParams) {
if (!TemplateParams->size() &&
D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
@@ -5119,113 +5400,43 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
<< II
<< SourceRange(TemplateParams->getTemplateLoc(),
TemplateParams->getRAngleLoc());
+ TemplateParams = nullptr;
} else {
- // Only C++1y supports variable templates (N3651).
- Diag(D.getIdentifierLoc(),
- getLangOpts().CPlusPlus1y
- ? diag::warn_cxx11_compat_variable_template
- : diag::ext_variable_template);
-
if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
// This is an explicit specialization or a partial specialization.
- // Check that we can declare a specialization here
-
+ // FIXME: Check that we can declare a specialization here.
IsVariableTemplateSpecialization = true;
IsPartialSpecialization = TemplateParams->size() > 0;
-
} else { // if (TemplateParams->size() > 0)
// This is a template declaration.
IsVariableTemplate = true;
// Check that we can declare a template here.
if (CheckTemplateDeclScope(S, TemplateParams))
- return 0;
-
- // If there is a previous declaration with the same name, check
- // whether this is a valid redeclaration.
- if (PrevDecl && !isDeclInScope(PrevDecl, DC, S))
- PrevDecl = PrevVarTemplate = 0;
-
- if (PrevVarTemplate) {
- // Ensure that the template parameter lists are compatible.
- if (!TemplateParameterListsAreEqual(
- TemplateParams, PrevVarTemplate->getTemplateParameters(),
- /*Complain=*/true, TPL_TemplateMatch))
- return 0;
- } else if (PrevDecl && PrevDecl->isTemplateParameter()) {
- // Maybe we will complain about the shadowed template parameter.
- DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
-
- // Just pretend that we didn't see the previous declaration.
- PrevDecl = 0;
- } else if (PrevDecl) {
- // C++ [temp]p5:
- // ... a template name declared in namespace scope or in class
- // scope shall be unique in that scope.
- Diag(D.getIdentifierLoc(), diag::err_redefinition_different_kind)
- << Name;
- Diag(PrevDecl->getLocation(), diag::note_previous_definition);
- return 0;
- }
+ return nullptr;
- // Check the template parameter list of this declaration, possibly
- // merging in the template parameter list from the previous variable
- // template declaration.
- if (CheckTemplateParameterList(
- TemplateParams,
- PrevVarTemplate ? PrevVarTemplate->getTemplateParameters()
- : 0,
- (D.getCXXScopeSpec().isSet() && DC && DC->isRecord() &&
- DC->isDependentContext())
- ? TPC_ClassTemplateMember
- : TPC_VarTemplate))
- Invalid = true;
-
- if (D.getCXXScopeSpec().isSet()) {
- // If the name of the template was qualified, we must be defining
- // the template out-of-line.
- if (!D.getCXXScopeSpec().isInvalid() && !Invalid &&
- !PrevVarTemplate) {
- Diag(D.getIdentifierLoc(), diag::err_member_decl_does_not_match)
- << Name << DC << /*IsDefinition*/true
- << D.getCXXScopeSpec().getRange();
- Invalid = true;
- }
- }
+ // Only C++1y supports variable templates (N3651).
+ Diag(D.getIdentifierLoc(),
+ getLangOpts().CPlusPlus1y
+ ? diag::warn_cxx11_compat_variable_template
+ : diag::ext_variable_template);
}
}
- } else if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
- TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
-
- // We have encountered something that the user meant to be a
- // specialization (because it has explicitly-specified template
- // arguments) but that was not introduced with a "template<>" (or had
- // too few of them).
- // FIXME: Differentiate between attempts for explicit instantiations
- // (starting with "template") and the rest.
- Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header)
- << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)
- << FixItHint::CreateInsertion(D.getDeclSpec().getLocStart(),
- "template<> ");
- IsVariableTemplateSpecialization = true;
+ } else {
+ assert(D.getName().getKind() != UnqualifiedId::IK_TemplateId &&
+ "should have a 'template<>' for this decl");
}
if (IsVariableTemplateSpecialization) {
- if (!PrevVarTemplate) {
- Diag(D.getIdentifierLoc(), diag::err_var_spec_no_template)
- << IsPartialSpecialization;
- return 0;
- }
-
SourceLocation TemplateKWLoc =
TemplateParamLists.size() > 0
? TemplateParamLists[0]->getTemplateLoc()
: SourceLocation();
DeclResult Res = ActOnVarTemplateSpecialization(
- S, PrevVarTemplate, D, TInfo, TemplateKWLoc, TemplateParams, SC,
+ S, D, TInfo, TemplateKWLoc, TemplateParams, SC,
IsPartialSpecialization);
if (Res.isInvalid())
- return 0;
+ return nullptr;
NewVD = cast<VarDecl>(Res.get());
AddToScope = false;
} else
@@ -5236,7 +5447,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (IsVariableTemplate) {
NewTemplate =
VarTemplateDecl::Create(Context, DC, D.getIdentifierLoc(), Name,
- TemplateParams, NewVD, PrevVarTemplate);
+ TemplateParams, NewVD);
NewVD->setDescribedVarTemplate(NewTemplate);
}
@@ -5253,18 +5464,13 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
SetNestedNameSpecifier(NewVD, D);
- // FIXME: Do we need D.getCXXScopeSpec().isSet()?
- if (TemplateParams && TemplateParamLists.size() > 1 &&
- (!IsVariableTemplateSpecialization || D.getCXXScopeSpec().isSet())) {
+ // If we have any template parameter lists that don't directly belong to
+ // the variable (matching the scope specifier), store them.
+ unsigned VDTemplateParamLists = TemplateParams ? 1 : 0;
+ if (TemplateParamLists.size() > VDTemplateParamLists)
NewVD->setTemplateParameterListsInfo(
- Context, TemplateParamLists.size() - 1, TemplateParamLists.data());
- } else if (IsVariableTemplateSpecialization ||
- (!TemplateParams && TemplateParamLists.size() > 0 &&
- (D.getCXXScopeSpec().isSet()))) {
- NewVD->setTemplateParameterListsInfo(Context,
- TemplateParamLists.size(),
- TemplateParamLists.data());
- }
+ Context, TemplateParamLists.size() - VDTemplateParamLists,
+ TemplateParamLists.data());
if (D.getDeclSpec().isConstexprSpecified())
NewVD->setConstexpr(true);
@@ -5311,7 +5517,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// that a local variable with thread storage duration still has to
// be marked 'static'. Also note that it's possible to get these
// semantics in C++ using __attribute__((gnu_inline)).
- if (SC == SC_Static && S->getFnParent() != 0 &&
+ if (SC == SC_Static && S->getFnParent() != nullptr &&
!NewVD->getType().isConstQualified()) {
FunctionDecl *CurFD = getCurFunctionDecl();
if (CurFD && isFunctionDefinitionDiscarded(*this, CurFD)) {
@@ -5346,19 +5552,23 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Handle attributes prior to checking for duplicates in MergeVarDecl
ProcessDeclAttributes(S, NewVD, D);
- if (NewVD->hasAttrs())
- CheckAlignasUnderalignment(NewVD);
-
if (getLangOpts().CUDA) {
// CUDA B.2.5: "__shared__ and __constant__ variables have implied static
// storage [duration]."
- if (SC == SC_None && S->getFnParent() != 0 &&
+ if (SC == SC_None && S->getFnParent() != nullptr &&
(NewVD->hasAttr<CUDASharedAttr>() ||
NewVD->hasAttr<CUDAConstantAttr>())) {
NewVD->setStorageClass(SC_Static);
}
}
+ // Ensure that dllimport globals without explicit storage class are treated as
+ // extern. The storage class is set above using parsed attributes. Now we can
+ // check the VarDecl itself.
+ assert(!NewVD->hasAttr<DLLImportAttr>() ||
+ NewVD->getAttr<DLLImportAttr>()->isInherited() ||
+ NewVD->isStaticDataMember() || NewVD->getStorageClass() != SC_None);
+
// In auto-retain/release, infer strong retension for variables of
// retainable type.
if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewVD))
@@ -5369,13 +5579,14 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// The parser guarantees this is a string.
StringLiteral *SE = cast<StringLiteral>(E);
StringRef Label = SE->getString();
- if (S->getFnParent() != 0) {
+ if (S->getFnParent() != nullptr) {
switch (SC) {
case SC_None:
case SC_Auto:
Diag(E->getExprLoc(), diag::warn_asm_label_on_auto_decl) << Label;
break;
case SC_Register:
+ // Local Named register
if (!Context.getTargetInfo().isValidGCCRegisterName(Label))
Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label;
break;
@@ -5385,10 +5596,18 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
case SC_OpenCLWorkGroupLocal:
break;
}
+ } else if (SC == SC_Register) {
+ // Global Named register
+ if (!Context.getTargetInfo().isValidGCCRegisterName(Label))
+ Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label;
+ if (!R->isIntegralType(Context) && !R->isPointerType()) {
+ Diag(D.getLocStart(), diag::err_asm_bad_register_type);
+ NewVD->setInvalidDecl(true);
+ }
}
NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0),
- Context, Label));
+ Context, Label, 0));
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier());
@@ -5399,15 +5618,16 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
// Diagnose shadowed variables before filtering for scope.
- if (!D.getCXXScopeSpec().isSet())
+ if (D.getCXXScopeSpec().isEmpty())
CheckShadow(S, NewVD, Previous);
// Don't consider existing declarations that are in a different
// scope and are out-of-semantic-context declarations (if the new
// declaration has linkage).
- FilterLookupForScope(
- Previous, OriginalDC, S, shouldConsiderLinkage(NewVD),
- IsExplicitSpecialization || IsVariableTemplateSpecialization);
+ FilterLookupForScope(Previous, OriginalDC, S, shouldConsiderLinkage(NewVD),
+ D.getCXXScopeSpec().isNotEmpty() ||
+ IsExplicitSpecialization ||
+ IsVariableTemplateSpecialization);
// Check whether the previous declaration is in the same block scope. This
// affects whether we merge types with it, per C++11 [dcl.array]p3.
@@ -5420,6 +5640,11 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (!getLangOpts().CPlusPlus) {
D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous));
} else {
+ // If this is an explicit specialization of a static data member, check it.
+ if (IsExplicitSpecialization && !NewVD->isInvalidDecl() &&
+ CheckMemberSpecialization(NewVD, Previous))
+ NewVD->setInvalidDecl();
+
// Merge the decl with the existing one if appropriate.
if (!Previous.empty()) {
if (Previous.isSingleResult() &&
@@ -5440,24 +5665,37 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewVD->setInvalidDecl();
}
- if (!IsVariableTemplateSpecialization) {
- if (PrevVarTemplate) {
- LookupResult PrevDecl(*this, GetNameForDeclarator(D),
- LookupOrdinaryName, ForRedeclaration);
- PrevDecl.addDecl(PrevVarTemplate->getTemplatedDecl());
- D.setRedeclaration(CheckVariableDeclaration(NewVD, PrevDecl));
- } else
- D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous));
- }
+ if (!IsVariableTemplateSpecialization)
+ D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous));
+
+ if (NewTemplate) {
+ VarTemplateDecl *PrevVarTemplate =
+ NewVD->getPreviousDecl()
+ ? NewVD->getPreviousDecl()->getDescribedVarTemplate()
+ : nullptr;
+
+ // Check the template parameter list of this declaration, possibly
+ // merging in the template parameter list from the previous variable
+ // template declaration.
+ if (CheckTemplateParameterList(
+ TemplateParams,
+ PrevVarTemplate ? PrevVarTemplate->getTemplateParameters()
+ : nullptr,
+ (D.getCXXScopeSpec().isSet() && DC && DC->isRecord() &&
+ DC->isDependentContext())
+ ? TPC_ClassTemplateMember
+ : TPC_VarTemplate))
+ NewVD->setInvalidDecl();
- // This is an explicit specialization of a static data member. Check it.
- if (IsExplicitSpecialization && !NewVD->isInvalidDecl() &&
- CheckMemberSpecialization(NewVD, Previous))
- NewVD->setInvalidDecl();
+ // If we are providing an explicit specialization of a static variable
+ // template, make a note of that.
+ if (PrevVarTemplate &&
+ PrevVarTemplate->getInstantiatedFromMemberTemplate())
+ PrevVarTemplate->setMemberSpecialization();
+ }
}
ProcessPragmaWeak(S, NewVD);
- checkAttributesAfterMerging(*this, *NewVD);
// If this is the first declaration of an extern C variable, update
// the map of such variables.
@@ -5470,16 +5708,21 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (MangleNumberingContext *MCtx =
getCurrentMangleNumberContext(NewVD->getDeclContext(),
ManglingContextDecl)) {
- Context.setManglingNumber(NewVD, MCtx->getManglingNumber(NewVD));
+ Context.setManglingNumber(
+ NewVD, MCtx->getManglingNumber(NewVD, S->getMSLocalManglingNumber()));
+ Context.setStaticLocalNumber(NewVD, MCtx->getStaticLocalNumber(NewVD));
}
}
- // If we are providing an explicit specialization of a static variable
- // template, make a note of that.
- if (PrevVarTemplate && PrevVarTemplate->getInstantiatedFromMemberTemplate())
- PrevVarTemplate->setMemberSpecialization();
+ if (D.isRedeclaration() && !Previous.empty()) {
+ checkDLLAttributeRedeclaration(
+ *this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewVD,
+ IsExplicitSpecialization);
+ }
if (NewTemplate) {
+ if (NewVD->isInvalidDecl())
+ NewTemplate->setInvalidDecl();
ActOnDocumentableDecl(NewTemplate);
return NewTemplate;
}
@@ -5498,8 +5741,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
///
void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) {
// Return if warning is ignored.
- if (Diags.getDiagnosticLevel(diag::warn_decl_shadow, R.getNameLoc()) ==
- DiagnosticsEngine::Ignored)
+ if (Diags.isIgnored(diag::warn_decl_shadow, R.getNameLoc()))
return;
// Don't diagnose declarations at file scope.
@@ -5526,11 +5768,9 @@ void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) {
if (shadowedVar->isExternC()) {
// For shadowing external vars, make sure that we point to the global
// declaration, not a locally scoped extern declaration.
- for (VarDecl::redecl_iterator
- I = shadowedVar->redecls_begin(), E = shadowedVar->redecls_end();
- I != E; ++I)
+ for (auto I : shadowedVar->redecls())
if (I->isFileVarDecl()) {
- ShadowedDecl = *I;
+ ShadowedDecl = I;
break;
}
}
@@ -5566,14 +5806,15 @@ void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) {
DeclarationName Name = R.getLookupName();
// Emit warning and note.
+ if (getSourceManager().isInSystemMacro(R.getNameLoc()))
+ return;
Diag(R.getNameLoc(), diag::warn_decl_shadow) << Name << Kind << OldDC;
Diag(ShadowedDecl->getLocation(), diag::note_previous_declaration);
}
/// \brief Check -Wshadow without the advantage of a previous lookup.
void Sema::CheckShadow(Scope *S, VarDecl *D) {
- if (Diags.getDiagnosticLevel(diag::warn_decl_shadow, D->getLocation()) ==
- DiagnosticsEngine::Ignored)
+ if (Diags.isIgnored(diag::warn_decl_shadow, D->getLocation()))
return;
LookupResult R(*this, D->getDeclName(), D->getLocation(),
@@ -5711,6 +5952,9 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
if (T->isUndeducedType())
return;
+ if (NewVD->hasAttrs())
+ CheckAlignasUnderalignment(NewVD);
+
if (T->isObjCObjectType()) {
Diag(NewVD->getLocation(), diag::err_statically_allocated_object)
<< FixItHint::CreateInsertion(NewVD->getLocation(), "*");
@@ -5769,7 +6013,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
TypeSourceInfo *FixedTInfo =
TryToFixInvalidVariablyModifiedTypeSourceInfo(TInfo, Context,
SizeIsNegative, Oversized);
- if (FixedTInfo == 0 && T->isVariableArrayType()) {
+ if (!FixedTInfo && T->isVariableArrayType()) {
const VariableArrayType *VAT = Context.getAsVariableArrayType(T);
// FIXME: This won't give the correct result for
// int a[10][n];
@@ -5788,7 +6032,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
return;
}
- if (FixedTInfo == 0) {
+ if (!FixedTInfo) {
if (NewVD->isFileVarDecl())
Diag(NewVD->getLocation(), diag::err_vm_decl_in_file_scope);
else
@@ -5828,7 +6072,6 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
if (NewVD->isConstexpr() && !T->isDependentType() &&
RequireLiteralType(NewVD->getLocation(), T,
diag::err_constexpr_var_non_literal)) {
- // Can't perform this check until the type is deduced.
NewVD->setInvalidDecl();
return;
}
@@ -5947,9 +6190,8 @@ bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
bool hasNonDeletedOverridenMethods = false;
bool AddedAny = false;
if (DC->lookupInBases(&FindOverriddenMethod, &Data, Paths)) {
- for (CXXBasePaths::decl_iterator I = Paths.found_decls_begin(),
- E = Paths.found_decls_end(); I != E; ++I) {
- if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) {
+ for (auto *I : Paths.found_decls()) {
+ if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(I)) {
MD->addOverriddenMethod(OldMD->getCanonicalDecl());
if (!CheckOverridingFunctionReturnType(MD, OldMD) &&
!CheckOverridingFunctionAttributes(MD, OldMD) &&
@@ -5993,9 +6235,9 @@ class DifferentNameValidatorCCC : public CorrectionCandidateCallback {
DifferentNameValidatorCCC(ASTContext &Context, FunctionDecl *TypoFD,
CXXRecordDecl *Parent)
: Context(Context), OriginalFD(TypoFD),
- ExpectedParent(Parent ? Parent->getCanonicalDecl() : 0) {}
+ ExpectedParent(Parent ? Parent->getCanonicalDecl() : nullptr) {}
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
if (candidate.getEditDistance() == 0)
return false;
@@ -6062,7 +6304,7 @@ static NamedDecl *DiagnoseInvalidRedeclaration(
"Cannot have an ambiguity in previous-declaration lookup");
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
DifferentNameValidatorCCC Validator(SemaRef.Context, NewFD,
- MD ? MD->getParent() : 0);
+ MD ? MD->getParent() : nullptr);
if (!Prev.empty()) {
for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end();
Func != FuncEnd; ++Func) {
@@ -6080,7 +6322,7 @@ static NamedDecl *DiagnoseInvalidRedeclaration(
} else if ((Correction = SemaRef.CorrectTypo(
Prev.getLookupNameInfo(), Prev.getLookupKind(), S,
&ExtraArgs.D.getCXXScopeSpec(), Validator,
- IsLocalFriend ? 0 : NewDC))) {
+ Sema::CTK_ErrorRecovery, IsLocalFriend ? nullptr : NewDC))) {
// Set up everything for the call to ActOnFunctionDeclarator
ExtraArgs.D.SetIdentifier(Correction.getCorrectionAsIdentifierInfo(),
ExtraArgs.D.getIdentifierLoc());
@@ -6114,7 +6356,7 @@ static NamedDecl *DiagnoseInvalidRedeclaration(
ExtraArgs.AddToScope);
if (Trap.hasErrorOccurred())
- Result = 0;
+ Result = nullptr;
}
if (Result) {
@@ -6174,7 +6416,7 @@ static NamedDecl *DiagnoseInvalidRedeclaration(
IsMember ? diag::note_member_def_close_match
: diag::note_local_decl_close_match);
}
- return 0;
+ return nullptr;
}
static FunctionDecl::StorageClass getFunctionStorageClass(Sema &SemaRef,
@@ -6221,7 +6463,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
DeclarationNameInfo NameInfo = SemaRef.GetNameForDeclarator(D);
DeclarationName Name = NameInfo.getName();
- FunctionDecl *NewFD = 0;
+ FunctionDecl *NewFD = nullptr;
bool isInline = D.getDeclSpec().isInlineSpecified();
if (!SemaRef.getLangOpts().CPlusPlus) {
@@ -6254,10 +6496,9 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
// For record types, this is done by the AbstractClassUsageDiagnoser once
// the class has been completely parsed.
if (!DC->isRecord() &&
- SemaRef.RequireNonAbstractType(D.getIdentifierLoc(),
- R->getAs<FunctionType>()->getResultType(),
- diag::err_abstract_type_in_decl,
- SemaRef.AbstractReturnType))
+ SemaRef.RequireNonAbstractType(
+ D.getIdentifierLoc(), R->getAs<FunctionType>()->getReturnType(),
+ diag::err_abstract_type_in_decl, SemaRef.AbstractReturnType))
D.setInvalidType();
if (Name.getNameKind() == DeclarationName::CXXConstructorName) {
@@ -6292,15 +6533,6 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
SemaRef.AdjustDestructorExceptionSpec(Record, NewDD);
}
- // The Microsoft ABI requires that we perform the destructor body
- // checks (i.e. operator delete() lookup) at every declaration, as
- // any translation unit may need to emit a deleting destructor.
- if (SemaRef.Context.getTargetInfo().getCXXABI().isMicrosoft() &&
- !Record->isDependentType() && Record->getDefinition() &&
- !Record->isBeingDefined()) {
- SemaRef.CheckDestructor(NewDD);
- }
-
IsVirtualOkay = true;
return NewDD;
@@ -6321,7 +6553,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
if (!DC->isRecord()) {
SemaRef.Diag(D.getIdentifierLoc(),
diag::err_conv_function_not_member);
- return 0;
+ return nullptr;
}
SemaRef.CheckConversionDeclarator(D, R, SC);
@@ -6341,7 +6573,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
SemaRef.Diag(D.getIdentifierLoc(), diag::err_constructor_return_type)
<< SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
<< SourceRange(D.getIdentifierLoc());
- return 0;
+ return nullptr;
}
// This is a C++ method declaration.
@@ -6363,26 +6595,11 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
}
}
-void Sema::checkVoidParamDecl(ParmVarDecl *Param) {
- // In C++, the empty parameter-type-list must be spelled "void"; a
- // typedef of void is not permitted.
- if (getLangOpts().CPlusPlus &&
- Param->getType().getUnqualifiedType() != Context.VoidTy) {
- bool IsTypeAlias = false;
- if (const TypedefType *TT = Param->getType()->getAs<TypedefType>())
- IsTypeAlias = isa<TypeAliasDecl>(TT->getDecl());
- else if (const TemplateSpecializationType *TST =
- Param->getType()->getAs<TemplateSpecializationType>())
- IsTypeAlias = TST->isTypeAlias();
- Diag(Param->getLocation(), diag::err_param_typedef_of_void)
- << IsTypeAlias;
- }
-}
-
enum OpenCLParamType {
ValidKernelParam,
PtrPtrKernelParam,
PtrKernelParam,
+ PrivatePtrKernelParam,
InvalidKernelParam,
RecordKernelParam
};
@@ -6390,7 +6607,10 @@ enum OpenCLParamType {
static OpenCLParamType getOpenCLKernelParameterType(QualType PT) {
if (PT->isPointerType()) {
QualType PointeeType = PT->getPointeeType();
- return PointeeType->isPointerType() ? PtrPtrKernelParam : PtrKernelParam;
+ if (PointeeType->isPointerType())
+ return PtrPtrKernelParam;
+ return PointeeType.getAddressSpace() == 0 ? PrivatePtrKernelParam
+ : PtrKernelParam;
}
// TODO: Forbid the other integer types (size_t, ptrdiff_t...) when they can
@@ -6435,6 +6655,14 @@ static void checkIsValidOpenCLKernelParameter(
D.setInvalidType();
return;
+ case PrivatePtrKernelParam:
+ // OpenCL v1.2 s6.9.a:
+ // A kernel function argument cannot be declared as a
+ // pointer to the private address space.
+ S.Diag(Param->getLocation(), diag::err_opencl_private_ptr_kernel_param);
+ D.setInvalidType();
+ return;
+
// OpenCL v1.2 s6.9.k:
// Arguments to kernel functions in a program cannot be declared with the
// built-in scalar types bool, half, size_t, ptrdiff_t, intptr_t, and
@@ -6464,7 +6692,7 @@ static void checkIsValidOpenCLKernelParameter(
// Track where we are in the nested structs. Items will migrate from
// VisitStack to HistoryStack as we do the DFS for bad field.
SmallVector<const FieldDecl *, 4> HistoryStack;
- HistoryStack.push_back((const FieldDecl *) 0);
+ HistoryStack.push_back(nullptr);
const RecordDecl *PD = PT->castAs<RecordType>()->getDecl();
VisitStack.push_back(PD);
@@ -6493,11 +6721,9 @@ static void checkIsValidOpenCLKernelParameter(
}
// Add a null marker so we know when we've gone back up a level
- VisitStack.push_back((const Decl *) 0);
+ VisitStack.push_back(nullptr);
- for (RecordDecl::field_iterator I = RD->field_begin(),
- E = RD->field_end(); I != E; ++I) {
- const FieldDecl *FD = *I;
+ for (const auto *FD : RD->fields()) {
QualType QT = FD->getType();
if (ValidTypes.count(QT.getTypePtr()))
@@ -6516,7 +6742,8 @@ static void checkIsValidOpenCLKernelParameter(
// Arguments to kernel functions that are declared to be a struct or union
// do not allow OpenCL objects to be passed as elements of the struct or
// union.
- if (ParamType == PtrKernelParam || ParamType == PtrPtrKernelParam) {
+ if (ParamType == PtrKernelParam || ParamType == PtrPtrKernelParam ||
+ ParamType == PrivatePtrKernelParam) {
S.Diag(Param->getLocation(),
diag::err_record_with_pointers_kernel_param)
<< PT->isUnionType()
@@ -6569,7 +6796,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
adjustMemberFunctionCC(R, D.isStaticMember());
bool isFriend = false;
- FunctionTemplateDecl *FunctionTemplate = 0;
+ FunctionTemplateDecl *FunctionTemplate = nullptr;
bool isExplicitSpecialization = false;
bool isFunctionTemplateSpecialization = false;
@@ -6584,7 +6811,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
FunctionDecl *NewFD = CreateNewFunctionDecl(*this, D, DC, R, TInfo, SC,
isVirtualOkay);
- if (!NewFD) return 0;
+ if (!NewFD) return nullptr;
if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer())
NewFD->setTopLevelDeclInObjCContainer();
@@ -6631,19 +6858,23 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (TemplateParameterList *TemplateParams =
MatchTemplateParametersToScopeSpecifier(
D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
- D.getCXXScopeSpec(), TemplateParamLists, isFriend,
- isExplicitSpecialization, Invalid)) {
+ D.getCXXScopeSpec(),
+ D.getName().getKind() == UnqualifiedId::IK_TemplateId
+ ? D.getName().TemplateId
+ : nullptr,
+ TemplateParamLists, isFriend, isExplicitSpecialization,
+ Invalid)) {
if (TemplateParams->size() > 0) {
// This is a function template
// Check that we can declare a template here.
if (CheckTemplateDeclScope(S, TemplateParams))
- return 0;
+ return nullptr;
// A destructor cannot be a template.
if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
Diag(NewFD->getLocation(), diag::err_destructor_template);
- return 0;
+ return nullptr;
}
// If we're adding a template to a dependent context, we may need to
@@ -6673,9 +6904,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// This is a function template specialization.
isFunctionTemplateSpecialization = true;
// For source fidelity, store all the template param lists.
- NewFD->setTemplateParameterListsInfo(Context,
- TemplateParamLists.size(),
- TemplateParamLists.data());
+ if (TemplateParamLists.size() > 0)
+ NewFD->setTemplateParameterListsInfo(Context,
+ TemplateParamLists.size(),
+ TemplateParamLists.data());
// C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);".
if (isFriend) {
@@ -6690,7 +6922,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
SourceLocation InsertLoc;
if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
InsertLoc = D.getName().getSourceRange().getEnd();
- InsertLoc = PP.getLocForEndOfToken(InsertLoc);
+ InsertLoc = getLocForEndOfToken(InsertLoc);
}
Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend)
@@ -6742,14 +6974,14 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
if (getLangOpts().CPlusPlus1y &&
- NewFD->getResultType()->isUndeducedType())
+ NewFD->getReturnType()->isUndeducedType())
Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_auto_fn_virtual);
}
if (getLangOpts().CPlusPlus1y &&
(NewFD->isDependentContext() ||
(isFriend && CurContext->isDependentContext())) &&
- NewFD->getResultType()->isUndeducedType()) {
+ NewFD->getReturnType()->isUndeducedType()) {
// If the function template is referenced directly (for instance, as a
// member of the current instantiation), pretend it has a dependent type.
// This is not really justified by the standard, but is the only sane
@@ -6758,9 +6990,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// a friend yet, so 'isDependentContext' on the FD doesn't work.
const FunctionProtoType *FPT =
NewFD->getType()->castAs<FunctionProtoType>();
- QualType Result = SubstAutoType(FPT->getResultType(),
- Context.DependentTy);
- NewFD->setType(Context.getFunctionType(Result, FPT->getArgTypes(),
+ QualType Result =
+ SubstAutoType(FPT->getReturnType(), Context.DependentTy);
+ NewFD->setType(Context.getFunctionType(Result, FPT->getParamTypes(),
FPT->getExtProtoInfo()));
}
@@ -6833,6 +7065,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
// If a function is defined as defaulted or deleted, mark it as such now.
+ // FIXME: Does this ever happen? ActOnStartOfFunctionDef forces the function
+ // definition kind to FDK_Definition.
switch (D.getFunctionDefinitionKind()) {
case FDK_Declaration:
case FDK_Definition:
@@ -6878,13 +7112,14 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
getLangOpts().CPlusPlus11 && FPT && !FPT->hasExceptionSpec()) {
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.ExceptionSpecType = EST_BasicNoexcept;
- NewFD->setType(Context.getFunctionType(FPT->getResultType(),
- FPT->getArgTypes(), EPI));
+ NewFD->setType(Context.getFunctionType(FPT->getReturnType(),
+ FPT->getParamTypes(), EPI));
}
}
// Filter out previous declarations that don't match the scope.
FilterLookupForScope(Previous, OriginalDC, S, shouldConsiderLinkage(NewFD),
+ D.getCXXScopeSpec().isNotEmpty() ||
isExplicitSpecialization ||
isFunctionTemplateSpecialization);
@@ -6893,7 +7128,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// The parser guarantees this is a string.
StringLiteral *SE = cast<StringLiteral>(E);
NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), Context,
- SE->getString()));
+ SE->getString(), 0));
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier());
@@ -6914,14 +7149,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// single void argument.
// We let through "const void" here because Sema::GetTypeForDeclarator
// already checks for that case.
- if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
- FTI.ArgInfo[0].Param &&
- cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType()) {
- // Empty arg list, don't push any params.
- checkVoidParamDecl(cast<ParmVarDecl>(FTI.ArgInfo[0].Param));
- } else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) {
- for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
- ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
+ if (FTIHasNonVoidParameters(FTI) && FTI.Params[0].Param) {
+ for (unsigned i = 0, e = FTI.NumParams; i != e; ++i) {
+ ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param);
assert(Param->getDeclContext() != NewFD && "Was set before ?");
Param->setDeclContext(NewFD);
Params.push_back(Param);
@@ -6942,10 +7172,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// @endcode
// Synthesize a parameter for each argument type.
- for (FunctionProtoType::arg_type_iterator AI = FT->arg_type_begin(),
- AE = FT->arg_type_end(); AI != AE; ++AI) {
+ for (const auto &AI : FT->param_types()) {
ParmVarDecl *Param =
- BuildParmVarDeclForTypedef(NewFD, D.getIdentifierLoc(), *AI);
+ BuildParmVarDeclForTypedef(NewFD, D.getIdentifierLoc(), AI);
Param->setScopeInfo(0, Params.size());
Params.push_back(Param);
}
@@ -6969,30 +7198,53 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (D.getDeclSpec().isNoreturnSpecified())
NewFD->addAttr(
::new(Context) C11NoReturnAttr(D.getDeclSpec().getNoreturnSpecLoc(),
- Context));
+ Context, 0));
// Functions returning a variably modified type violate C99 6.7.5.2p2
// because all functions have linkage.
if (!NewFD->isInvalidDecl() &&
- NewFD->getResultType()->isVariablyModifiedType()) {
+ NewFD->getReturnType()->isVariablyModifiedType()) {
Diag(NewFD->getLocation(), diag::err_vm_func_decl);
NewFD->setInvalidDecl();
}
+ if (D.isFunctionDefinition() && CodeSegStack.CurrentValue &&
+ !NewFD->hasAttr<SectionAttr>()) {
+ NewFD->addAttr(
+ SectionAttr::CreateImplicit(Context, SectionAttr::Declspec_allocate,
+ CodeSegStack.CurrentValue->getString(),
+ CodeSegStack.CurrentPragmaLocation));
+ if (UnifySection(CodeSegStack.CurrentValue->getString(),
+ PSF_Implicit | PSF_Execute | PSF_Read, NewFD))
+ NewFD->dropAttr<SectionAttr>();
+ }
+
// Handle attributes.
ProcessDeclAttributes(S, NewFD, D);
- QualType RetType = NewFD->getResultType();
+ QualType RetType = NewFD->getReturnType();
const CXXRecordDecl *Ret = RetType->isRecordType() ?
RetType->getAsCXXRecordDecl() : RetType->getPointeeCXXRecordDecl();
if (!NewFD->isInvalidDecl() && !NewFD->hasAttr<WarnUnusedResultAttr>() &&
Ret && Ret->hasAttr<WarnUnusedResultAttr>()) {
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
- // Attach the attribute to the new decl. Don't apply the attribute if it
- // returns an instance of the class (e.g. assignment operators).
- if (!MD || MD->getParent() != Ret) {
- NewFD->addAttr(new (Context) WarnUnusedResultAttr(SourceRange(),
- Context));
+ // Attach WarnUnusedResult to functions returning types with that attribute.
+ // Don't apply the attribute to that type's own non-static member functions
+ // (to avoid warning on things like assignment operators)
+ if (!MD || MD->getParent() != Ret)
+ NewFD->addAttr(WarnUnusedResultAttr::CreateImplicit(Context));
+ }
+
+ if (getLangOpts().OpenCL) {
+ // OpenCL v1.1 s6.5: Using an address space qualifier in a function return
+ // type declaration will generate a compilation error.
+ unsigned AddressSpace = RetType.getAddressSpace();
+ if (AddressSpace == LangAS::opencl_local ||
+ AddressSpace == LangAS::opencl_global ||
+ AddressSpace == LangAS::opencl_constant) {
+ Diag(NewFD->getLocation(),
+ diag::err_opencl_return_value_with_address_space);
+ NewFD->setInvalidDecl();
}
}
@@ -7050,21 +7302,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
<< SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc);
HasExplicitTemplateArgs = false;
- } else if (!isFunctionTemplateSpecialization &&
- !D.getDeclSpec().isFriendSpecified()) {
- // We have encountered something that the user meant to be a
- // specialization (because it has explicitly-specified template
- // arguments) but that was not introduced with a "template<>" (or had
- // too few of them).
- // FIXME: Differentiate between attempts for explicit instantiations
- // (starting with "template") and the rest.
- Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header)
- << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)
- << FixItHint::CreateInsertion(
- D.getDeclSpec().getLocStart(),
- "template<> ");
- isFunctionTemplateSpecialization = true;
} else {
+ assert((isFunctionTemplateSpecialization ||
+ D.getDeclSpec().isFriendSpecified()) &&
+ "should have a 'template<>' for this decl");
// "friend void foo<>(int);" is an implicit specialization decl.
isFunctionTemplateSpecialization = true;
}
@@ -7076,7 +7317,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// friend void foo<>(int);
// Go ahead and fake up a template id.
HasExplicitTemplateArgs = true;
- TemplateArgs.setLAngleLoc(D.getIdentifierLoc());
+ TemplateArgs.setLAngleLoc(D.getIdentifierLoc());
TemplateArgs.setRAngleLoc(D.getIdentifierLoc());
}
@@ -7104,7 +7345,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
diag::err_function_specialization_in_class)
<< NewFD->getDeclName();
} else if (CheckFunctionTemplateSpecialization(NewFD,
- (HasExplicitTemplateArgs ? &TemplateArgs : 0),
+ (HasExplicitTemplateArgs ? &TemplateArgs
+ : nullptr),
Previous))
NewFD->setInvalidDecl();
@@ -7141,12 +7383,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (!NewFD->isInvalidDecl() && NewFD->isMSVCRTEntryPoint())
CheckMSVCRTEntryPoint(NewFD);
- if (NewFD->isInvalidDecl()) {
- // If this is a class member, mark the class invalid immediately.
- // This avoids some consistency errors later.
- if (CXXMethodDecl* methodDecl = dyn_cast<CXXMethodDecl>(NewFD))
- methodDecl->getParent()->setInvalidDecl();
- } else
+ if (!NewFD->isInvalidDecl())
D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous,
isExplicitSpecialization));
}
@@ -7178,7 +7415,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
FunctionTemplateDecl *PrevTemplate =
FunctionTemplate->getPreviousDecl();
CheckTemplateParameterList(FunctionTemplate->getTemplateParameters(),
- PrevTemplate ? PrevTemplate->getTemplateParameters() : 0,
+ PrevTemplate ? PrevTemplate->getTemplateParameters()
+ : nullptr,
D.getDeclSpec().isFriendSpecified()
? (D.isFunctionDefinition()
? TPC_FriendFunctionTemplateDefinition
@@ -7232,7 +7470,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// whether the parameter types are references).
if (NamedDecl *Result = DiagnoseInvalidRedeclaration(
- *this, Previous, NewFD, ExtraArgs, false, 0)) {
+ *this, Previous, NewFD, ExtraArgs, false, nullptr)) {
AddToScope = ExtraArgs.AddToScope;
return Result;
}
@@ -7248,11 +7486,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
}
- } else if (!D.isFunctionDefinition() && D.getCXXScopeSpec().isSet() &&
+ } else if (!D.isFunctionDefinition() &&
+ isa<CXXMethodDecl>(NewFD) && NewFD->isOutOfLine() &&
!isFriend && !isFunctionTemplateSpecialization &&
!isExplicitSpecialization) {
// An out-of-line member function declaration must also be a
- // definition (C++ [dcl.meaning]p1).
+ // definition (C++ [class.mfct]p2).
// Note that this is not the case for explicit specializations of
// function templates or member functions of class templates, per
// C++ [temp.expl.spec]p2. We also allow these declarations as an
@@ -7281,7 +7520,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
EPI.Variadic = true;
EPI.ExtInfo = FT->getExtInfo();
- QualType R = Context.getFunctionType(FT->getResultType(), None, EPI);
+ QualType R = Context.getFunctionType(FT->getReturnType(), None, EPI);
NewFD->setType(R);
}
@@ -7294,6 +7533,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// marking the function.
AddCFAuditedAttribute(NewFD);
+ // If this is a function definition, check if we have to apply optnone due to
+ // a pragma.
+ if(D.isFunctionDefinition())
+ AddRangeBasedOptnone(NewFD);
+
// If this is the first declaration of an extern C variable, update
// the map of such variables.
if (NewFD->isFirstDecl() && !NewFD->isInvalidDecl() &&
@@ -7303,6 +7547,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Set this FunctionDecl's range up to the right paren.
NewFD->setRangeEnd(D.getSourceRange().getEnd());
+ if (D.isRedeclaration() && !Previous.empty()) {
+ checkDLLAttributeRedeclaration(
+ *this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewFD,
+ isExplicitSpecialization || isFunctionTemplateSpecialization);
+ }
+
if (getLangOpts().CPlusPlus) {
if (FunctionTemplate) {
if (NewFD->isInvalidDecl())
@@ -7320,18 +7570,17 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
// OpenCL v1.2, s6.9 -- Kernels can only have return type void.
- if (!NewFD->getResultType()->isVoidType()) {
- Diag(D.getIdentifierLoc(),
- diag::err_expected_kernel_void_return_type);
+ if (!NewFD->getReturnType()->isVoidType()) {
+ SourceRange RTRange = NewFD->getReturnTypeSourceRange();
+ Diag(D.getIdentifierLoc(), diag::err_expected_kernel_void_return_type)
+ << (RTRange.isValid() ? FixItHint::CreateReplacement(RTRange, "void")
+ : FixItHint());
D.setInvalidType();
}
llvm::SmallPtrSet<const Type *, 16> ValidTypes;
- for (FunctionDecl::param_iterator PI = NewFD->param_begin(),
- PE = NewFD->param_end(); PI != PE; ++PI) {
- ParmVarDecl *Param = *PI;
+ for (auto Param : NewFD->params())
checkIsValidOpenCLKernelParameter(*this, D, Param, ValidTypes);
- }
}
MarkUnusedFileScopedDecl(NewFD);
@@ -7341,7 +7590,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (!NewFD->isInvalidDecl() &&
NewFD->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
if (II->isStr("cudaConfigureCall")) {
- if (!R->getAs<FunctionType>()->getResultType()->isScalarType())
+ if (!R->getAs<FunctionType>()->getReturnType()->isScalarType())
Diag(NewFD->getLocation(), diag::err_config_scalar_return);
Context.setcudaConfigureCallDecl(NewFD);
@@ -7383,8 +7632,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
LookupResult &Previous,
bool IsExplicitSpecialization) {
- assert(!NewFD->getResultType()->isVariablyModifiedType()
- && "Variably modified return types are not handled here");
+ assert(!NewFD->getReturnType()->isVariablyModifiedType() &&
+ "Variably modified return types are not handled here");
// Determine whether the type of this function should be merged with
// a previous visible declaration. This never happens for functions in C++,
@@ -7396,7 +7645,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
filterNonConflictingPreviousDecls(Context, NewFD, Previous);
bool Redeclaration = false;
- NamedDecl *OldDecl = 0;
+ NamedDecl *OldDecl = nullptr;
// Merge or overload the declaration with an existing declaration of
// the same name, if appropriate.
@@ -7432,7 +7681,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// with that name must be marked "overloadable".
Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing)
<< Redeclaration << NewFD;
- NamedDecl *OverloadedDecl = 0;
+ NamedDecl *OverloadedDecl = nullptr;
if (Redeclaration)
OverloadedDecl = OldDecl;
else if (!Previous.empty())
@@ -7440,8 +7689,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
if (OverloadedDecl)
Diag(OverloadedDecl->getLocation(),
diag::note_attribute_overloadable_prev_overload);
- NewFD->addAttr(::new (Context) OverloadableAttr(SourceLocation(),
- Context));
+ NewFD->addAttr(OverloadableAttr::CreateImplicit(Context));
}
}
}
@@ -7464,12 +7712,11 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
<< Redeclaration << NewFD;
Diag(Previous.getFoundDecl()->getLocation(),
diag::note_attribute_overloadable_prev_overload);
- NewFD->addAttr(::new (Context) OverloadableAttr(SourceLocation(),
- Context));
+ NewFD->addAttr(OverloadableAttr::CreateImplicit(Context));
}
if (IsOverload(NewFD, cast<FunctionDecl>(OldDecl), false)) {
Redeclaration = false;
- OldDecl = 0;
+ OldDecl = nullptr;
}
}
}
@@ -7488,17 +7735,16 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
if (!getLangOpts().CPlusPlus1y && MD && MD->isConstexpr() &&
!MD->isStatic() && !isa<CXXConstructorDecl>(MD) &&
(MD->getTypeQualifiers() & Qualifiers::Const) == 0) {
- CXXMethodDecl *OldMD = dyn_cast_or_null<CXXMethodDecl>(OldDecl);
- if (FunctionTemplateDecl *OldTD =
- dyn_cast_or_null<FunctionTemplateDecl>(OldDecl))
- OldMD = dyn_cast<CXXMethodDecl>(OldTD->getTemplatedDecl());
+ CXXMethodDecl *OldMD = nullptr;
+ if (OldDecl)
+ OldMD = dyn_cast<CXXMethodDecl>(OldDecl->getAsFunction());
if (!OldMD || !OldMD->isStatic()) {
const FunctionProtoType *FPT =
MD->getType()->castAs<FunctionProtoType>();
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.TypeQuals |= Qualifiers::Const;
- MD->setType(Context.getFunctionType(FPT->getResultType(),
- FPT->getArgTypes(), EPI));
+ MD->setType(Context.getFunctionType(FPT->getReturnType(),
+ FPT->getParamTypes(), EPI));
// Warn that we did this, if we're not performing template instantiation.
// In that case, we'll have warned already when the template was defined.
@@ -7506,7 +7752,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
SourceLocation AddConstLoc;
if (FunctionTypeLoc FTL = MD->getTypeSourceInfo()->getTypeLoc()
.IgnoreParens().getAs<FunctionTypeLoc>())
- AddConstLoc = PP.getLocForEndOfToken(FTL.getRParenLoc());
+ AddConstLoc = getLocForEndOfToken(FTL.getRParenLoc());
Diag(MD->getLocation(), diag::warn_cxx1y_compat_constexpr_not_const)
<< FixItHint::CreateInsertion(AddConstLoc, " const");
@@ -7656,7 +7902,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// compatible, and if it does, warn the user.
// But, issue any diagnostic on the first declaration only.
if (NewFD->isExternC() && Previous.empty()) {
- QualType R = NewFD->getResultType();
+ QualType R = NewFD->getReturnType();
if (R->isIncompleteType() && !R->isVoidType())
Diag(NewFD->getLocation(), diag::warn_return_value_udt_incomplete)
<< NewFD << R;
@@ -7668,26 +7914,10 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
return Redeclaration;
}
-static SourceRange getResultSourceRange(const FunctionDecl *FD) {
- const TypeSourceInfo *TSI = FD->getTypeSourceInfo();
- if (!TSI)
- return SourceRange();
-
- TypeLoc TL = TSI->getTypeLoc();
- FunctionTypeLoc FunctionTL = TL.getAs<FunctionTypeLoc>();
- if (!FunctionTL)
- return SourceRange();
-
- TypeLoc ResultTL = FunctionTL.getResultLoc();
- if (ResultTL.getUnqualifiedLoc().getAs<BuiltinTypeLoc>())
- return ResultTL.getSourceRange();
-
- return SourceRange();
-}
-
void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
- // C++11 [basic.start.main]p3: A program that declares main to be inline,
- // static or constexpr is ill-formed.
+ // C++11 [basic.start.main]p3:
+ // A program that [...] declares main to be inline, static or
+ // constexpr is ill-formed.
// C11 6.7.4p4: In a hosted environment, no function specifier(s) shall
// appear in a declaration of main.
// static main is not an error under C99, but we should warn about it.
@@ -7701,8 +7931,7 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
<< FixItHint::CreateRemoval(DS.getInlineSpecLoc());
if (DS.isNoreturnSpecified()) {
SourceLocation NoreturnLoc = DS.getNoreturnSpecLoc();
- SourceRange NoreturnRange(NoreturnLoc,
- PP.getLocForEndOfToken(NoreturnLoc));
+ SourceRange NoreturnRange(NoreturnLoc, getLocForEndOfToken(NoreturnLoc));
Diag(NoreturnLoc, diag::ext_noreturn_main);
Diag(NoreturnLoc, diag::note_main_remove_noreturn)
<< FixItHint::CreateRemoval(NoreturnRange);
@@ -7724,41 +7953,44 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
assert(T->isFunctionType() && "function decl is not of function type");
const FunctionType* FT = T->castAs<FunctionType>();
- // All the standards say that main() should should return 'int'.
- if (Context.hasSameUnqualifiedType(FT->getResultType(), Context.IntTy)) {
+ if (getLangOpts().GNUMode && !getLangOpts().CPlusPlus) {
+ // In C with GNU extensions we allow main() to have non-integer return
+ // type, but we should warn about the extension, and we disable the
+ // implicit-return-zero rule.
+
+ // GCC in C mode accepts qualified 'int'.
+ if (Context.hasSameUnqualifiedType(FT->getReturnType(), Context.IntTy))
+ FD->setHasImplicitReturnZero(true);
+ else {
+ Diag(FD->getTypeSpecStartLoc(), diag::ext_main_returns_nonint);
+ SourceRange RTRange = FD->getReturnTypeSourceRange();
+ if (RTRange.isValid())
+ Diag(RTRange.getBegin(), diag::note_main_change_return_type)
+ << FixItHint::CreateReplacement(RTRange, "int");
+ }
+ } else {
// In C and C++, main magically returns 0 if you fall off the end;
// set the flag which tells us that.
// This is C++ [basic.start.main]p5 and C99 5.1.2.2.3.
- FD->setHasImplicitReturnZero(true);
- // In C with GNU extensions we allow main() to have non-integer return
- // type, but we should warn about the extension, and we disable the
- // implicit-return-zero rule.
- } else if (getLangOpts().GNUMode && !getLangOpts().CPlusPlus) {
- Diag(FD->getTypeSpecStartLoc(), diag::ext_main_returns_nonint);
-
- SourceRange ResultRange = getResultSourceRange(FD);
- if (ResultRange.isValid())
- Diag(ResultRange.getBegin(), diag::note_main_change_return_type)
- << FixItHint::CreateReplacement(ResultRange, "int");
-
- // Otherwise, this is just a flat-out error.
- } else {
- SourceRange ResultRange = getResultSourceRange(FD);
- if (ResultRange.isValid())
+ // All the standards say that main() should return 'int'.
+ if (Context.hasSameType(FT->getReturnType(), Context.IntTy))
+ FD->setHasImplicitReturnZero(true);
+ else {
+ // Otherwise, this is just a flat-out error.
+ SourceRange RTRange = FD->getReturnTypeSourceRange();
Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint)
- << FixItHint::CreateReplacement(ResultRange, "int");
- else
- Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint);
-
- FD->setInvalidDecl(true);
+ << (RTRange.isValid() ? FixItHint::CreateReplacement(RTRange, "int")
+ : FixItHint());
+ FD->setInvalidDecl(true);
+ }
}
// Treat protoless main() as nullary.
if (isa<FunctionNoProtoType>(FT)) return;
const FunctionProtoType* FTP = cast<const FunctionProtoType>(FT);
- unsigned nparams = FTP->getNumArgs();
+ unsigned nparams = FTP->getNumParams();
assert(FD->getNumParams() == nparams);
bool HasExtraParameters = (nparams > 3);
@@ -7783,7 +8015,7 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
QualType Expected[] = { Context.IntTy, CharPP, CharPP, CharPP };
for (unsigned i = 0; i < nparams; ++i) {
- QualType AT = FTP->getArgType(i);
+ QualType AT = FTP->getParamType(i);
bool mismatch = true;
@@ -7818,7 +8050,7 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
}
if (!FD->isInvalidDecl() && FD->getDescribedFunctionTemplate()) {
- Diag(FD->getLocation(), diag::err_mainlike_template_decl) << FD->getName();
+ Diag(FD->getLocation(), diag::err_mainlike_template_decl) << FD;
FD->setInvalidDecl();
}
}
@@ -7830,15 +8062,15 @@ void Sema::CheckMSVCRTEntryPoint(FunctionDecl *FD) {
// Set an implicit return of 'zero' if the function can return some integral,
// enumeration, pointer or nullptr type.
- if (FT->getResultType()->isIntegralOrEnumerationType() ||
- FT->getResultType()->isAnyPointerType() ||
- FT->getResultType()->isNullPtrType())
+ if (FT->getReturnType()->isIntegralOrEnumerationType() ||
+ FT->getReturnType()->isAnyPointerType() ||
+ FT->getReturnType()->isNullPtrType())
// DllMain is exempt because a return value of zero means it failed.
if (FD->getName() != "DllMain")
FD->setHasImplicitReturnZero(true);
if (!FD->isInvalidDecl() && FD->getDescribedFunctionTemplate()) {
- Diag(FD->getLocation(), diag::err_mainlike_template_decl) << FD->getName();
+ Diag(FD->getLocation(), diag::err_mainlike_template_decl) << FD;
FD->setInvalidDecl();
}
}
@@ -7852,10 +8084,11 @@ bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
// "may accept other forms of constant expressions" exception.
// (We never end up here for C++, so the constant expression
// rules there don't matter.)
- if (Init->isConstantInitializer(Context, false))
+ const Expr *Culprit;
+ if (Init->isConstantInitializer(Context, false, &Culprit))
return false;
- Diag(Init->getExprLoc(), diag::err_init_element_not_constant)
- << Init->getSourceRange();
+ Diag(Culprit->getExprLoc(), diag::err_init_element_not_constant)
+ << Culprit->getSourceRange();
return true;
}
@@ -8029,7 +8262,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
bool DirectInit, bool TypeMayContainAuto) {
// If there is no declaration, there was an error parsing it. Just ignore
// the initializer.
- if (RealDecl == 0 || RealDecl->isInvalidDecl())
+ if (!RealDecl || RealDecl->isInvalidDecl())
return;
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(RealDecl)) {
@@ -8084,6 +8317,11 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
return;
} else {
DeduceInit = CXXDirectInit->getExpr(0);
+ if (isa<InitListExpr>(DeduceInit))
+ Diag(CXXDirectInit->getLocStart(),
+ diag::err_auto_var_init_paren_braces)
+ << VDecl->getDeclName() << VDecl->getType()
+ << VDecl->getSourceRange();
}
}
@@ -8096,7 +8334,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
VDecl->setInvalidDecl();
return;
}
- Init = Result.take();
+ Init = Result.get();
DefaultedToAuto = true;
}
@@ -8141,6 +8379,13 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
return;
}
+ // dllimport cannot be used on variable definitions.
+ if (VDecl->hasAttr<DLLImportAttr>() && !VDecl->isStaticDataMember()) {
+ Diag(VDecl->getLocation(), diag::err_attribute_dllimport_data_definition);
+ VDecl->setInvalidDecl();
+ return;
+ }
+
if (VDecl->isLocalVarDecl() && VDecl->hasExternalStorage()) {
// C99 6.7.8p5. C++ has no such restriction, but that is a defect.
Diag(VDecl->getLocation(), diag::err_block_extern_cant_init);
@@ -8176,8 +8421,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
VDecl->setInvalidDecl();
return;
}
-
- const VarDecl* PrevInit = 0;
+
+ const VarDecl *PrevInit = nullptr;
if (getLangOpts().CPlusPlus) {
// C++ [class.static.data]p4
// If a static data member is of const integral or const
@@ -8192,9 +8437,9 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// data members we also need to check whether there was an in-class
// declaration with an initializer.
if (VDecl->isStaticDataMember() && VDecl->getAnyInitializer(PrevInit)) {
- Diag(VDecl->getLocation(), diag::err_redefinition)
- << VDecl->getDeclName();
- Diag(PrevInit->getLocation(), diag::note_previous_definition);
+ Diag(Init->getExprLoc(), diag::err_static_data_member_reinitialization)
+ << VDecl->getDeclName();
+ Diag(PrevInit->getInit()->getExprLoc(), diag::note_previous_initializer) << 0;
return;
}
@@ -8228,7 +8473,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
VDecl->setInvalidDecl();
return;
}
- Init = Result.take();
+ Init = Result.get();
}
// Perform the initialization.
@@ -8256,7 +8501,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
return;
}
- Init = Result.takeAs<Expr>();
+ Init = Result.getAs<Expr>();
}
// Check for self-references within variable initializers.
@@ -8287,13 +8532,10 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// 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) {
- DiagnosticsEngine::Level Level =
- Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
- Init->getLocStart());
- if (Level != DiagnosticsEngine::Ignored)
+ if (VDecl->getType().getObjCLifetime() == Qualifiers::OCL_Strong &&
+ !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak,
+ Init->getLocStart()))
getCurFunction()->markSafeWeakUse(Init);
- }
}
// The initialization is usually a full-expression.
@@ -8314,7 +8556,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
VDecl->setInvalidDecl();
return;
}
- Init = Result.take();
+ Init = Result.get();
// Attach the initializer to the decl.
VDecl->setInit(Init);
@@ -8324,6 +8566,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// static storage duration shall be constant expressions or string literals.
// C++ does not have this restriction.
if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl()) {
+ const Expr *Culprit;
if (VDecl->getStorageClass() == SC_Static)
CheckForConstantInitializer(Init, DclT);
// C89 is stricter than C99 for non-static aggregate types.
@@ -8332,10 +8575,10 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// constant expressions.
else if (!getLangOpts().C99 && VDecl->getType()->isAggregateType() &&
isa<InitListExpr>(Init) &&
- !Init->isConstantInitializer(Context, false))
- Diag(Init->getExprLoc(),
+ !Init->isConstantInitializer(Context, false, &Culprit))
+ Diag(Culprit->getExprLoc(),
diag::ext_aggregate_init_not_constant)
- << Init->getSourceRange();
+ << Culprit->getSourceRange();
}
} else if (VDecl->isStaticDataMember() &&
VDecl->getLexicalDeclContext()->isRecord()) {
@@ -8444,19 +8687,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// C99 6.7.8p4. All file scoped initializers need to be constant.
if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl())
CheckForConstantInitializer(Init, DclT);
- else if (VDecl->getTLSKind() == VarDecl::TLS_Static &&
- !VDecl->isInvalidDecl() && !DclT->isDependentType() &&
- !Init->isValueDependent() && !VDecl->isConstexpr() &&
- !Init->isConstantInitializer(
- Context, VDecl->getType()->isReferenceType())) {
- // GNU C++98 edits for __thread, [basic.start.init]p4:
- // An object of thread storage duration shall not require dynamic
- // initialization.
- // FIXME: Need strict checking here.
- Diag(VDecl->getLocation(), diag::err_thread_dynamic_init);
- if (getLangOpts().CPlusPlus11)
- Diag(VDecl->getLocation(), diag::note_use_thread_local);
- }
}
// We will represent direct-initialization similarly to copy-initialization:
@@ -8512,7 +8742,7 @@ void Sema::ActOnInitializerError(Decl *D) {
return;
}
- // Require an abstract type.
+ // Require a non-abstract type.
if (RequireNonAbstractType(VD->getLocation(), Ty,
diag::err_abstract_type_in_decl,
AbstractVariableType)) {
@@ -8527,7 +8757,7 @@ void Sema::ActOnInitializerError(Decl *D) {
void Sema::ActOnUninitializedDecl(Decl *RealDecl,
bool TypeMayContainAuto) {
// If there is no declaration, there was an error parsing it. Just ignore it.
- if (RealDecl == 0)
+ if (!RealDecl)
return;
if (VarDecl *Var = dyn_cast<VarDecl>(RealDecl)) {
@@ -8558,6 +8788,16 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
return;
}
+ // OpenCL v1.1 s6.5.3: variables declared in the constant address space must
+ // be initialized.
+ if (!Var->isInvalidDecl() &&
+ Var->getType().getAddressSpace() == LangAS::opencl_constant &&
+ Var->getStorageClass() != SC_Extern && !Var->getInit()) {
+ Diag(Var->getLocation(), diag::err_opencl_constant_no_init);
+ Var->setInvalidDecl();
+ return;
+ }
+
switch (Var->isThisDeclarationADefinition()) {
case VarDecl::Definition:
if (!Var->isStaticDataMember() || !Var->getAnyInitializer())
@@ -8657,11 +8897,13 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
if (Var->isInvalidDecl())
return;
- if (RequireCompleteType(Var->getLocation(),
- Context.getBaseElementType(Type),
- diag::err_typecheck_decl_incomplete_type)) {
- Var->setInvalidDecl();
- return;
+ if (!Var->hasAttr<AliasAttr>()) {
+ if (RequireCompleteType(Var->getLocation(),
+ Context.getBaseElementType(Type),
+ diag::err_typecheck_decl_incomplete_type)) {
+ Var->setInvalidDecl();
+ return;
+ }
}
// The variable can not have an abstract class type.
@@ -8768,6 +9010,37 @@ void Sema::ActOnCXXForRangeDecl(Decl *D) {
}
}
+StmtResult
+Sema::ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc,
+ IdentifierInfo *Ident,
+ ParsedAttributes &Attrs,
+ SourceLocation AttrEnd) {
+ // C++1y [stmt.iter]p1:
+ // A range-based for statement of the form
+ // for ( for-range-identifier : for-range-initializer ) statement
+ // is equivalent to
+ // for ( auto&& for-range-identifier : for-range-initializer ) statement
+ DeclSpec DS(Attrs.getPool().getFactory());
+
+ const char *PrevSpec;
+ unsigned DiagID;
+ DS.SetTypeSpecType(DeclSpec::TST_auto, IdentLoc, PrevSpec, DiagID,
+ getPrintingPolicy());
+
+ Declarator D(DS, Declarator::ForContext);
+ D.SetIdentifier(Ident, IdentLoc);
+ D.takeAttributes(Attrs, AttrEnd);
+
+ ParsedAttributes EmptyAttrs(Attrs.getPool().getFactory());
+ D.AddTypeInfo(DeclaratorChunk::getReference(0, IdentLoc, /*lvalue*/false),
+ EmptyAttrs, IdentLoc);
+ Decl *Var = ActOnDeclarator(S, D);
+ cast<VarDecl>(Var)->setCXXForRangeDecl(true);
+ FinalizeDeclaration(Var);
+ return ActOnDeclStmt(FinalizeDeclaratorGroup(S, DS, Var), IdentLoc,
+ AttrEnd.isValid() ? AttrEnd : IdentLoc);
+}
+
void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
if (var->isInvalidDecl()) return;
@@ -8788,11 +9061,16 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
}
}
+ // 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
+ // class members because the linkage of an anonymous class can
+ // change if it's later given a typedef name.
if (var->isThisDeclarationADefinition() &&
+ var->getDeclContext()->getRedeclContext()->isFileContext() &&
var->isExternallyVisible() && var->hasLinkage() &&
- getDiagnostics().getDiagnosticLevel(
- diag::warn_missing_variable_declarations,
- var->getLocation())) {
+ !getDiagnostics().isIgnored(diag::warn_missing_variable_declarations,
+ var->getLocation())) {
// Find a previous declaration that's not a definition.
VarDecl *prev = var->getPreviousDecl();
while (prev && prev->isThisDeclarationADefinition())
@@ -8802,14 +9080,58 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
Diag(var->getLocation(), diag::warn_missing_variable_declarations) << var;
}
- if (var->getTLSKind() == VarDecl::TLS_Static &&
- var->getType().isDestructedType()) {
- // GNU C++98 edits for __thread, [basic.start.term]p3:
- // The type of an object with thread storage duration shall not
- // have a non-trivial destructor.
- Diag(var->getLocation(), diag::err_thread_nontrivial_dtor);
- if (getLangOpts().CPlusPlus11)
- Diag(var->getLocation(), diag::note_use_thread_local);
+ if (var->getTLSKind() == VarDecl::TLS_Static) {
+ const Expr *Culprit;
+ if (var->getType().isDestructedType()) {
+ // GNU C++98 edits for __thread, [basic.start.term]p3:
+ // The type of an object with thread storage duration shall not
+ // have a non-trivial destructor.
+ Diag(var->getLocation(), diag::err_thread_nontrivial_dtor);
+ if (getLangOpts().CPlusPlus11)
+ Diag(var->getLocation(), diag::note_use_thread_local);
+ } else if (getLangOpts().CPlusPlus && var->hasInit() &&
+ !var->getInit()->isConstantInitializer(
+ Context, var->getType()->isReferenceType(), &Culprit)) {
+ // GNU C++98 edits for __thread, [basic.start.init]p4:
+ // An object of thread storage duration shall not require dynamic
+ // initialization.
+ // FIXME: Need strict checking here.
+ Diag(Culprit->getExprLoc(), diag::err_thread_dynamic_init)
+ << Culprit->getSourceRange();
+ if (getLangOpts().CPlusPlus11)
+ Diag(var->getLocation(), diag::note_use_thread_local);
+ }
+
+ }
+
+ if (var->isThisDeclarationADefinition() &&
+ ActiveTemplateInstantiations.empty()) {
+ PragmaStack<StringLiteral *> *Stack = nullptr;
+ int SectionFlags = PSF_Implicit | PSF_Read;
+ if (var->getType().isConstQualified())
+ Stack = &ConstSegStack;
+ else if (!var->getInit()) {
+ Stack = &BSSSegStack;
+ SectionFlags |= PSF_Write;
+ } else {
+ Stack = &DataSegStack;
+ SectionFlags |= PSF_Write;
+ }
+ if (!var->hasAttr<SectionAttr>() && Stack->CurrentValue)
+ var->addAttr(
+ SectionAttr::CreateImplicit(Context, SectionAttr::Declspec_allocate,
+ Stack->CurrentValue->getString(),
+ Stack->CurrentPragmaLocation));
+ if (const SectionAttr *SA = var->getAttr<SectionAttr>())
+ if (UnifySection(SA->getName(), SectionFlags, var))
+ var->dropAttr<SectionAttr>();
+
+ // Apply the init_seg attribute if this has an initializer. If the
+ // initializer turns out to not be dynamic, we'll end up ignoring this
+ // attribute.
+ if (CurInitSeg && var->getInit())
+ var->addAttr(InitSegAttr::CreateImplicit(Context, CurInitSeg->getString(),
+ CurInitSegLoc));
}
// All the following checks are C++ only.
@@ -8835,7 +9157,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
var, var->getType(), varRef, /*AllowNRVO=*/true);
if (!result.isInvalid()) {
result = MaybeCreateExprWithCleanups(result);
- Expr *init = result.takeAs<Expr>();
+ Expr *init = result.getAs<Expr>();
Context.setBlockVarCopyInits(var, init);
}
}
@@ -8848,9 +9170,8 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
if (!var->getDeclContext()->isDependentContext() &&
Init && !Init->isValueDependent()) {
if (IsGlobal && !var->isConstexpr() &&
- getDiagnostics().getDiagnosticLevel(diag::warn_global_constructor,
- var->getLocation())
- != DiagnosticsEngine::Ignored) {
+ !getDiagnostics().isIgnored(diag::warn_global_constructor,
+ var->getLocation())) {
// Warn about globals which don't have a constant initializer. Don't
// warn about globals with a non-trivial destructor because we already
// warned about them.
@@ -8901,9 +9222,45 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
if (!VD)
return;
+ checkAttributesAfterMerging(*this, *VD);
+
+ // Static locals inherit dll attributes from their function.
+ if (VD->isStaticLocal()) {
+ if (FunctionDecl *FD =
+ dyn_cast<FunctionDecl>(VD->getParentFunctionOrMethod())) {
+ if (Attr *A = getDLLAttr(FD)) {
+ auto *NewAttr = cast<InheritableAttr>(A->clone(getASTContext()));
+ NewAttr->setInherited(true);
+ VD->addAttr(NewAttr);
+ }
+ }
+ }
+
+ // Imported static data members cannot be defined out-of-line.
+ if (const DLLImportAttr *IA = VD->getAttr<DLLImportAttr>()) {
+ if (VD->isStaticDataMember() && VD->isOutOfLine() &&
+ VD->isThisDeclarationADefinition()) {
+ // We allow definitions of dllimport class template static data members
+ // with a warning.
+ CXXRecordDecl *Context =
+ cast<CXXRecordDecl>(VD->getFirstDecl()->getDeclContext());
+ bool IsClassTemplateMember =
+ isa<ClassTemplatePartialSpecializationDecl>(Context) ||
+ Context->getDescribedClassTemplate();
+
+ Diag(VD->getLocation(),
+ IsClassTemplateMember
+ ? diag::warn_attribute_dllimport_static_field_definition
+ : diag::err_attribute_dllimport_static_field_definition);
+ Diag(IA->getLocation(), diag::note_attribute);
+ if (!IsClassTemplateMember)
+ VD->setInvalidDecl();
+ }
+ }
+
if (UsedAttr *Attr = VD->getAttr<UsedAttr>()) {
if (!Attr->isInherited() && !VD->isThisDeclarationADefinition()) {
- Diag(Attr->getLocation(), diag::warn_attribute_ignored) << "used";
+ Diag(Attr->getLocation(), diag::warn_attribute_ignored) << Attr;
VD->dropAttr<UsedAttr>();
}
}
@@ -8923,10 +9280,12 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
const DeclContext *DC = VD->getDeclContext();
// If there's a #pragma GCC visibility in scope, and this isn't a class
// member, set the visibility of this variable.
- if (!DC->isRecord() && VD->isExternallyVisible())
+ if (DC->getRedeclContext()->isFileContext() && VD->isExternallyVisible())
AddPushedVisibilityAttribute(VD);
- if (VD->isFileVarDecl())
+ // FIXME: Warn on unused templates.
+ if (VD->isFileVarDecl() && !VD->getDescribedVarTemplate() &&
+ !isa<VarTemplatePartialSpecializationDecl>(VD))
MarkUnusedFileScopedDecl(VD);
// Now we have parsed the initializer and can update the table of magic
@@ -8935,10 +9294,7 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
!VD->getType()->isIntegralOrEnumerationType())
return;
- for (specific_attr_iterator<TypeTagForDatatypeAttr>
- I = ThisDecl->specific_attr_begin<TypeTagForDatatypeAttr>(),
- E = ThisDecl->specific_attr_end<TypeTagForDatatypeAttr>();
- I != E; ++I) {
+ for (const auto *I : ThisDecl->specific_attrs<TypeTagForDatatypeAttr>()) {
const Expr *MagicValueExpr = VD->getInit();
if (!MagicValueExpr) {
continue;
@@ -8972,7 +9328,7 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
if (DS.isTypeSpecOwned())
Decls.push_back(DS.getRepAsDecl());
- DeclaratorDecl *FirstDeclaratorInGroup = 0;
+ DeclaratorDecl *FirstDeclaratorInGroup = nullptr;
for (unsigned i = 0, e = Group.size(); i != e; ++i)
if (Decl *D = Group[i]) {
if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D))
@@ -8983,7 +9339,7 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
if (DeclSpec::isDeclRep(DS.getTypeSpecType())) {
if (TagDecl *Tag = dyn_cast_or_null<TagDecl>(DS.getRepAsDecl())) {
- HandleTagNumbering(*this, Tag);
+ HandleTagNumbering(*this, Tag, S);
if (!Tag->hasNameForLinkage() && !Tag->hasDeclaratorForAnonDecl())
Tag->setDeclaratorForAnonDecl(FirstDeclaratorInGroup);
}
@@ -8995,7 +9351,7 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
/// BuildDeclaratorGroup - convert a list of declarations into a declaration
/// group, performing any necessary semantic checking.
Sema::DeclGroupPtrTy
-Sema::BuildDeclaratorGroup(llvm::MutableArrayRef<Decl *> Group,
+Sema::BuildDeclaratorGroup(MutableArrayRef<Decl *> Group,
bool TypeMayContainAuto) {
// C++0x [dcl.spec.auto]p7:
// If the type deduced for the template parameter U is not the same in each
@@ -9007,7 +9363,7 @@ Sema::BuildDeclaratorGroup(llvm::MutableArrayRef<Decl *> Group,
if (TypeMayContainAuto && Group.size() > 1) {
QualType Deduced;
CanQualType DeducedCanon;
- VarDecl *DeducedDecl = 0;
+ VarDecl *DeducedDecl = nullptr;
for (unsigned i = 0, e = Group.size(); i != e; ++i) {
if (VarDecl *D = dyn_cast<VarDecl>(Group[i])) {
AutoType *AT = D->getType()->getContainedAutoType();
@@ -9052,9 +9408,7 @@ void Sema::ActOnDocumentableDecls(ArrayRef<Decl *> Group) {
if (Group.empty() || !Group[0])
return;
- if (Diags.getDiagnosticLevel(diag::warn_doc_param_not_found,
- Group[0]->getLocation())
- == DiagnosticsEngine::Ignored)
+ if (Diags.isIgnored(diag::warn_doc_param_not_found, Group[0]->getLocation()))
return;
if (Group.size() >= 2) {
@@ -9133,12 +9487,12 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
}
// Ensure we have a valid name
- IdentifierInfo *II = 0;
+ IdentifierInfo *II = nullptr;
if (D.hasName()) {
II = D.getIdentifier();
if (!II) {
Diag(D.getIdentifierLoc(), diag::err_bad_parameter_name)
- << GetNameForDeclarator(D).getName().getAsString();
+ << GetNameForDeclarator(D).getName();
D.setInvalidType(true);
}
}
@@ -9154,14 +9508,14 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
// Just pretend that we didn't see the previous declaration.
- PrevDecl = 0;
+ PrevDecl = nullptr;
} else if (S->isDeclScope(PrevDecl)) {
Diag(D.getIdentifierLoc(), diag::err_param_redefinition) << II;
Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
// Recover by removing the name
- II = 0;
- D.SetIdentifier(0, D.getIdentifierLoc());
+ II = nullptr;
+ D.SetIdentifier(nullptr, D.getIdentifierLoc());
D.setInvalidType(true);
}
}
@@ -9211,9 +9565,9 @@ ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC,
/* FIXME: setting StartLoc == Loc.
Would it be worth to modify callers so as to provide proper source
location for the unnamed parameters, embedding the parameter's type? */
- ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, Loc, 0,
+ ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, Loc, nullptr,
T, Context.getTrivialTypeSourceInfo(T, Loc),
- SC_None, 0);
+ SC_None, nullptr);
Param->setImplicit();
return Param;
}
@@ -9293,7 +9647,7 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc,
ParmVarDecl *New = ParmVarDecl::Create(Context, DC, StartLoc, NameLoc, Name,
Context.getAdjustedParameterType(T),
TSInfo,
- StorageClass, 0);
+ StorageClass, nullptr);
// Parameters can not be abstract class types.
// For record types, this is done by the AbstractClassUsageDiagnoser once
@@ -9319,8 +9673,12 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc,
// Since all parameters have automatic store duration, they can not have
// an address space.
if (T.getAddressSpace() != 0) {
- Diag(NameLoc, diag::err_arg_with_address_space);
- New->setInvalidDecl();
+ // OpenCL allows function arguments declared to be an array of a type
+ // to be qualified with an address space.
+ if (!(getLangOpts().OpenCL && T->isArrayType())) {
+ Diag(NameLoc, diag::err_arg_with_address_space);
+ New->setInvalidDecl();
+ }
}
return New;
@@ -9333,16 +9691,15 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
// Verify 6.9.1p6: 'every identifier in the identifier list shall be declared'
// for a K&R function.
if (!FTI.hasPrototype) {
- for (int i = FTI.NumArgs; i != 0; /* decrement in loop */) {
+ for (int i = FTI.NumParams; i != 0; /* decrement in loop */) {
--i;
- if (FTI.ArgInfo[i].Param == 0) {
+ if (FTI.Params[i].Param == nullptr) {
SmallString<256> Code;
- llvm::raw_svector_ostream(Code) << " int "
- << FTI.ArgInfo[i].Ident->getName()
- << ";\n";
- Diag(FTI.ArgInfo[i].IdentLoc, diag::ext_param_not_declared)
- << FTI.ArgInfo[i].Ident
- << FixItHint::CreateInsertion(LocAfterDecls, Code.str());
+ llvm::raw_svector_ostream(Code)
+ << " int " << FTI.Params[i].Ident->getName() << ";\n";
+ Diag(FTI.Params[i].IdentLoc, diag::ext_param_not_declared)
+ << FTI.Params[i].Ident
+ << FixItHint::CreateInsertion(LocAfterDecls, Code.str());
// Implicitly declare the argument as type 'int' for lack of a better
// type.
@@ -9350,21 +9707,21 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
DeclSpec DS(attrs);
const char* PrevSpec; // unused
unsigned DiagID; // unused
- DS.SetTypeSpecType(DeclSpec::TST_int, FTI.ArgInfo[i].IdentLoc,
- PrevSpec, DiagID);
+ DS.SetTypeSpecType(DeclSpec::TST_int, FTI.Params[i].IdentLoc, PrevSpec,
+ DiagID, Context.getPrintingPolicy());
// Use the identifier location for the type source range.
- DS.SetRangeStart(FTI.ArgInfo[i].IdentLoc);
- DS.SetRangeEnd(FTI.ArgInfo[i].IdentLoc);
+ DS.SetRangeStart(FTI.Params[i].IdentLoc);
+ DS.SetRangeEnd(FTI.Params[i].IdentLoc);
Declarator ParamD(DS, Declarator::KNRTypeListContext);
- ParamD.SetIdentifier(FTI.ArgInfo[i].Ident, FTI.ArgInfo[i].IdentLoc);
- FTI.ArgInfo[i].Param = ActOnParamDeclarator(S, ParamD);
+ ParamD.SetIdentifier(FTI.Params[i].Ident, FTI.Params[i].IdentLoc);
+ FTI.Params[i].Param = ActOnParamDeclarator(S, ParamD);
}
}
}
}
Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
- assert(getCurFunctionDecl() == 0 && "Function parsing confused");
+ assert(getCurFunctionDecl() == nullptr && "Function parsing confused");
assert(D.isFunctionDeclarator() && "Not a function declarator!");
Scope *ParentScope = FnBodyScope->getParent();
@@ -9373,6 +9730,10 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
return ActOnStartOfFunctionDef(FnBodyScope, DP);
}
+void Sema::ActOnFinishInlineMethodDef(CXXMethodDecl *D) {
+ Consumer.HandleInlineMethodDefinition(D);
+}
+
static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD,
const FunctionDecl*& PossibleZeroParamPrototype) {
// Don't warn about invalid declarations.
@@ -9456,7 +9817,7 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator,
LambdaScopeInfo *LSI = S.PushLambdaScope();
LSI->CallOperator = CallOperator;
LSI->Lambda = LambdaClass;
- LSI->ReturnType = CallOperator->getResultType();
+ LSI->ReturnType = CallOperator->getReturnType();
const LambdaCaptureDefault LCD = LambdaClass->getLambdaCaptureDefault();
if (LCD == LCD_None)
@@ -9472,23 +9833,22 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator,
// Add the captures to the LSI so they can be noted as already
// captured within tryCaptureVar.
- for (LambdaExpr::capture_iterator C = LambdaClass->captures_begin(),
- CEnd = LambdaClass->captures_end(); C != CEnd; ++C) {
- if (C->capturesVariable()) {
- VarDecl *VD = C->getCapturedVar();
+ for (const auto &C : LambdaClass->captures()) {
+ if (C.capturesVariable()) {
+ VarDecl *VD = C.getCapturedVar();
if (VD->isInitCapture())
S.CurrentInstantiationScope->InstantiatedLocal(VD, VD);
QualType CaptureType = VD->getType();
- const bool ByRef = C->getCaptureKind() == LCK_ByRef;
+ const bool ByRef = C.getCaptureKind() == LCK_ByRef;
LSI->addCapture(VD, /*IsBlock*/false, ByRef,
- /*RefersToEnclosingLocal*/true, C->getLocation(),
- /*EllipsisLoc*/C->isPackExpansion()
- ? C->getEllipsisLoc() : SourceLocation(),
- CaptureType, /*Expr*/ 0);
-
- } else if (C->capturesThis()) {
- LSI->addThisCapture(/*Nested*/ false, C->getLocation(),
- S.getCurrentThisType(), /*Expr*/ 0);
+ /*RefersToEnclosingLocal*/true, C.getLocation(),
+ /*EllipsisLoc*/C.isPackExpansion()
+ ? C.getEllipsisLoc() : SourceLocation(),
+ CaptureType, /*Expr*/ nullptr);
+
+ } else if (C.capturesThis()) {
+ LSI->addThisCapture(/*Nested*/ false, C.getLocation(),
+ S.getCurrentThisType(), /*Expr*/ nullptr);
}
}
}
@@ -9499,7 +9859,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
if (!D)
return D;
- FunctionDecl *FD = 0;
+ FunctionDecl *FD = nullptr;
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
FD = FunTmpl->getTemplatedDecl();
@@ -9539,7 +9899,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
// The return type of a function definition must be complete
// (C99 6.9.1p3, C++ [dcl.fct]p6).
- QualType ResultType = FD->getResultType();
+ QualType ResultType = FD->getReturnType();
if (!ResultType->isDependentType() && !ResultType->isVoidType() &&
!FD->isInvalidDecl() &&
RequireCompleteType(FD->getLocation(), ResultType,
@@ -9551,7 +9911,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
// prototype declaration. This warning is issued even if the
// definition itself provides a prototype. The aim is to detect
// global functions that fail to be declared in header files.
- const FunctionDecl *PossibleZeroParamPrototype = 0;
+ const FunctionDecl *PossibleZeroParamPrototype = nullptr;
if (ShouldWarnAboutMissingPrototype(FD, PossibleZeroParamPrototype)) {
Diag(FD->getLocation(), diag::warn_missing_prototype) << FD;
@@ -9578,8 +9938,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
/*CheckParameterNames=*/true);
// Introduce our parameters into the function scope
- for (unsigned p = 0, NumParams = FD->getNumParams(); p < NumParams; ++p) {
- ParmVarDecl *Param = FD->getParamDecl(p);
+ for (auto Param : FD->params()) {
Param->setOwningFunction(FD);
// If this has an identifier, add it to the scope stack.
@@ -9604,9 +9963,8 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
// and reattach to the current context.
if (D->getLexicalDeclContext() == Context.getTranslationUnitDecl()) {
// Is the decl actually in the context?
- for (DeclContext::decl_iterator DI = Context.getTranslationUnitDecl()->decls_begin(),
- DE = Context.getTranslationUnitDecl()->decls_end(); DI != DE; ++DI) {
- if (*DI == D) {
+ for (const auto *DI : Context.getTranslationUnitDecl()->decls()) {
+ if (DI == D) {
Context.getTranslationUnitDecl()->removeDecl(D);
break;
}
@@ -9621,10 +9979,9 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
// Similarly, dive into enums and fish their constants out, making them
// accessible in this scope.
- if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
- for (EnumDecl::enumerator_iterator EI = ED->enumerator_begin(),
- EE = ED->enumerator_end(); EI != EE; ++EI)
- PushOnScopeChains(*EI, FnBodyScope, /*AddToContext=*/false);
+ if (auto *ED = dyn_cast<EnumDecl>(D)) {
+ for (auto *EI : ED->enumerators())
+ PushOnScopeChains(EI, FnBodyScope, /*AddToContext=*/false);
}
}
}
@@ -9633,35 +9990,22 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
if (const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>())
ResolveExceptionSpec(D->getLocation(), FPT);
- // Checking attributes of current function definition
- // dllimport attribute.
- DLLImportAttr *DA = FD->getAttr<DLLImportAttr>();
- if (DA && (!FD->getAttr<DLLExportAttr>())) {
- // dllimport attribute cannot be directly applied to definition.
- // Microsoft accepts dllimport for functions defined within class scope.
- if (!DA->isInherited() &&
- !(LangOpts.MicrosoftExt && FD->getLexicalDeclContext()->isRecord())) {
- Diag(FD->getLocation(),
- diag::err_attribute_can_be_applied_only_to_symbol_declaration)
- << "dllimport";
- FD->setInvalidDecl();
- return D;
- }
-
- // Visual C++ appears to not think this is an issue, so only issue
- // a warning when Microsoft extensions are disabled.
- if (!LangOpts.MicrosoftExt) {
- // If a symbol previously declared dllimport is later defined, the
- // attribute is ignored in subsequent references, and a warning is
- // emitted.
- Diag(FD->getLocation(),
- diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
- << FD->getName() << "dllimport";
- }
+ // dllimport cannot be applied to non-inline function definitions.
+ if (FD->hasAttr<DLLImportAttr>() && !FD->isInlined() &&
+ !FD->isTemplateInstantiation()) {
+ assert(!FD->hasAttr<DLLExportAttr>());
+ Diag(FD->getLocation(), diag::err_attribute_dllimport_function_definition);
+ FD->setInvalidDecl();
+ return D;
}
// We want to attach documentation to original Decl (which might be
// a function template).
ActOnDocumentableDecl(D);
+ if (getCurLexicalContext()->isObjCContainer() &&
+ getCurLexicalContext()->getDeclKind() != Decl::ObjCCategoryImpl &&
+ getCurLexicalContext()->getDeclKind() != Decl::ObjCImplementation)
+ Diag(FD->getLocation(), diag::warn_function_def_in_objc_container);
+
return D;
}
@@ -9675,49 +10019,53 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
/// use the named return value optimization.
///
/// This function applies a very simplistic algorithm for NRVO: if every return
-/// statement in the function has the same NRVO candidate, that candidate is
-/// the NRVO variable.
-///
-/// FIXME: Employ a smarter algorithm that accounts for multiple return
-/// statements and the lifetimes of the NRVO candidates. We should be able to
-/// find a maximal set of NRVO variables.
+/// statement in the scope of a variable has the same NRVO candidate, that
+/// candidate is an NRVO variable.
void Sema::computeNRVO(Stmt *Body, FunctionScopeInfo *Scope) {
ReturnStmt **Returns = Scope->Returns.data();
- const VarDecl *NRVOCandidate = 0;
for (unsigned I = 0, E = Scope->Returns.size(); I != E; ++I) {
- if (!Returns[I]->getNRVOCandidate())
- return;
-
- if (!NRVOCandidate)
- NRVOCandidate = Returns[I]->getNRVOCandidate();
- else if (NRVOCandidate != Returns[I]->getNRVOCandidate())
- return;
+ if (const VarDecl *NRVOCandidate = Returns[I]->getNRVOCandidate()) {
+ if (!NRVOCandidate->isNRVOVariable())
+ Returns[I]->setNRVOCandidate(nullptr);
+ }
}
-
- if (NRVOCandidate)
- const_cast<VarDecl*>(NRVOCandidate)->setNRVOVariable(true);
}
-bool Sema::canSkipFunctionBody(Decl *D) {
- if (!Consumer.shouldSkipFunctionBody(D))
+bool Sema::canDelayFunctionBody(const Declarator &D) {
+ // We can't delay parsing the body of a constexpr function template (yet).
+ if (D.getDeclSpec().isConstexprSpecified())
return false;
- if (isa<ObjCMethodDecl>(D))
- return true;
+ // We can't delay parsing the body of a function template with a deduced
+ // return type (yet).
+ if (D.getDeclSpec().containsPlaceholderType()) {
+ // If the placeholder introduces a non-deduced trailing return type,
+ // we can still delay parsing it.
+ if (D.getNumTypeObjects()) {
+ const auto &Outer = D.getTypeObject(D.getNumTypeObjects() - 1);
+ if (Outer.Kind == DeclaratorChunk::Function &&
+ Outer.Fun.hasTrailingReturnType()) {
+ QualType Ty = GetTypeFromParser(Outer.Fun.getTrailingReturnType());
+ return Ty.isNull() || !Ty->isUndeducedType();
+ }
+ }
+ return false;
+ }
- FunctionDecl *FD = 0;
- if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D))
- FD = FTD->getTemplatedDecl();
- else
- FD = cast<FunctionDecl>(D);
+ return true;
+}
+bool Sema::canSkipFunctionBody(Decl *D) {
// We cannot skip the body of a function (or function template) which is
// constexpr, since we may need to evaluate its body in order to parse the
// 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.
- return !FD->isConstexpr() && !FD->getResultType()->isUndeducedType();
+ if (const FunctionDecl *FD = D->getAsFunction())
+ if (FD->isConstexpr() || FD->getReturnType()->isUndeducedType())
+ return false;
+ return Consumer.shouldSkipFunctionBody(D);
}
Decl *Sema::ActOnSkippedFunctionBody(Decl *Decl) {
@@ -9725,7 +10073,7 @@ Decl *Sema::ActOnSkippedFunctionBody(Decl *Decl) {
FD->setHasSkippedBody();
else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(Decl))
MD->setHasSkippedBody();
- return ActOnFinishFunctionBody(Decl, 0);
+ return ActOnFinishFunctionBody(Decl, nullptr);
}
Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) {
@@ -9734,32 +10082,27 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) {
Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
bool IsInstantiation) {
- FunctionDecl *FD = 0;
- FunctionTemplateDecl *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(dcl);
- if (FunTmpl)
- FD = FunTmpl->getTemplatedDecl();
- else
- FD = dyn_cast_or_null<FunctionDecl>(dcl);
+ FunctionDecl *FD = dcl ? dcl->getAsFunction() : nullptr;
sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
- sema::AnalysisBasedWarnings::Policy *ActivePolicy = 0;
+ sema::AnalysisBasedWarnings::Policy *ActivePolicy = nullptr;
if (FD) {
FD->setBody(Body);
if (getLangOpts().CPlusPlus1y && !FD->isInvalidDecl() && Body &&
- !FD->isDependentContext() && FD->getResultType()->isUndeducedType()) {
+ !FD->isDependentContext() && FD->getReturnType()->isUndeducedType()) {
// If the function has a deduced result type but contains no 'return'
// statements, the result type as written must be exactly 'auto', and
// the deduced result type is 'void'.
- if (!FD->getResultType()->getAs<AutoType>()) {
+ if (!FD->getReturnType()->getAs<AutoType>()) {
Diag(dcl->getLocation(), diag::err_auto_fn_no_return_but_not_auto)
- << FD->getResultType();
+ << FD->getReturnType();
FD->setInvalidDecl();
} else {
// Substitute 'void' for the 'auto' in the type.
TypeLoc ResultType = FD->getTypeSourceInfo()->getTypeLoc().
- IgnoreParens().castAs<FunctionProtoTypeLoc>().getResultLoc();
+ IgnoreParens().castAs<FunctionProtoTypeLoc>().getReturnLoc();
Context.adjustDeducedFunctionResultType(
FD, SubstAutoType(ResultType.getType(), Context.VoidTy));
}
@@ -9783,15 +10126,17 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
WP.disableCheckFallThrough();
// MSVC permits the use of pure specifier (=0) on function definition,
- // defined at class scope, warn about this non standard construct.
+ // defined at class scope, warn about this non-standard construct.
if (getLangOpts().MicrosoftExt && FD->isPure() && FD->isCanonicalDecl())
- Diag(FD->getLocation(), diag::warn_pure_function_definition);
+ Diag(FD->getLocation(), diag::ext_pure_function_definition);
if (!FD->isInvalidDecl()) {
- DiagnoseUnusedParameters(FD->param_begin(), FD->param_end());
+ // Don't diagnose unused parameters of defaulted or deleted functions.
+ if (Body)
+ DiagnoseUnusedParameters(FD->param_begin(), FD->param_end());
DiagnoseSizeOfParametersAndReturnValue(FD->param_begin(), FD->param_end(),
- FD->getResultType(), FD);
-
+ FD->getReturnType(), FD);
+
// If this is a constructor, we need a vtable.
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(FD))
MarkVTableUsed(FD->getLocation(), Constructor->getParent());
@@ -9799,7 +10144,7 @@ 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->getResultType()->isRecordType() &&
+ if (getLangOpts().CPlusPlus && FD->getReturnType()->isRecordType() &&
!FD->isDependentContext())
computeNRVO(Body, getCurFunction());
}
@@ -9812,8 +10157,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
if (!MD->isInvalidDecl()) {
DiagnoseUnusedParameters(MD->param_begin(), MD->param_end());
DiagnoseSizeOfParametersAndReturnValue(MD->param_begin(), MD->param_end(),
- MD->getResultType(), MD);
-
+ MD->getReturnType(), MD);
+
if (Body)
computeNRVO(Body, getCurFunction());
}
@@ -9822,8 +10167,41 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
<< MD->getSelector().getAsString();
getCurFunction()->ObjCShouldCallSuper = false;
}
+ if (getCurFunction()->ObjCWarnForNoDesignatedInitChain) {
+ const ObjCMethodDecl *InitMethod = nullptr;
+ bool isDesignated =
+ MD->isDesignatedInitializerForTheInterface(&InitMethod);
+ assert(isDesignated && InitMethod);
+ (void)isDesignated;
+
+ auto superIsNSObject = [&](const ObjCMethodDecl *MD) {
+ auto IFace = MD->getClassInterface();
+ if (!IFace)
+ return false;
+ auto SuperD = IFace->getSuperClass();
+ if (!SuperD)
+ return false;
+ return SuperD->getIdentifier() ==
+ NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject);
+ };
+ // Don't issue this warning for unavailable inits or direct subclasses
+ // of NSObject.
+ if (!MD->isUnavailable() && !superIsNSObject(MD)) {
+ Diag(MD->getLocation(),
+ diag::warn_objc_designated_init_missing_super_call);
+ Diag(InitMethod->getLocation(),
+ diag::note_objc_designated_init_marked_here);
+ }
+ getCurFunction()->ObjCWarnForNoDesignatedInitChain = false;
+ }
+ if (getCurFunction()->ObjCWarnForNoInitDelegation) {
+ // Don't issue this warning for unavaialable inits.
+ if (!MD->isUnavailable())
+ Diag(MD->getLocation(), diag::warn_objc_secondary_init_missing_init_call);
+ getCurFunction()->ObjCWarnForNoInitDelegation = false;
+ }
} else {
- return 0;
+ return nullptr;
}
assert(!getCurFunction()->ObjCShouldCallSuper &&
@@ -9840,8 +10218,6 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
// Verify that gotos and switch cases don't jump into scopes illegally.
if (getCurFunction()->NeedsScopeChecking() &&
- !dcl->isInvalidDecl() &&
- !hasAnyUnrecoverableErrorsInThisFunction() &&
!PP.isCodeCompletionEnabled())
DiagnoseInvalidJumps(Body);
@@ -9856,11 +10232,11 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
// If any errors have occurred, clear out any temporaries that may have
// been leftover. This ensures that these temporaries won't be picked up for
// deletion in some later function.
- if (PP.getDiagnostics().hasErrorOccurred() ||
- PP.getDiagnostics().getSuppressAllDiagnostics()) {
+ if (getDiagnostics().hasErrorOccurred() ||
+ getDiagnostics().getSuppressAllDiagnostics()) {
DiscardCleanupsInEvaluationContext();
}
- if (!PP.getDiagnostics().hasUncompilableErrorOccurred() &&
+ if (!getDiagnostics().hasUncompilableErrorOccurred() &&
!isa<FunctionTemplateDecl>(dcl)) {
// Since the body is valid, issue any analysis-based warnings that are
// enabled.
@@ -9938,7 +10314,8 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
TypoCorrection Corrected;
DeclFilterCCC<FunctionDecl> Validator;
if (S && (Corrected = CorrectTypo(DeclarationNameInfo(&II, Loc),
- LookupOrdinaryName, S, 0, Validator)))
+ LookupOrdinaryName, S, nullptr, Validator,
+ CTK_NonError)))
diagnoseTypo(Corrected, PDiag(diag::note_function_suggestion),
/*ErrorRecovery*/false);
}
@@ -9948,16 +10325,17 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
AttributeFactory attrFactory;
DeclSpec DS(attrFactory);
unsigned DiagID;
- bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy, DiagID);
+ bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy, DiagID,
+ Context.getPrintingPolicy());
(void)Error; // Silence warning.
assert(!Error && "Error setting up implicit decl!");
SourceLocation NoLoc;
Declarator D(DS, Declarator::BlockContext);
D.AddTypeInfo(DeclaratorChunk::getFunction(/*HasProto=*/false,
/*IsAmbiguous=*/false,
- /*RParenLoc=*/NoLoc,
- /*ArgInfo=*/0,
- /*NumArgs=*/0,
+ /*LParenLoc=*/NoLoc,
+ /*Params=*/nullptr,
+ /*NumParams=*/0,
/*EllipsisLoc=*/NoLoc,
/*RParenLoc=*/NoLoc,
/*TypeQuals=*/0,
@@ -9968,10 +10346,10 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
/*MutableLoc=*/NoLoc,
EST_None,
/*ESpecLoc=*/NoLoc,
- /*Exceptions=*/0,
- /*ExceptionRanges=*/0,
+ /*Exceptions=*/nullptr,
+ /*ExceptionRanges=*/nullptr,
/*NumExceptions=*/0,
- /*NoexceptExpr=*/0,
+ /*NoexceptExpr=*/nullptr,
Loc, Loc, D),
DS.getAttributes(),
SourceLocation());
@@ -10012,25 +10390,27 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
unsigned FormatIdx;
bool HasVAListArg;
if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) {
- if (!FD->getAttr<FormatAttr>()) {
+ if (!FD->hasAttr<FormatAttr>()) {
const char *fmt = "printf";
unsigned int NumParams = FD->getNumParams();
if (FormatIdx < NumParams && // NumParams may be 0 (e.g. vfprintf)
FD->getParamDecl(FormatIdx)->getType()->isObjCObjectPointerType())
fmt = "NSString";
- FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
+ FD->addAttr(FormatAttr::CreateImplicit(Context,
&Context.Idents.get(fmt),
FormatIdx+1,
- HasVAListArg ? 0 : FormatIdx+2));
+ HasVAListArg ? 0 : FormatIdx+2,
+ FD->getLocation()));
}
}
if (Context.BuiltinInfo.isScanfLike(BuiltinID, FormatIdx,
HasVAListArg)) {
- if (!FD->getAttr<FormatAttr>())
- FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
+ if (!FD->hasAttr<FormatAttr>())
+ FD->addAttr(FormatAttr::CreateImplicit(Context,
&Context.Idents.get("scanf"),
FormatIdx+1,
- HasVAListArg ? 0 : FormatIdx+2));
+ HasVAListArg ? 0 : FormatIdx+2,
+ FD->getLocation()));
}
// Mark const if we don't care about errno and that is the only
@@ -10038,17 +10418,18 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
// IRgen to use LLVM intrinsics for such functions.
if (!getLangOpts().MathErrno &&
Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) {
- if (!FD->getAttr<ConstAttr>())
- FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context));
+ if (!FD->hasAttr<ConstAttr>())
+ FD->addAttr(ConstAttr::CreateImplicit(Context, FD->getLocation()));
}
if (Context.BuiltinInfo.isReturnsTwice(BuiltinID) &&
- !FD->getAttr<ReturnsTwiceAttr>())
- FD->addAttr(::new (Context) ReturnsTwiceAttr(FD->getLocation(), Context));
- if (Context.BuiltinInfo.isNoThrow(BuiltinID) && !FD->getAttr<NoThrowAttr>())
- FD->addAttr(::new (Context) NoThrowAttr(FD->getLocation(), Context));
- if (Context.BuiltinInfo.isConst(BuiltinID) && !FD->getAttr<ConstAttr>())
- FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context));
+ !FD->hasAttr<ReturnsTwiceAttr>())
+ FD->addAttr(ReturnsTwiceAttr::CreateImplicit(Context,
+ FD->getLocation()));
+ if (Context.BuiltinInfo.isNoThrow(BuiltinID) && !FD->hasAttr<NoThrowAttr>())
+ FD->addAttr(NoThrowAttr::CreateImplicit(Context, FD->getLocation()));
+ if (Context.BuiltinInfo.isConst(BuiltinID) && !FD->hasAttr<ConstAttr>())
+ FD->addAttr(ConstAttr::CreateImplicit(Context, FD->getLocation()));
}
IdentifierInfo *Name = FD->getIdentifier();
@@ -10067,17 +10448,19 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
if (Name->isStr("asprintf") || Name->isStr("vasprintf")) {
// FIXME: asprintf and vasprintf aren't C99 functions. Should they be
// target-specific builtins, perhaps?
- if (!FD->getAttr<FormatAttr>())
- FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
+ if (!FD->hasAttr<FormatAttr>())
+ FD->addAttr(FormatAttr::CreateImplicit(Context,
&Context.Idents.get("printf"), 2,
- Name->isStr("vasprintf") ? 0 : 3));
+ Name->isStr("vasprintf") ? 0 : 3,
+ FD->getLocation()));
}
if (Name->isStr("__CFStringMakeConstantString")) {
// We already have a __builtin___CFStringMakeConstantString,
// but builds that use -fno-constant-cfstrings don't go through that.
- if (!FD->getAttr<FormatArgAttr>())
- FD->addAttr(::new (Context) FormatArgAttr(FD->getLocation(), Context, 1));
+ if (!FD->hasAttr<FormatArgAttr>())
+ FD->addAttr(FormatArgAttr::CreateImplicit(Context, 1,
+ FD->getLocation()));
}
}
@@ -10140,6 +10523,26 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
if (!Context.hasSameType(T, Context.getTagDeclType(tagFromDeclSpec)))
break;
+ // If we've already computed linkage for the anonymous tag, then
+ // adding a typedef name for the anonymous decl can change that
+ // linkage, which might be a serious problem. Diagnose this as
+ // unsupported and ignore the typedef name. TODO: we should
+ // pursue this as a language defect and establish a formal rule
+ // for how to handle it.
+ if (tagFromDeclSpec->hasLinkageBeenComputed()) {
+ Diag(D.getIdentifierLoc(), diag::err_typedef_changes_linkage);
+
+ SourceLocation tagLoc = D.getDeclSpec().getTypeSpecTypeLoc();
+ tagLoc = getLocForEndOfToken(tagLoc);
+
+ llvm::SmallString<40> textToInsert;
+ textToInsert += ' ';
+ textToInsert += D.getIdentifier()->getName();
+ Diag(tagLoc, diag::note_typedef_changes_linkage)
+ << FixItHint::CreateInsertion(tagLoc, textToInsert);
+ break;
+ }
+
// Otherwise, set this is the anon-decl typedef for the tag.
tagFromDeclSpec->setTypedefNameForAnonDecl(NewTD);
break;
@@ -10179,7 +10582,7 @@ bool Sema::CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped,
if (IsScoped != Prev->isScoped()) {
Diag(EnumLoc, diag::err_enum_redeclare_scoped_mismatch)
<< Prev->isScoped();
- Diag(Prev->getLocation(), diag::note_previous_use);
+ Diag(Prev->getLocation(), diag::note_previous_declaration);
return true;
}
@@ -10188,15 +10591,17 @@ bool Sema::CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped,
!Prev->getIntegerType()->isDependentType() &&
!Context.hasSameUnqualifiedType(EnumUnderlyingTy,
Prev->getIntegerType())) {
+ // TODO: Highlight the underlying type of the redeclaration.
Diag(EnumLoc, diag::err_enum_redeclare_type_mismatch)
<< EnumUnderlyingTy << Prev->getIntegerType();
- Diag(Prev->getLocation(), diag::note_previous_use);
+ Diag(Prev->getLocation(), diag::note_previous_declaration)
+ << Prev->getIntegerTypeRange();
return true;
}
} else if (IsFixed != Prev->isFixed()) {
Diag(EnumLoc, diag::err_enum_redeclare_fixed_mismatch)
<< Prev->isFixed();
- Diag(Prev->getLocation(), diag::note_previous_use);
+ Diag(Prev->getLocation(), diag::note_previous_declaration);
return true;
}
@@ -10276,8 +10681,7 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
}
bool previousMismatch = false;
- for (TagDecl::redecl_iterator I(Previous->redecls_begin()),
- E(Previous->redecls_end()); I != E; ++I) {
+ for (auto I : Previous->redecls()) {
if (I->getTagKind() != NewTag) {
if (!previousMismatch) {
previousMismatch = true;
@@ -10308,7 +10712,7 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
<< getRedeclDiagFromTagKind(OldTag);
Diag(Redecl->getLocation(), diag::note_previous_use);
- // If there is a previous defintion, suggest a fix-it.
+ // If there is a previous definition, suggest a fix-it.
if (Previous->getDefinition()) {
Diag(NewTagLoc, diag::note_struct_class_suggestion)
<< getRedeclDiagFromTagKind(Redecl->getTagKind())
@@ -10321,10 +10725,56 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
return false;
}
+/// Add a minimal nested name specifier fixit hint to allow lookup of a tag name
+/// from an outer enclosing namespace or file scope inside a friend declaration.
+/// This should provide the commented out code in the following snippet:
+/// namespace N {
+/// struct X;
+/// namespace M {
+/// struct Y { friend struct /*N::*/ X; };
+/// }
+/// }
+static FixItHint createFriendTagNNSFixIt(Sema &SemaRef, NamedDecl *ND, Scope *S,
+ SourceLocation NameLoc) {
+ // While the decl is in a namespace, do repeated lookup of that name and see
+ // if we get the same namespace back. If we do not, continue until
+ // translation unit scope, at which point we have a fully qualified NNS.
+ SmallVector<IdentifierInfo *, 4> Namespaces;
+ DeclContext *DC = ND->getDeclContext()->getRedeclContext();
+ for (; !DC->isTranslationUnit(); DC = DC->getParent()) {
+ // This tag should be declared in a namespace, which can only be enclosed by
+ // other namespaces. Bail if there's an anonymous namespace in the chain.
+ NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(DC);
+ if (!Namespace || Namespace->isAnonymousNamespace())
+ return FixItHint();
+ IdentifierInfo *II = Namespace->getIdentifier();
+ Namespaces.push_back(II);
+ NamedDecl *Lookup = SemaRef.LookupSingleName(
+ S, II, NameLoc, Sema::LookupNestedNameSpecifierName);
+ if (Lookup == Namespace)
+ break;
+ }
+
+ // Once we have all the namespaces, reverse them to go outermost first, and
+ // build an NNS.
+ SmallString<64> Insertion;
+ llvm::raw_svector_ostream OS(Insertion);
+ if (DC->isTranslationUnit())
+ OS << "::";
+ std::reverse(Namespaces.begin(), Namespaces.end());
+ for (auto *II : Namespaces)
+ OS << II->getName() << "::";
+ OS.flush();
+ return FixItHint::CreateInsertion(NameLoc, Insertion);
+}
+
/// ActOnTag - 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.
+///
+/// IsTypeSpecifier is true if this is a type-specifier (or
+/// trailing-type-specifier) other than one in an alias-declaration.
Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
SourceLocation KWLoc, CXXScopeSpec &SS,
IdentifierInfo *Name, SourceLocation NameLoc,
@@ -10334,10 +10784,11 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
bool &OwnedDecl, bool &IsDependent,
SourceLocation ScopedEnumKWLoc,
bool ScopedEnumUsesClassTag,
- TypeResult UnderlyingType) {
+ TypeResult UnderlyingType,
+ bool IsTypeSpecifier) {
// If this is not a definition, it must have a name.
IdentifierInfo *OrigName = Name;
- assert((Name != 0 || TUK == TUK_Definition) &&
+ assert((Name != nullptr || TUK == TUK_Definition) &&
"Nameless record must be a definition!");
assert(TemplateParameterLists.size() == 0 || TUK != TUK_Reference);
@@ -10356,11 +10807,11 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
(SS.isNotEmpty() && TUK != TUK_Reference)) {
if (TemplateParameterList *TemplateParams =
MatchTemplateParametersToScopeSpecifier(
- KWLoc, NameLoc, SS, TemplateParameterLists, TUK == TUK_Friend,
- isExplicitSpecialization, Invalid)) {
+ KWLoc, NameLoc, SS, nullptr, TemplateParameterLists,
+ TUK == TUK_Friend, isExplicitSpecialization, Invalid)) {
if (Kind == TTK_Enum) {
Diag(KWLoc, diag::err_enum_template);
- return 0;
+ return nullptr;
}
if (TemplateParams->size() > 0) {
@@ -10368,13 +10819,14 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// be a member of another template).
if (Invalid)
- return 0;
+ 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());
return Result.get();
@@ -10400,7 +10852,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
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 = 0;
+ TypeSourceInfo *TI = nullptr;
GetTypeFromParser(UnderlyingType.get(), &TI);
EnumUnderlying = TI;
@@ -10412,7 +10864,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
UPPC_FixedUnderlyingType))
EnumUnderlying = Context.IntTy.getTypePtr();
- } else if (getLangOpts().MicrosoftMode)
+ } else if (getLangOpts().MSVCCompat)
// Microsoft enums are always of int type.
EnumUnderlying = Context.IntTy.getTypePtr();
}
@@ -10426,13 +10878,12 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
Redecl = NotForRedeclaration;
LookupResult Previous(*this, Name, NameLoc, LookupTagName, Redecl);
- bool FriendSawTagOutsideEnclosingNamespace = false;
if (Name && SS.isNotEmpty()) {
// We have a nested-name tag ('struct foo::bar').
// Check for invalid 'foo::'.
if (SS.isInvalid()) {
- Name = 0;
+ Name = nullptr;
goto CreateNewDecl;
}
@@ -10442,26 +10893,26 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
DC = computeDeclContext(SS, false);
if (!DC) {
IsDependent = true;
- return 0;
+ return nullptr;
}
} else {
DC = computeDeclContext(SS, true);
if (!DC) {
Diag(SS.getRange().getBegin(), diag::err_dependent_nested_name_spec)
<< SS.getRange();
- return 0;
+ return nullptr;
}
}
if (RequireCompleteDeclContext(SS, DC))
- return 0;
+ return nullptr;
SearchDC = DC;
// Look-up name inside 'foo::'.
LookupQualifiedName(Previous, DC);
if (Previous.isAmbiguous())
- return 0;
+ return nullptr;
if (Previous.empty()) {
// Name lookup did not find anything. However, if the
@@ -10473,13 +10924,13 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
if (Previous.wasNotFoundInCurrentInstantiation() &&
(TUK == TUK_Reference || TUK == TUK_Friend)) {
IsDependent = true;
- return 0;
+ return nullptr;
}
// A tag 'foo::bar' must already exist.
Diag(NameLoc, diag::err_not_tag_in_scope)
<< Kind << Name << DC << SS.getRange();
- Name = 0;
+ Name = nullptr;
Invalid = true;
goto CreateNewDecl;
}
@@ -10511,26 +10962,41 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// the entity has been previously declared shall not consider
// any scopes outside the innermost enclosing namespace.
//
+ // MSVC doesn't implement the above rule for types, so a friend tag
+ // declaration may be a redeclaration of a type declared in an enclosing
+ // scope. They do implement this rule for friend functions.
+ //
// Does it matter that this should be by scope instead of by
// semantic context?
if (!Previous.empty() && TUK == TUK_Friend) {
DeclContext *EnclosingNS = SearchDC->getEnclosingNamespaceContext();
LookupResult::Filter F = Previous.makeFilter();
+ bool FriendSawTagOutsideEnclosingNamespace = false;
while (F.hasNext()) {
NamedDecl *ND = F.next();
DeclContext *DC = ND->getDeclContext()->getRedeclContext();
if (DC->isFileContext() &&
!EnclosingNS->Encloses(ND->getDeclContext())) {
- F.erase();
- FriendSawTagOutsideEnclosingNamespace = true;
+ if (getLangOpts().MSVCCompat)
+ FriendSawTagOutsideEnclosingNamespace = true;
+ else
+ F.erase();
}
}
F.done();
+
+ // Diagnose this MSVC extension in the easy case where lookup would have
+ // unambiguously found something outside the enclosing namespace.
+ if (Previous.isSingleResult() && FriendSawTagOutsideEnclosingNamespace) {
+ NamedDecl *ND = Previous.getFoundDecl();
+ Diag(NameLoc, diag::ext_friend_tag_redecl_outside_namespace)
+ << createFriendTagNNSFixIt(*this, ND, S, NameLoc);
+ }
}
-
+
// Note: there used to be some attempt at recovery here.
if (Previous.isAmbiguous())
- return 0;
+ return nullptr;
if (!getLangOpts().CPlusPlus && TUK != TUK_Reference) {
// FIXME: This makes sure that we ignore the contexts associated
@@ -10540,11 +11006,6 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
while (isa<RecordDecl>(SearchDC) || isa<EnumDecl>(SearchDC))
SearchDC = SearchDC->getParent();
}
- } else if (S->isFunctionPrototypeScope()) {
- // If this is an enum declaration in function prototype scope, set its
- // initial context to the translation unit.
- // FIXME: [citation needed]
- SearchDC = Context.getTranslationUnitDecl();
}
if (Previous.isSingleResult() &&
@@ -10634,7 +11095,9 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
}
if (!Previous.empty()) {
- NamedDecl *PrevDecl = (*Previous.begin())->getUnderlyingDecl();
+ NamedDecl *PrevDecl = Previous.getFoundDecl();
+ NamedDecl *DirectPrevDecl =
+ getLangOpts().MSVCCompat ? *Previous.begin() : PrevDecl;
// It's okay to have a tag decl in the same scope as a typedef
// which hides a tag decl in the same scope. Finding this
@@ -10666,7 +11129,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// in the same scope (so that the definition/declaration completes or
// rementions the tag), reuse the decl.
if (TUK == TUK_Reference || TUK == TUK_Friend ||
- isDeclInScope(PrevDecl, SearchDC, S, isExplicitSpecialization)) {
+ isDeclInScope(DirectPrevDecl, SearchDC, S,
+ SS.isNotEmpty() || isExplicitSpecialization)) {
// Make sure that this wasn't declared as an enum and now used as a
// struct or something similar.
if (!isAcceptableTagRedeclaration(PrevTagDecl, Kind,
@@ -10688,7 +11152,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
Kind = PrevTagDecl->getTagKind();
else {
// Recover by making this an anonymous redefinition.
- Name = 0;
+ Name = nullptr;
Previous.clear();
Invalid = true;
}
@@ -10709,7 +11173,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
QualType EnumUnderlyingTy;
if (TypeSourceInfo *TI = EnumUnderlying.dyn_cast<TypeSourceInfo*>())
- EnumUnderlyingTy = TI->getType();
+ EnumUnderlyingTy = TI->getType().getUnqualifiedType();
else if (const Type *T = EnumUnderlying.dyn_cast<const Type*>())
EnumUnderlyingTy = QualType(T, 0);
@@ -10718,7 +11182,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, PrevEnum))
- return TUK == TUK_Declaration ? PrevTagDecl : 0;
+ return TUK == TUK_Declaration ? PrevTagDecl : nullptr;
}
// C++11 [class.mem]p1:
@@ -10732,14 +11196,17 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
}
if (!Invalid) {
- // If this is a use, just return the declaration we found.
+ // If this is a use, just return the declaration we found, unless
+ // we have attributes.
// FIXME: In the future, return a variant or some other clue
// for the consumer of this Decl to know it doesn't own it.
// For our current ASTs this shouldn't be a problem, but will
// need to be changed with DeclGroups.
- if ((TUK == TUK_Reference && (!PrevTagDecl->getFriendObjectKind() ||
- getLangOpts().MicrosoftExt)) || TUK == TUK_Friend)
+ if (!Attr &&
+ ((TUK == TUK_Reference &&
+ (!PrevTagDecl->getFriendObjectKind() || getLangOpts().MicrosoftExt))
+ || TUK == TUK_Friend))
return PrevTagDecl;
// Diagnose attempts to redefine a tag.
@@ -10771,7 +11238,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// If this is a redefinition, recover by making this
// struct be anonymous, which will make any later
// references get the previous definition.
- Name = 0;
+ Name = nullptr;
Previous.clear();
Invalid = true;
}
@@ -10784,14 +11251,22 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
Diag(NameLoc, diag::err_nested_redefinition) << Name;
Diag(PrevTagDecl->getLocation(),
diag::note_previous_definition);
- Name = 0;
+ Name = nullptr;
Previous.clear();
Invalid = true;
}
}
// Okay, this is definition of a previously declared or referenced
- // tag PrevDecl. We're going to create a new Decl for it.
+ // tag. We're going to create a new Decl for it.
+ }
+
+ // Okay, we're going to make a redeclaration. If this is some kind
+ // of reference, make sure we build the redeclaration in the same DC
+ // as the original, and ignore the current access specifier.
+ if (TUK == TUK_Friend || TUK == TUK_Reference) {
+ SearchDC = PrevTagDecl->getDeclContext();
+ AS = AS_none;
}
}
// If we get here we have (another) forward declaration or we
@@ -10827,8 +11302,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
Invalid = true;
// Otherwise, only diagnose if the declaration is in scope.
- } else if (!isDeclInScope(PrevDecl, SearchDC, S,
- isExplicitSpecialization)) {
+ } else if (!isDeclInScope(PrevDecl, SearchDC, S,
+ SS.isNotEmpty() || isExplicitSpecialization)) {
// do nothing
// Diagnose implicit declarations introduced by elaborated types.
@@ -10857,7 +11332,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// issue an error and recover by making this tag be anonymous.
Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
- Name = 0;
+ Name = nullptr;
Invalid = true;
}
@@ -10869,7 +11344,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
CreateNewDecl:
- TagDecl *PrevDecl = 0;
+ TagDecl *PrevDecl = nullptr;
if (Previous.isSingleResult())
PrevDecl = cast<TagDecl>(Previous.getFoundDecl());
@@ -10904,7 +11379,7 @@ CreateNewDecl:
Diag(Def->getLocation(), diag::note_previous_definition);
} else {
unsigned DiagID = diag::ext_forward_ref_enum;
- if (getLangOpts().MicrosoftMode)
+ if (getLangOpts().MSVCCompat)
DiagID = diag::ext_ms_forward_ref_enum;
else if (getLangOpts().CPlusPlus)
DiagID = diag::err_forward_ref_enum;
@@ -10944,6 +11419,14 @@ CreateNewDecl:
cast_or_null<RecordDecl>(PrevDecl));
}
+ // C++11 [dcl.type]p3:
+ // A type-specifier-seq shall not define a class or enumeration [...].
+ if (getLangOpts().CPlusPlus && IsTypeSpecifier && TUK == TUK_Definition) {
+ Diag(New->getLocation(), diag::err_type_defined_in_type_specifier)
+ << Context.getTagDeclType(New);
+ Invalid = true;
+ }
+
// Maybe add qualifier info.
if (SS.isNotEmpty()) {
if (SS.isSet()) {
@@ -10995,23 +11478,37 @@ CreateNewDecl:
else if (!SearchDC->isFunctionOrMethod())
New->setModulePrivate();
}
-
+
// If this is a specialization of a member class (of a class template),
// check the specialization.
if (isExplicitSpecialization && CheckMemberSpecialization(New, Previous))
Invalid = true;
-
+
+ // If we're declaring or defining a tag in function prototype scope in C,
+ // note that this type can only be used within the function and add it to
+ // the list of decls to inject into the function definition scope.
+ if ((Name || Kind == TTK_Enum) &&
+ getNonFieldDeclScope(S)->isFunctionPrototypeScope()) {
+ if (getLangOpts().CPlusPlus) {
+ // C++ [dcl.fct]p6:
+ // Types shall not be defined in return or parameter types.
+ if (TUK == TUK_Definition && !IsTypeSpecifier) {
+ Diag(Loc, diag::err_type_defined_in_param_type)
+ << Name;
+ Invalid = true;
+ }
+ } else {
+ Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New);
+ }
+ DeclsInPrototypeScope.push_back(New);
+ }
+
if (Invalid)
New->setInvalidDecl();
if (Attr)
ProcessDeclAttributeList(S, New, Attr);
- // If we're declaring or defining a tag in function prototype scope
- // in C, note that this type can only be used within the function.
- if (Name && S->isFunctionPrototypeScope() && !getLangOpts().CPlusPlus)
- Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New);
-
// Set the lexical context. If the tag has a C++ scope specifier, the
// lexical context will be different from the semantic context.
New->setLexicalDeclContext(CurContext);
@@ -11021,8 +11518,7 @@ CreateNewDecl:
// declaration so we always pass true to setObjectOfFriendDecl to make
// the tag name visible.
if (TUK == TUK_Friend)
- New->setObjectOfFriendDecl(!FriendSawTagOutsideEnclosingNamespace &&
- getLangOpts().MicrosoftExt);
+ New->setObjectOfFriendDecl(getLangOpts().MSVCCompat);
// Set the access specifier.
if (!Invalid && SearchDC->isRecord())
@@ -11060,12 +11556,6 @@ CreateNewDecl:
II->isStr("FILE"))
Context.setFILEDecl(New);
- // If we were in function prototype scope (and not in C++ mode), add this
- // tag to the list of decls to inject into the function definition scope.
- if (S->isFunctionPrototypeScope() && !getLangOpts().CPlusPlus &&
- InFunctionDeclarator && Name)
- DeclsInPrototypeScope.push_back(New);
-
if (PrevDecl)
mergeDeclAttributes(New, PrevDecl);
@@ -11076,7 +11566,7 @@ CreateNewDecl:
OwnedDecl = true;
// In C++, don't return an invalid declaration. We can't recover well from
// the cases where we make the type anonymous.
- return (Invalid && getLangOpts().CPlusPlus) ? 0 : New;
+ return (Invalid && getLangOpts().CPlusPlus) ? nullptr : New;
}
void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) {
@@ -11128,7 +11618,7 @@ void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD,
= CXXRecordDecl::Create(Context, Record->getTagKind(), CurContext,
Record->getLocStart(), Record->getLocation(),
Record->getIdentifier(),
- /*PrevDecl=*/0,
+ /*PrevDecl=*/nullptr,
/*DelayTypeCreation=*/true);
Context.getTypeDeclType(InjectedClassName, Record);
InjectedClassName->setImplicit();
@@ -11181,7 +11671,7 @@ void Sema::ActOnObjCTemporaryExitContainerContext(DeclContext *DC) {
void Sema::ActOnObjCReenterContainerContext(DeclContext *DC) {
ActOnObjCContainerStartDefinition(cast<Decl>(DC));
- OriginalLexicalContext = 0;
+ OriginalLexicalContext = nullptr;
}
void Sema::ActOnTagDefinitionError(Scope *S, Decl *TagD) {
@@ -11229,13 +11719,13 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc,
// If the bit-width is type- or value-dependent, don't try to check
// it now.
if (BitWidth->isValueDependent() || BitWidth->isTypeDependent())
- return Owned(BitWidth);
+ return BitWidth;
llvm::APSInt Value;
ExprResult ICE = VerifyIntegerConstantExpression(BitWidth, &Value);
if (ICE.isInvalid())
return ICE;
- BitWidth = ICE.take();
+ BitWidth = ICE.get();
if (Value != 0 && ZeroWidth)
*ZeroWidth = false;
@@ -11255,7 +11745,8 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc,
if (!FieldTy->isDependentType()) {
uint64_t TypeSize = Context.getTypeSize(FieldTy);
if (Value.getZExtValue() > TypeSize) {
- if (!getLangOpts().CPlusPlus || IsMsStruct) {
+ if (!getLangOpts().CPlusPlus || IsMsStruct ||
+ Context.getTargetInfo().getCXXABI().isMicrosoft()) {
if (FieldName)
return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_size)
<< FieldName << (unsigned)Value.getZExtValue()
@@ -11275,7 +11766,7 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc,
}
}
- return Owned(BitWidth);
+ return BitWidth;
}
/// ActOnField - Each field of a C struct/union is passed into this in order
@@ -11333,7 +11824,7 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
<< DeclSpec::getSpecifierName(TSCS);
// Check to see if this name was declared as a member previously
- NamedDecl *PrevDecl = 0;
+ NamedDecl *PrevDecl = nullptr;
LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration);
LookupName(Previous, S);
switch (Previous.getResultKind()) {
@@ -11357,11 +11848,11 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
// Just pretend that we didn't see the previous declaration.
- PrevDecl = 0;
+ PrevDecl = nullptr;
}
if (PrevDecl && !isDeclInScope(PrevDecl, Record, S))
- PrevDecl = 0;
+ PrevDecl = nullptr;
bool Mutable
= (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_mutable);
@@ -11474,10 +11965,10 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
// If this is declared as a bit-field, check the bit-field.
if (!InvalidDecl && BitWidth) {
BitWidth = VerifyBitField(Loc, II, T, Record->isMsStruct(Context), BitWidth,
- &ZeroWidth).take();
+ &ZeroWidth).get();
if (!BitWidth) {
InvalidDecl = true;
- BitWidth = 0;
+ BitWidth = nullptr;
ZeroWidth = false;
}
}
@@ -11500,6 +11991,12 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
}
}
+ // C++11 [class.union]p8 (DR1460):
+ // At most one variant member of a union may have a
+ // brace-or-equal-initializer.
+ if (InitStyle != ICIS_NoInit)
+ checkDuplicateDefaultInit(*this, cast<CXXRecordDecl>(Record), Loc);
+
FieldDecl *NewFD = FieldDecl::Create(Context, Record, TSSL, Loc, II, T, TInfo,
BitWidth, Mutable, InitStyle);
if (InvalidDecl)
@@ -11603,8 +12100,9 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) {
SourceLocation Loc = FD->getLocation();
if (getSourceManager().isInSystemHeader(Loc)) {
if (!FD->hasAttr<UnavailableAttr>())
- FD->addAttr(new (Context) UnavailableAttr(Loc, Context,
- "this system field has retaining ownership"));
+ FD->addAttr(UnavailableAttr::CreateImplicit(Context,
+ "this system field has retaining ownership",
+ Loc));
return false;
}
}
@@ -11655,7 +12153,7 @@ Decl *Sema::ActOnIvar(Scope *S,
if (BitWidth) {
// 6.7.2.1p3, 6.7.2.1p4
- BitWidth = VerifyBitField(Loc, II, T, /*IsMsStruct*/false, BitWidth).take();
+ BitWidth = VerifyBitField(Loc, II, T, /*IsMsStruct*/false, BitWidth).get();
if (!BitWidth)
D.setInvalidType();
} else {
@@ -11682,7 +12180,7 @@ Decl *Sema::ActOnIvar(Scope *S,
// Must set ivar's DeclContext to its enclosing interface.
ObjCContainerDecl *EnclosingDecl = cast<ObjCContainerDecl>(CurContext);
if (!EnclosingDecl || EnclosingDecl->isInvalidDecl())
- return 0;
+ return nullptr;
ObjCContainerDecl *EnclosingContext;
if (ObjCImplementationDecl *IMPDecl =
dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {
@@ -11698,7 +12196,7 @@ Decl *Sema::ActOnIvar(Scope *S,
dyn_cast<ObjCCategoryDecl>(EnclosingDecl)) {
if (LangOpts.ObjCRuntime.isFragile() || !CDecl->IsClassExtension()) {
Diag(Loc, diag::err_misplaced_ivar) << CDecl->IsClassExtension();
- return 0;
+ return nullptr;
}
}
EnclosingContext = EnclosingDecl;
@@ -11776,7 +12274,7 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc,
Expr * BW = IntegerLiteral::Create(Context, Zero, Context.IntTy, DeclLoc);
Ivar = ObjCIvarDecl::Create(Context, cast<ObjCContainerDecl>(CurContext),
- DeclLoc, DeclLoc, 0,
+ DeclLoc, DeclLoc, nullptr,
Context.CharTy,
Context.getTrivialTypeSourceInfo(Context.CharTy,
DeclLoc),
@@ -11813,9 +12311,8 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
// members of anonymous structs and unions in the total.
unsigned NumNamedMembers = 0;
if (Record) {
- for (RecordDecl::decl_iterator i = Record->decls_begin(),
- e = Record->decls_end(); i != e; i++) {
- if (IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(*i))
+ for (const auto *I : Record->decls()) {
+ if (const auto *IFD = dyn_cast<IndirectFieldDecl>(I))
if (IFD->getDeclName())
++NumNamedMembers;
}
@@ -11902,9 +12399,14 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
Diag(FD->getLocation(), diag::ext_c99_flexible_array_member)
<< FD->getDeclName() << Record->getTagKind();
- if (!FD->getType()->isDependentType() &&
- !Context.getBaseElementType(FD->getType()).isPODType(Context)) {
- Diag(FD->getLocation(), diag::err_flexible_array_has_nonpod_type)
+ // If the element type has a non-trivial destructor, we would not
+ // implicitly destroy the elements, so disallow it for now.
+ //
+ // FIXME: GCC allows this. We should probably either implicitly delete
+ // the destructor of the containing class, or just allow this.
+ QualType BaseElem = Context.getBaseElementType(FD->getType());
+ if (!BaseElem->isDependentType() && BaseElem.isDestructedType()) {
+ Diag(FD->getLocation(), diag::err_flexible_array_has_nontrivial_dtor)
<< FD->getDeclName() << FD->getType();
FD->setInvalidDecl();
EnclosingDecl->setInvalidDecl();
@@ -11972,8 +12474,9 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
SourceLocation loc = FD->getLocation();
if (getSourceManager().isInSystemHeader(loc)) {
if (!FD->hasAttr<UnavailableAttr>()) {
- FD->addAttr(new (Context) UnavailableAttr(loc, Context,
- "this system field has retaining ownership"));
+ FD->addAttr(UnavailableAttr::CreateImplicit(Context,
+ "this system field has retaining ownership",
+ loc));
}
} else {
Diag(FD->getLocation(), diag::err_arc_objc_object_in_tag)
@@ -12021,12 +12524,6 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
if (getLangOpts().CPlusPlus11)
AdjustDestructorExceptionSpec(CXXRecord,
CXXRecord->getDestructor());
-
- // The Microsoft ABI requires that we perform the destructor body
- // checks (i.e. operator delete() lookup) at every declaration, as
- // any translation unit may need to emit a deleting destructor.
- if (Context.getTargetInfo().getCXXABI().isMicrosoft())
- CheckDestructor(CXXRecord->getDestructor());
}
// Add any implicitly-declared members to this class.
@@ -12078,9 +12575,15 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
if (!Completed)
Record->completeDefinition();
- if (Record->hasAttrs())
+ if (Record->hasAttrs()) {
CheckAlignasUnderalignment(Record);
+ if (const MSInheritanceAttr *IA = Record->getAttr<MSInheritanceAttr>())
+ checkMSInheritanceAttrOnDefinition(cast<CXXRecordDecl>(Record),
+ IA->getRange(), IA->getBestCase(),
+ IA->getSemanticSpelling());
+ }
+
// Check if the structure/union declaration is a type that can have zero
// size in C. For C this is a language extension, for C++ it may cause
// compatibility problems.
@@ -12175,10 +12678,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
Diag(ClsIvar->getLocation(), diag::note_previous_definition);
continue;
}
- for (ObjCInterfaceDecl::known_extensions_iterator
- Ext = IDecl->known_extensions_begin(),
- ExtEnd = IDecl->known_extensions_end();
- Ext != ExtEnd; ++Ext) {
+ for (const auto *Ext : IDecl->known_extensions()) {
if (const ObjCIvarDecl *ClsExtIvar
= Ext->getIvarDecl(ClsFields[i]->getIdentifier())) {
Diag(ClsFields[i]->getLocation(),
@@ -12251,10 +12751,10 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
QualType EltTy;
if (Val && DiagnoseUnexpandedParameterPack(Val, UPPC_EnumeratorValue))
- Val = 0;
+ Val = nullptr;
if (Val)
- Val = DefaultLvalueConversion(Val).take();
+ Val = DefaultLvalueConversion(Val).get();
if (Val) {
if (Enum->isDependentType() || Val->isTypeDependent())
@@ -12262,7 +12762,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
else {
SourceLocation ExpLoc;
if (getLangOpts().CPlusPlus11 && Enum->isFixed() &&
- !getLangOpts().MicrosoftMode) {
+ !getLangOpts().MSVCCompat) {
// C++11 [dcl.enum]p5: If the underlying type is fixed, [...] the
// constant-expression in the enumerator-definition shall be a converted
// constant expression of the underlying type.
@@ -12271,12 +12771,12 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
CheckConvertedConstantExpression(Val, EltTy, EnumVal,
CCEK_Enumerator);
if (Converted.isInvalid())
- Val = 0;
+ Val = nullptr;
else
- Val = Converted.take();
+ Val = Converted.get();
} else if (!Val->isValueDependent() &&
!(Val = VerifyIntegerConstantExpression(Val,
- &EnumVal).take())) {
+ &EnumVal).get())) {
// C99 6.7.2.2p2: Make sure we have an integer constant expression.
} else {
if (Enum->isFixed()) {
@@ -12287,13 +12787,13 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
// we perform a non-narrowing conversion as part of converted constant
// expression checking.
if (!isRepresentableIntegerValue(Context, EnumVal, EltTy)) {
- if (getLangOpts().MicrosoftMode) {
+ if (getLangOpts().MSVCCompat) {
Diag(IdLoc, diag::ext_enumerator_too_large) << EltTy;
- Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take();
+ Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).get();
} else
Diag(IdLoc, diag::err_enumerator_too_large) << EltTy;
} else
- Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take();
+ Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).get();
} else if (getLangOpts().CPlusPlus) {
// C++11 [dcl.enum]p5:
// If the underlying type is not fixed, the type of each enumerator
@@ -12314,7 +12814,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
<< (EnumVal.isUnsigned() || EnumVal.isNonNegative());
else if (!Context.hasSameType(Val->getType(), Context.IntTy)) {
// Force the type of the expression to 'int'.
- Val = ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast).take();
+ Val = ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast).get();
}
EltTy = Val->getType();
}
@@ -12371,7 +12871,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
<< EnumVal.toString(10)
<< EltTy;
else
- Diag(IdLoc, diag::warn_enumerator_too_large)
+ Diag(IdLoc, diag::ext_enumerator_increment_too_large)
<< EnumVal.toString(10);
} else {
EltTy = T;
@@ -12433,7 +12933,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(IdLoc, PrevDecl);
// Just pretend that we didn't see the previous declaration.
- PrevDecl = 0;
+ PrevDecl = nullptr;
}
if (PrevDecl) {
@@ -12447,7 +12947,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
else
Diag(IdLoc, diag::err_redefinition) << Id;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
- return 0;
+ return nullptr;
}
}
@@ -12549,9 +13049,7 @@ struct DenseMapInfoDupKey {
static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements,
EnumDecl *Enum,
QualType EnumType) {
- if (S.Diags.getDiagnosticLevel(diag::warn_duplicate_enum_values,
- Enum->getLocation()) ==
- DiagnosticsEngine::Ignored)
+ if (S.Diags.isIgnored(diag::warn_duplicate_enum_values, Enum->getLocation()))
return;
// Avoid anonymous enums
if (!Enum->getIdentifier())
@@ -12729,7 +13227,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
// The C99 rule is modified by a gcc extension
QualType BestPromotionType;
- bool Packed = Enum->getAttr<PackedAttr>() ? true : false;
+ bool Packed = Enum->hasAttr<PackedAttr>();
// -fshort-enums is the equivalent to specifying the packed attribute on all
// enum definitions.
if (LangOpts.ShortEnums)
@@ -12769,7 +13267,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
BestWidth = Context.getTargetInfo().getLongLongWidth();
if (NumNegativeBits > BestWidth || NumPositiveBits >= BestWidth)
- Diag(Enum->getLocation(), diag::warn_enum_too_large);
+ Diag(Enum->getLocation(), diag::ext_enum_too_large);
BestType = Context.LongLongTy;
}
}
@@ -12860,7 +13358,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
ECD->setInitExpr(ImplicitCastExpr::Create(Context, NewTy,
CK_IntegralCast,
ECD->getInitExpr(),
- /*base paths*/ 0,
+ /*base paths*/ nullptr,
VK_RValue));
if (getLangOpts().CPlusPlus)
// C++ [dcl.enum]p4: Following the closing brace of an
@@ -12874,11 +13372,6 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
Enum->completeDefinition(BestType, BestPromotionType,
NumPositiveBits, NumNegativeBits);
- // If we're declaring a function, ensure this decl isn't forgotten about -
- // it needs to go into the function scope.
- if (InFunctionDeclarator)
- DeclsInPrototypeScope.push_back(Enum);
-
CheckForDuplicateEnumValues(*this, Elements, Enum, EnumType);
// Now that the enum type is defined, ensure it's not been underaligned.
@@ -12898,15 +13391,54 @@ Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr,
return New;
}
+static void checkModuleImportContext(Sema &S, Module *M,
+ SourceLocation ImportLoc,
+ DeclContext *DC) {
+ if (auto *LSD = dyn_cast<LinkageSpecDecl>(DC)) {
+ switch (LSD->getLanguage()) {
+ case LinkageSpecDecl::lang_c:
+ if (!M->IsExternC) {
+ S.Diag(ImportLoc, diag::err_module_import_in_extern_c)
+ << M->getFullModuleName();
+ S.Diag(LSD->getLocStart(), diag::note_module_import_in_extern_c);
+ return;
+ }
+ break;
+ case LinkageSpecDecl::lang_cxx:
+ break;
+ }
+ DC = LSD->getParent();
+ }
+
+ while (isa<LinkageSpecDecl>(DC))
+ DC = DC->getParent();
+ if (!isa<TranslationUnitDecl>(DC)) {
+ S.Diag(ImportLoc, diag::err_module_import_not_at_top_level)
+ << M->getFullModuleName() << DC;
+ S.Diag(cast<Decl>(DC)->getLocStart(),
+ diag::note_module_import_not_at_top_level)
+ << DC;
+ }
+}
+
DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
SourceLocation ImportLoc,
ModuleIdPath Path) {
- Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
- Module::AllVisible,
- /*IsIncludeDirective=*/false);
+ Module *Mod =
+ getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible,
+ /*IsIncludeDirective=*/false);
if (!Mod)
return true;
-
+
+ checkModuleImportContext(*this, Mod, ImportLoc, CurContext);
+
+ // FIXME: we should support importing a submodule within a different submodule
+ // of the same top-level module. Until we do, make it an error rather than
+ // silently ignoring the import.
+ if (Mod->getTopLevelModuleName() == getLangOpts().CurrentModule)
+ Diag(ImportLoc, diag::err_module_self_import)
+ << Mod->getFullModuleName() << getLangOpts().CurrentModule;
+
SmallVector<SourceLocation, 2> IdentifierLocs;
Module *ModCheck = Mod;
for (unsigned I = 0, N = Path.size(); I != N; ++I) {
@@ -12928,12 +13460,19 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
}
void Sema::ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod) {
+ checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext);
+
// FIXME: Should we synthesize an ImportDecl here?
- PP.getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, DirectiveLoc,
- /*Complain=*/true);
+ getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, DirectiveLoc,
+ /*Complain=*/true);
}
-void Sema::createImplicitModuleImport(SourceLocation Loc, Module *Mod) {
+void Sema::createImplicitModuleImportForErrorRecovery(SourceLocation Loc,
+ Module *Mod) {
+ // Bail if we're not allowed to implicitly import a module here.
+ if (isSFINAEContext() || !getLangOpts().ModulesErrorRecovery)
+ return;
+
// Create the implicit import declaration.
TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();
ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU,
@@ -12942,8 +13481,8 @@ void Sema::createImplicitModuleImport(SourceLocation Loc, Module *Mod) {
Consumer.HandleImplicitImportDecl(ImportD);
// Make the module visible.
- PP.getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, Loc,
- /*Complain=*/false);
+ getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, Loc,
+ /*Complain=*/false);
}
void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name,
@@ -12953,8 +13492,8 @@ void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name,
SourceLocation AliasNameLoc) {
Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc,
LookupOrdinaryName);
- AsmLabelAttr *Attr =
- ::new (Context) AsmLabelAttr(AliasNameLoc, Context, AliasName->getName());
+ AsmLabelAttr *Attr = ::new (Context) AsmLabelAttr(AliasNameLoc, Context,
+ AliasName->getName(), 0);
if (PrevDecl)
PrevDecl->addAttr(Attr);
@@ -12969,11 +13508,11 @@ void Sema::ActOnPragmaWeakID(IdentifierInfo* Name,
Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc, LookupOrdinaryName);
if (PrevDecl) {
- PrevDecl->addAttr(::new (Context) WeakAttr(PragmaLoc, Context));
+ PrevDecl->addAttr(WeakAttr::CreateImplicit(Context, PragmaLoc));
} else {
(void)WeakUndeclaredIdentifiers.insert(
std::pair<IdentifierInfo*,WeakInfo>
- (Name, WeakInfo((IdentifierInfo*)0, NameLoc)));
+ (Name, WeakInfo((IdentifierInfo*)nullptr, NameLoc)));
}
}
@@ -13002,5 +13541,22 @@ Decl *Sema::getObjCDeclContext() const {
AvailabilityResult Sema::getCurContextAvailability() const {
const Decl *D = cast<Decl>(getCurObjCLexicalContext());
+ // If we are within an Objective-C method, we should consult
+ // both the availability of the method as well as the
+ // enclosing class. If the class is (say) deprecated,
+ // the entire method is considered deprecated from the
+ // purpose of checking if the current context is deprecated.
+ if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ AvailabilityResult R = MD->getAvailability();
+ if (R != AR_Available)
+ return R;
+ D = MD->getClassInterface();
+ }
+ // If we are within an Objective-c @implementation, it
+ // gets the same availability context as the @interface.
+ else if (const ObjCImplementationDecl *ID =
+ dyn_cast<ObjCImplementationDecl>(D)) {
+ D = ID->getClassInterface();
+ }
return D->getAvailability();
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
index 3e58386..61683cd 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
@@ -12,13 +12,13 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "TargetAttributesSema.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/AST/Mangle.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/SourceManager.h"
@@ -32,86 +32,23 @@
using namespace clang;
using namespace sema;
-/// These constants match the enumerated choices of
-/// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type.
-enum AttributeDeclKind {
- ExpectedFunction,
- ExpectedUnion,
- ExpectedVariableOrFunction,
- ExpectedFunctionOrMethod,
- ExpectedParameter,
- ExpectedFunctionMethodOrBlock,
- ExpectedFunctionMethodOrClass,
- ExpectedFunctionMethodOrParameter,
- ExpectedClass,
- ExpectedVariable,
- ExpectedMethod,
- ExpectedVariableFunctionOrLabel,
- ExpectedFieldOrGlobalVar,
- ExpectedStruct,
- ExpectedVariableFunctionOrTag,
- ExpectedTLSVar,
- ExpectedVariableOrField,
- ExpectedVariableFieldOrTag,
- ExpectedTypeOrNamespace,
- ExpectedObjectiveCInterface,
- ExpectedMethodOrProperty,
- ExpectedStructOrUnion,
- ExpectedStructOrUnionOrClass
-};
+namespace AttributeLangSupport {
+ enum LANG {
+ C,
+ Cpp,
+ ObjC
+ };
+}
//===----------------------------------------------------------------------===//
// Helper functions
//===----------------------------------------------------------------------===//
-static const FunctionType *getFunctionType(const Decl *D,
- bool blocksToo = true) {
- QualType Ty;
- if (const ValueDecl *decl = dyn_cast<ValueDecl>(D))
- Ty = decl->getType();
- else if (const FieldDecl *decl = dyn_cast<FieldDecl>(D))
- Ty = decl->getType();
- else if (const TypedefNameDecl* decl = dyn_cast<TypedefNameDecl>(D))
- Ty = decl->getUnderlyingType();
- else
- return 0;
-
- if (Ty->isFunctionPointerType())
- Ty = Ty->getAs<PointerType>()->getPointeeType();
- else if (blocksToo && Ty->isBlockPointerType())
- Ty = Ty->getAs<BlockPointerType>()->getPointeeType();
-
- return Ty->getAs<FunctionType>();
-}
-
-// FIXME: We should provide an abstraction around a method or function
-// to provide the following bits of information.
-
-/// isFunction - Return true if the given decl has function
-/// type (function or function-typed variable).
-static bool isFunction(const Decl *D) {
- return getFunctionType(D, false) != NULL;
-}
-
/// isFunctionOrMethod - Return true if the given decl has function
/// type (function or function-typed variable) or an Objective-C
/// method.
static bool isFunctionOrMethod(const Decl *D) {
- return isFunction(D) || isa<ObjCMethodDecl>(D);
-}
-
-/// isFunctionOrMethodOrBlock - 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) {
- if (isFunctionOrMethod(D))
- return true;
- // check for block is more involved.
- if (const VarDecl *V = dyn_cast<VarDecl>(D)) {
- QualType Ty = V->getType();
- return Ty->isBlockPointerType();
- }
- return isa<BlockDecl>(D);
+ return (D->getFunctionType() != nullptr) || isa<ObjCMethodDecl>(D);
}
/// Return true if the given decl has a declarator that should have
@@ -126,42 +63,39 @@ static bool hasDeclarator(const Decl *D) {
/// information. This decl should have already passed
/// isFunctionOrMethod or isFunctionOrMethodOrBlock.
static bool hasFunctionProto(const Decl *D) {
- if (const FunctionType *FnTy = getFunctionType(D))
+ if (const FunctionType *FnTy = D->getFunctionType())
return isa<FunctionProtoType>(FnTy);
- else {
- assert(isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D));
- return true;
- }
+ return isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D);
}
-/// getFunctionOrMethodNumArgs - Return number of function or method
-/// arguments. It is an error to call this on a K&R function (use
+/// getFunctionOrMethodNumParams - Return number of function or method
+/// parameters. It is an error to call this on a K&R function (use
/// hasFunctionProto first).
-static unsigned getFunctionOrMethodNumArgs(const Decl *D) {
- if (const FunctionType *FnTy = getFunctionType(D))
- return cast<FunctionProtoType>(FnTy)->getNumArgs();
+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))
return BD->getNumParams();
return cast<ObjCMethodDecl>(D)->param_size();
}
-static QualType getFunctionOrMethodArgType(const Decl *D, unsigned Idx) {
- if (const FunctionType *FnTy = getFunctionType(D))
- return cast<FunctionProtoType>(FnTy)->getArgType(Idx);
+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))
return BD->getParamDecl(Idx)->getType();
- return cast<ObjCMethodDecl>(D)->param_begin()[Idx]->getType();
+ return cast<ObjCMethodDecl>(D)->parameters()[Idx]->getType();
}
static QualType getFunctionOrMethodResultType(const Decl *D) {
- if (const FunctionType *FnTy = getFunctionType(D))
- return cast<FunctionProtoType>(FnTy)->getResultType();
- return cast<ObjCMethodDecl>(D)->getResultType();
+ if (const FunctionType *FnTy = D->getFunctionType())
+ return cast<FunctionType>(FnTy)->getReturnType();
+ return cast<ObjCMethodDecl>(D)->getReturnType();
}
static bool isFunctionOrMethodVariadic(const Decl *D) {
- if (const FunctionType *FnTy = getFunctionType(D)) {
+ if (const FunctionType *FnTy = D->getFunctionType()) {
const FunctionProtoType *proto = cast<FunctionProtoType>(FnTy);
return proto->isVariadic();
} else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
@@ -227,30 +161,63 @@ static bool checkAttributeNumArgs(Sema &S, const AttributeList &Attr,
return true;
}
-
/// \brief Check if the attribute has at least as many args as Num. May
/// output an error.
static bool checkAttributeAtLeastNumArgs(Sema &S, const AttributeList &Attr,
unsigned Num) {
if (getNumAttributeArgs(Attr) < Num) {
- S.Diag(Attr.getLoc(), diag::err_attribute_too_few_arguments) << Num;
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_few_arguments)
+ << Attr.getName() << Num;
return false;
}
return true;
}
-/// \brief Check if IdxExpr is a valid argument index for a function or
+/// \brief If Expr is a valid integer constant, get the value of the integer
+/// expression and return success or failure. May output an error.
+static bool checkUInt32Argument(Sema &S, const AttributeList &Attr,
+ 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(Attr.getLoc(), diag::err_attribute_argument_n_type)
+ << Attr.getName() << Idx << AANT_ArgumentIntegerConstant
+ << Expr->getSourceRange();
+ else
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
+ << Attr.getName() << AANT_ArgumentIntegerConstant
+ << Expr->getSourceRange();
+ return false;
+ }
+ Val = (uint32_t)I.getZExtValue();
+ return true;
+}
+
+/// \brief Diagnose mutually exclusive attributes when present on a given
+/// declaration. Returns true if diagnosed.
+template <typename AttrTy>
+static bool checkAttrMutualExclusion(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (AttrTy *A = D->getAttr<AttrTy>()) {
+ S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
+ << Attr.getName() << A;
+ return true;
+ }
+ return false;
+}
+
+/// \brief 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.
-static bool checkFunctionOrMethodArgumentIndex(Sema &S, const Decl *D,
- StringRef AttrName,
- SourceLocation AttrLoc,
- unsigned AttrArgNum,
- const Expr *IdxExpr,
- uint64_t &Idx)
-{
+static bool checkFunctionOrMethodParameterIndex(Sema &S, const Decl *D,
+ const AttributeList &Attr,
+ unsigned AttrArgNum,
+ const Expr *IdxExpr,
+ uint64_t &Idx) {
assert(isFunctionOrMethod(D));
// In C++ the implicit 'this' function parameter also counts.
@@ -258,30 +225,30 @@ static bool checkFunctionOrMethodArgumentIndex(Sema &S, const Decl *D,
bool HP = hasFunctionProto(D);
bool HasImplicitThisParam = isInstanceMethod(D);
bool IV = HP && isFunctionOrMethodVariadic(D);
- unsigned NumArgs = (HP ? getFunctionOrMethodNumArgs(D) : 0) +
- HasImplicitThisParam;
+ unsigned NumParams =
+ (HP ? getFunctionOrMethodNumParams(D) : 0) + HasImplicitThisParam;
llvm::APSInt IdxInt;
if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
!IdxExpr->isIntegerConstantExpr(IdxInt, S.Context)) {
- std::string Name = std::string("'") + AttrName.str() + std::string("'");
- S.Diag(AttrLoc, diag::err_attribute_argument_n_type) << Name.c_str()
- << AttrArgNum << AANT_ArgumentIntegerConstant << IdxExpr->getSourceRange();
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
+ << Attr.getName() << AttrArgNum << AANT_ArgumentIntegerConstant
+ << IdxExpr->getSourceRange();
return false;
}
Idx = IdxInt.getLimitedValue();
- if (Idx < 1 || (!IV && Idx > NumArgs)) {
- S.Diag(AttrLoc, diag::err_attribute_argument_out_of_bounds)
- << AttrName << AttrArgNum << IdxExpr->getSourceRange();
+ if (Idx < 1 || (!IV && Idx > NumParams)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
+ << Attr.getName() << AttrArgNum << IdxExpr->getSourceRange();
return false;
}
Idx--; // Convert to zero-based.
if (HasImplicitThisParam) {
if (Idx == 0) {
- S.Diag(AttrLoc,
+ S.Diag(Attr.getLoc(),
diag::err_attribute_invalid_implicit_this_argument)
- << AttrName << IdxExpr->getSourceRange();
+ << Attr.getName() << IdxExpr->getSourceRange();
return false;
}
--Idx;
@@ -326,17 +293,13 @@ bool Sema::checkStringLiteralArgumentAttr(const AttributeList &Attr,
return true;
}
-///
-/// \brief Check if passed in Decl is a field or potentially shared global var
-/// \return true if the Decl is a field or potentially shared global variable
-///
-static bool mayBeSharedVariable(const Decl *D) {
- if (isa<FieldDecl>(D))
- return true;
- if (const VarDecl *vd = dyn_cast<VarDecl>(D))
- return vd->hasGlobalStorage() && !vd->getTLSKind();
-
- return false;
+/// \brief 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()));
}
/// \brief Check if the passed-in expression is of type int or bool.
@@ -367,28 +330,24 @@ static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) {
/// \return true if the Decl is a pointer type; false otherwise
static bool threadSafetyCheckIsPointer(Sema &S, const Decl *D,
const AttributeList &Attr) {
- if (const ValueDecl *vd = dyn_cast<ValueDecl>(D)) {
- QualType QT = vd->getType();
- if (QT->isAnyPointerType())
- return true;
-
- if (const RecordType *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.)
- if (RT->isIncompleteType())
- return true;
+ const ValueDecl *vd = cast<ValueDecl>(D);
+ QualType QT = vd->getType();
+ if (QT->isAnyPointerType())
+ return true;
- if (threadSafetyCheckIsSmartPointer(S, RT))
- return true;
- }
+ if (const RecordType *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.)
+ if (RT->isIncompleteType())
+ return true;
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_pointer)
- << Attr.getName()->getName() << QT;
- } else {
- S.Diag(Attr.getLoc(), diag::err_attribute_can_be_applied_only_to_value_decl)
- << Attr.getName();
+ if (threadSafetyCheckIsSmartPointer(S, RT))
+ return true;
}
+
+ S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_pointer)
+ << Attr.getName() << QT;
return false;
}
@@ -402,68 +361,101 @@ static const RecordType *getRecordType(QualType QT) {
if (const PointerType *PT = QT->getAs<PointerType>())
return PT->getPointeeType()->getAs<RecordType>();
- return 0;
-}
-
-
-static bool checkBaseClassIsLockableCallback(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path, void *Unused) {
- const RecordType *RT = Specifier->getType()->getAs<RecordType>();
- if (RT->getDecl()->getAttr<LockableAttr>())
- return true;
- return false;
+ return nullptr;
}
-
-/// \brief Thread Safety Analysis: Checks that the passed in RecordType
-/// resolves to a lockable object.
-static void checkForLockableRecord(Sema &S, Decl *D, const AttributeList &Attr,
- QualType Ty) {
+static bool checkRecordTypeForCapability(Sema &S, QualType Ty) {
const RecordType *RT = getRecordType(Ty);
- // Warn if could not get record type for this argument.
- if (!RT) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_argument_not_class)
- << Attr.getName() << Ty.getAsString();
- return;
- }
+ if (!RT)
+ return false;
- // Don't check for lockable if the class hasn't been defined yet.
+ // Don't check for the capability if the class hasn't been defined yet.
if (RT->isIncompleteType())
- return;
+ return true;
- // Allow smart pointers to be used as lockable objects.
+ // Allow smart pointers to be used as capability objects.
// FIXME -- Check the type that the smart pointer points to.
if (threadSafetyCheckIsSmartPointer(S, RT))
- return;
+ return true;
- // Check if the type is lockable.
+ // Check if the record itself has a capability.
RecordDecl *RD = RT->getDecl();
- if (RD->getAttr<LockableAttr>())
- return;
+ if (RD->hasAttr<CapabilityAttr>())
+ return true;
- // Else check if any base classes are lockable.
+ // Else check if any base classes have a capability.
if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
CXXBasePaths BPaths(false, false);
- if (CRD->lookupInBases(checkBaseClassIsLockableCallback, 0, BPaths))
- return;
+ if (CRD->lookupInBases([](const CXXBaseSpecifier *BS, CXXBasePath &P,
+ void *) {
+ return BS->getType()->getAs<RecordType>()
+ ->getDecl()->hasAttr<CapabilityAttr>();
+ }, nullptr, BPaths))
+ return true;
+ }
+ return false;
+}
+
+static bool checkTypedefTypeForCapability(QualType Ty) {
+ const auto *TD = Ty->getAs<TypedefType>();
+ if (!TD)
+ return false;
+
+ TypedefNameDecl *TN = TD->getDecl();
+ if (!TN)
+ return false;
+
+ return TN->hasAttr<CapabilityAttr>();
+}
+
+static bool typeHasCapability(Sema &S, QualType Ty) {
+ if (checkTypedefTypeForCapability(Ty))
+ return true;
+
+ if (checkRecordTypeForCapability(S, Ty))
+ return true;
+
+ return false;
+}
+
+static bool isCapabilityExpr(Sema &S, const Expr *Ex) {
+ // Capability expressions are simple expressions involving the boolean logic
+ // operators &&, || or !, a simple DeclRefExpr, CastExpr or a ParenExpr. Once
+ // a DeclRefExpr is found, its type should be checked to determine whether it
+ // is a capability or not.
+
+ if (const auto *E = dyn_cast<DeclRefExpr>(Ex))
+ return typeHasCapability(S, E->getType());
+ else if (const auto *E = dyn_cast<CastExpr>(Ex))
+ return isCapabilityExpr(S, E->getSubExpr());
+ else if (const auto *E = dyn_cast<ParenExpr>(Ex))
+ return isCapabilityExpr(S, E->getSubExpr());
+ else if (const auto *E = dyn_cast<UnaryOperator>(Ex)) {
+ if (E->getOpcode() == UO_LNot)
+ return isCapabilityExpr(S, E->getSubExpr());
+ return false;
+ } else if (const auto *E = dyn_cast<BinaryOperator>(Ex)) {
+ if (E->getOpcode() == BO_LAnd || E->getOpcode() == BO_LOr)
+ return isCapabilityExpr(S, E->getLHS()) &&
+ isCapabilityExpr(S, E->getRHS());
+ return false;
}
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_argument_not_lockable)
- << Attr.getName() << Ty.getAsString();
+ return false;
}
-/// \brief Thread Safety Analysis: Checks that all attribute arguments, starting
-/// from Sidx, resolve to a lockable object.
+/// \brief 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 checkAttrArgsAreLockableObjs(Sema &S, Decl *D,
- const AttributeList &Attr,
- SmallVectorImpl<Expr*> &Args,
- int Sidx = 0,
- bool ParamIdxOk = false) {
- for(unsigned Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) {
+static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D,
+ const AttributeList &Attr,
+ SmallVectorImpl<Expr *> &Args,
+ int Sidx = 0,
+ bool ParamIdxOk = false) {
+ for (unsigned Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) {
Expr *ArgExp = Attr.getArgAsExpr(Idx);
if (ArgExp->isTypeDependent()) {
@@ -499,7 +491,7 @@ static void checkAttrArgsAreLockableObjs(Sema &S, Decl *D,
if (DRE->getDecl()->isCXXInstanceMember())
ArgTy = DRE->getDecl()->getType();
- // First see if we can just cast to record type, or point to record type.
+ // First see if we can just cast to record type, or pointer to record type.
const RecordType *RT = getRecordType(ArgTy);
// Now check if we index into a record type function param.
@@ -520,7 +512,13 @@ static void checkAttrArgsAreLockableObjs(Sema &S, Decl *D,
}
}
- checkForLockableRecord(S, D, Attr, ArgTy);
+ // If the type does not have a capability, see if the components of the
+ // expression have capabilities. This allows for writing C code where the
+ // 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;
Args.push_back(ArgExp);
}
@@ -534,38 +532,8 @@ static void checkAttrArgsAreLockableObjs(Sema &S, Decl *D,
// least add some helper functions to check most argument patterns (#
// and types of args).
-enum ThreadAttributeDeclKind {
- ThreadExpectedFieldOrGlobalVar,
- ThreadExpectedFunctionOrMethod,
- ThreadExpectedClassOrStruct
-};
-
-static bool checkGuardedVarAttrCommon(Sema &S, Decl *D,
- const AttributeList &Attr) {
- // D must be either a member field or global (potentially shared) variable.
- if (!mayBeSharedVariable(D)) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)
- << Attr.getName() << ThreadExpectedFieldOrGlobalVar;
- return false;
- }
-
- return true;
-}
-
-static void handleGuardedVarAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkGuardedVarAttrCommon(S, D, Attr))
- return;
-
- D->addAttr(::new (S.Context)
- GuardedVarAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
static void handlePtGuardedVarAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- if (!checkGuardedVarAttrCommon(S, D, Attr))
- return;
-
if (!threadSafetyCheckIsPointer(S, D, Attr))
return;
@@ -577,16 +545,9 @@ static void handlePtGuardedVarAttr(Sema &S, Decl *D,
static bool checkGuardedByAttrCommon(Sema &S, Decl *D,
const AttributeList &Attr,
Expr* &Arg) {
- // D must be either a member field or global (potentially shared) variable.
- if (!mayBeSharedVariable(D)) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)
- << Attr.getName() << ThreadExpectedFieldOrGlobalVar;
- return false;
- }
-
SmallVector<Expr*, 1> Args;
// check that all arguments are lockable objects
- checkAttrArgsAreLockableObjs(S, D, Attr, Args);
+ checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
unsigned Size = Args.size();
if (Size != 1)
return false;
@@ -597,16 +558,17 @@ static bool checkGuardedByAttrCommon(Sema &S, Decl *D,
}
static void handleGuardedByAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- Expr *Arg = 0;
+ Expr *Arg = nullptr;
if (!checkGuardedByAttrCommon(S, D, Attr, Arg))
return;
- D->addAttr(::new (S.Context) GuardedByAttr(Attr.getRange(), S.Context, Arg));
+ D->addAttr(::new (S.Context) GuardedByAttr(Attr.getRange(), S.Context, Arg,
+ Attr.getAttributeSpellingListIndex()));
}
static void handlePtGuardedByAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- Expr *Arg = 0;
+ Expr *Arg = nullptr;
if (!checkGuardedByAttrCommon(S, D, Attr, Arg))
return;
@@ -614,85 +576,8 @@ static void handlePtGuardedByAttr(Sema &S, Decl *D,
return;
D->addAttr(::new (S.Context) PtGuardedByAttr(Attr.getRange(),
- S.Context, Arg));
-}
-
-static bool checkLockableAttrCommon(Sema &S, Decl *D,
- const AttributeList &Attr) {
- // FIXME: Lockable structs for C code.
- if (!isa<RecordDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)
- << Attr.getName() << ThreadExpectedClassOrStruct;
- return false;
- }
-
- return true;
-}
-
-static void handleLockableAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkLockableAttrCommon(S, D, Attr))
- return;
-
- D->addAttr(::new (S.Context) LockableAttr(Attr.getRange(), S.Context));
-}
-
-static void handleScopedLockableAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!checkLockableAttrCommon(S, D, Attr))
- return;
-
- D->addAttr(::new (S.Context)
- ScopedLockableAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleNoThreadSafetyAnalysis(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)
- << Attr.getName() << ThreadExpectedFunctionOrMethod;
- return;
- }
-
- D->addAttr(::new (S.Context) NoThreadSafetyAnalysisAttr(Attr.getRange(),
- S.Context));
-}
-
-static void handleNoSanitizeAddressAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionOrMethod;
- return;
- }
-
- D->addAttr(::new (S.Context)
- NoSanitizeAddressAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleNoSanitizeMemory(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionOrMethod;
- return;
- }
-
- D->addAttr(::new (S.Context) NoSanitizeMemoryAttr(Attr.getRange(),
- S.Context));
-}
-
-static void handleNoSanitizeThread(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionOrMethod;
- return;
- }
-
- D->addAttr(::new (S.Context) NoSanitizeThreadAttr(Attr.getRange(),
- S.Context));
+ S.Context, Arg,
+ Attr.getAttributeSpellingListIndex()));
}
static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D,
@@ -701,19 +586,11 @@ static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D,
if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
return false;
- // D must be either a member field or global (potentially shared) variable.
- ValueDecl *VD = dyn_cast<ValueDecl>(D);
- if (!VD || !mayBeSharedVariable(D)) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)
- << Attr.getName() << ThreadExpectedFieldOrGlobalVar;
- return false;
- }
-
// Check that this attribute only applies to lockable types.
- QualType QT = VD->getType();
+ QualType QT = cast<ValueDecl>(D)->getType();
if (!QT->isDependentType()) {
const RecordType *RT = getRecordType(QT);
- if (!RT || !RT->getDecl()->getAttr<LockableAttr>()) {
+ if (!RT || !RT->getDecl()->hasAttr<CapabilityAttr>()) {
S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_lockable)
<< Attr.getName();
return false;
@@ -721,7 +598,7 @@ static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D,
}
// Check that all arguments are lockable objects.
- checkAttrArgsAreLockableObjs(S, D, Attr, Args);
+ checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
if (Args.empty())
return false;
@@ -758,47 +635,12 @@ static bool checkLockFunAttrCommon(Sema &S, Decl *D,
const AttributeList &Attr,
SmallVectorImpl<Expr *> &Args) {
// zero or more arguments ok
-
- // check that the attribute is applied to a function
- if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)
- << Attr.getName() << ThreadExpectedFunctionOrMethod;
- return false;
- }
-
// check that all arguments are lockable objects
- checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true);
+ checkAttrArgsAreCapabilityObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true);
return true;
}
-static void handleSharedLockFunctionAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- SmallVector<Expr*, 1> Args;
- if (!checkLockFunAttrCommon(S, D, Attr, Args))
- return;
-
- unsigned Size = Args.size();
- Expr **StartArg = Size == 0 ? 0 : &Args[0];
- D->addAttr(::new (S.Context)
- SharedLockFunctionAttr(Attr.getRange(), S.Context, StartArg, Size,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleExclusiveLockFunctionAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- SmallVector<Expr*, 1> Args;
- if (!checkLockFunAttrCommon(S, D, Attr, Args))
- return;
-
- unsigned Size = Args.size();
- Expr **StartArg = Size == 0 ? 0 : &Args[0];
- D->addAttr(::new (S.Context)
- ExclusiveLockFunctionAttr(Attr.getRange(), S.Context,
- StartArg, Size,
- Attr.getAttributeSpellingListIndex()));
-}
-
static void handleAssertSharedLockAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
SmallVector<Expr*, 1> Args;
@@ -806,7 +648,7 @@ static void handleAssertSharedLockAttr(Sema &S, Decl *D,
return;
unsigned Size = Args.size();
- Expr **StartArg = Size == 0 ? 0 : &Args[0];
+ Expr **StartArg = Size == 0 ? nullptr : &Args[0];
D->addAttr(::new (S.Context)
AssertSharedLockAttr(Attr.getRange(), S.Context, StartArg, Size,
Attr.getAttributeSpellingListIndex()));
@@ -819,7 +661,7 @@ static void handleAssertExclusiveLockAttr(Sema &S, Decl *D,
return;
unsigned Size = Args.size();
- Expr **StartArg = Size == 0 ? 0 : &Args[0];
+ Expr **StartArg = Size == 0 ? nullptr : &Args[0];
D->addAttr(::new (S.Context)
AssertExclusiveLockAttr(Attr.getRange(), S.Context,
StartArg, Size,
@@ -833,12 +675,6 @@ static bool checkTryLockFunAttrCommon(Sema &S, Decl *D,
if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
return false;
- if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)
- << Attr.getName() << ThreadExpectedFunctionOrMethod;
- return false;
- }
-
if (!isIntOrBool(Attr.getArgAsExpr(0))) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
<< Attr.getName() << 1 << AANT_ArgumentIntOrBool;
@@ -846,7 +682,7 @@ static bool checkTryLockFunAttrCommon(Sema &S, Decl *D,
}
// check that all arguments are lockable objects
- checkAttrArgsAreLockableObjs(S, D, Attr, Args, 1);
+ checkAttrArgsAreCapabilityObjs(S, D, Attr, Args, 1);
return true;
}
@@ -877,84 +713,11 @@ static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D,
Attr.getAttributeSpellingListIndex()));
}
-static bool checkLocksRequiredCommon(Sema &S, Decl *D,
- const AttributeList &Attr,
- SmallVectorImpl<Expr *> &Args) {
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
- return false;
-
- if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)
- << Attr.getName() << ThreadExpectedFunctionOrMethod;
- return false;
- }
-
- // check that all arguments are lockable objects
- checkAttrArgsAreLockableObjs(S, D, Attr, Args);
- if (Args.empty())
- return false;
-
- return true;
-}
-
-static void handleExclusiveLocksRequiredAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- SmallVector<Expr*, 1> Args;
- if (!checkLocksRequiredCommon(S, D, Attr, Args))
- return;
-
- Expr **StartArg = &Args[0];
- D->addAttr(::new (S.Context)
- ExclusiveLocksRequiredAttr(Attr.getRange(), S.Context,
- StartArg, Args.size(),
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleSharedLocksRequiredAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- SmallVector<Expr*, 1> Args;
- if (!checkLocksRequiredCommon(S, D, Attr, Args))
- return;
-
- Expr **StartArg = &Args[0];
- D->addAttr(::new (S.Context)
- SharedLocksRequiredAttr(Attr.getRange(), S.Context,
- StartArg, Args.size(),
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleUnlockFunAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- // zero or more arguments ok
-
- if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)
- << Attr.getName() << ThreadExpectedFunctionOrMethod;
- return;
- }
-
- // check that all arguments are lockable objects
- SmallVector<Expr*, 1> Args;
- checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true);
- unsigned Size = Args.size();
- Expr **StartArg = Size == 0 ? 0 : &Args[0];
-
- D->addAttr(::new (S.Context)
- UnlockFunctionAttr(Attr.getRange(), S.Context, StartArg, Size,
- Attr.getAttributeSpellingListIndex()));
-}
-
static void handleLockReturnedAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)
- << Attr.getName() << ThreadExpectedFunctionOrMethod;
- return;
- }
-
// check that the argument is lockable object
SmallVector<Expr*, 1> Args;
- checkAttrArgsAreLockableObjs(S, D, Attr, Args);
+ checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
unsigned Size = Args.size();
if (Size == 0)
return;
@@ -969,15 +732,9 @@ static void handleLocksExcludedAttr(Sema &S, Decl *D,
if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
return;
- if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)
- << Attr.getName() << ThreadExpectedFunctionOrMethod;
- return;
- }
-
// check that all arguments are lockable objects
SmallVector<Expr*, 1> Args;
- checkAttrArgsAreLockableObjs(S, D, Attr, Args);
+ checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
unsigned Size = Args.size();
if (Size == 0)
return;
@@ -988,6 +745,34 @@ static void handleLocksExcludedAttr(Sema &S, Decl *D,
Attr.getAttributeSpellingListIndex()));
}
+static void handleEnableIfAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ Expr *Cond = Attr.getArgAsExpr(0);
+ if (!Cond->isTypeDependent()) {
+ ExprResult Converted = S.PerformContextuallyConvertToBool(Cond);
+ if (Converted.isInvalid())
+ return;
+ Cond = Converted.get();
+ }
+
+ StringRef Msg;
+ if (!S.checkStringLiteralArgumentAttr(Attr, 1, Msg))
+ return;
+
+ SmallVector<PartialDiagnosticAt, 8> Diags;
+ if (!Cond->isValueDependent() &&
+ !Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(D),
+ Diags)) {
+ S.Diag(Attr.getLoc(), diag::err_enable_if_never_constant_expr);
+ for (int I = 0, N = Diags.size(); I != N; ++I)
+ S.Diag(Diags[I].first, Diags[I].second);
+ return;
+ }
+
+ D->addAttr(::new (S.Context)
+ EnableIfAttr(Attr.getRange(), S.Context, Cond, Msg,
+ Attr.getAttributeSpellingListIndex()));
+}
+
static void handleConsumableAttr(Sema &S, Decl *D, const AttributeList &Attr) {
ConsumableAttr::ConsumedState DefaultState;
@@ -1004,18 +789,13 @@ static void handleConsumableAttr(Sema &S, Decl *D, const AttributeList &Attr) {
<< Attr.getName() << AANT_ArgumentIdentifier;
return;
}
-
- if (!isa<CXXRecordDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
- Attr.getName() << ExpectedClass;
- return;
- }
D->addAttr(::new (S.Context)
ConsumableAttr(Attr.getRange(), S.Context, DefaultState,
Attr.getAttributeSpellingListIndex()));
}
+
static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD,
const AttributeList &Attr) {
ASTContext &CurrContext = S.getASTContext();
@@ -1038,12 +818,6 @@ static void handleCallableWhenAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
return;
-
- if (!isa<CXXMethodDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
- Attr.getName() << ExpectedMethod;
- return;
- }
if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
return;
@@ -1076,13 +850,7 @@ static void handleCallableWhenAttr(Sema &S, Decl *D,
static void handleParamTypestateAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!checkAttributeNumArgs(S, Attr, 1)) return;
-
- if (!isa<ParmVarDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
- Attr.getName() << ExpectedParameter;
- return;
- }
-
+
ParamTypestateAttr::ConsumedState ParamState;
if (Attr.isArgIdent(0)) {
@@ -1123,12 +891,6 @@ static void handleReturnTypestateAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!checkAttributeNumArgs(S, Attr, 1)) return;
- if (!(isa<FunctionDecl>(D) || isa<ParmVarDecl>(D))) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
- Attr.getName() << ExpectedFunctionMethodOrParameter;
- return;
- }
-
ReturnTypestateAttr::ConsumedState ReturnState;
if (Attr.isArgIdent(0)) {
@@ -1179,12 +941,6 @@ static void handleReturnTypestateAttr(Sema &S, Decl *D,
static void handleSetTypestateAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (!checkAttributeNumArgs(S, Attr, 1))
return;
-
- if (!isa<CXXMethodDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
- Attr.getName() << ExpectedMethod;
- return;
- }
if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
return;
@@ -1214,12 +970,6 @@ static void handleTestTypestateAttr(Sema &S, Decl *D,
if (!checkAttributeNumArgs(S, Attr, 1))
return;
- if (!isa<CXXMethodDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
- Attr.getName() << ExpectedMethod;
- return;
- }
-
if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
return;
@@ -1245,21 +995,14 @@ static void handleTestTypestateAttr(Sema &S, Decl *D,
static void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D,
const AttributeList &Attr) {
- TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
- if (TD == 0) {
- // __attribute__((ext_vector_type(N))) can only be applied to typedefs
- // and type-ids.
- S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef);
- return;
- }
-
// Remember this typedef decl, we will need it later for diagnostics.
- S.ExtVectorDecls.push_back(TD);
+ 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));
+ TD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
// If the alignment is less than or equal to 8 bits, the packed attribute
// has no effect.
@@ -1276,28 +1019,6 @@ static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
}
-static void handleMsStructAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (RecordDecl *RD = dyn_cast<RecordDecl>(D))
- RD->addAttr(::new (S.Context)
- MsStructAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- else
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
-}
-
-static void handleIBAction(Sema &S, Decl *D, const AttributeList &Attr) {
- // The IBAction attributes only apply to instance methods.
- if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
- if (MD->isInstanceMethod()) {
- D->addAttr(::new (S.Context)
- IBActionAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- return;
- }
-
- S.Diag(Attr.getLoc(), diag::warn_attribute_ibaction) << Attr.getName();
-}
-
static bool checkIBOutletCommon(Sema &S, Decl *D, const AttributeList &Attr) {
// The IBOutlet/IBOutletCollection attributes only apply to instance
// variables or properties of Objective-C classes. The outlet must also
@@ -1359,7 +1080,7 @@ static void handleIBOutletCollection(Sema &S, Decl *D,
}
}
- TypeSourceInfo *QTLoc = 0;
+ TypeSourceInfo *QTLoc = nullptr;
QualType QT = S.GetTypeFromParser(PT, &QTLoc);
if (!QTLoc)
QTLoc = S.Context.getTrivialTypeSourceInfo(QT, Attr.getLoc());
@@ -1384,9 +1105,8 @@ static void possibleTransparentUnionPointerType(QualType &T) {
if (const RecordType *UT = T->getAsUnionType())
if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) {
RecordDecl *UD = UT->getDecl();
- for (RecordDecl::field_iterator it = UD->field_begin(),
- itend = UD->field_end(); it != itend; ++it) {
- QualType QT = it->getType();
+ for (const auto *I : UD->fields()) {
+ QualType QT = I->getType();
if (QT->isAnyPointerType() || QT->isBlockPointerType()) {
T = QT;
return;
@@ -1395,74 +1115,34 @@ static void possibleTransparentUnionPointerType(QualType &T) {
}
}
-static void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!isFunctionOrMethod(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionOrMethod;
- return;
- }
+static bool attrNonNullArgCheck(Sema &S, QualType T, const AttributeList &Attr,
+ SourceRange R, bool isReturnValue = false) {
+ T = T.getNonReferenceType();
+ possibleTransparentUnionPointerType(T);
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
- return;
-
- SmallVector<unsigned, 8> SizeArgs;
- for (unsigned i = 0; i < Attr.getNumArgs(); ++i) {
- Expr *Ex = Attr.getArgAsExpr(i);
- uint64_t Idx;
- if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(),
- Attr.getLoc(), i + 1, Ex, Idx))
- return;
-
- // check if the function argument is of an integer type
- QualType T = getFunctionOrMethodArgType(D, Idx).getNonReferenceType();
- if (!T->isIntegerType()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
- << Attr.getName() << AANT_ArgumentIntegerConstant
- << Ex->getSourceRange();
- return;
- }
- SizeArgs.push_back(Idx);
- }
-
- // check if the function returns a pointer
- if (!getFunctionType(D)->getResultType()->isAnyPointerType()) {
- S.Diag(Attr.getLoc(), diag::warn_ns_attribute_wrong_return_type)
- << Attr.getName() << 0 /*function*/<< 1 /*pointer*/ << D->getSourceRange();
+ if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
+ S.Diag(Attr.getLoc(),
+ isReturnValue ? diag::warn_attribute_return_pointers_only
+ : diag::warn_attribute_pointers_only)
+ << Attr.getName() << R;
+ return false;
}
-
- D->addAttr(::new (S.Context)
- AllocSizeAttr(Attr.getRange(), S.Context,
- SizeArgs.data(), SizeArgs.size(),
- Attr.getAttributeSpellingListIndex()));
+ return true;
}
static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // GCC ignores the nonnull attribute on K&R style function prototypes, so we
- // ignore it as well
- if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
- return;
- }
-
SmallVector<unsigned, 8> NonNullArgs;
for (unsigned i = 0; i < Attr.getNumArgs(); ++i) {
Expr *Ex = Attr.getArgAsExpr(i);
uint64_t Idx;
- if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(),
- Attr.getLoc(), i + 1, Ex, Idx))
+ if (!checkFunctionOrMethodParameterIndex(S, D, Attr, i + 1, Ex, Idx))
return;
// Is the function argument a pointer type?
- QualType T = getFunctionOrMethodArgType(D, Idx).getNonReferenceType();
- possibleTransparentUnionPointerType(T);
-
- if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
- // FIXME: Should also highlight argument in decl.
- S.Diag(Attr.getLoc(), diag::warn_nonnull_pointers_only)
- << "nonnull" << Ex->getSourceRange();
+ // FIXME: Should also highlight argument in decl in the diagnostic.
+ if (!attrNonNullArgCheck(S, getFunctionOrMethodParamType(D, Idx), Attr,
+ Ex->getSourceRange()))
continue;
- }
NonNullArgs.push_back(Idx);
}
@@ -1470,8 +1150,8 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// If no arguments were specified to __attribute__((nonnull)) then all pointer
// arguments have a nonnull attribute.
if (NonNullArgs.empty()) {
- for (unsigned i = 0, e = getFunctionOrMethodNumArgs(D); i != e; ++i) {
- QualType T = getFunctionOrMethodArgType(D, i).getNonReferenceType();
+ for (unsigned i = 0, e = getFunctionOrMethodNumParams(D); i != e; ++i) {
+ QualType T = getFunctionOrMethodParamType(D, i).getNonReferenceType();
possibleTransparentUnionPointerType(T);
if (T->isAnyPointerType() || T->isBlockPointerType())
NonNullArgs.push_back(i);
@@ -1495,13 +1175,37 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
Attr.getAttributeSpellingListIndex()));
}
-static const char *ownershipKindToDiagName(OwnershipAttr::OwnershipKind K) {
- switch (K) {
- case OwnershipAttr::Holds: return "'ownership_holds'";
- case OwnershipAttr::Takes: return "'ownership_takes'";
- case OwnershipAttr::Returns: return "'ownership_returns'";
+static void handleNonNullAttrParameter(Sema &S, ParmVarDecl *D,
+ const AttributeList &Attr) {
+ if (Attr.getNumArgs() > 0) {
+ if (D->getFunctionType()) {
+ handleNonNullAttr(S, D, Attr);
+ } else {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_parm_no_args)
+ << D->getSourceRange();
+ }
+ return;
}
- llvm_unreachable("unknown ownership");
+
+ // Is the argument a pointer type?
+ if (!attrNonNullArgCheck(S, D->getType(), Attr, D->getSourceRange()))
+ return;
+
+ D->addAttr(::new (S.Context)
+ NonNullAttr(Attr.getRange(), S.Context, nullptr, 0,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleReturnsNonNullAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ QualType ResultType = getFunctionOrMethodResultType(D);
+ if (!attrNonNullArgCheck(S, ResultType, Attr, Attr.getRange(),
+ /* isReturnValue */ true))
+ return;
+
+ D->addAttr(::new (S.Context)
+ ReturnsNonNullAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
@@ -1519,58 +1223,49 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
return;
}
- // Figure out our Kind, and check arguments while we're at it.
- OwnershipAttr::OwnershipKind K;
- switch (AL.getKind()) {
- case AttributeList::AT_ownership_takes:
- K = OwnershipAttr::Takes;
- if (AL.getNumArgs() < 2) {
- S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) << 2;
- return;
- }
- break;
- case AttributeList::AT_ownership_holds:
- K = OwnershipAttr::Holds;
+ // Figure out our Kind.
+ OwnershipAttr::OwnershipKind K =
+ OwnershipAttr(AL.getLoc(), S.Context, nullptr, nullptr, 0,
+ AL.getAttributeSpellingListIndex()).getOwnKind();
+
+ // Check arguments.
+ switch (K) {
+ case OwnershipAttr::Takes:
+ case OwnershipAttr::Holds:
if (AL.getNumArgs() < 2) {
- S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) << 2;
+ S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments)
+ << AL.getName() << 2;
return;
}
break;
- case AttributeList::AT_ownership_returns:
- K = OwnershipAttr::Returns;
-
+ case OwnershipAttr::Returns:
if (AL.getNumArgs() > 2) {
- S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << 1;
+ S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments)
+ << AL.getName() << 1;
return;
}
break;
- default:
- // This should never happen given how we are called.
- llvm_unreachable("Unknown ownership attribute");
}
- if (!isFunction(D) || !hasFunctionProto(D)) {
- S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
- << AL.getName() << ExpectedFunction;
- return;
- }
-
- StringRef Module = AL.getArgAsIdent(0)->Ident->getName();
+ IdentifierInfo *Module = AL.getArgAsIdent(0)->Ident;
// Normalize the argument, __foo__ becomes foo.
- if (Module.startswith("__") && Module.endswith("__"))
- Module = Module.substr(2, Module.size() - 4);
+ StringRef ModuleName = Module->getName();
+ if (ModuleName.startswith("__") && ModuleName.endswith("__") &&
+ ModuleName.size() > 4) {
+ ModuleName = ModuleName.drop_front(2).drop_back(2);
+ Module = &S.PP.getIdentifierTable().get(ModuleName);
+ }
SmallVector<unsigned, 8> OwnershipArgs;
for (unsigned i = 1; i < AL.getNumArgs(); ++i) {
Expr *Ex = AL.getArgAsExpr(i);
uint64_t Idx;
- if (!checkFunctionOrMethodArgumentIndex(S, D, AL.getName()->getName(),
- AL.getLoc(), i, Ex, Idx))
+ if (!checkFunctionOrMethodParameterIndex(S, D, AL, i, Ex, Idx))
return;
// Is the function argument a pointer type?
- QualType T = getFunctionOrMethodArgType(D, Idx);
+ QualType T = getFunctionOrMethodParamType(D, Idx);
int Err = -1; // No error
switch (K) {
case OwnershipAttr::Takes:
@@ -1590,13 +1285,13 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
}
// Check we don't have a conflict with another ownership attribute.
- for (specific_attr_iterator<OwnershipAttr>
- i = D->specific_attr_begin<OwnershipAttr>(),
- e = D->specific_attr_end<OwnershipAttr>(); i != e; ++i) {
- if ((*i)->getOwnKind() != K && (*i)->args_end() !=
- std::find((*i)->args_begin(), (*i)->args_end(), Idx)) {
+ for (const auto *I : D->specific_attrs<OwnershipAttr>()) {
+ // FIXME: A returns attribute should conflict with any returns attribute
+ // with a different index too.
+ if (I->getOwnKind() != K && I->args_end() !=
+ std::find(I->args_begin(), I->args_end(), Idx)) {
S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
- << AL.getName() << ownershipKindToDiagName((*i)->getOwnKind());
+ << AL.getName() << I;
return;
}
}
@@ -1608,7 +1303,7 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
llvm::array_pod_sort(start, start + size);
D->addAttr(::new (S.Context)
- OwnershipAttr(AL.getLoc(), S.Context, K, Module, start, size,
+ OwnershipAttr(AL.getLoc(), S.Context, Module, start, size,
AL.getAttributeSpellingListIndex()));
}
@@ -1620,12 +1315,6 @@ static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedVariableOrFunction;
- return;
- }
-
NamedDecl *nd = cast<NamedDecl>(D);
// gcc rejects
@@ -1640,8 +1329,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->getNameAsString();
+ S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_global_context)
+ << nd;
return;
}
@@ -1698,77 +1387,22 @@ static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) {
Attr.getAttributeSpellingListIndex()));
}
-static void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D) && !isa<ObjCMethodDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionOrMethod;
- return;
- }
-
- D->addAttr(::new (S.Context)
- MinSizeAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
+ if (checkAttrMutualExclusion<HotAttr>(S, D, Attr))
return;
- }
-
- if (D->hasAttr<HotAttr>()) {
- S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
- << Attr.getName() << "hot";
- return;
- }
D->addAttr(::new (S.Context) ColdAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
}
static void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
- return;
- }
-
- if (D->hasAttr<ColdAttr>()) {
- S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
- << Attr.getName() << "cold";
+ if (checkAttrMutualExclusion<ColdAttr>(S, D, Attr))
return;
- }
D->addAttr(::new (S.Context) HotAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
}
-static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
- return;
- }
-
- D->addAttr(::new (S.Context)
- NakedAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleAlwaysInlineAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
- return;
- }
-
- D->addAttr(::new (S.Context)
- AlwaysInlineAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
static void handleTLSModelAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
StringRef Model;
@@ -1777,12 +1411,6 @@ static void handleTLSModelAttr(Sema &S, Decl *D,
if (!S.checkStringLiteralArgumentAttr(Attr, 0, Model, &LiteralLoc))
return;
- if (!isa<VarDecl>(D) || !cast<VarDecl>(D)->getTLSKind()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedTLSVar;
- return;
- }
-
// Check that the value.
if (Model != "global-dynamic" && Model != "local-dynamic"
&& Model != "initial-exec" && Model != "local-exec") {
@@ -1797,7 +1425,7 @@ static void handleTLSModelAttr(Sema &S, Decl *D,
static void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- QualType RetTy = FD->getResultType();
+ QualType RetTy = FD->getReturnType();
if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) {
D->addAttr(::new (S.Context)
MallocAttr(Attr.getRange(), S.Context,
@@ -1809,35 +1437,15 @@ static void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) {
S.Diag(Attr.getLoc(), diag::warn_attribute_malloc_pointer_only);
}
-static void handleMayAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- D->addAttr(::new (S.Context)
- MayAliasAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleNoCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (isa<VarDecl>(D))
- D->addAttr(::new (S.Context)
- NoCommonAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- else
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedVariable;
-}
-
static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (S.LangOpts.CPlusPlus) {
- S.Diag(Attr.getLoc(), diag::err_common_not_supported_cplusplus);
+ S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang)
+ << Attr.getName() << AttributeLangSupport::Cpp;
return;
}
- if (isa<VarDecl>(D))
- D->addAttr(::new (S.Context)
- CommonAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- else
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedVariable;
+ D->addAttr(::new (S.Context) CommonAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) {
@@ -1872,8 +1480,8 @@ static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D,
// because 'analyzer_noreturn' does not impact the type.
if (!isFunctionOrMethod(D) && !isa<BlockDecl>(D)) {
ValueDecl *VD = dyn_cast<ValueDecl>(D);
- if (VD == 0 || (!VD->getType()->isBlockPointerType()
- && !VD->getType()->isFunctionPointerType())) {
+ if (!VD || (!VD->getType()->isBlockPointerType() &&
+ !VD->getType()->isFunctionPointerType())) {
S.Diag(Attr.getLoc(),
Attr.isCXX11Attribute() ? diag::err_attribute_wrong_decl_type
: diag::warn_attribute_wrong_decl_type)
@@ -1887,23 +1495,6 @@ static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D,
Attr.getAttributeSpellingListIndex()));
}
-static void handleCXX11NoReturnAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- // C++11 [dcl.attr.noreturn]p1:
- // The attribute may be applied to the declarator-id in a function
- // declaration.
- FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
- if (!FD) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionOrMethod;
- return;
- }
-
- D->addAttr(::new (S.Context)
- CXX11NoReturnAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
// PS3 PPU-specific.
static void handleVecReturnAttr(Sema &S, Decl *D, const AttributeList &Attr) {
/*
@@ -1929,14 +1520,8 @@ static void handleVecReturnAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return result; // This will be returned in a register
}
*/
- if (!isa<RecordDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedClass;
- return;
- }
-
- if (D->getAttr<VecReturnAttr>()) {
- S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "vecreturn";
+ if (VecReturnAttr *A = D->getAttr<VecReturnAttr>()) {
+ S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << A;
return;
}
@@ -1953,9 +1538,8 @@ static void handleVecReturnAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- for (RecordDecl::field_iterator iter = record->field_begin();
- iter != record->field_end(); iter++) {
- if ((count == 1) || !iter->getType()->isVectorType()) {
+ for (const auto *I : record->fields()) {
+ if ((count == 1) || !I->getType()->isVectorType()) {
S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
return;
}
@@ -1977,10 +1561,6 @@ static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D,
diag::err_carries_dependency_param_not_function_decl);
return;
}
- } else if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionMethodOrParameter;
- return;
}
D->addAttr(::new (S.Context) CarriesDependencyAttr(
@@ -1988,36 +1568,10 @@ static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D,
Attr.getAttributeSpellingListIndex()));
}
-static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!isa<VarDecl>(D) && !isa<ObjCIvarDecl>(D) && !isFunctionOrMethod(D) &&
- !isa<TypeDecl>(D) && !isa<LabelDecl>(D) && !isa<FieldDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedVariableFunctionOrLabel;
- return;
- }
-
- D->addAttr(::new (S.Context)
- UnusedAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleReturnsTwiceAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
- return;
- }
-
- D->addAttr(::new (S.Context)
- ReturnsTwiceAttr(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) << "used";
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
return;
}
} else if (!isFunctionOrMethod(D)) {
@@ -2034,29 +1588,15 @@ static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// check the attribute arguments.
if (Attr.getNumArgs() > 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1;
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
+ << Attr.getName() << 1;
return;
}
- int priority = 65535; // FIXME: Do not hardcode such constants.
- if (Attr.getNumArgs() > 0) {
- Expr *E = Attr.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
- << E->getSourceRange();
- return;
- }
- priority = Idx.getZExtValue();
- }
-
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
+ uint32_t priority = ConstructorAttr::DefaultPriority;
+ if (Attr.getNumArgs() > 0 &&
+ !checkUInt32Argument(S, Attr, Attr.getArgAsExpr(0), priority))
return;
- }
D->addAttr(::new (S.Context)
ConstructorAttr(Attr.getRange(), S.Context, priority,
@@ -2066,29 +1606,15 @@ static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// check the attribute arguments.
if (Attr.getNumArgs() > 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1;
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
+ << Attr.getName() << 1;
return;
}
- int priority = 65535; // FIXME: Do not hardcode such constants.
- if (Attr.getNumArgs() > 0) {
- Expr *E = Attr.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
- << E->getSourceRange();
- return;
- }
- priority = Idx.getZExtValue();
- }
-
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
+ uint32_t priority = DestructorAttr::DefaultPriority;
+ if (Attr.getNumArgs() > 0 &&
+ !checkUInt32Argument(S, Attr, Attr.getArgAsExpr(0), priority))
return;
- }
D->addAttr(::new (S.Context)
DestructorAttr(Attr.getRange(), S.Context, priority,
@@ -2100,7 +1626,8 @@ static void handleAttrWithMessage(Sema &S, Decl *D,
const AttributeList &Attr) {
unsigned NumArgs = Attr.getNumArgs();
if (NumArgs > 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1;
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
+ << Attr.getName() << 1;
return;
}
@@ -2113,36 +1640,17 @@ static void handleAttrWithMessage(Sema &S, Decl *D,
Attr.getAttributeSpellingListIndex()));
}
-static void handleArcWeakrefUnavailableAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- D->addAttr(::new (S.Context)
- ArcWeakrefUnavailableAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleObjCRootClassAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!isa<ObjCInterfaceDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedObjectiveCInterface;
+static void handleObjCSuppresProtocolAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (!cast<ObjCProtocolDecl>(D)->isThisDeclarationADefinition()) {
+ S.Diag(Attr.getLoc(), diag::err_objc_attr_protocol_requires_definition)
+ << Attr.getName() << Attr.getRange();
return;
}
-
- D->addAttr(::new (S.Context)
- ObjCRootClassAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-static void handleObjCRequiresPropertyDefsAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!isa<ObjCInterfaceDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_suppress_autosynthesis);
- return;
- }
-
D->addAttr(::new (S.Context)
- ObjCRequiresPropertyDefsAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ ObjCExplicitProtocolImplAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static bool checkAvailabilityAttr(Sema &S, SourceRange Range,
@@ -2312,7 +1820,7 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range,
MergedIntroduced == Introduced &&
MergedDeprecated == Deprecated &&
MergedObsoleted == Obsoleted)
- return NULL;
+ return nullptr;
// Only create a new attribute if !Override, but we want to do
// the checking.
@@ -2324,7 +1832,7 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range,
Obsoleted, IsUnavailable, Message,
AttrSpellingListIndex);
}
- return NULL;
+ return nullptr;
}
static void handleAvailabilityAttr(Sema &S, Decl *D,
@@ -2373,7 +1881,7 @@ static T *mergeVisibilityAttr(Sema &S, Decl *D, SourceRange range,
if (existingAttr) {
typename T::VisibilityType existingValue = existingAttr->getVisibility();
if (existingValue == value)
- return NULL;
+ return nullptr;
S.Diag(existingAttr->getLocation(), diag::err_mismatched_visibility);
S.Diag(range.getBegin(), diag::note_previous_attribute);
D->dropAttr<T>();
@@ -2450,13 +1958,7 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr,
static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl,
const AttributeList &Attr) {
- ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(decl);
- if (!method) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << ExpectedMethod;
- return;
- }
-
+ ObjCMethodDecl *method = cast<ObjCMethodDecl>(decl);
if (!Attr.isArgIdent(0)) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
<< Attr.getName() << 1 << AANT_ArgumentIdentifier;
@@ -2471,30 +1973,17 @@ static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl,
return;
}
- if (F == ObjCMethodFamilyAttr::OMF_init &&
- !method->getResultType()->isObjCObjectPointerType()) {
+ if (F == ObjCMethodFamilyAttr::OMF_init &&
+ !method->getReturnType()->isObjCObjectPointerType()) {
S.Diag(method->getLocation(), diag::err_init_method_bad_return_type)
- << method->getResultType();
+ << method->getReturnType();
// Ignore the attribute.
return;
}
method->addAttr(new (S.Context) ObjCMethodFamilyAttr(Attr.getRange(),
- S.Context, F));
-}
-
-static void handleObjCExceptionAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- ObjCInterfaceDecl *OCI = dyn_cast<ObjCInterfaceDecl>(D);
- if (OCI == 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedObjectiveCInterface;
- return;
- }
-
- D->addAttr(::new (S.Context)
- ObjCExceptionAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ S.Context, F,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -2526,18 +2015,6 @@ static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) {
Attr.getAttributeSpellingListIndex()));
}
-static void
-handleOverloadableAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_overloadable_not_function);
- return;
- }
-
- D->addAttr(::new (S.Context)
- OverloadableAttr(Attr.getRange(), S.Context,
- Attr.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)
@@ -2561,11 +2038,12 @@ static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// check the attribute arguments.
if (Attr.getNumArgs() > 2) {
- S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2;
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
+ << Attr.getName() << 2;
return;
}
- unsigned sentinel = 0;
+ unsigned sentinel = (unsigned)SentinelAttr::DefaultSentinel;
if (Attr.getNumArgs() > 0) {
Expr *E = Attr.getArgAsExpr(0);
llvm::APSInt Idx(32);
@@ -2586,7 +2064,7 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) {
sentinel = Idx.getZExtValue();
}
- unsigned nullPos = 0;
+ unsigned nullPos = (unsigned)SentinelAttr::DefaultNullPos;
if (Attr.getNumArgs() > 1) {
Expr *E = Attr.getArgAsExpr(1);
llvm::APSInt Idx(32);
@@ -2632,7 +2110,8 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) {
} else if (const VarDecl *V = dyn_cast<VarDecl>(D)) {
QualType Ty = V->getType();
if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) {
- const FunctionType *FT = Ty->isFunctionPointerType() ? getFunctionType(D)
+ const FunctionType *FT = Ty->isFunctionPointerType()
+ ? D->getFunctionType()
: Ty->getAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>();
if (!cast<FunctionProtoType>(FT)->isVariadic()) {
int m = Ty->isFunctionPointerType() ? 0 : 1;
@@ -2654,27 +2133,15 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) {
Attr.getAttributeSpellingListIndex()));
}
-static void handleWarnUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (RecordDecl *RD = dyn_cast<RecordDecl>(D))
- RD->addAttr(::new (S.Context) WarnUnusedAttr(Attr.getRange(), S.Context));
- else
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
-}
-
static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!isFunction(D) && !isa<ObjCMethodDecl>(D) && !isa<CXXRecordDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionMethodOrClass;
- return;
- }
-
- if (isFunction(D) && getFunctionType(D)->getResultType()->isVoidType()) {
+ if (D->getFunctionType() &&
+ D->getFunctionType()->getReturnType()->isVoidType()) {
S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method)
<< Attr.getName() << 0;
return;
}
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
- if (MD->getResultType()->isVoidType()) {
+ if (MD->getReturnType()->isVoidType()) {
S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method)
<< Attr.getName() << 1;
return;
@@ -2685,24 +2152,6 @@ static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr)
Attr.getAttributeSpellingListIndex()));
}
-static void handleWeakAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D)) {
- if (isa<CXXRecordDecl>(D)) {
- D->addAttr(::new (S.Context) WeakAttr(Attr.getRange(), S.Context));
- return;
- }
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedVariableOrFunction;
- return;
- }
-
- NamedDecl *nd = cast<NamedDecl>(D);
-
- nd->addAttr(::new (S.Context)
- WeakAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// weak_import only applies to variable & function declarations.
bool isDef = false;
@@ -2727,66 +2176,40 @@ static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
// Handles reqd_work_group_size and work_group_size_hint.
+template <typename WorkGroupAttr>
static void handleWorkGroupSize(Sema &S, Decl *D,
const AttributeList &Attr) {
- unsigned WGSize[3];
+ uint32_t WGSize[3];
for (unsigned i = 0; i < 3; ++i) {
- Expr *E = Attr.getArgAsExpr(i);
- llvm::APSInt ArgNum(32);
- if (E->isTypeDependent() || E->isValueDependent() ||
- !E->isIntegerConstantExpr(ArgNum, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
- << Attr.getName() << AANT_ArgumentIntegerConstant
- << E->getSourceRange();
+ const Expr *E = Attr.getArgAsExpr(i);
+ if (!checkUInt32Argument(S, Attr, E, WGSize[i], i))
+ return;
+ if (WGSize[i] == 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_is_zero)
+ << Attr.getName() << E->getSourceRange();
return;
}
- WGSize[i] = (unsigned) ArgNum.getZExtValue();
- }
-
- if (Attr.getKind() == AttributeList::AT_ReqdWorkGroupSize
- && D->hasAttr<ReqdWorkGroupSizeAttr>()) {
- ReqdWorkGroupSizeAttr *A = D->getAttr<ReqdWorkGroupSizeAttr>();
- if (!(A->getXDim() == WGSize[0] &&
- A->getYDim() == WGSize[1] &&
- A->getZDim() == WGSize[2])) {
- S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) <<
- Attr.getName();
- }
}
- if (Attr.getKind() == AttributeList::AT_WorkGroupSizeHint
- && D->hasAttr<WorkGroupSizeHintAttr>()) {
- WorkGroupSizeHintAttr *A = D->getAttr<WorkGroupSizeHintAttr>();
- if (!(A->getXDim() == WGSize[0] &&
- A->getYDim() == WGSize[1] &&
- A->getZDim() == WGSize[2])) {
- S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) <<
- Attr.getName();
- }
- }
+ WorkGroupAttr *Existing = D->getAttr<WorkGroupAttr>();
+ if (Existing && !(Existing->getXDim() == WGSize[0] &&
+ Existing->getYDim() == WGSize[1] &&
+ Existing->getZDim() == WGSize[2]))
+ S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr.getName();
- if (Attr.getKind() == AttributeList::AT_ReqdWorkGroupSize)
- D->addAttr(::new (S.Context)
- ReqdWorkGroupSizeAttr(Attr.getRange(), S.Context,
- WGSize[0], WGSize[1], WGSize[2],
- Attr.getAttributeSpellingListIndex()));
- else
- D->addAttr(::new (S.Context)
- WorkGroupSizeHintAttr(Attr.getRange(), S.Context,
- WGSize[0], WGSize[1], WGSize[2],
+ D->addAttr(::new (S.Context) WorkGroupAttr(Attr.getRange(), S.Context,
+ WGSize[0], WGSize[1], WGSize[2],
Attr.getAttributeSpellingListIndex()));
}
static void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &Attr) {
- assert(Attr.getKind() == AttributeList::AT_VecTypeHint);
-
if (!Attr.hasParsedType()) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
<< Attr.getName() << 1;
return;
}
- TypeSourceInfo *ParmTSI = 0;
+ TypeSourceInfo *ParmTSI = nullptr;
QualType ParmType = S.GetTypeFromParser(Attr.getTypeArg(), &ParmTSI);
assert(ParmTSI && "no type source info for attribute argument");
@@ -2798,9 +2221,7 @@ static void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- if (Attr.getKind() == AttributeList::AT_VecTypeHint &&
- D->hasAttr<VecTypeHintAttr>()) {
- VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>();
+ if (VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>()) {
if (!S.Context.hasSameType(A->getTypeHint(), ParmType)) {
S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr.getName();
return;
@@ -2808,7 +2229,8 @@ static void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &Attr) {
}
D->addAttr(::new (S.Context) VecTypeHintAttr(Attr.getLoc(), S.Context,
- ParmTSI));
+ ParmTSI,
+ Attr.getAttributeSpellingListIndex()));
}
SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range,
@@ -2816,10 +2238,10 @@ SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range,
unsigned AttrSpellingListIndex) {
if (SectionAttr *ExistingAttr = D->getAttr<SectionAttr>()) {
if (ExistingAttr->getName() == Name)
- return NULL;
+ return nullptr;
Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section);
Diag(Range.getBegin(), diag::note_previous_attribute);
- return NULL;
+ return nullptr;
}
return ::new (Context) SectionAttr(Range, Context, Name,
AttrSpellingListIndex);
@@ -2841,12 +2263,6 @@ static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- // This attribute cannot be applied to local variables.
- if (isa<VarDecl>(D) && cast<VarDecl>(D)->hasLocalStorage()) {
- S.Diag(LiteralLoc, diag::err_attribute_section_local_variable);
- return;
- }
-
unsigned Index = Attr.getAttributeSpellingListIndex();
SectionAttr *NewAttr = S.mergeSectionAttr(D, Attr.getRange(), Str, Index);
if (NewAttr)
@@ -2854,44 +2270,16 @@ static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
-static void handleNothrowAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (NoThrowAttr *Existing = D->getAttr<NoThrowAttr>()) {
- if (Existing->getLocation().isInvalid())
- Existing->setRange(Attr.getRange());
- } else {
- D->addAttr(::new (S.Context)
- NoThrowAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- }
-}
-
-static void handleConstAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (ConstAttr *Existing = D->getAttr<ConstAttr>()) {
- if (Existing->getLocation().isInvalid())
- Existing->setRange(Attr.getRange());
- } else {
- D->addAttr(::new (S.Context)
- ConstAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex() ));
- }
-}
-
-static void handlePureAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- D->addAttr(::new (S.Context)
- PureAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- VarDecl *VD = dyn_cast<VarDecl>(D);
- if (!VD || !VD->hasLocalStorage()) {
+ VarDecl *VD = cast<VarDecl>(D);
+ if (!VD->hasLocalStorage()) {
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
return;
}
Expr *E = Attr.getArgAsExpr(0);
SourceLocation Loc = E->getExprLoc();
- FunctionDecl *FD = 0;
+ FunctionDecl *FD = nullptr;
DeclarationNameInfo NI;
// gcc only allows for simple identifiers. Since we support more than gcc, we
@@ -2948,20 +2336,13 @@ static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) {
/// 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) {
- if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
- return;
- }
-
Expr *IdxExpr = Attr.getArgAsExpr(0);
- uint64_t ArgIdx;
- if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(),
- Attr.getLoc(), 1, IdxExpr, ArgIdx))
+ uint64_t Idx;
+ if (!checkFunctionOrMethodParameterIndex(S, D, Attr, 1, IdxExpr, Idx))
return;
// make sure the format string is really a string
- QualType Ty = getFunctionOrMethodArgType(D, ArgIdx);
+ QualType Ty = getFunctionOrMethodParamType(D, Idx);
bool not_nsstring_type = !isNSStringType(Ty, S.Context);
if (not_nsstring_type &&
@@ -2986,7 +2367,7 @@ static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- // We cannot use the ArgIdx returned from checkFunctionOrMethodArgumentIndex
+ // 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;
@@ -3033,12 +2414,12 @@ static void handleInitPriorityAttr(Sema &S, Decl *D,
return;
}
- if (!isa<VarDecl>(D) || S.getCurFunctionOrMethodDecl()) {
+ if (S.getCurFunctionOrMethodDecl()) {
S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr);
Attr.setInvalid();
return;
}
- QualType T = dyn_cast<VarDecl>(D)->getType();
+ QualType T = cast<VarDecl>(D)->getType();
if (S.Context.getAsArrayType(T))
T = S.Context.getBaseElementType(T);
if (!T->getAs<RecordType>()) {
@@ -3046,22 +2427,17 @@ static void handleInitPriorityAttr(Sema &S, Decl *D,
Attr.setInvalid();
return;
}
-
- Expr *priorityExpr = Attr.getArgAsExpr(0);
-
- llvm::APSInt priority(32);
- if (priorityExpr->isTypeDependent() || priorityExpr->isValueDependent() ||
- !priorityExpr->isIntegerConstantExpr(priority, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
- << Attr.getName() << AANT_ArgumentIntegerConstant
- << priorityExpr->getSourceRange();
+
+ Expr *E = Attr.getArgAsExpr(0);
+ uint32_t prioritynum;
+ if (!checkUInt32Argument(S, Attr, E, prioritynum)) {
Attr.setInvalid();
return;
}
- unsigned prioritynum = priority.getZExtValue();
+
if (prioritynum < 101 || prioritynum > 65535) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_outof_range)
- << priorityExpr->getSourceRange();
+ << E->getSourceRange();
Attr.setInvalid();
return;
}
@@ -3075,19 +2451,15 @@ FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range,
int FirstArg,
unsigned AttrSpellingListIndex) {
// Check whether we already have an equivalent format attribute.
- for (specific_attr_iterator<FormatAttr>
- i = D->specific_attr_begin<FormatAttr>(),
- e = D->specific_attr_end<FormatAttr>();
- i != e ; ++i) {
- FormatAttr *f = *i;
- if (f->getType() == Format &&
- f->getFormatIdx() == FormatIdx &&
- f->getFirstArg() == FirstArg) {
+ for (auto *F : D->specific_attrs<FormatAttr>()) {
+ if (F->getType() == Format &&
+ F->getFormatIdx() == FormatIdx &&
+ F->getFirstArg() == FirstArg) {
// If we don't have a valid location for this attribute, adopt the
// location.
- if (f->getLocation().isInvalid())
- f->setRange(Range);
- return NULL;
+ if (F->getLocation().isInvalid())
+ F->setRange(Range);
+ return nullptr;
}
}
@@ -3104,17 +2476,10 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- if (!isFunctionOrMethodOrBlock(D) || !hasFunctionProto(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
- return;
- }
-
// In C++ the implicit 'this' function parameter also counts, and they are
// counted from one.
bool HasImplicitThisParam = isInstanceMethod(D);
- unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam;
- unsigned FirstIdx = 1;
+ unsigned NumArgs = getFunctionOrMethodNumParams(D) + HasImplicitThisParam;
IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident;
StringRef Format = II->getName();
@@ -3134,29 +2499,24 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (Kind == InvalidFormat) {
S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
- << "format" << II->getName();
+ << Attr.getName() << II->getName();
return;
}
// checks for the 2nd argument
Expr *IdxExpr = Attr.getArgAsExpr(1);
- llvm::APSInt Idx(32);
- if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
- !IdxExpr->isIntegerConstantExpr(Idx, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
- << Attr.getName() << 2 << AANT_ArgumentIntegerConstant
- << IdxExpr->getSourceRange();
+ uint32_t Idx;
+ if (!checkUInt32Argument(S, Attr, IdxExpr, Idx, 2))
return;
- }
- if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
+ if (Idx < 1 || Idx > NumArgs) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << "format" << 2 << IdxExpr->getSourceRange();
+ << Attr.getName() << 2 << IdxExpr->getSourceRange();
return;
}
// FIXME: Do we need to bounds check?
- unsigned ArgIdx = Idx.getZExtValue() - 1;
+ unsigned ArgIdx = Idx - 1;
if (HasImplicitThisParam) {
if (ArgIdx == 0) {
@@ -3169,7 +2529,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
// make sure the format string is really a string
- QualType Ty = getFunctionOrMethodArgType(D, ArgIdx);
+ QualType Ty = getFunctionOrMethodParamType(D, ArgIdx);
if (Kind == CFStringFormat) {
if (!isCFStringType(Ty, S.Context)) {
@@ -3196,14 +2556,9 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// check the 3rd argument
Expr *FirstArgExpr = Attr.getArgAsExpr(2);
- llvm::APSInt FirstArg(32);
- if (FirstArgExpr->isTypeDependent() || FirstArgExpr->isValueDependent() ||
- !FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
- << Attr.getName() << 3 << AANT_ArgumentIntegerConstant
- << FirstArgExpr->getSourceRange();
+ uint32_t FirstArg;
+ if (!checkUInt32Argument(S, Attr, FirstArgExpr, FirstArg, 3))
return;
- }
// check if the function is variadic if the 3rd argument non-zero
if (FirstArg != 0) {
@@ -3226,13 +2581,12 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// 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)
- << "format" << 3 << FirstArgExpr->getSourceRange();
+ << Attr.getName() << 3 << FirstArgExpr->getSourceRange();
return;
}
FormatAttr *NewAttr = S.mergeFormatAttr(D, Attr.getRange(), II,
- Idx.getZExtValue(),
- FirstArg.getZExtValue(),
+ Idx, FirstArg,
Attr.getAttributeSpellingListIndex());
if (NewAttr)
D->addAttr(NewAttr);
@@ -3241,7 +2595,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleTransparentUnionAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
// Try to find the underlying union declaration.
- RecordDecl *RD = 0;
+ RecordDecl *RD = nullptr;
TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
if (TD && TD->getUnderlyingType()->isUnionType())
RD = TD->getUnderlyingType()->getAsUnionType()->getDecl();
@@ -3280,8 +2634,13 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D,
uint64_t FirstAlign = S.Context.getTypeAlign(FirstType);
for (; Field != FieldEnd; ++Field) {
QualType FieldType = Field->getType();
+ // FIXME: this isn't fully correct; we also need to test whether the
+ // members of the union would all have the same calling convention as the
+ // first member of the union. Checking just the size and alignment isn't
+ // sufficient (consider structs passed on the stack instead of in registers
+ // as an example).
if (S.Context.getTypeSize(FieldType) != FirstSize ||
- S.Context.getTypeAlign(FieldType) != FirstAlign) {
+ S.Context.getTypeAlign(FieldType) > FirstAlign) {
// Warn if we drop the attribute.
bool isSize = S.Context.getTypeSize(FieldType) != FirstSize;
unsigned FieldBits = isSize? S.Context.getTypeSize(FieldType)
@@ -3310,10 +2669,8 @@ static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
// Don't duplicate annotations that are already set.
- for (specific_attr_iterator<AnnotateAttr>
- i = D->specific_attr_begin<AnnotateAttr>(),
- e = D->specific_attr_end<AnnotateAttr>(); i != e; ++i) {
- if ((*i)->getAnnotation() == Str)
+ for (const auto *I : D->specific_attrs<AnnotateAttr>()) {
+ if (I->getAnnotation() == Str)
return;
}
@@ -3332,7 +2689,7 @@ static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (Attr.getNumArgs() == 0) {
D->addAttr(::new (S.Context) AlignedAttr(Attr.getRange(), S.Context,
- true, 0, Attr.getAttributeSpellingListIndex()));
+ true, nullptr, Attr.getAttributeSpellingListIndex()));
return;
}
@@ -3380,15 +2737,14 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
if (FD->isBitField())
DiagKind = 3;
} else if (!isa<TagDecl>(D)) {
- Diag(AttrLoc, diag::err_attribute_wrong_decl_type)
- << (TmpAttr.isC11() ? "'_Alignas'" : "'alignas'")
+ Diag(AttrLoc, diag::err_attribute_wrong_decl_type) << &TmpAttr
<< (TmpAttr.isC11() ? ExpectedVariableOrField
: ExpectedVariableFieldOrTag);
return;
}
if (DiagKind != -1) {
Diag(AttrLoc, diag::err_alignas_attribute_wrong_decl_type)
- << TmpAttr.isC11() << DiagKind;
+ << &TmpAttr << DiagKind;
return;
}
}
@@ -3422,18 +2778,16 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
return;
}
- if (TmpAttr.isDeclspec()) {
- // We've already verified it's a power of 2, now let's make sure it's
- // 8192 or less.
- if (Alignment.getZExtValue() > 8192) {
- Diag(AttrLoc, diag::err_attribute_aligned_greater_than_8192)
- << E->getSourceRange();
- return;
- }
+ // Alignment calculations can wrap around if it's greater than 2**28.
+ unsigned MaxValidAlignment = TmpAttr.isDeclspec() ? 8192 : 268435456;
+ if (Alignment.getZExtValue() > MaxValidAlignment) {
+ Diag(AttrLoc, diag::err_attribute_aligned_too_great) << MaxValidAlignment
+ << E->getSourceRange();
+ return;
}
AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, true,
- ICE.take(), SpellingListIndex);
+ ICE.get(), SpellingListIndex);
AA->setPackExpansion(IsPackExpansion);
D->addAttr(AA);
}
@@ -3463,15 +2817,13 @@ void Sema::CheckAlignasUnderalignment(Decl *D) {
// The combined effect of all alignment attributes in a declaration shall
// not specify an alignment that is less strict than the alignment that
// would otherwise be required for the entity being declared.
- AlignedAttr *AlignasAttr = 0;
+ AlignedAttr *AlignasAttr = nullptr;
unsigned Align = 0;
- for (specific_attr_iterator<AlignedAttr>
- I = D->specific_attr_begin<AlignedAttr>(),
- E = D->specific_attr_end<AlignedAttr>(); I != E; ++I) {
+ for (auto *I : D->specific_attrs<AlignedAttr>()) {
if (I->isAlignmentDependent())
return;
if (I->isAlignas())
- AlignasAttr = *I;
+ AlignasAttr = I;
Align = std::max(Align, I->getAlignment(Context));
}
@@ -3484,6 +2836,35 @@ void Sema::CheckAlignasUnderalignment(Decl *D) {
}
}
+bool Sema::checkMSInheritanceAttrOnDefinition(
+ CXXRecordDecl *RD, SourceRange Range, bool BestCase,
+ MSInheritanceAttr::Spelling SemanticSpelling) {
+ assert(RD->hasDefinition() && "RD has no definition!");
+
+ // We may not have seen base specifiers or any virtual methods yet. We will
+ // have to wait until the record is defined to catch any mismatches.
+ if (!RD->getDefinition()->isCompleteDefinition())
+ return false;
+
+ // The unspecified model never matches what a definition could need.
+ if (SemanticSpelling == MSInheritanceAttr::Keyword_unspecified_inheritance)
+ return false;
+
+ if (BestCase) {
+ if (RD->calculateInheritanceModel() == SemanticSpelling)
+ return false;
+ } else {
+ if (RD->calculateInheritanceModel() <= SemanticSpelling)
+ return false;
+ }
+
+ Diag(Range.getBegin(), diag::err_mismatched_ms_inheritance)
+ << 0 /*definition*/;
+ Diag(RD->getDefinition()->getLocation(), diag::note_defined_here)
+ << RD->getNameAsString();
+ return true;
+}
+
/// handleModeAttr - This attribute modifies the width of a decl with primitive
/// type.
///
@@ -3553,7 +2934,7 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
OldTy = VD->getType();
else {
S.Diag(D->getLocation(), diag::err_attr_wrong_decl)
- << "mode" << Attr.getRange();
+ << Attr.getName() << Attr.getRange();
return;
}
@@ -3575,7 +2956,7 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// FIXME: Make sure floating-point mappings are accurate
// FIXME: Support XF and TF types
if (!DestWidth) {
- S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode) << Name;
+ S.Diag(Attr.getLoc(), diag::err_machine_mode) << 0 /*Unknown*/ << Name;
return;
}
@@ -3588,7 +2969,7 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
NewTy = S.Context.getRealTypeForBitwidth(DestWidth);
if (NewTy.isNull()) {
- S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
+ S.Diag(Attr.getLoc(), diag::err_machine_mode) << 1 /*Unsupported*/ << Name;
return;
}
@@ -3625,141 +3006,44 @@ static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) {
Attr.getAttributeSpellingListIndex()));
}
-static void handleNoInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
+static void handleAlwaysInlineAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (checkAttrMutualExclusion<OptimizeNoneAttr>(S, D, Attr))
return;
- }
D->addAttr(::new (S.Context)
- NoInlineAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ AlwaysInlineAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
-static void handleNoInstrumentFunctionAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
+static void handleOptimizeNoneAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (checkAttrMutualExclusion<AlwaysInlineAttr>(S, D, Attr))
return;
- }
D->addAttr(::new (S.Context)
- NoInstrumentFunctionAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleConstantAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (S.LangOpts.CUDA) {
- if (!isa<VarDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedVariable;
- return;
- }
-
- D->addAttr(::new (S.Context)
- CUDAConstantAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- } else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "constant";
- }
-}
-
-static void handleDeviceAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (S.LangOpts.CUDA) {
- // check the attribute arguments.
- if (Attr.getNumArgs() != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 0;
- return;
- }
-
- if (!isa<FunctionDecl>(D) && !isa<VarDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedVariableOrFunction;
- return;
- }
-
- D->addAttr(::new (S.Context)
- CUDADeviceAttr(Attr.getRange(), S.Context,
+ OptimizeNoneAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
- } else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "device";
- }
}
static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (S.LangOpts.CUDA) {
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
- return;
- }
-
- FunctionDecl *FD = cast<FunctionDecl>(D);
- if (!FD->getResultType()->isVoidType()) {
- TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens();
- if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) {
- S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
- << FD->getType()
- << FixItHint::CreateReplacement(FTL.getResultLoc().getSourceRange(),
- "void");
- } else {
- S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
- << FD->getType();
- }
- return;
- }
-
- D->addAttr(::new (S.Context)
- CUDAGlobalAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- } else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "global";
+ FunctionDecl *FD = cast<FunctionDecl>(D);
+ if (!FD->getReturnType()->isVoidType()) {
+ SourceRange RTRange = FD->getReturnTypeSourceRange();
+ S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
+ << FD->getType()
+ << (RTRange.isValid() ? FixItHint::CreateReplacement(RTRange, "void")
+ : FixItHint());
+ return;
}
-}
-static void handleHostAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (S.LangOpts.CUDA) {
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
- return;
- }
-
- D->addAttr(::new (S.Context)
- CUDAHostAttr(Attr.getRange(), S.Context,
+ D->addAttr(::new (S.Context)
+ CUDAGlobalAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
- } else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "host";
- }
-}
-
-static void handleSharedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (S.LangOpts.CUDA) {
- if (!isa<VarDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedVariable;
- return;
- }
-
- D->addAttr(::new (S.Context)
- CUDASharedAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- } else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "shared";
- }
}
static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- FunctionDecl *Fn = dyn_cast<FunctionDecl>(D);
- if (Fn == 0) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
- return;
- }
-
+ FunctionDecl *Fn = cast<FunctionDecl>(D);
if (!Fn->isInlineSpecified()) {
S.Diag(Attr.getLoc(), diag::warn_gnu_inline_attribute_requires_inline);
return;
@@ -3856,25 +3140,6 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
}
-static void handleOpenCLKernelAttr(Sema &S, Decl *D, const AttributeList &Attr){
- D->addAttr(::new (S.Context) OpenCLKernelAttr(Attr.getRange(), S.Context));
-}
-
-static void handleOpenCLImageAccessAttr(Sema &S, Decl *D, const AttributeList &Attr){
- Expr *E = Attr.getArgAsExpr(0);
- llvm::APSInt ArgNum(32);
- if (E->isTypeDependent() || E->isValueDependent() ||
- !E->isIntegerConstantExpr(ArgNum, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
- << Attr.getName() << AANT_ArgumentIntegerConstant
- << E->getSourceRange();
- return;
- }
-
- D->addAttr(::new (S.Context) OpenCLImageAccessAttr(
- Attr.getRange(), S.Context, ArgNum.getZExtValue()));
-}
-
bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
const FunctionDecl *FD) {
if (attr.isInvalid())
@@ -3886,8 +3151,7 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
return true;
}
- // TODO: diagnose uses of these conventions on the wrong target. Or, better
- // move to TargetAttributesSema one day.
+ // TODO: diagnose uses of these conventions on the wrong target.
switch (attr.getKind()) {
case AttributeList::AT_CDecl: CC = CC_C; break;
case AttributeList::AT_FastCall: CC = CC_X86FastCall; break;
@@ -3940,24 +3204,6 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
return false;
}
-static void handleRegparmAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (hasDeclarator(D)) return;
-
- unsigned numParams;
- if (S.CheckRegparmAttr(Attr, numParams))
- return;
-
- if (!isa<ObjCMethodDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionOrMethod;
- return;
- }
-
- D->addAttr(::new (S.Context)
- RegparmAttr(Attr.getRange(), S.Context, numParams,
- Attr.getAttributeSpellingListIndex()));
-}
-
/// 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) {
@@ -3969,13 +3215,9 @@ bool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) {
return true;
}
+ uint32_t NP;
Expr *NumParamsExpr = Attr.getArgAsExpr(0);
- llvm::APSInt NumParams(32);
- if (NumParamsExpr->isTypeDependent() || NumParamsExpr->isValueDependent() ||
- !NumParamsExpr->isIntegerConstantExpr(NumParams, Context)) {
- Diag(Attr.getLoc(), diag::err_attribute_argument_type)
- << Attr.getName() << AANT_ArgumentIntegerConstant
- << NumParamsExpr->getSourceRange();
+ if (!checkUInt32Argument(*this, Attr, NumParamsExpr, NP)) {
Attr.setInvalid();
return true;
}
@@ -3987,7 +3229,7 @@ bool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) {
return true;
}
- numParams = NumParams.getZExtValue();
+ numParams = NP;
if (numParams > Context.getTargetInfo().getRegParmMax()) {
Diag(Attr.getLoc(), diag::err_attribute_regparm_invalid_number)
<< Context.getTargetInfo().getRegParmMax() << NumParamsExpr->getSourceRange();
@@ -3998,53 +3240,28 @@ bool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) {
return false;
}
-static void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){
- if (S.LangOpts.CUDA) {
- // check the attribute arguments.
- if (Attr.getNumArgs() != 1 && Attr.getNumArgs() != 2) {
- // FIXME: 0 is not okay.
- S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2;
- return;
- }
-
- if (!isFunctionOrMethod(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionOrMethod;
- return;
- }
-
- Expr *MaxThreadsExpr = Attr.getArgAsExpr(0);
- llvm::APSInt MaxThreads(32);
- if (MaxThreadsExpr->isTypeDependent() ||
- MaxThreadsExpr->isValueDependent() ||
- !MaxThreadsExpr->isIntegerConstantExpr(MaxThreads, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
- << Attr.getName() << 1 << AANT_ArgumentIntegerConstant
- << MaxThreadsExpr->getSourceRange();
- return;
- }
+static void handleLaunchBoundsAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 1 && Attr.getNumArgs() != 2) {
+ // FIXME: 0 is not okay.
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
+ << Attr.getName() << 2;
+ return;
+ }
- llvm::APSInt MinBlocks(32);
- if (Attr.getNumArgs() > 1) {
- Expr *MinBlocksExpr = Attr.getArgAsExpr(1);
- if (MinBlocksExpr->isTypeDependent() ||
- MinBlocksExpr->isValueDependent() ||
- !MinBlocksExpr->isIntegerConstantExpr(MinBlocks, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
- << Attr.getName() << 2 << AANT_ArgumentIntegerConstant
- << MinBlocksExpr->getSourceRange();
- return;
- }
- }
+ uint32_t MaxThreads, MinBlocks = 0;
+ if (!checkUInt32Argument(S, Attr, Attr.getArgAsExpr(0), MaxThreads, 1))
+ return;
+ if (Attr.getNumArgs() > 1 && !checkUInt32Argument(S, Attr,
+ Attr.getArgAsExpr(1),
+ MinBlocks, 2))
+ return;
- D->addAttr(::new (S.Context)
- CUDALaunchBoundsAttr(Attr.getRange(), S.Context,
- MaxThreads.getZExtValue(),
- MinBlocks.getZExtValue(),
- Attr.getAttributeSpellingListIndex()));
- } else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "launch_bounds";
- }
+ D->addAttr(::new (S.Context)
+ CUDALaunchBoundsAttr(Attr.getRange(), S.Context,
+ MaxThreads, MinBlocks,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
@@ -4058,7 +3275,6 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
if (!checkAttributeNumArgs(S, Attr, 3))
return;
- StringRef AttrName = Attr.getName()->getName();
IdentifierInfo *ArgumentKind = Attr.getArgAsIdent(0)->Ident;
if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) {
@@ -4068,21 +3284,19 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
}
uint64_t ArgumentIdx;
- if (!checkFunctionOrMethodArgumentIndex(S, D, AttrName,
- Attr.getLoc(), 2,
- Attr.getArgAsExpr(1), ArgumentIdx))
+ if (!checkFunctionOrMethodParameterIndex(S, D, Attr, 2, Attr.getArgAsExpr(1),
+ ArgumentIdx))
return;
uint64_t TypeTagIdx;
- if (!checkFunctionOrMethodArgumentIndex(S, D, AttrName,
- Attr.getLoc(), 3,
- Attr.getArgAsExpr(2), TypeTagIdx))
+ if (!checkFunctionOrMethodParameterIndex(S, D, Attr, 3, Attr.getArgAsExpr(2),
+ TypeTagIdx))
return;
- bool IsPointer = (AttrName == "pointer_with_type_tag");
+ bool IsPointer = (Attr.getName()->getName() == "pointer_with_type_tag");
if (IsPointer) {
// Ensure that buffer has a pointer type.
- QualType BufferTy = getFunctionOrMethodArgType(D, ArgumentIdx);
+ QualType BufferTy = getFunctionOrMethodParamType(D, ArgumentIdx);
if (!BufferTy->isPointerType()) {
S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only)
<< Attr.getName();
@@ -4106,8 +3320,14 @@ static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D,
if (!checkAttributeNumArgs(S, Attr, 1))
return;
+ if (!isa<VarDecl>(D)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+ << Attr.getName() << ExpectedVariable;
+ return;
+ }
+
IdentifierInfo *PointerKind = Attr.getArgAsIdent(0)->Ident;
- TypeSourceInfo *MatchingCTypeLoc = 0;
+ TypeSourceInfo *MatchingCTypeLoc = nullptr;
S.GetTypeFromParser(Attr.getMatchingCType(), &MatchingCTypeLoc);
assert(MatchingCTypeLoc && "no type source info for attribute argument");
@@ -4123,6 +3343,11 @@ static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D,
// Checker-specific attribute handlers.
//===----------------------------------------------------------------------===//
+static bool isValidSubjectOfNSReturnsRetainedAttribute(QualType type) {
+ return type->isDependentType() ||
+ type->isObjCRetainableType();
+}
+
static bool isValidSubjectOfNSAttribute(Sema &S, QualType type) {
return type->isDependentType() ||
type->isObjCObjectPointerType() ||
@@ -4135,14 +3360,9 @@ static bool isValidSubjectOfCFAttribute(Sema &S, QualType type) {
}
static void handleNSConsumedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- ParmVarDecl *param = dyn_cast<ParmVarDecl>(D);
- if (!param) {
- S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type)
- << Attr.getRange() << Attr.getName() << ExpectedParameter;
- return;
- }
-
+ ParmVarDecl *param = cast<ParmVarDecl>(D);
bool typeOK, cf;
+
if (Attr.getKind() == AttributeList::AT_NSConsumed) {
typeOK = isValidSubjectOfNSAttribute(S, param->getType());
cf = false;
@@ -4167,33 +3387,20 @@ static void handleNSConsumedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
Attr.getAttributeSpellingListIndex()));
}
-static void handleNSConsumesSelfAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!isa<ObjCMethodDecl>(D)) {
- S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type)
- << Attr.getRange() << Attr.getName() << ExpectedMethod;
- return;
- }
-
- D->addAttr(::new (S.Context)
- NSConsumesSelfAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
static void handleNSReturnsRetainedAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
QualType returnType;
if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
- returnType = MD->getResultType();
+ returnType = MD->getReturnType();
else if (S.getLangOpts().ObjCAutoRefCount && hasDeclarator(D) &&
(Attr.getKind() == AttributeList::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->getResultType();
+ returnType = FD->getReturnType();
else {
S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type)
<< Attr.getRange() << Attr.getName()
@@ -4205,8 +3412,12 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D,
bool cf;
switch (Attr.getKind()) {
default: llvm_unreachable("invalid ownership attribute");
- case AttributeList::AT_NSReturnsAutoreleased:
case AttributeList::AT_NSReturnsRetained:
+ typeOK = isValidSubjectOfNSReturnsRetainedAttribute(returnType);
+ cf = false;
+ break;
+
+ case AttributeList::AT_NSReturnsAutoreleased:
case AttributeList::AT_NSReturnsNotRetained:
typeOK = isValidSubjectOfNSAttribute(S, returnType);
cf = false;
@@ -4263,27 +3474,17 @@ static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,
SourceLocation loc = attr.getLoc();
QualType resultType;
-
- ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(D);
-
- if (!method) {
- ObjCPropertyDecl *property = dyn_cast<ObjCPropertyDecl>(D);
- if (!property) {
- S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
- << SourceRange(loc, loc) << attr.getName() << ExpectedMethodOrProperty;
- return;
- }
- resultType = property->getType();
- }
+ if (isa<ObjCMethodDecl>(D))
+ resultType = cast<ObjCMethodDecl>(D)->getReturnType();
else
- // Check that the method returns a normal pointer.
- resultType = method->getResultType();
+ resultType = cast<ObjCPropertyDecl>(D)->getType();
if (!resultType->isReferenceType() &&
(!resultType->isPointerType() || resultType->isObjCRetainableType())) {
S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type)
<< SourceRange(loc)
- << attr.getName() << (method ? EP_ObjCMethod : EP_ObjCProperty)
+ << attr.getName()
+ << (isa<ObjCMethodDecl>(D) ? EP_ObjCMethod : EP_ObjCProperty)
<< /*non-retainable pointer*/ 2;
// Drop the attribute.
@@ -4297,14 +3498,8 @@ static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,
static void handleObjCRequiresSuperAttr(Sema &S, Decl *D,
const AttributeList &attr) {
- SourceLocation loc = attr.getLoc();
- ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(D);
+ ObjCMethodDecl *method = cast<ObjCMethodDecl>(D);
- if (!method) {
- S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
- << SourceRange(loc, loc) << attr.getName() << ExpectedMethod;
- return;
- }
DeclContext *DC = method->getDeclContext();
if (const ObjCProtocolDecl *PDecl = dyn_cast_or_null<ObjCProtocolDecl>(DC)) {
S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol)
@@ -4323,97 +3518,94 @@ static void handleObjCRequiresSuperAttr(Sema &S, Decl *D,
attr.getAttributeSpellingListIndex()));
}
-/// Handle cf_audited_transfer and cf_unknown_transfer.
-static void handleCFTransferAttr(Sema &S, Decl *D, const AttributeList &A) {
- if (!isa<FunctionDecl>(D)) {
- S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
- << A.getRange() << A.getName() << ExpectedFunction;
+static void handleCFAuditedTransferAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (checkAttrMutualExclusion<CFUnknownTransferAttr>(S, D, Attr))
return;
- }
- bool IsAudited = (A.getKind() == AttributeList::AT_CFAuditedTransfer);
+ D->addAttr(::new (S.Context)
+ CFAuditedTransferAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
+}
- // Check whether there's a conflicting attribute already present.
- Attr *Existing;
- if (IsAudited) {
- Existing = D->getAttr<CFUnknownTransferAttr>();
- } else {
- Existing = D->getAttr<CFAuditedTransferAttr>();
- }
- if (Existing) {
- S.Diag(D->getLocStart(), diag::err_attributes_are_not_compatible)
- << A.getName()
- << (IsAudited ? "cf_unknown_transfer" : "cf_audited_transfer")
- << A.getRange() << Existing->getRange();
+static void handleCFUnknownTransferAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (checkAttrMutualExclusion<CFAuditedTransferAttr>(S, D, Attr))
return;
- }
- // All clear; add the attribute.
- if (IsAudited) {
- D->addAttr(::new (S.Context)
- CFAuditedTransferAttr(A.getRange(), S.Context,
- A.getAttributeSpellingListIndex()));
- } else {
- D->addAttr(::new (S.Context)
- CFUnknownTransferAttr(A.getRange(), S.Context,
- A.getAttributeSpellingListIndex()));
- }
+ D->addAttr(::new (S.Context)
+ CFUnknownTransferAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
-static void handleNSBridgedAttr(Sema &S, Scope *Sc, Decl *D,
+static void handleObjCBridgeAttr(Sema &S, Scope *Sc, Decl *D,
const AttributeList &Attr) {
- RecordDecl *RD = dyn_cast<RecordDecl>(D);
- if (!RD || RD->isUnion()) {
- S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
- << Attr.getRange() << Attr.getName() << ExpectedStruct;
- }
-
- IdentifierLoc *Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : 0;
-
- // In Objective-C, verify that the type names an Objective-C type.
- // We don't want to check this outside of ObjC because people sometimes
- // do crazy C declarations of Objective-C types.
- if (Parm && S.getLangOpts().ObjC1) {
- // Check for an existing type with this name.
- LookupResult R(S, DeclarationName(Parm->Ident), Parm->Loc,
- Sema::LookupOrdinaryName);
- if (S.LookupName(R, Sc)) {
- NamedDecl *Target = R.getFoundDecl();
- if (Target && !isa<ObjCInterfaceDecl>(Target)) {
- S.Diag(D->getLocStart(), diag::err_ns_bridged_not_interface);
- S.Diag(Target->getLocStart(), diag::note_declared_at);
- }
- }
- }
+ IdentifierLoc * Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : nullptr;
+ if (!Parm) {
+ S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << Attr.getName() << 0;
+ return;
+ }
+
D->addAttr(::new (S.Context)
- NSBridgedAttr(Attr.getRange(), S.Context, Parm ? Parm->Ident : 0,
+ ObjCBridgeAttr(Attr.getRange(), S.Context, Parm->Ident,
Attr.getAttributeSpellingListIndex()));
}
-static void handleObjCBridgeAttr(Sema &S, Scope *Sc, Decl *D,
- const AttributeList &Attr) {
- if (!isa<RecordDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName()
- << (S.getLangOpts().CPlusPlus ? ExpectedStructOrUnionOrClass
- : ExpectedStructOrUnion);
+static void handleObjCBridgeMutableAttr(Sema &S, Scope *Sc, Decl *D,
+ const AttributeList &Attr) {
+ IdentifierLoc * Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : nullptr;
+
+ if (!Parm) {
+ S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << Attr.getName() << 0;
return;
}
- if (Attr.getNumArgs() != 1) {
- S.Diag(D->getLocStart(), diag::err_objc_bridge_not_id);
+ D->addAttr(::new (S.Context)
+ ObjCBridgeMutableAttr(Attr.getRange(), S.Context, Parm->Ident,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleObjCBridgeRelatedAttr(Sema &S, Scope *Sc, Decl *D,
+ const AttributeList &Attr) {
+ IdentifierInfo *RelatedClass =
+ Attr.isArgIdent(0) ? Attr.getArgAsIdent(0)->Ident : nullptr;
+ if (!RelatedClass) {
+ S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << Attr.getName() << 0;
return;
}
- IdentifierLoc *Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : 0;
- if (!Parm) {
- S.Diag(D->getLocStart(), diag::err_objc_bridge_not_id);
+ IdentifierInfo *ClassMethod =
+ Attr.getArgAsIdent(1) ? Attr.getArgAsIdent(1)->Ident : nullptr;
+ IdentifierInfo *InstanceMethod =
+ Attr.getArgAsIdent(2) ? Attr.getArgAsIdent(2)->Ident : nullptr;
+ D->addAttr(::new (S.Context)
+ ObjCBridgeRelatedAttr(Attr.getRange(), S.Context, RelatedClass,
+ ClassMethod, InstanceMethod,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleObjCDesignatedInitializer(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ ObjCInterfaceDecl *IFace;
+ if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(D->getDeclContext()))
+ IFace = CatDecl->getClassInterface();
+ else
+ IFace = cast<ObjCInterfaceDecl>(D->getDeclContext());
+ IFace->setHasDesignatedInitializers();
+ D->addAttr(::new (S.Context)
+ ObjCDesignatedInitializerAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleObjCRuntimeName(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ StringRef MetaDataName;
+ if (!S.checkStringLiteralArgumentAttr(Attr, 0, MetaDataName))
return;
- }
-
D->addAttr(::new (S.Context)
- ObjCBridgeAttr(Attr.getRange(), S.Context, Parm ? Parm->Ident : 0,
- Attr.getAttributeSpellingListIndex()));
+ ObjCRuntimeNameAttr(Attr.getRange(), S.Context,
+ MetaDataName,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleObjCOwnershipAttr(Sema &S, Decl *D,
@@ -4426,12 +3618,6 @@ static void handleObjCOwnershipAttr(Sema &S, Decl *D,
static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- if (!isa<VarDecl>(D) && !isa<FieldDecl>(D)) {
- S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
- << Attr.getRange() << Attr.getName() << ExpectedVariable;
- return;
- }
-
ValueDecl *vd = cast<ValueDecl>(D);
QualType type = vd->getType();
@@ -4475,19 +3661,18 @@ static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D,
// Microsoft specific attribute handlers.
//===----------------------------------------------------------------------===//
-// Check if MS extensions or some other language extensions are enabled. If
-// not, issue a diagnostic that the given attribute is unused.
-static bool checkMicrosoftExt(Sema &S, const AttributeList &Attr,
- bool OtherExtension = false) {
- if (S.LangOpts.MicrosoftExt || OtherExtension)
- return true;
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
- return false;
-}
-
static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkMicrosoftExt(S, Attr, S.LangOpts.Borland))
+ if (!S.LangOpts.CPlusPlus) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang)
+ << Attr.getName() << AttributeLangSupport::C;
+ return;
+ }
+
+ if (!isa<CXXRecordDecl>(D)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << ExpectedClass;
return;
+ }
StringRef StrRef;
SourceLocation LiteralLoc;
@@ -4521,55 +3706,299 @@ static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) {
Attr.getAttributeSpellingListIndex()));
}
-static void handleInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkMicrosoftExt(S, Attr))
+static void handleMSInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (!S.LangOpts.CPlusPlus) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang)
+ << Attr.getName() << AttributeLangSupport::C;
return;
+ }
+ MSInheritanceAttr *IA = S.mergeMSInheritanceAttr(
+ D, Attr.getRange(), /*BestCase=*/true,
+ Attr.getAttributeSpellingListIndex(),
+ (MSInheritanceAttr::Spelling)Attr.getSemanticSpelling());
+ if (IA)
+ D->addAttr(IA);
+}
- AttributeList::Kind Kind = Attr.getKind();
- if (Kind == AttributeList::AT_SingleInheritance)
- D->addAttr(
- ::new (S.Context)
- SingleInheritanceAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- else if (Kind == AttributeList::AT_MultipleInheritance)
- D->addAttr(
- ::new (S.Context)
- MultipleInheritanceAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- else if (Kind == AttributeList::AT_VirtualInheritance)
- D->addAttr(
- ::new (S.Context)
- VirtualInheritanceAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+static void handleDeclspecThreadAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ VarDecl *VD = cast<VarDecl>(D);
+ if (!S.Context.getTargetInfo().isTLSSupported()) {
+ S.Diag(Attr.getLoc(), diag::err_thread_unsupported);
+ return;
+ }
+ if (VD->getTSCSpec() != TSCS_unspecified) {
+ S.Diag(Attr.getLoc(), diag::err_declspec_thread_on_thread_variable);
+ return;
+ }
+ if (VD->hasLocalStorage()) {
+ S.Diag(Attr.getLoc(), diag::err_thread_non_global) << "__declspec(thread)";
+ return;
+ }
+ VD->addAttr(::new (S.Context) ThreadAttr(
+ Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
}
-static void handlePortabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkMicrosoftExt(S, Attr))
+static void handleARMInterruptAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ // Check the attribute arguments.
+ if (Attr.getNumArgs() > 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
+ << Attr.getName() << 1;
+ return;
+ }
+
+ StringRef Str;
+ SourceLocation ArgLoc;
+
+ if (Attr.getNumArgs() == 0)
+ Str = "";
+ else if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &ArgLoc))
return;
- AttributeList::Kind Kind = Attr.getKind();
- if (Kind == AttributeList::AT_Win64)
- D->addAttr(
- ::new (S.Context) Win64Attr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ ARMInterruptAttr::InterruptType Kind;
+ if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
+ << Attr.getName() << Str << ArgLoc;
+ return;
+ }
+
+ unsigned Index = Attr.getAttributeSpellingListIndex();
+ D->addAttr(::new (S.Context)
+ ARMInterruptAttr(Attr.getLoc(), S.Context, Kind, Index));
}
-static void handleForceInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkMicrosoftExt(S, Attr))
+static void handleMSP430InterruptAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (!checkAttributeNumArgs(S, Attr, 1))
+ return;
+
+ if (!Attr.isArgExpr(0)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName()
+ << AANT_ArgumentIntegerConstant;
+ return;
+ }
+
+ // FIXME: Check for decl - it should be void ()(void).
+
+ Expr *NumParamsExpr = static_cast<Expr *>(Attr.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
+ << 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()
+ << NumParamsExpr->getSourceRange();
return;
+ }
+
D->addAttr(::new (S.Context)
- ForceInlineAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ MSP430InterruptAttr(Attr.getLoc(), S.Context, Num,
+ Attr.getAttributeSpellingListIndex()));
+ D->addAttr(UsedAttr::CreateImplicit(S.Context));
}
-static void handleSelectAnyAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkMicrosoftExt(S, Attr))
+static void handleInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ // Dispatch the interrupt attribute based on the current target.
+ if (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::msp430)
+ handleMSP430InterruptAttr(S, D, Attr);
+ else
+ handleARMInterruptAttr(S, D, Attr);
+}
+
+static void handleX86ForceAlignArgPointerAttr(Sema &S, Decl *D,
+ const AttributeList& Attr) {
+ // 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);
+ if (VD && VD->getType()->isFunctionPointerType())
+ return;
+ // Also don't warn on function pointer typedefs.
+ TypedefNameDecl *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;
return;
- // Check linkage after possibly merging declaratinos. See
- // checkAttributesAfterMerging().
+ }
+
D->addAttr(::new (S.Context)
- SelectAnyAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ X86ForceAlignArgPointerAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range,
+ unsigned AttrSpellingListIndex) {
+ if (D->hasAttr<DLLExportAttr>()) {
+ Diag(Range.getBegin(), diag::warn_attribute_ignored) << "'dllimport'";
+ return nullptr;
+ }
+
+ if (D->hasAttr<DLLImportAttr>())
+ return nullptr;
+
+ return ::new (Context) DLLImportAttr(Range, Context, AttrSpellingListIndex);
+}
+
+DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range,
+ unsigned AttrSpellingListIndex) {
+ if (DLLImportAttr *Import = D->getAttr<DLLImportAttr>()) {
+ Diag(Import->getLocation(), diag::warn_attribute_ignored) << Import;
+ D->dropAttr<DLLImportAttr>();
+ }
+
+ if (D->hasAttr<DLLExportAttr>())
+ return nullptr;
+
+ return ::new (Context) DLLExportAttr(Range, Context, AttrSpellingListIndex);
+}
+
+static void handleDLLAttr(Sema &S, Decl *D, const AttributeList &A) {
+ if (isa<ClassTemplatePartialSpecializationDecl>(D) &&
+ S.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored)
+ << A.getName();
+ return;
+ }
+
+ unsigned Index = A.getAttributeSpellingListIndex();
+ Attr *NewAttr = A.getKind() == AttributeList::AT_DLLExport
+ ? (Attr *)S.mergeDLLExportAttr(D, A.getRange(), Index)
+ : (Attr *)S.mergeDLLImportAttr(D, A.getRange(), Index);
+ if (NewAttr)
+ D->addAttr(NewAttr);
+}
+
+MSInheritanceAttr *
+Sema::mergeMSInheritanceAttr(Decl *D, SourceRange Range, bool BestCase,
+ unsigned AttrSpellingListIndex,
+ MSInheritanceAttr::Spelling SemanticSpelling) {
+ if (MSInheritanceAttr *IA = D->getAttr<MSInheritanceAttr>()) {
+ if (IA->getSemanticSpelling() == SemanticSpelling)
+ return nullptr;
+ Diag(IA->getLocation(), diag::err_mismatched_ms_inheritance)
+ << 1 /*previous declaration*/;
+ Diag(Range.getBegin(), diag::note_previous_ms_inheritance);
+ D->dropAttr<MSInheritanceAttr>();
+ }
+
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(D);
+ if (RD->hasDefinition()) {
+ if (checkMSInheritanceAttrOnDefinition(RD, Range, BestCase,
+ SemanticSpelling)) {
+ return nullptr;
+ }
+ } else {
+ if (isa<ClassTemplatePartialSpecializationDecl>(RD)) {
+ Diag(Range.getBegin(), diag::warn_ignored_ms_inheritance)
+ << 1 /*partial specialization*/;
+ return nullptr;
+ }
+ if (RD->getDescribedClassTemplate()) {
+ Diag(Range.getBegin(), diag::warn_ignored_ms_inheritance)
+ << 0 /*primary template*/;
+ return nullptr;
+ }
+ }
+
+ return ::new (Context)
+ MSInheritanceAttr(Range, Context, BestCase, AttrSpellingListIndex);
+}
+
+static void handleCapabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ // 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
+ // concept, and so they use the same semantic attribute. Eventually, the
+ // lockable attribute will be removed.
+ //
+ // For backward compatibility, any capability which has no specified string
+ // literal will be considered a "mutex."
+ StringRef N("mutex");
+ SourceLocation LiteralLoc;
+ if (Attr.getKind() == AttributeList::AT_Capability &&
+ !S.checkStringLiteralArgumentAttr(Attr, 0, N, &LiteralLoc))
+ return;
+
+ // Currently, there are only two names allowed for a capability: role and
+ // mutex (case insensitive). Diagnose other capability names.
+ 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()));
+}
+
+static void handleAssertCapabilityAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ D->addAttr(::new (S.Context) AssertCapabilityAttr(Attr.getRange(), S.Context,
+ Attr.getArgAsExpr(0),
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleAcquireCapabilityAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ SmallVector<Expr*, 1> Args;
+ if (!checkLockFunAttrCommon(S, D, Attr, Args))
+ return;
+
+ D->addAttr(::new (S.Context) AcquireCapabilityAttr(Attr.getRange(),
+ S.Context,
+ Args.data(), Args.size(),
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleTryAcquireCapabilityAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ SmallVector<Expr*, 2> Args;
+ if (!checkTryLockFunAttrCommon(S, D, Attr, Args))
+ return;
+
+ D->addAttr(::new (S.Context) TryAcquireCapabilityAttr(Attr.getRange(),
+ S.Context,
+ Attr.getArgAsExpr(0),
+ Args.data(),
+ Args.size(),
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleReleaseCapabilityAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ // Check that all arguments are lockable objects.
+ SmallVector<Expr *, 1> Args;
+ checkAttrArgsAreCapabilityObjs(S, D, Attr, Args, 0, true);
+
+ D->addAttr(::new (S.Context) ReleaseCapabilityAttr(
+ Attr.getRange(), S.Context, Args.data(), Args.size(),
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleRequiresCapabilityAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+ return;
+
+ // check that all arguments are lockable objects
+ SmallVector<Expr*, 1> Args;
+ checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
+ if (Args.empty())
+ return;
+
+ RequiresCapabilityAttr *RCA = ::new (S.Context)
+ RequiresCapabilityAttr(Attr.getRange(), S.Context, Args.data(),
+ Args.size(), Attr.getAttributeSpellingListIndex());
+
+ D->addAttr(RCA);
}
/// Handles semantic checking for features that are common to all attributes,
@@ -4583,15 +4012,24 @@ static bool handleCommonAttributeFeatures(Sema &S, Scope *scope, Decl *D,
// We also bail on unknown and ignored attributes because those are handled
// as part of the target-specific handling logic.
if (Attr.hasCustomParsing() ||
- Attr.getKind() == AttributeList::UnknownAttribute ||
- Attr.getKind() == AttributeList::IgnoredAttribute)
+ Attr.getKind() == AttributeList::UnknownAttribute)
return false;
+ // Check whether the attribute requires specific language extensions to be
+ // enabled.
+ if (!Attr.diagnoseLangOpts(S))
+ return true;
+
// If there are no optional arguments, then checking for the argument count
// is trivial.
if (Attr.getMinArgs() == Attr.getMaxArgs() &&
!checkAttributeNumArgs(S, Attr, Attr.getMinArgs()))
return true;
+
+ // Check whether the attribute appertains to the given subject.
+ if (!Attr.diagnoseAppertainsTo(S, D))
+ return true;
+
return false;
}
@@ -4605,7 +4043,7 @@ static bool handleCommonAttributeFeatures(Sema &S, Scope *scope, Decl *D,
static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
const AttributeList &Attr,
bool IncludeCXX11Attributes) {
- if (Attr.isInvalid())
+ if (Attr.isInvalid() || Attr.getKind() == AttributeList::IgnoredAttribute)
return;
// Ignore C++11 attributes on declarator chunks: they appertain to the type
@@ -4613,145 +4051,282 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
if (Attr.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().getTriple())) {
+ S.Diag(Attr.getLoc(), Attr.isDeclspecAttribute()
+ ? diag::warn_unhandled_ms_attribute_ignored
+ : diag::warn_unknown_attribute_ignored)
+ << Attr.getName();
+ return;
+ }
+
if (handleCommonAttributeFeatures(S, scope, D, Attr))
return;
switch (Attr.getKind()) {
- case AttributeList::AT_IBAction: handleIBAction(S, D, Attr); break;
- case AttributeList::AT_IBOutlet: handleIBOutlet(S, D, Attr); break;
+ default:
+ // Type attributes are handled elsewhere; silently move on.
+ assert(Attr.isTypeAttr() && "Non-type attribute not handled");
+ break;
+ case AttributeList::AT_Interrupt:
+ handleInterruptAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_X86ForceAlignArgPointer:
+ handleX86ForceAlignArgPointerAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_DLLExport:
+ case AttributeList::AT_DLLImport:
+ handleDLLAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_Mips16:
+ handleSimpleAttribute<Mips16Attr>(S, D, Attr);
+ break;
+ case AttributeList::AT_NoMips16:
+ handleSimpleAttribute<NoMips16Attr>(S, D, Attr);
+ break;
+ case AttributeList::AT_IBAction:
+ handleSimpleAttribute<IBActionAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_IBOutlet:
+ handleIBOutlet(S, D, Attr);
+ break;
case AttributeList::AT_IBOutletCollection:
- handleIBOutletCollection(S, D, Attr); break;
- case AttributeList::AT_AddressSpace:
- case AttributeList::AT_ObjCGC:
- case AttributeList::AT_VectorSize:
- case AttributeList::AT_NeonVectorType:
- case AttributeList::AT_NeonPolyVectorType:
- case AttributeList::AT_Ptr32:
- case AttributeList::AT_Ptr64:
- case AttributeList::AT_SPtr:
- case AttributeList::AT_UPtr:
- // Ignore these, these are type attributes, handled by
- // ProcessTypeAttributes.
- break;
- case AttributeList::AT_Alias: handleAliasAttr (S, D, Attr); break;
- case AttributeList::AT_Aligned: handleAlignedAttr (S, D, Attr); break;
- case AttributeList::AT_AllocSize: handleAllocSizeAttr (S, D, Attr); break;
+ handleIBOutletCollection(S, D, Attr);
+ break;
+ case AttributeList::AT_Alias:
+ handleAliasAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_Aligned:
+ handleAlignedAttr(S, D, Attr);
+ break;
case AttributeList::AT_AlwaysInline:
- handleAlwaysInlineAttr (S, D, Attr); break;
+ handleAlwaysInlineAttr(S, D, Attr);
+ break;
case AttributeList::AT_AnalyzerNoReturn:
- handleAnalyzerNoReturnAttr (S, D, Attr); break;
- case AttributeList::AT_TLSModel: handleTLSModelAttr (S, D, Attr); break;
- case AttributeList::AT_Annotate: handleAnnotateAttr (S, D, Attr); break;
- case AttributeList::AT_Availability:handleAvailabilityAttr(S, D, Attr); break;
+ handleAnalyzerNoReturnAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_TLSModel:
+ handleTLSModelAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_Annotate:
+ handleAnnotateAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_Availability:
+ handleAvailabilityAttr(S, D, Attr);
+ break;
case AttributeList::AT_CarriesDependency:
handleDependencyAttr(S, scope, D, Attr);
break;
- case AttributeList::AT_Common: handleCommonAttr (S, D, Attr); break;
- case AttributeList::AT_CUDAConstant:handleConstantAttr (S, D, Attr); break;
- case AttributeList::AT_Constructor: handleConstructorAttr (S, D, Attr); break;
+ case AttributeList::AT_Common:
+ handleCommonAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_CUDAConstant:
+ handleSimpleAttribute<CUDAConstantAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_Constructor:
+ handleConstructorAttr(S, D, Attr);
+ break;
case AttributeList::AT_CXX11NoReturn:
- handleCXX11NoReturnAttr(S, D, Attr);
+ handleSimpleAttribute<CXX11NoReturnAttr>(S, D, Attr);
break;
case AttributeList::AT_Deprecated:
handleAttrWithMessage<DeprecatedAttr>(S, D, Attr);
break;
- case AttributeList::AT_Destructor: handleDestructorAttr (S, D, Attr); break;
+ case AttributeList::AT_Destructor:
+ handleDestructorAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_EnableIf:
+ handleEnableIfAttr(S, D, Attr);
+ break;
case AttributeList::AT_ExtVectorType:
handleExtVectorTypeAttr(S, scope, D, Attr);
break;
case AttributeList::AT_MinSize:
- handleMinSizeAttr(S, D, Attr);
- break;
- case AttributeList::AT_Format: handleFormatAttr (S, D, Attr); break;
- case AttributeList::AT_FormatArg: handleFormatArgAttr (S, D, Attr); break;
- case AttributeList::AT_CUDAGlobal: handleGlobalAttr (S, D, Attr); break;
- case AttributeList::AT_CUDADevice: handleDeviceAttr (S, D, Attr); break;
- case AttributeList::AT_CUDAHost: handleHostAttr (S, D, Attr); break;
- case AttributeList::AT_GNUInline: handleGNUInlineAttr (S, D, Attr); break;
+ handleSimpleAttribute<MinSizeAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_OptimizeNone:
+ handleOptimizeNoneAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_Flatten:
+ handleSimpleAttribute<FlattenAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_Format:
+ handleFormatAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_FormatArg:
+ handleFormatArgAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_CUDAGlobal:
+ handleGlobalAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_CUDADevice:
+ handleSimpleAttribute<CUDADeviceAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_CUDAHost:
+ handleSimpleAttribute<CUDAHostAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_GNUInline:
+ handleGNUInlineAttr(S, D, Attr);
+ break;
case AttributeList::AT_CUDALaunchBounds:
handleLaunchBoundsAttr(S, D, Attr);
break;
- case AttributeList::AT_Malloc: handleMallocAttr (S, D, Attr); break;
- case AttributeList::AT_MayAlias: handleMayAliasAttr (S, D, Attr); break;
- case AttributeList::AT_Mode: handleModeAttr (S, D, Attr); break;
- case AttributeList::AT_NoCommon: handleNoCommonAttr (S, D, Attr); break;
- case AttributeList::AT_NonNull: handleNonNullAttr (S, D, Attr); break;
- case AttributeList::AT_Overloadable:handleOverloadableAttr(S, D, Attr); break;
- case AttributeList::AT_ownership_returns:
- case AttributeList::AT_ownership_takes:
- case AttributeList::AT_ownership_holds:
- handleOwnershipAttr (S, D, Attr); break;
- case AttributeList::AT_Cold: handleColdAttr (S, D, Attr); break;
- case AttributeList::AT_Hot: handleHotAttr (S, D, Attr); break;
- case AttributeList::AT_Naked: handleNakedAttr (S, D, Attr); break;
- case AttributeList::AT_NoReturn: handleNoReturnAttr (S, D, Attr); break;
- case AttributeList::AT_NoThrow: handleNothrowAttr (S, D, Attr); break;
- case AttributeList::AT_CUDAShared: handleSharedAttr (S, D, Attr); break;
- case AttributeList::AT_VecReturn: handleVecReturnAttr (S, D, Attr); break;
+ case AttributeList::AT_Malloc:
+ handleMallocAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_MayAlias:
+ handleSimpleAttribute<MayAliasAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_Mode:
+ handleModeAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_NoCommon:
+ handleSimpleAttribute<NoCommonAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_NoSplitStack:
+ handleSimpleAttribute<NoSplitStackAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_NonNull:
+ if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(D))
+ handleNonNullAttrParameter(S, PVD, Attr);
+ else
+ handleNonNullAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_ReturnsNonNull:
+ handleReturnsNonNullAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_Overloadable:
+ handleSimpleAttribute<OverloadableAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_Ownership:
+ handleOwnershipAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_Cold:
+ handleColdAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_Hot:
+ handleHotAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_Naked:
+ handleSimpleAttribute<NakedAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_NoReturn:
+ handleNoReturnAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_NoThrow:
+ handleSimpleAttribute<NoThrowAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_CUDAShared:
+ handleSimpleAttribute<CUDASharedAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_VecReturn:
+ handleVecReturnAttr(S, D, Attr);
+ break;
case AttributeList::AT_ObjCOwnership:
- handleObjCOwnershipAttr(S, D, Attr); break;
+ handleObjCOwnershipAttr(S, D, Attr);
+ break;
case AttributeList::AT_ObjCPreciseLifetime:
- handleObjCPreciseLifetimeAttr(S, D, Attr); break;
+ handleObjCPreciseLifetimeAttr(S, D, Attr);
+ break;
case AttributeList::AT_ObjCReturnsInnerPointer:
- handleObjCReturnsInnerPointerAttr(S, D, Attr); break;
+ handleObjCReturnsInnerPointerAttr(S, D, Attr);
+ break;
case AttributeList::AT_ObjCRequiresSuper:
- handleObjCRequiresSuperAttr(S, D, Attr); break;
-
- case AttributeList::AT_NSBridged:
- handleNSBridgedAttr(S, scope, D, Attr); break;
-
+ handleObjCRequiresSuperAttr(S, D, Attr);
+ break;
+
case AttributeList::AT_ObjCBridge:
- handleObjCBridgeAttr(S, scope, D, Attr); break;
+ handleObjCBridgeAttr(S, scope, D, Attr);
+ break;
+
+ case AttributeList::AT_ObjCBridgeMutable:
+ handleObjCBridgeMutableAttr(S, scope, D, Attr);
+ break;
+
+ case AttributeList::AT_ObjCBridgeRelated:
+ handleObjCBridgeRelatedAttr(S, scope, D, Attr);
+ break;
+ case AttributeList::AT_ObjCDesignatedInitializer:
+ handleObjCDesignatedInitializer(S, D, Attr);
+ break;
+
+ case AttributeList::AT_ObjCRuntimeName:
+ handleObjCRuntimeName(S, D, Attr);
+ break;
+
case AttributeList::AT_CFAuditedTransfer:
+ handleCFAuditedTransferAttr(S, D, Attr);
+ break;
case AttributeList::AT_CFUnknownTransfer:
- handleCFTransferAttr(S, D, Attr); break;
+ handleCFUnknownTransferAttr(S, D, Attr);
+ break;
- // Checker-specific.
case AttributeList::AT_CFConsumed:
- case AttributeList::AT_NSConsumed: handleNSConsumedAttr (S, D, Attr); break;
+ case AttributeList::AT_NSConsumed:
+ handleNSConsumedAttr(S, D, Attr);
+ break;
case AttributeList::AT_NSConsumesSelf:
- handleNSConsumesSelfAttr(S, D, Attr); break;
+ handleSimpleAttribute<NSConsumesSelfAttr>(S, D, Attr);
+ 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); break;
-
+ handleNSReturnsRetainedAttr(S, D, Attr);
+ break;
case AttributeList::AT_WorkGroupSizeHint:
+ handleWorkGroupSize<WorkGroupSizeHintAttr>(S, D, Attr);
+ break;
case AttributeList::AT_ReqdWorkGroupSize:
- handleWorkGroupSize(S, D, Attr); break;
-
+ handleWorkGroupSize<ReqdWorkGroupSizeAttr>(S, D, Attr);
+ break;
case AttributeList::AT_VecTypeHint:
- handleVecTypeHint(S, D, Attr); break;
+ handleVecTypeHint(S, D, Attr);
+ break;
- case AttributeList::AT_InitPriority:
- handleInitPriorityAttr(S, D, Attr); break;
-
- case AttributeList::AT_Packed: handlePackedAttr (S, D, Attr); break;
- case AttributeList::AT_Section: handleSectionAttr (S, D, Attr); break;
+ case AttributeList::AT_InitPriority:
+ handleInitPriorityAttr(S, D, Attr);
+ break;
+
+ case AttributeList::AT_Packed:
+ handlePackedAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_Section:
+ handleSectionAttr(S, D, Attr);
+ break;
case AttributeList::AT_Unavailable:
handleAttrWithMessage<UnavailableAttr>(S, D, Attr);
break;
- case AttributeList::AT_ArcWeakrefUnavailable:
- handleArcWeakrefUnavailableAttr (S, D, Attr);
+ case AttributeList::AT_ArcWeakrefUnavailable:
+ handleSimpleAttribute<ArcWeakrefUnavailableAttr>(S, D, Attr);
break;
case AttributeList::AT_ObjCRootClass:
- handleObjCRootClassAttr(S, D, Attr);
+ handleSimpleAttribute<ObjCRootClassAttr>(S, D, Attr);
break;
- case AttributeList::AT_ObjCRequiresPropertyDefs:
- handleObjCRequiresPropertyDefsAttr (S, D, Attr);
+ case AttributeList::AT_ObjCExplicitProtocolImpl:
+ handleObjCSuppresProtocolAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_ObjCRequiresPropertyDefs:
+ handleSimpleAttribute<ObjCRequiresPropertyDefsAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_Unused:
+ handleSimpleAttribute<UnusedAttr>(S, D, Attr);
break;
- case AttributeList::AT_Unused: handleUnusedAttr (S, D, Attr); break;
case AttributeList::AT_ReturnsTwice:
- handleReturnsTwiceAttr(S, D, Attr);
+ handleSimpleAttribute<ReturnsTwiceAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_Used:
+ handleUsedAttr(S, D, Attr);
break;
- case AttributeList::AT_Used: handleUsedAttr (S, D, Attr); break;
case AttributeList::AT_Visibility:
handleVisibilityAttr(S, D, Attr, false);
break;
@@ -4759,36 +4334,58 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
handleVisibilityAttr(S, D, Attr, true);
break;
case AttributeList::AT_WarnUnused:
- handleWarnUnusedAttr(S, D, Attr);
+ handleSimpleAttribute<WarnUnusedAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_WarnUnusedResult:
+ handleWarnUnusedResult(S, D, Attr);
+ break;
+ case AttributeList::AT_Weak:
+ handleSimpleAttribute<WeakAttr>(S, D, Attr);
break;
- case AttributeList::AT_WarnUnusedResult: handleWarnUnusedResult(S, D, Attr);
+ case AttributeList::AT_WeakRef:
+ handleWeakRefAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_WeakImport:
+ handleWeakImportAttr(S, D, Attr);
break;
- case AttributeList::AT_Weak: handleWeakAttr (S, D, Attr); break;
- case AttributeList::AT_WeakRef: handleWeakRefAttr (S, D, Attr); break;
- case AttributeList::AT_WeakImport: handleWeakImportAttr (S, D, Attr); break;
case AttributeList::AT_TransparentUnion:
handleTransparentUnionAttr(S, D, Attr);
break;
case AttributeList::AT_ObjCException:
- handleObjCExceptionAttr(S, D, Attr);
+ handleSimpleAttribute<ObjCExceptionAttr>(S, D, Attr);
break;
case AttributeList::AT_ObjCMethodFamily:
handleObjCMethodFamilyAttr(S, D, Attr);
break;
- case AttributeList::AT_ObjCNSObject:handleObjCNSObject (S, D, Attr); break;
- case AttributeList::AT_Blocks: handleBlocksAttr (S, D, Attr); break;
- case AttributeList::AT_Sentinel: handleSentinelAttr (S, D, Attr); break;
- case AttributeList::AT_Const: handleConstAttr (S, D, Attr); break;
- case AttributeList::AT_Pure: handlePureAttr (S, D, Attr); break;
- case AttributeList::AT_Cleanup: handleCleanupAttr (S, D, Attr); break;
- case AttributeList::AT_NoDebug: handleNoDebugAttr (S, D, Attr); break;
- case AttributeList::AT_NoInline: handleNoInlineAttr (S, D, Attr); break;
- case AttributeList::AT_Regparm: handleRegparmAttr (S, D, Attr); break;
- case AttributeList::IgnoredAttribute:
- // Just ignore
- break;
- case AttributeList::AT_NoInstrumentFunction: // Interacts with -pg.
- handleNoInstrumentFunctionAttr(S, D, Attr);
+ case AttributeList::AT_ObjCNSObject:
+ handleObjCNSObject(S, D, Attr);
+ break;
+ case AttributeList::AT_Blocks:
+ handleBlocksAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_Sentinel:
+ handleSentinelAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_Const:
+ handleSimpleAttribute<ConstAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_Pure:
+ handleSimpleAttribute<PureAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_Cleanup:
+ handleCleanupAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_NoDebug:
+ handleNoDebugAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_NoDuplicate:
+ handleSimpleAttribute<NoDuplicateAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_NoInline:
+ handleSimpleAttribute<NoInlineAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_NoInstrumentFunction: // Interacts with -pg.
+ handleSimpleAttribute<NoInstrumentFunctionAttr>(S, D, Attr);
break;
case AttributeList::AT_StdCall:
case AttributeList::AT_CDecl:
@@ -4803,32 +4400,27 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
handleCallConvAttr(S, D, Attr);
break;
case AttributeList::AT_OpenCLKernel:
- handleOpenCLKernelAttr(S, D, Attr);
+ handleSimpleAttribute<OpenCLKernelAttr>(S, D, Attr);
break;
case AttributeList::AT_OpenCLImageAccess:
- handleOpenCLImageAccessAttr(S, D, Attr);
+ handleSimpleAttribute<OpenCLImageAccessAttr>(S, D, Attr);
break;
// Microsoft attributes:
case AttributeList::AT_MsStruct:
- handleMsStructAttr(S, D, Attr);
+ handleSimpleAttribute<MsStructAttr>(S, D, Attr);
break;
case AttributeList::AT_Uuid:
handleUuidAttr(S, D, Attr);
break;
- case AttributeList::AT_SingleInheritance:
- case AttributeList::AT_MultipleInheritance:
- case AttributeList::AT_VirtualInheritance:
- handleInheritanceAttr(S, D, Attr);
- break;
- case AttributeList::AT_Win64:
- handlePortabilityAttr(S, D, Attr);
- break;
- case AttributeList::AT_ForceInline:
- handleForceInlineAttr(S, D, Attr);
+ case AttributeList::AT_MSInheritance:
+ handleMSInheritanceAttr(S, D, Attr);
break;
case AttributeList::AT_SelectAny:
- handleSelectAnyAttr(S, D, Attr);
+ handleSimpleAttribute<SelectAnyAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_Thread:
+ handleDeclspecThreadAttr(S, D, Attr);
break;
// Thread safety attributes:
@@ -4839,28 +4431,25 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
handleAssertSharedLockAttr(S, D, Attr);
break;
case AttributeList::AT_GuardedVar:
- handleGuardedVarAttr(S, D, Attr);
+ handleSimpleAttribute<GuardedVarAttr>(S, D, Attr);
break;
case AttributeList::AT_PtGuardedVar:
handlePtGuardedVarAttr(S, D, Attr);
break;
case AttributeList::AT_ScopedLockable:
- handleScopedLockableAttr(S, D, Attr);
+ handleSimpleAttribute<ScopedLockableAttr>(S, D, Attr);
break;
case AttributeList::AT_NoSanitizeAddress:
- handleNoSanitizeAddressAttr(S, D, Attr);
+ handleSimpleAttribute<NoSanitizeAddressAttr>(S, D, Attr);
break;
case AttributeList::AT_NoThreadSafetyAnalysis:
- handleNoThreadSafetyAnalysis(S, D, Attr);
+ handleSimpleAttribute<NoThreadSafetyAnalysisAttr>(S, D, Attr);
break;
case AttributeList::AT_NoSanitizeThread:
- handleNoSanitizeThread(S, D, Attr);
+ handleSimpleAttribute<NoSanitizeThreadAttr>(S, D, Attr);
break;
case AttributeList::AT_NoSanitizeMemory:
- handleNoSanitizeMemory(S, D, Attr);
- break;
- case AttributeList::AT_Lockable:
- handleLockableAttr(S, D, Attr);
+ handleSimpleAttribute<NoSanitizeMemoryAttr>(S, D, Attr);
break;
case AttributeList::AT_GuardedBy:
handleGuardedByAttr(S, D, Attr);
@@ -4868,12 +4457,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_PtGuardedBy:
handlePtGuardedByAttr(S, D, Attr);
break;
- case AttributeList::AT_ExclusiveLockFunction:
- handleExclusiveLockFunctionAttr(S, D, Attr);
- break;
- case AttributeList::AT_ExclusiveLocksRequired:
- handleExclusiveLocksRequiredAttr(S, D, Attr);
- break;
case AttributeList::AT_ExclusiveTrylockFunction:
handleExclusiveTrylockFunctionAttr(S, D, Attr);
break;
@@ -4883,18 +4466,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_LocksExcluded:
handleLocksExcludedAttr(S, D, Attr);
break;
- case AttributeList::AT_SharedLockFunction:
- handleSharedLockFunctionAttr(S, D, Attr);
- break;
- case AttributeList::AT_SharedLocksRequired:
- handleSharedLocksRequiredAttr(S, D, Attr);
- break;
case AttributeList::AT_SharedTrylockFunction:
handleSharedTrylockFunctionAttr(S, D, Attr);
break;
- case AttributeList::AT_UnlockFunction:
- handleUnlockFunAttr(S, D, Attr);
- break;
case AttributeList::AT_AcquiredBefore:
handleAcquiredBeforeAttr(S, D, Attr);
break;
@@ -4902,10 +4476,38 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
handleAcquiredAfterAttr(S, D, Attr);
break;
+ // Capability analysis attributes.
+ case AttributeList::AT_Capability:
+ case AttributeList::AT_Lockable:
+ handleCapabilityAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_RequiresCapability:
+ handleRequiresCapabilityAttr(S, D, Attr);
+ break;
+
+ case AttributeList::AT_AssertCapability:
+ handleAssertCapabilityAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_AcquireCapability:
+ handleAcquireCapabilityAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_ReleaseCapability:
+ handleReleaseCapabilityAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_TryAcquireCapability:
+ handleTryAcquireCapabilityAttr(S, D, Attr);
+ break;
+
// Consumed analysis attributes.
case AttributeList::AT_Consumable:
handleConsumableAttr(S, D, Attr);
break;
+ case AttributeList::AT_ConsumableAutoCast:
+ handleSimpleAttribute<ConsumableAutoCastAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_ConsumableSetOnRead:
+ handleSimpleAttribute<ConsumableSetOnReadAttr>(S, D, Attr);
+ break;
case AttributeList::AT_CallableWhen:
handleCallableWhenAttr(S, D, Attr);
break;
@@ -4929,15 +4531,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_TypeTagForDatatype:
handleTypeTagForDatatypeAttr(S, D, Attr);
break;
-
- default:
- // Ask target about the attribute.
- const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema();
- if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S))
- S.Diag(Attr.getLoc(), Attr.isDeclspecAttribute() ?
- diag::warn_unhandled_ms_attribute_ignored :
- diag::warn_unknown_attribute_ignored) << Attr.getName();
- break;
}
}
@@ -4949,15 +4542,32 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
for (const AttributeList* l = AttrList; l; l = l->getNext())
ProcessDeclAttribute(*this, S, D, *l, 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)->getNameAsString();
+ Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias)
+ << cast<NamedDecl>(D);
D->dropAttr<WeakRefAttr>();
return;
}
+
+ if (!D->hasAttr<OpenCLKernelAttr>()) {
+ // These attributes cannot be applied to a non-kernel function.
+ if (Attr *A = D->getAttr<ReqdWorkGroupSizeAttr>()) {
+ Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
+ D->setInvalidDecl();
+ }
+ if (Attr *A = D->getAttr<WorkGroupSizeHintAttr>()) {
+ Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
+ D->setInvalidDecl();
+ }
+ if (Attr *A = D->getAttr<VecTypeHintAttr>()) {
+ Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
+ D->setInvalidDecl();
+ }
+ }
}
// Annotation attributes are the only attributes allowed after an access
@@ -5009,7 +4619,7 @@ void Sema::checkUnusedDeclAttributes(Declarator &D) {
NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
SourceLocation Loc) {
assert(isa<FunctionDecl>(ND) || isa<VarDecl>(ND));
- NamedDecl *NewD = 0;
+ NamedDecl *NewD = nullptr;
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
FunctionDecl *NewFD;
// FIXME: Missing call to CheckFunctionDeclaration().
@@ -5032,9 +4642,8 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
QualType FDTy = FD->getType();
if (const FunctionProtoType *FT = FDTy->getAs<FunctionProtoType>()) {
SmallVector<ParmVarDecl*, 16> Params;
- for (FunctionProtoType::arg_type_iterator AI = FT->arg_type_begin(),
- AE = FT->arg_type_end(); AI != AE; ++AI) {
- ParmVarDecl *Param = BuildParmVarDeclForTypedef(NewFD, Loc, *AI);
+ for (const auto &AI : FT->param_types()) {
+ ParmVarDecl *Param = BuildParmVarDeclForTypedef(NewFD, Loc, AI);
Param->setScopeInfo(0, Params.size());
Params.push_back(Param);
}
@@ -5061,18 +4670,20 @@ void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...))
IdentifierInfo *NDId = ND->getIdentifier();
NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias(), W.getLocation());
- NewD->addAttr(::new (Context) AliasAttr(W.getLocation(), Context,
- NDId->getName()));
- NewD->addAttr(::new (Context) WeakAttr(W.getLocation(), Context));
+ NewD->addAttr(AliasAttr::CreateImplicit(Context, NDId->getName(),
+ W.getLocation()));
+ NewD->addAttr(WeakAttr::CreateImplicit(Context, W.getLocation()));
WeakTopLevelDecl.push_back(NewD);
// FIXME: "hideous" code from Sema::LazilyCreateBuiltin
// to insert Decl at TU scope, sorry.
DeclContext *SavedContext = CurContext;
CurContext = Context.getTranslationUnitDecl();
+ NewD->setDeclContext(CurContext);
+ NewD->setLexicalDeclContext(CurContext);
PushOnScopeChains(NewD, S);
CurContext = SavedContext;
} else { // just add weak to existing
- ND->addAttr(::new (Context) WeakAttr(W.getLocation(), Context));
+ ND->addAttr(WeakAttr::CreateImplicit(Context, W.getLocation()));
}
}
@@ -5081,7 +4692,7 @@ void Sema::ProcessPragmaWeak(Scope *S, Decl *D) {
// have to do this.
LoadExternalWeakUndeclaredIdentifiers();
if (!WeakUndeclaredIdentifiers.empty()) {
- NamedDecl *ND = NULL;
+ NamedDecl *ND = nullptr;
if (VarDecl *VD = dyn_cast<VarDecl>(D))
if (VD->isExternC())
ND = VD;
@@ -5141,8 +4752,9 @@ static bool isForbiddenTypeAllowed(Sema &S, Decl *decl) {
static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &diag,
Decl *decl) {
if (decl && isForbiddenTypeAllowed(S, decl)) {
- decl->addAttr(new (S.Context) UnavailableAttr(diag.Loc, S.Context,
- "this system declaration uses an unsupported type"));
+ decl->addAttr(UnavailableAttr::CreateImplicit(S.Context,
+ "this system declaration uses an unsupported type",
+ diag.Loc));
return;
}
if (S.getLangOpts().ObjCAutoRefCount)
@@ -5190,9 +4802,11 @@ void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
switch (diag.Kind) {
case DelayedDiagnostic::Deprecation:
- // Don't bother giving deprecation diagnostics if the decl is invalid.
+ case DelayedDiagnostic::Unavailable:
+ // Don't bother giving deprecation/unavailable diagnostics if
+ // the decl is invalid.
if (!decl->isInvalidDecl())
- HandleDelayedDeprecationCheck(diag, decl);
+ HandleDelayedAvailabilityCheck(diag, decl);
break;
case DelayedDiagnostic::Access:
@@ -5227,61 +4841,125 @@ static bool isDeclDeprecated(Decl *D) {
return false;
}
+static bool isDeclUnavailable(Decl *D) {
+ do {
+ if (D->isUnavailable())
+ return true;
+ // A category implicitly has the availability of the interface.
+ if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(D))
+ return CatD->getClassInterface()->isUnavailable();
+ } while ((D = cast_or_null<Decl>(D->getDeclContext())));
+ return false;
+}
+
static void
-DoEmitDeprecationWarning(Sema &S, const NamedDecl *D, StringRef Message,
- SourceLocation Loc,
- const ObjCInterfaceDecl *UnknownObjCClass,
- const ObjCPropertyDecl *ObjCPropery) {
+DoEmitAvailabilityWarning(Sema &S,
+ DelayedDiagnostic::DDKind K,
+ Decl *Ctx,
+ const NamedDecl *D,
+ StringRef Message,
+ SourceLocation Loc,
+ const ObjCInterfaceDecl *UnknownObjCClass,
+ const ObjCPropertyDecl *ObjCProperty,
+ bool ObjCPropertyAccess) {
+
+ // Diagnostics for deprecated or unavailable.
+ unsigned diag, diag_message, diag_fwdclass_message;
+
+ // Matches 'diag::note_property_attribute' options.
+ unsigned property_note_select;
+
+ // Matches diag::note_availability_specified_here.
+ unsigned available_here_select_kind;
+
+ // Don't warn if our current context is deprecated or unavailable.
+ switch (K) {
+ case DelayedDiagnostic::Deprecation:
+ if (isDeclDeprecated(Ctx))
+ return;
+ diag = !ObjCPropertyAccess ? diag::warn_deprecated
+ : diag::warn_property_method_deprecated;
+ diag_message = diag::warn_deprecated_message;
+ diag_fwdclass_message = diag::warn_deprecated_fwdclass_message;
+ property_note_select = /* deprecated */ 0;
+ available_here_select_kind = /* deprecated */ 2;
+ break;
+
+ case DelayedDiagnostic::Unavailable:
+ if (isDeclUnavailable(Ctx))
+ return;
+ diag = !ObjCPropertyAccess ? diag::err_unavailable
+ : diag::err_property_method_unavailable;
+ diag_message = diag::err_unavailable_message;
+ diag_fwdclass_message = diag::warn_unavailable_fwdclass_message;
+ property_note_select = /* unavailable */ 1;
+ available_here_select_kind = /* unavailable */ 0;
+ break;
+
+ default:
+ llvm_unreachable("Neither a deprecation or unavailable kind");
+ }
+
DeclarationName Name = D->getDeclName();
if (!Message.empty()) {
- S.Diag(Loc, diag::warn_deprecated_message) << Name << Message;
- S.Diag(D->getLocation(),
- isa<ObjCMethodDecl>(D) ? diag::note_method_declared_at
- : diag::note_previous_decl) << Name;
- if (ObjCPropery)
- S.Diag(ObjCPropery->getLocation(), diag::note_property_attribute)
- << ObjCPropery->getDeclName() << 0;
+ S.Diag(Loc, diag_message) << Name << Message;
+ if (ObjCProperty)
+ S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
+ << ObjCProperty->getDeclName() << property_note_select;
} else if (!UnknownObjCClass) {
- S.Diag(Loc, diag::warn_deprecated) << D->getDeclName();
- S.Diag(D->getLocation(),
- isa<ObjCMethodDecl>(D) ? diag::note_method_declared_at
- : diag::note_previous_decl) << Name;
- if (ObjCPropery)
- S.Diag(ObjCPropery->getLocation(), diag::note_property_attribute)
- << ObjCPropery->getDeclName() << 0;
+ S.Diag(Loc, diag) << Name;
+ if (ObjCProperty)
+ S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
+ << ObjCProperty->getDeclName() << property_note_select;
} else {
- S.Diag(Loc, diag::warn_deprecated_fwdclass_message) << Name;
+ S.Diag(Loc, diag_fwdclass_message) << Name;
S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class);
}
-}
-void Sema::HandleDelayedDeprecationCheck(DelayedDiagnostic &DD,
- Decl *Ctx) {
- if (isDeclDeprecated(Ctx))
- return;
-
- DD.Triggered = true;
- DoEmitDeprecationWarning(*this, DD.getDeprecationDecl(),
- DD.getDeprecationMessage(), DD.Loc,
- DD.getUnknownObjCClass(),
- DD.getObjCProperty());
+ S.Diag(D->getLocation(), diag::note_availability_specified_here)
+ << D << available_here_select_kind;
}
-void Sema::EmitDeprecationWarning(NamedDecl *D, StringRef Message,
- SourceLocation Loc,
- const ObjCInterfaceDecl *UnknownObjCClass,
- const ObjCPropertyDecl *ObjCProperty) {
+void Sema::HandleDelayedAvailabilityCheck(DelayedDiagnostic &DD,
+ Decl *Ctx) {
+ DD.Triggered = true;
+ DoEmitAvailabilityWarning(*this,
+ (DelayedDiagnostic::DDKind) DD.Kind,
+ Ctx,
+ DD.getDeprecationDecl(),
+ DD.getDeprecationMessage(),
+ DD.Loc,
+ DD.getUnknownObjCClass(),
+ DD.getObjCProperty(), false);
+}
+
+void Sema::EmitAvailabilityWarning(AvailabilityDiagnostic AD,
+ NamedDecl *D, StringRef Message,
+ SourceLocation Loc,
+ const ObjCInterfaceDecl *UnknownObjCClass,
+ const ObjCPropertyDecl *ObjCProperty,
+ bool ObjCPropertyAccess) {
// Delay if we're currently parsing a declaration.
if (DelayedDiagnostics.shouldDelayDiagnostics()) {
- DelayedDiagnostics.add(DelayedDiagnostic::makeDeprecation(Loc, D,
- UnknownObjCClass,
- ObjCProperty,
- Message));
+ DelayedDiagnostics.add(DelayedDiagnostic::makeAvailability(AD, Loc, D,
+ UnknownObjCClass,
+ ObjCProperty,
+ Message,
+ ObjCPropertyAccess));
return;
}
- // Otherwise, don't warn if our current context is deprecated.
- if (isDeclDeprecated(cast<Decl>(getCurLexicalContext())))
- return;
- DoEmitDeprecationWarning(*this, D, Message, Loc, UnknownObjCClass, ObjCProperty);
+ Decl *Ctx = cast<Decl>(getCurLexicalContext());
+ DelayedDiagnostic::DDKind K;
+ switch (AD) {
+ case AD_Deprecation:
+ K = DelayedDiagnostic::Deprecation;
+ break;
+ case AD_Unavailable:
+ K = DelayedDiagnostic::Unavailable;
+ break;
+ }
+
+ DoEmitAvailabilityWarning(*this, K, Ctx, D, Message, Loc,
+ UnknownObjCClass, ObjCProperty, ObjCPropertyAccess);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
index 6b3400a..c5cd83d 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
@@ -18,7 +18,6 @@
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/CharUnits.h"
-#include "clang/AST/DeclVisitor.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecordLayout.h"
@@ -212,11 +211,9 @@ Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc,
"Shouldn't collect exceptions when throw-all is guaranteed.");
ComputedEST = EST_Dynamic;
// Record the exceptions in this function's exception specification.
- for (FunctionProtoType::exception_iterator E = Proto->exception_begin(),
- EEnd = Proto->exception_end();
- E != EEnd; ++E)
- if (ExceptionsSeen.insert(Self->Context.getCanonicalType(*E)))
- Exceptions.push_back(*E);
+ for (const auto &E : Proto->exceptions())
+ if (ExceptionsSeen.insert(Self->Context.getCanonicalType(E)))
+ Exceptions.push_back(E);
}
void Sema::ImplicitExceptionSpecification::CalledExpr(Expr *E) {
@@ -271,7 +268,7 @@ Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg,
ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Arg);
if (Result.isInvalid())
return true;
- Arg = Result.takeAs<Expr>();
+ Arg = Result.getAs<Expr>();
CheckCompletedExpr(Arg, EqualLoc);
Arg = MaybeCreateExprWithCleanups(Arg);
@@ -347,13 +344,16 @@ void Sema::ActOnParamUnparsedDefaultArgument(Decl *param,
/// ActOnParamDefaultArgumentError - Parsing or semantic analysis of
/// the default argument for the parameter param failed.
-void Sema::ActOnParamDefaultArgumentError(Decl *param) {
+void Sema::ActOnParamDefaultArgumentError(Decl *param,
+ SourceLocation EqualLoc) {
if (!param)
return;
ParmVarDecl *Param = cast<ParmVarDecl>(param);
Param->setInvalidDecl();
UnparsedDefaultArgLocs.erase(Param);
+ Param->setDefaultArg(new(Context)
+ OpaqueValueExpr(EqualLoc, Param->getType(), VK_RValue));
}
/// CheckExtraCXXDefaultArguments - Check for any extra default
@@ -380,20 +380,20 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) {
MightBeFunction = false;
continue;
}
- for (unsigned argIdx = 0, e = chunk.Fun.NumArgs; argIdx != e; ++argIdx) {
- ParmVarDecl *Param =
- cast<ParmVarDecl>(chunk.Fun.ArgInfo[argIdx].Param);
+ for (unsigned argIdx = 0, e = chunk.Fun.NumParams; argIdx != e;
+ ++argIdx) {
+ ParmVarDecl *Param = cast<ParmVarDecl>(chunk.Fun.Params[argIdx].Param);
if (Param->hasUnparsedDefaultArg()) {
- CachedTokens *Toks = chunk.Fun.ArgInfo[argIdx].DefaultArgTokens;
+ CachedTokens *Toks = chunk.Fun.Params[argIdx].DefaultArgTokens;
Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
<< SourceRange((*Toks)[1].getLocation(),
Toks->back().getLocation());
delete Toks;
- chunk.Fun.ArgInfo[argIdx].DefaultArgTokens = 0;
+ chunk.Fun.Params[argIdx].DefaultArgTokens = nullptr;
} else if (Param->getDefaultArg()) {
Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
<< Param->getDefaultArg()->getSourceRange();
- Param->setDefaultArg(0);
+ Param->setDefaultArg(nullptr);
}
}
} else if (chunk.Kind != DeclaratorChunk::Paren) {
@@ -479,7 +479,7 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
OldParam->getUninstantiatedDefaultArg());
else
NewParam->setDefaultArg(OldParam->getInit());
- DiagDefaultParamID = diag::warn_param_default_argument_redefinition;
+ DiagDefaultParamID = diag::ext_param_default_argument_redefinition;
Invalid = false;
}
}
@@ -586,6 +586,7 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
}
}
+ const FunctionDecl *Def;
// C++11 [dcl.constexpr]p1: If any declaration of a function or function
// template has a constexpr specifier then all its declarations shall
// contain the constexpr specifier.
@@ -594,6 +595,13 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
<< New << New->isConstexpr();
Diag(Old->getLocation(), diag::note_previous_declaration);
Invalid = true;
+ } else if (!Old->isInlined() && New->isInlined() && Old->isDefined(Def)) {
+ // C++11 [dcl.fcn.spec]p4:
+ // If the definition of a function appears in a translation unit before its
+ // first declaration as inline, the program is ill-formed.
+ Diag(New->getLocation(), diag::err_inline_decl_follows_def) << New;
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ Invalid = true;
}
// C++11 [dcl.fct.default]p4: If a friend declaration specifies a default
@@ -701,7 +709,7 @@ void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) {
for (p = 0; p <= LastMissingDefaultArg; ++p) {
ParmVarDecl *Param = FD->getParamDecl(p);
if (Param->hasDefaultArg()) {
- Param->setDefaultArg(0);
+ Param->setDefaultArg(nullptr);
}
}
}
@@ -714,8 +722,9 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef,
const FunctionDecl *FD) {
unsigned ArgIndex = 0;
const FunctionProtoType *FT = FD->getType()->getAs<FunctionProtoType>();
- for (FunctionProtoType::arg_type_iterator i = FT->arg_type_begin(),
- e = FT->arg_type_end(); i != e; ++i, ++ArgIndex) {
+ for (FunctionProtoType::param_type_iterator i = FT->param_type_begin(),
+ e = FT->param_type_end();
+ i != e; ++i, ++ArgIndex) {
const ParmVarDecl *PD = FD->getParamDecl(ArgIndex);
SourceLocation ParamLoc = PD->getLocation();
if (!(*i)->isDependentType() &&
@@ -760,10 +769,9 @@ bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD) {
Diag(NewFD->getLocation(), diag::err_constexpr_virtual_base)
<< isa<CXXConstructorDecl>(NewFD)
<< getRecordDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases();
- for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
- E = RD->vbases_end(); I != E; ++I)
- Diag(I->getLocStart(),
- diag::note_constexpr_virtual_base_here) << I->getSourceRange();
+ for (const auto &I : RD->vbases())
+ Diag(I.getLocStart(),
+ diag::note_constexpr_virtual_base_here) << I.getSourceRange();
return false;
}
}
@@ -789,7 +797,7 @@ bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD) {
}
// - its return type shall be a literal type;
- QualType RT = NewFD->getResultType();
+ QualType RT = NewFD->getReturnType();
if (!RT->isDependentType() &&
RequireLiteralType(NewFD->getLocation(), RT,
diag::err_constexpr_non_literal_return))
@@ -813,9 +821,8 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl,
// C++11 [dcl.constexpr]p3 and p4:
// The definition of a constexpr function(p3) or constructor(p4) [...] shall
// contain only
- for (DeclStmt::decl_iterator DclIt = DS->decl_begin(),
- DclEnd = DS->decl_end(); DclIt != DclEnd; ++DclIt) {
- switch ((*DclIt)->getKind()) {
+ for (const auto *DclIt : DS->decls()) {
+ switch (DclIt->getKind()) {
case Decl::StaticAssert:
case Decl::Using:
case Decl::UsingShadow:
@@ -831,7 +838,7 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl,
case Decl::TypeAlias: {
// - typedef declarations and alias-declarations that do not define
// classes or enumerations,
- TypedefNameDecl *TN = cast<TypedefNameDecl>(*DclIt);
+ const auto *TN = cast<TypedefNameDecl>(DclIt);
if (TN->getUnderlyingType()->isVariablyModifiedType()) {
// Don't allow variably-modified types in constexpr functions.
TypeLoc TL = TN->getTypeSourceInfo()->getTypeLoc();
@@ -846,7 +853,7 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl,
case Decl::Enum:
case Decl::CXXRecord:
// C++1y allows types to be defined, not just declared.
- if (cast<TagDecl>(*DclIt)->isThisDeclarationADefinition())
+ if (cast<TagDecl>(DclIt)->isThisDeclarationADefinition())
SemaRef.Diag(DS->getLocStart(),
SemaRef.getLangOpts().CPlusPlus1y
? diag::warn_cxx11_compat_constexpr_type_definition
@@ -865,7 +872,7 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl,
// C++1y [dcl.constexpr]p3 allows anything except:
// a definition of a variable of non-literal type or of static or
// thread storage duration or for which no initialization is performed.
- VarDecl *VD = cast<VarDecl>(*DclIt);
+ const auto *VD = cast<VarDecl>(DclIt);
if (VD->isThisDeclarationADefinition()) {
if (VD->isStaticLocal()) {
SemaRef.Diag(VD->getLocation(),
@@ -880,7 +887,8 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl,
diag::err_constexpr_local_var_non_literal_type,
isa<CXXConstructorDecl>(Dcl)))
return false;
- if (!VD->hasInit() && !VD->isCXXForRangeDecl()) {
+ if (!VD->getType()->isDependentType() &&
+ !VD->hasInit() && !VD->isCXXForRangeDecl()) {
SemaRef.Diag(VD->getLocation(),
diag::err_constexpr_local_var_no_init)
<< isa<CXXConstructorDecl>(Dcl);
@@ -932,8 +940,13 @@ static void CheckConstexprCtorInitializer(Sema &SemaRef,
if (Field->isUnnamedBitfield())
return;
+ // Anonymous unions with no variant members and empty anonymous structs do not
+ // need to be explicitly initialized. FIXME: Anonymous structs that contain no
+ // indirect fields don't need initializing.
if (Field->isAnonymousStructOrUnion() &&
- Field->getType()->getAsCXXRecordDecl()->isEmpty())
+ (Field->getType()->isUnionType()
+ ? !Field->getType()->getAsCXXRecordDecl()->hasVariantMembers()
+ : Field->getType()->getAsCXXRecordDecl()->isEmpty()))
return;
if (!Inits.count(Field)) {
@@ -944,12 +957,11 @@ static void CheckConstexprCtorInitializer(Sema &SemaRef,
SemaRef.Diag(Field->getLocation(), diag::note_constexpr_ctor_missing_init);
} else if (Field->isAnonymousStructOrUnion()) {
const RecordDecl *RD = Field->getType()->castAs<RecordType>()->getDecl();
- for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
- I != E; ++I)
+ for (auto *I : RD->fields())
// If an anonymous union contains an anonymous struct of which any member
// is initialized, all members must be initialized.
- if (!RD->isUnion() || Inits.count(*I))
- CheckConstexprCtorInitializer(SemaRef, Dcl, *I, Inits, Diagnosed);
+ if (!RD->isUnion() || Inits.count(I))
+ CheckConstexprCtorInitializer(SemaRef, Dcl, I, Inits, Diagnosed);
}
}
@@ -993,9 +1005,8 @@ CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S,
Cxx1yLoc = S->getLocStart();
CompoundStmt *CompStmt = cast<CompoundStmt>(S);
- for (CompoundStmt::body_iterator BodyIt = CompStmt->body_begin(),
- BodyEnd = CompStmt->body_end(); BodyIt != BodyEnd; ++BodyIt) {
- if (!CheckConstexprFunctionStmt(SemaRef, Dcl, *BodyIt, ReturnStmts,
+ for (auto *BodyIt : CompStmt->body()) {
+ if (!CheckConstexprFunctionStmt(SemaRef, Dcl, BodyIt, ReturnStmts,
Cxx1yLoc))
return false;
}
@@ -1097,9 +1108,8 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) {
// [... list of cases ...]
CompoundStmt *CompBody = cast<CompoundStmt>(Body);
SourceLocation Cxx1yLoc;
- for (CompoundStmt::body_iterator BodyIt = CompBody->body_begin(),
- BodyEnd = CompBody->body_end(); BodyIt != BodyEnd; ++BodyIt) {
- if (!CheckConstexprFunctionStmt(*this, Dcl, *BodyIt, ReturnStmts, Cxx1yLoc))
+ for (auto *BodyIt : CompBody->body()) {
+ if (!CheckConstexprFunctionStmt(*this, Dcl, BodyIt, ReturnStmts, Cxx1yLoc))
return false;
}
@@ -1116,11 +1126,12 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) {
// DR1359:
// - every non-variant non-static data member and base class sub-object
// shall be initialized;
- // - if the class is a non-empty union, or for each non-empty anonymous
- // union member of a non-union class, exactly one non-static data member
+ // DR1460:
+ // - if the class is a union having variant members, exactly one of them
// shall be initialized;
if (RD->isUnion()) {
- if (Constructor->getNumCtorInitializers() == 0 && !RD->isEmpty()) {
+ if (Constructor->getNumCtorInitializers() == 0 &&
+ RD->hasVariantMembers()) {
Diag(Dcl->getLocation(), diag::err_constexpr_union_ctor_no_init);
return false;
}
@@ -1139,25 +1150,26 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) {
break;
}
}
+ // DR1460:
+ // - if the class is a union-like class, but is not a union, for each of
+ // its anonymous union members having variant members, exactly one of
+ // them shall be initialized;
if (AnyAnonStructUnionMembers ||
Constructor->getNumCtorInitializers() != RD->getNumBases() + Fields) {
// Check initialization of non-static data members. Base classes are
// always initialized so do not need to be checked. Dependent bases
// might not have initializers in the member initializer list.
llvm::SmallSet<Decl*, 16> Inits;
- for (CXXConstructorDecl::init_const_iterator
- I = Constructor->init_begin(), E = Constructor->init_end();
- I != E; ++I) {
- if (FieldDecl *FD = (*I)->getMember())
+ for (const auto *I: Constructor->inits()) {
+ if (FieldDecl *FD = I->getMember())
Inits.insert(FD);
- else if (IndirectFieldDecl *ID = (*I)->getIndirectMember())
+ else if (IndirectFieldDecl *ID = I->getIndirectMember())
Inits.insert(ID->chain_begin(), ID->chain_end());
}
bool Diagnosed = false;
- for (CXXRecordDecl::field_iterator I = RD->field_begin(),
- E = RD->field_end(); I != E; ++I)
- CheckConstexprCtorInitializer(*this, Dcl, *I, Inits, Diagnosed);
+ for (auto *I : RD->fields())
+ CheckConstexprCtorInitializer(*this, Dcl, I, Inits, Diagnosed);
if (Diagnosed)
return false;
}
@@ -1165,10 +1177,12 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) {
} else {
if (ReturnStmts.empty()) {
// C++1y doesn't require constexpr functions to contain a 'return'
- // statement. We still do, unless the return type is void, because
+ // statement. We still do, unless the return type might be void, because
// otherwise if there's no return statement, the function cannot
// be used in a core constant expression.
- bool OK = getLangOpts().CPlusPlus1y && Dcl->getResultType()->isVoidType();
+ bool OK = getLangOpts().CPlusPlus1y &&
+ (Dcl->getReturnType()->isVoidType() ||
+ Dcl->getReturnType()->isDependentType());
Diag(Dcl->getLocation(),
OK ? diag::warn_cxx11_compat_constexpr_body_no_return
: diag::err_constexpr_body_no_return);
@@ -1261,10 +1275,8 @@ static bool findCircularInheritance(const CXXRecordDecl *Class,
Class = Class->getCanonicalDecl();
while (true) {
- for (CXXRecordDecl::base_class_const_iterator I = Current->bases_begin(),
- E = Current->bases_end();
- I != E; ++I) {
- CXXRecordDecl *Base = I->getType()->getAsCXXRecordDecl();
+ for (const auto &I : Current->bases()) {
+ CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl();
if (!Base)
continue;
@@ -1287,6 +1299,57 @@ static bool findCircularInheritance(const CXXRecordDecl *Class,
return false;
}
+/// \brief Perform propagation of DLL attributes from a derived class to a
+/// templated base class for MS compatibility.
+static void propagateDLLAttrToBaseClassTemplate(
+ Sema &S, CXXRecordDecl *Class, Attr *ClassAttr,
+ ClassTemplateSpecializationDecl *BaseTemplateSpec, SourceLocation BaseLoc) {
+ if (getDLLAttr(
+ BaseTemplateSpec->getSpecializedTemplate()->getTemplatedDecl())) {
+ // If the base class template has a DLL attribute, don't try to change it.
+ return;
+ }
+
+ if (BaseTemplateSpec->getSpecializationKind() == TSK_Undeclared) {
+ // If the base class is not already specialized, we can do the propagation.
+ auto *NewAttr = cast<InheritableAttr>(ClassAttr->clone(S.getASTContext()));
+ NewAttr->setInherited(true);
+ BaseTemplateSpec->addAttr(NewAttr);
+ return;
+ }
+
+ bool DifferentAttribute = false;
+ if (Attr *SpecializationAttr = getDLLAttr(BaseTemplateSpec)) {
+ if (!SpecializationAttr->isInherited()) {
+ // The template has previously been specialized or instantiated with an
+ // explicit attribute. We should not try to change it.
+ return;
+ }
+ if (SpecializationAttr->getKind() == ClassAttr->getKind()) {
+ // The specialization already has the right attribute.
+ return;
+ }
+ DifferentAttribute = true;
+ }
+
+ // The template was previously instantiated or explicitly specialized without
+ // a dll attribute, or the template was previously instantiated with a
+ // different inherited attribute. It's too late for us to change the
+ // attribute, so warn that this is unsupported.
+ S.Diag(BaseLoc, diag::warn_attribute_dll_instantiated_base_class)
+ << BaseTemplateSpec->isExplicitSpecialization() << DifferentAttribute;
+ S.Diag(ClassAttr->getLocation(), diag::note_attribute);
+ if (BaseTemplateSpec->isExplicitSpecialization()) {
+ S.Diag(BaseTemplateSpec->getLocation(),
+ diag::note_template_class_explicit_specialization_was_here)
+ << BaseTemplateSpec;
+ } else {
+ S.Diag(BaseTemplateSpec->getPointOfInstantiation(),
+ diag::note_template_class_instantiation_was_here)
+ << BaseTemplateSpec;
+ }
+}
+
/// \brief Check the validity of a C++ base class specifier.
///
/// \returns a new CXXBaseSpecifier if well-formed, emits diagnostics
@@ -1304,7 +1367,7 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
if (Class->isUnion()) {
Diag(Class->getLocation(), diag::err_base_clause_on_union)
<< SpecifierRange;
- return 0;
+ return nullptr;
}
if (EllipsisLoc.isValid() &&
@@ -1330,8 +1393,8 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
if (BaseDecl->getCanonicalDecl() != Class->getCanonicalDecl())
Diag(BaseDecl->getLocation(), diag::note_previous_decl)
<< BaseType;
-
- return 0;
+
+ return nullptr;
}
}
@@ -1343,14 +1406,25 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
// Base specifiers must be record types.
if (!BaseType->isRecordType()) {
Diag(BaseLoc, diag::err_base_must_be_class) << SpecifierRange;
- return 0;
+ return nullptr;
}
// C++ [class.union]p1:
// A union shall not be used as a base class.
if (BaseType->isUnionType()) {
Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange;
- return 0;
+ return nullptr;
+ }
+
+ // For the MS ABI, propagate DLL attributes to base class templates.
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ if (Attr *ClassAttr = getDLLAttr(Class)) {
+ if (auto *BaseTemplate = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
+ BaseType->getAsCXXRecordDecl())) {
+ propagateDLLAttrToBaseClassTemplate(*this, Class, ClassAttr,
+ BaseTemplate, BaseLoc);
+ }
+ }
}
// C++ [class.derived]p2:
@@ -1359,7 +1433,7 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
if (RequireCompleteType(BaseLoc, BaseType,
diag::err_incomplete_base_class, SpecifierRange)) {
Class->setInvalidDecl();
- return 0;
+ return nullptr;
}
// If the base class is polymorphic or isn't empty, the new one is/isn't, too.
@@ -1379,7 +1453,7 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
if (CXXBaseDecl->hasFlexibleArrayMember()) {
Diag(BaseLoc, diag::err_base_class_has_flexible_array_member)
<< CXXBaseDecl->getDeclName();
- return 0;
+ return nullptr;
}
// C++ [class]p3:
@@ -1389,9 +1463,9 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
Diag(BaseLoc, diag::err_class_marked_final_used_as_base)
<< CXXBaseDecl->getDeclName()
<< FA->isSpelledAsSealed();
- Diag(CXXBaseDecl->getLocation(), diag::note_previous_decl)
- << CXXBaseDecl->getDeclName();
- return 0;
+ Diag(CXXBaseDecl->getLocation(), diag::note_entity_declared_at)
+ << CXXBaseDecl->getDeclName() << FA->getRange();
+ return nullptr;
}
if (BaseDecl->isInvalidDecl())
@@ -1422,6 +1496,9 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
if (!Class)
return true;
+ // We haven't yet attached the base specifiers.
+ Class->setIsParsingBaseSpecifiers();
+
// We do not support any C++11 attributes on base-specifiers yet.
// Diagnose any attributes we see.
if (!Attributes.empty()) {
@@ -1438,7 +1515,7 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
}
}
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
GetTypeFromParser(basetype, &TInfo);
if (EllipsisLoc.isInvalid() &&
@@ -1509,7 +1586,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
Invalid = true;
}
if (RD->hasAttr<WeakAttr>())
- Class->addAttr(::new (Context) WeakAttr(SourceRange(), Context));
+ Class->addAttr(WeakAttr::CreateImplicit(Context));
}
}
}
@@ -1841,10 +1918,10 @@ static bool InitializationHasSideEffects(const FieldDecl &FD) {
}
static AttributeList *getMSPropertyAttr(AttributeList *list) {
- for (AttributeList* it = list; it != 0; it = it->getNext())
+ for (AttributeList *it = list; it != nullptr; it = it->getNext())
if (it->isDeclspecPropertyAttribute())
return it;
- return 0;
+ return nullptr;
}
/// ActOnCXXMemberDeclarator - This is invoked when a C++ class member
@@ -1913,7 +1990,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
else
Diag(Loc, diag::err_invalid_member_in_interface)
<< (InvalidDecl-1) << "";
- return 0;
+ return nullptr;
}
}
@@ -1952,20 +2029,26 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr_member);
SourceLocation ConstexprLoc = DS.getConstexprSpecLoc();
if (InitStyle == ICIS_NoInit) {
- B << 0 << 0 << FixItHint::CreateReplacement(ConstexprLoc, "const");
- D.getMutableDeclSpec().ClearConstexprSpec();
- const char *PrevSpec;
- unsigned DiagID;
- bool Failed = D.getMutableDeclSpec().SetTypeQual(DeclSpec::TQ_const, ConstexprLoc,
- PrevSpec, DiagID, getLangOpts());
- (void)Failed;
- assert(!Failed && "Making a constexpr member const shouldn't fail");
+ B << 0 << 0;
+ if (D.getDeclSpec().getTypeQualifiers() & DeclSpec::TQ_const)
+ B << FixItHint::CreateRemoval(ConstexprLoc);
+ else {
+ B << FixItHint::CreateReplacement(ConstexprLoc, "const");
+ D.getMutableDeclSpec().ClearConstexprSpec();
+ const char *PrevSpec;
+ unsigned DiagID;
+ bool Failed = D.getMutableDeclSpec().SetTypeQual(
+ DeclSpec::TQ_const, ConstexprLoc, PrevSpec, DiagID, getLangOpts());
+ (void)Failed;
+ assert(!Failed && "Making a constexpr member const shouldn't fail");
+ }
} else {
B << 1;
const char *PrevSpec;
unsigned DiagID;
if (D.getMutableDeclSpec().SetStorageClassSpec(
- *this, DeclSpec::SCS_static, ConstexprLoc, PrevSpec, DiagID)) {
+ *this, DeclSpec::SCS_static, ConstexprLoc, PrevSpec, DiagID,
+ Context.getPrintingPolicy())) {
assert(DS.getStorageClassSpec() == DeclSpec::SCS_mutable &&
"This is the only DeclSpec that should fail to be applied");
B << 1;
@@ -1984,7 +2067,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
if (!Name.isIdentifier()) {
Diag(Loc, diag::err_bad_variable_name)
<< Name;
- return 0;
+ return nullptr;
}
IdentifierInfo *II = Name.getAsIdentifierInfo();
@@ -2007,7 +2090,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
<< SourceRange(TemplateParams->getTemplateLoc(),
TemplateParams->getRAngleLoc());
}
- return 0;
+ return nullptr;
}
if (SS.isSet() && !SS.isInvalid()) {
@@ -2032,7 +2115,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
Member = HandleMSProperty(S, cast<CXXRecordDecl>(CurContext), Loc, D,
BitWidth, InitStyle, AS, MSPropertyAttr);
if (!Member)
- return 0;
+ return nullptr;
isInstField = false;
} else {
Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D,
@@ -2044,7 +2127,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
Member = HandleDeclarator(S, D, TemplateParameterLists);
if (!Member)
- return 0;
+ return nullptr;
// Non-instance-fields can't have a bitfield.
if (BitWidth) {
@@ -2067,7 +2150,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
<< BitWidth->getSourceRange();
}
- BitWidth = 0;
+ BitWidth = nullptr;
Member->setInvalidDecl();
}
@@ -2082,7 +2165,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
}
if (VS.isOverrideSpecified())
- Member->addAttr(new (Context) OverrideAttr(VS.getOverrideLoc(), Context));
+ Member->addAttr(new (Context) OverrideAttr(VS.getOverrideLoc(), Context, 0));
if (VS.isFinalSpecified())
Member->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context,
VS.isFinalSpelledSealed()));
@@ -2101,9 +2184,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
FieldDecl *FD = cast<FieldDecl>(Member);
FieldCollector->Add(FD);
- if (Diags.getDiagnosticLevel(diag::warn_unused_private_field,
- FD->getLocation())
- != DiagnosticsEngine::Ignored) {
+ if (!Diags.isIgnored(diag::warn_unused_private_field, FD->getLocation())) {
// Remember all explicit private FieldDecls that have a name, no side
// effects and are not part of a dependent type declaration.
if (!FD->isImplicit() && FD->getDeclName() &&
@@ -2278,7 +2359,7 @@ namespace {
// In class initializers will point to the constructor.
UninitializedFieldVisitor(S, Decls, Constructor).Visit(E);
} else {
- UninitializedFieldVisitor(S, Decls, 0).Visit(E);
+ UninitializedFieldVisitor(S, Decls, nullptr).Visit(E);
}
}
@@ -2291,9 +2372,8 @@ namespace {
static void DiagnoseUninitializedFields(
Sema &SemaRef, const CXXConstructorDecl *Constructor) {
- if (SemaRef.getDiagnostics().getDiagnosticLevel(diag::warn_field_is_uninit,
- Constructor->getLocation())
- == DiagnosticsEngine::Ignored) {
+ if (SemaRef.getDiagnostics().isIgnored(diag::warn_field_is_uninit,
+ Constructor->getLocation())) {
return;
}
@@ -2306,38 +2386,44 @@ namespace {
llvm::SmallPtrSet<ValueDecl*, 4> UninitializedFields;
// At the beginning, all fields are uninitialized.
- for (DeclContext::decl_iterator I = RD->decls_begin(), E = RD->decls_end();
- I != E; ++I) {
- if (FieldDecl *FD = dyn_cast<FieldDecl>(*I)) {
+ for (auto *I : RD->decls()) {
+ if (auto *FD = dyn_cast<FieldDecl>(I)) {
UninitializedFields.insert(FD);
- } else if (IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(*I)) {
+ } else if (auto *IFD = dyn_cast<IndirectFieldDecl>(I)) {
UninitializedFields.insert(IFD->getAnonField());
}
}
- for (CXXConstructorDecl::init_const_iterator FieldInit =
- Constructor->init_begin(),
- FieldInitEnd = Constructor->init_end();
- FieldInit != FieldInitEnd; ++FieldInit) {
-
- Expr *InitExpr = (*FieldInit)->getInit();
+ for (const auto *FieldInit : Constructor->inits()) {
+ Expr *InitExpr = FieldInit->getInit();
CheckInitExprContainsUninitializedFields(
SemaRef, InitExpr, UninitializedFields, Constructor);
- if (FieldDecl *Field = (*FieldInit)->getAnyMember())
+ if (FieldDecl *Field = FieldInit->getAnyMember())
UninitializedFields.erase(Field);
}
}
} // namespace
-/// ActOnCXXInClassMemberInitializer - 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::ActOnCXXInClassMemberInitializer(Decl *D, SourceLocation InitLoc,
- Expr *InitExpr) {
+/// \brief 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() {
+ // Create a synthetic function scope to represent the call to the constructor
+ // that notionally surrounds a use of this initializer.
+ PushFunctionScope();
+}
+
+/// \brief 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,
+ SourceLocation InitLoc,
+ Expr *InitExpr) {
+ // Pop the notional constructor scope we created earlier.
+ PopFunctionScopeInfo(nullptr, D);
+
FieldDecl *FD = cast<FieldDecl>(D);
assert(FD->getInClassInitStyle() != ICIS_NoInit &&
"must set init style when field is created");
@@ -2371,13 +2457,13 @@ Sema::ActOnCXXInClassMemberInitializer(Decl *D, SourceLocation InitLoc,
// C++11 [class.base.init]p7:
// The initialization of each base and member constitutes a
// full-expression.
- Init = ActOnFinishFullExpr(Init.take(), InitLoc);
+ Init = ActOnFinishFullExpr(Init.get(), InitLoc);
if (Init.isInvalid()) {
FD->setInvalidDecl();
return;
}
- InitExpr = Init.release();
+ InitExpr = Init.get();
FD->setInClassInitializer(InitExpr);
}
@@ -2391,14 +2477,12 @@ static bool FindBaseInitializer(Sema &SemaRef,
const CXXBaseSpecifier *&DirectBaseSpec,
const CXXBaseSpecifier *&VirtualBaseSpec) {
// First, check for a direct base class.
- DirectBaseSpec = 0;
- for (CXXRecordDecl::base_class_const_iterator Base
- = ClassDecl->bases_begin();
- Base != ClassDecl->bases_end(); ++Base) {
- if (SemaRef.Context.hasSameUnqualifiedType(BaseType, Base->getType())) {
+ DirectBaseSpec = nullptr;
+ for (const auto &Base : ClassDecl->bases()) {
+ if (SemaRef.Context.hasSameUnqualifiedType(BaseType, Base.getType())) {
// We found a direct base of this type. That's what we're
// initializing.
- DirectBaseSpec = &*Base;
+ DirectBaseSpec = &Base;
break;
}
}
@@ -2406,7 +2490,7 @@ static bool FindBaseInitializer(Sema &SemaRef,
// Check for a virtual base class.
// FIXME: We might be able to short-circuit this if we know in advance that
// there are no virtual bases.
- VirtualBaseSpec = 0;
+ VirtualBaseSpec = nullptr;
if (!DirectBaseSpec || !DirectBaseSpec->isVirtual()) {
// We haven't found a base yet; search the class hierarchy for a
// virtual base class.
@@ -2471,7 +2555,7 @@ public:
explicit MemInitializerValidatorCCC(CXXRecordDecl *ClassDecl)
: ClassDecl(ClassDecl) {}
- bool ValidateCandidate(const TypoCorrection &candidate) LLVM_OVERRIDE {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
if (NamedDecl *ND = candidate.getCorrectionDecl()) {
if (FieldDecl *Member = dyn_cast<FieldDecl>(ND))
return Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl);
@@ -2543,7 +2627,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
}
// It didn't name a member, so see if it names a class.
QualType BaseType;
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
if (TemplateTypeTy) {
BaseType = GetTypeFromParser(TemplateTypeTy, &TInfo);
@@ -2585,7 +2669,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
MemInitializerValidatorCCC Validator(ClassDecl);
if (R.empty() && BaseType.isNull() &&
(Corr = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, &SS,
- Validator, ClassDecl))) {
+ Validator, CTK_ErrorRecovery, ClassDecl))) {
if (FieldDecl *Member = Corr.getCorrectionDeclAs<FieldDecl>()) {
// We have found a non-static data member with a similar
// name to what was typed; complain and initialize that
@@ -2629,13 +2713,10 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
if (BaseType.isNull()) {
BaseType = Context.getTypeDeclType(TyD);
- if (SS.isSet()) {
- NestedNameSpecifier *Qualifier =
- static_cast<NestedNameSpecifier*>(SS.getScopeRep());
-
+ if (SS.isSet())
// FIXME: preserve source range information
- BaseType = Context.getElaboratedType(ETK_None, Qualifier, BaseType);
- }
+ BaseType = Context.getElaboratedType(ETK_None, SS.getScopeRep(),
+ BaseType);
}
}
@@ -2731,15 +2812,17 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
// Initialize the member.
InitializedEntity MemberEntity =
- DirectMember ? InitializedEntity::InitializeMember(DirectMember, 0)
- : InitializedEntity::InitializeMember(IndirectMember, 0);
+ DirectMember ? InitializedEntity::InitializeMember(DirectMember, nullptr)
+ : InitializedEntity::InitializeMember(IndirectMember,
+ nullptr);
InitializationKind Kind =
InitList ? InitializationKind::CreateDirectList(IdLoc)
: InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(),
InitRange.getEnd());
InitializationSequence InitSeq(*this, MemberEntity, Kind, Args);
- ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind, Args, 0);
+ ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind, Args,
+ nullptr);
if (MemberInit.isInvalid())
return true;
@@ -2792,7 +2875,7 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init,
InitRange.getEnd());
InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args);
ExprResult DelegationInit = InitSeq.Perform(*this, DelegationEntity, Kind,
- Args, 0);
+ Args, nullptr);
if (DelegationInit.isInvalid())
return true;
@@ -2815,10 +2898,10 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init,
// initializer. However, deconstructing the ASTs is a dicey process,
// and this approach is far more likely to get the corner cases right.
if (CurContext->isDependentContext())
- DelegationInit = Owned(Init);
+ DelegationInit = Init;
return new (Context) CXXCtorInitializer(Context, TInfo, InitRange.getBegin(),
- DelegationInit.takeAs<Expr>(),
+ DelegationInit.getAs<Expr>(),
InitRange.getEnd());
}
@@ -2860,8 +2943,8 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
}
// Check for direct and virtual base classes.
- const CXXBaseSpecifier *DirectBaseSpec = 0;
- const CXXBaseSpecifier *VirtualBaseSpec = 0;
+ const CXXBaseSpecifier *DirectBaseSpec = nullptr;
+ const CXXBaseSpecifier *VirtualBaseSpec = nullptr;
if (!Dependent) {
if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0),
BaseType))
@@ -2925,7 +3008,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
: InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(),
InitRange.getEnd());
InitializationSequence InitSeq(*this, BaseEntity, Kind, Args);
- ExprResult BaseInit = InitSeq.Perform(*this, BaseEntity, Kind, Args, 0);
+ ExprResult BaseInit = InitSeq.Perform(*this, BaseEntity, Kind, Args, nullptr);
if (BaseInit.isInvalid())
return true;
@@ -2944,12 +3027,12 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
// initializer. However, deconstructing the ASTs is a dicey process,
// and this approach is far more likely to get the corner cases right.
if (CurContext->isDependentContext())
- BaseInit = Owned(Init);
+ BaseInit = Init;
return new (Context) CXXCtorInitializer(Context, BaseTInfo,
BaseSpec->isVirtual(),
InitRange.getBegin(),
- BaseInit.takeAs<Expr>(),
+ BaseInit.getAs<Expr>(),
InitRange.getEnd(), EllipsisLoc);
}
@@ -2964,7 +3047,7 @@ static Expr *CastForMoving(Sema &SemaRef, Expr *E, QualType T = QualType()) {
return SemaRef.BuildCXXNamedCast(ExprLoc, tok::kw_static_cast, TargetLoc, E,
SourceRange(ExprLoc, ExprLoc),
- E->getSourceRange()).take();
+ E->getSourceRange()).get();
}
/// ImplicitInitializerKind - How an implicit base or member initializer should
@@ -3006,7 +3089,7 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
VK_LValue, SourceLocation());
if (ArgExpr.isInvalid())
return true;
- Args.push_back(CastForMoving(SemaRef, ArgExpr.take(), PD->getType()));
+ Args.push_back(CastForMoving(SemaRef, ArgExpr.get(), PD->getType()));
}
InitializationKind InitKind = InitializationKind::CreateDirect(
@@ -3035,7 +3118,7 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(),
SourceLocation(), Param, false,
Constructor->getLocation(), ParamType,
- VK_LValue, 0);
+ VK_LValue, nullptr);
SemaRef.MarkDeclRefReferenced(cast<DeclRefExpr>(CopyCtorArg));
@@ -3053,7 +3136,7 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
CopyCtorArg = SemaRef.ImpCastExprToType(CopyCtorArg, ArgTy,
CK_UncheckedDerivedToBase,
Moving ? VK_XValue : VK_LValue,
- &BasePath).take();
+ &BasePath).get();
InitializationKind InitKind
= InitializationKind::CreateDirect(Constructor->getLocation(),
@@ -3074,7 +3157,7 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
SourceLocation()),
BaseSpec->isVirtual(),
SourceLocation(),
- BaseInit.takeAs<Expr>(),
+ BaseInit.getAs<Expr>(),
SourceLocation(),
SourceLocation());
@@ -3108,7 +3191,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
Expr *MemberExprBase =
DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(),
SourceLocation(), Param, false,
- Loc, ParamType, VK_LValue, 0);
+ Loc, ParamType, VK_LValue, nullptr);
SemaRef.MarkDeclRefReferenced(cast<DeclRefExpr>(MemberExprBase));
@@ -3129,9 +3212,9 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
/*IsArrow=*/false,
SS,
/*TemplateKWLoc=*/SourceLocation(),
- /*FirstQualifierInScope=*/0,
+ /*FirstQualifierInScope=*/nullptr,
MemberLookup,
- /*TemplateArgs=*/0);
+ /*TemplateArgs=*/nullptr);
if (CtorArg.isInvalid())
return true;
@@ -3139,7 +3222,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
// - if a member m has rvalue reference type T&&, it is direct-initialized
// with static_cast<T&&>(x.m);
if (RefersToRValueRef(CtorArg.get())) {
- CtorArg = CastForMoving(SemaRef, CtorArg.take());
+ CtorArg = CastForMoving(SemaRef, CtorArg.get());
}
// When the field we are copying is an array, create index variables for
@@ -3154,7 +3237,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
= SemaRef.Context.getAsConstantArrayType(BaseType)) {
InitializingArray = true;
// Create the iteration variable for this array index.
- IdentifierInfo *IterationVarName = 0;
+ IdentifierInfo *IterationVarName = nullptr;
{
SmallString<8> Str;
llvm::raw_svector_ostream OS(Str);
@@ -3173,13 +3256,13 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
= SemaRef.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc);
assert(!IterationVarRef.isInvalid() &&
"Reference to invented variable cannot fail!");
- IterationVarRef = SemaRef.DefaultLvalueConversion(IterationVarRef.take());
+ IterationVarRef = SemaRef.DefaultLvalueConversion(IterationVarRef.get());
assert(!IterationVarRef.isInvalid() &&
"Conversion of invented variable cannot fail!");
// Subscript the array with this iteration variable.
- CtorArg = SemaRef.CreateBuiltinArraySubscriptExpr(CtorArg.take(), Loc,
- IterationVarRef.take(),
+ CtorArg = SemaRef.CreateBuiltinArraySubscriptExpr(CtorArg.get(), Loc,
+ IterationVarRef.get(),
Loc);
if (CtorArg.isInvalid())
return true;
@@ -3189,7 +3272,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
// The array subscript expression is an lvalue, which is wrong for moving.
if (Moving && InitializingArray)
- CtorArg = CastForMoving(SemaRef, CtorArg.take());
+ CtorArg = CastForMoving(SemaRef, CtorArg.get());
// Construct the entity that we will be initializing. For an array, this
// will be first element in the array, which may require several levels
@@ -3209,7 +3292,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
InitializationKind InitKind =
InitializationKind::CreateDirect(Loc, SourceLocation(), SourceLocation());
- Expr *CtorArgE = CtorArg.takeAs<Expr>();
+ Expr *CtorArgE = CtorArg.getAs<Expr>();
InitializationSequence InitSeq(SemaRef, Entities.back(), InitKind, CtorArgE);
ExprResult MemberInit
@@ -3225,11 +3308,11 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
CXXMemberInit
= new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Indirect,
Loc, Loc,
- MemberInit.takeAs<Expr>(),
+ MemberInit.getAs<Expr>(),
Loc);
} else
CXXMemberInit = CXXCtorInitializer::Create(SemaRef.Context, Field, Loc,
- Loc, MemberInit.takeAs<Expr>(),
+ Loc, MemberInit.getAs<Expr>(),
Loc,
IndexVariables.data(),
IndexVariables.size());
@@ -3308,7 +3391,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
}
// Nothing to initialize.
- CXXMemberInit = 0;
+ CXXMemberInit = nullptr;
return false;
}
@@ -3320,6 +3403,7 @@ struct BaseAndFieldInfo {
ImplicitInitializerKind IIK;
llvm::DenseMap<const void *, CXXCtorInitializer*> AllBaseFields;
SmallVector<CXXCtorInitializer*, 8> AllToInit;
+ llvm::DenseMap<TagDecl*, FieldDecl*> ActiveUnionMember;
BaseAndFieldInfo(Sema &S, CXXConstructorDecl *Ctor, bool ErrorsInInits)
: S(S), Ctor(Ctor), AnyErrorsInInits(ErrorsInInits) {
@@ -3357,20 +3441,48 @@ struct BaseAndFieldInfo {
return false;
}
-};
-}
-/// \brief Determine whether the given indirect field declaration is somewhere
-/// within an anonymous union.
-static bool isWithinAnonymousUnion(IndirectFieldDecl *F) {
- for (IndirectFieldDecl::chain_iterator C = F->chain_begin(),
- CEnd = F->chain_end();
- C != CEnd; ++C)
- if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>((*C)->getDeclContext()))
- if (Record->isUnion())
+ bool isInactiveUnionMember(FieldDecl *Field) {
+ RecordDecl *Record = Field->getParent();
+ if (!Record->isUnion())
+ return false;
+
+ if (FieldDecl *Active =
+ ActiveUnionMember.lookup(Record->getCanonicalDecl()))
+ return Active != Field->getCanonicalDecl();
+
+ // In an implicit copy or move constructor, ignore any in-class initializer.
+ if (isImplicitCopyOrMove())
+ return true;
+
+ // If there's no explicit initialization, the field is active only if it
+ // has an in-class initializer...
+ if (Field->hasInClassInitializer())
+ return false;
+ // ... or it's an anonymous struct or union whose class has an in-class
+ // initializer.
+ if (!Field->isAnonymousStructOrUnion())
+ return true;
+ CXXRecordDecl *FieldRD = Field->getType()->getAsCXXRecordDecl();
+ return !FieldRD->hasInClassInitializer();
+ }
+
+ /// \brief 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,
+ IndirectFieldDecl *Indirect) {
+ if (!Indirect)
+ return isInactiveUnionMember(Field);
+
+ for (auto *C : Indirect->chain()) {
+ FieldDecl *Field = dyn_cast<FieldDecl>(C);
+ if (Field && isInactiveUnionMember(Field))
return true;
-
- return false;
+ }
+ return false;
+ }
+};
}
/// \brief Determine whether the given type is an incomplete or zero-lenfgth
@@ -3391,17 +3503,30 @@ static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) {
static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
FieldDecl *Field,
- IndirectFieldDecl *Indirect = 0) {
+ IndirectFieldDecl *Indirect = nullptr) {
if (Field->isInvalidDecl())
return false;
// Overwhelmingly common case: we have a direct initializer for this field.
- if (CXXCtorInitializer *Init = Info.AllBaseFields.lookup(Field))
+ if (CXXCtorInitializer *Init =
+ Info.AllBaseFields.lookup(Field->getCanonicalDecl()))
return Info.addFieldInitializer(Init);
- // C++11 [class.base.init]p8: if the entity is a non-static data member that
- // has a brace-or-equal-initializer, the entity is initialized as specified
- // in [dcl.init].
+ // C++11 [class.base.init]p8:
+ // if the entity is a non-static data member that has a
+ // brace-or-equal-initializer and either
+ // -- the constructor's class is a union and no other variant member of that
+ // union is designated by a mem-initializer-id or
+ // -- the constructor's class is not a union, and, if the entity is a member
+ // of an anonymous union, no other member of that union is designated by
+ // a mem-initializer-id,
+ // the entity is initialized as specified in [dcl.init].
+ //
+ // We also apply the same rules to handle anonymous structs within anonymous
+ // unions.
+ if (Info.isWithinInactiveUnionMember(Field, Indirect))
+ return false;
+
if (Field->hasInClassInitializer() && !Info.isImplicitCopyOrMove()) {
Expr *DIE = CXXDefaultInitExpr::Create(SemaRef.Context,
Info.Ctor->getLocation(), Field);
@@ -3419,12 +3544,6 @@ static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
return Info.addFieldInitializer(Init);
}
- // Don't build an implicit initializer for union members if none was
- // explicitly specified.
- if (Field->getParent()->isUnion() ||
- (Indirect && isWithinAnonymousUnion(Indirect)))
- return false;
-
// Don't initialize incomplete or zero-length arrays.
if (isIncompleteOrZeroLengthArrayType(SemaRef.Context, Field->getType()))
return false;
@@ -3435,7 +3554,7 @@ static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
if (Info.AnyErrorsInInits)
return false;
- CXXCtorInitializer *Init = 0;
+ CXXCtorInitializer *Init = nullptr;
if (BuildImplicitMemberInitializer(Info.S, Info.Ctor, Info.IIK, Field,
Indirect, Init))
return true;
@@ -3502,24 +3621,35 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
if (Member->isBaseInitializer())
Info.AllBaseFields[Member->getBaseClass()->getAs<RecordType>()] = Member;
- else
- Info.AllBaseFields[Member->getAnyMember()] = Member;
+ else {
+ Info.AllBaseFields[Member->getAnyMember()->getCanonicalDecl()] = Member;
+
+ if (IndirectFieldDecl *F = Member->getIndirectMember()) {
+ for (auto *C : F->chain()) {
+ FieldDecl *FD = dyn_cast<FieldDecl>(C);
+ if (FD && FD->getParent()->isUnion())
+ Info.ActiveUnionMember.insert(std::make_pair(
+ FD->getParent()->getCanonicalDecl(), FD->getCanonicalDecl()));
+ }
+ } else if (FieldDecl *FD = Member->getMember()) {
+ if (FD->getParent()->isUnion())
+ Info.ActiveUnionMember.insert(std::make_pair(
+ FD->getParent()->getCanonicalDecl(), FD->getCanonicalDecl()));
+ }
+ }
}
// Keep track of the direct virtual bases.
llvm::SmallPtrSet<CXXBaseSpecifier *, 16> DirectVBases;
- for (CXXRecordDecl::base_class_iterator I = ClassDecl->bases_begin(),
- E = ClassDecl->bases_end(); I != E; ++I) {
- if (I->isVirtual())
- DirectVBases.insert(I);
+ for (auto &I : ClassDecl->bases()) {
+ if (I.isVirtual())
+ DirectVBases.insert(&I);
}
// Push virtual bases before others.
- for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(),
- E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
-
+ for (auto &VBase : ClassDecl->vbases()) {
if (CXXCtorInitializer *Value
- = Info.AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
+ = Info.AllBaseFields.lookup(VBase.getType()->getAs<RecordType>())) {
// [class.base.init]p7, per DR257:
// A mem-initializer where the mem-initializer-id names a virtual base
// class is ignored during execution of a constructor of any class that
@@ -3528,7 +3658,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
// FIXME: Provide a fixit to remove the base specifier. This requires
// tracking the location of the associated comma for a base specifier.
Diag(Value->getSourceLocation(), diag::warn_abstract_vbase_init_ignored)
- << VBase->getType() << ClassDecl;
+ << VBase.getType() << ClassDecl;
DiagnoseAbstractType(ClassDecl);
}
@@ -3538,10 +3668,10 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
// If a given [...] base class is not named by a mem-initializer-id
// [...] and the entity is not a virtual base class of an abstract
// class, then [...] the entity is default-initialized.
- bool IsInheritedVirtualBase = !DirectVBases.count(VBase);
+ bool IsInheritedVirtualBase = !DirectVBases.count(&VBase);
CXXCtorInitializer *CXXBaseInit;
if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK,
- VBase, IsInheritedVirtualBase,
+ &VBase, IsInheritedVirtualBase,
CXXBaseInit)) {
HadError = true;
continue;
@@ -3552,19 +3682,18 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
}
// Non-virtual bases.
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
- E = ClassDecl->bases_end(); Base != E; ++Base) {
+ for (auto &Base : ClassDecl->bases()) {
// Virtuals are in the virtual base list and already constructed.
- if (Base->isVirtual())
+ if (Base.isVirtual())
continue;
if (CXXCtorInitializer *Value
- = Info.AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) {
+ = Info.AllBaseFields.lookup(Base.getType()->getAs<RecordType>())) {
Info.AllToInit.push_back(Value);
} else if (!AnyErrors) {
CXXCtorInitializer *CXXBaseInit;
if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK,
- Base, /*IsInheritedVirtualBase=*/false,
+ &Base, /*IsInheritedVirtualBase=*/false,
CXXBaseInit)) {
HadError = true;
continue;
@@ -3575,10 +3704,8 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
}
// Fields.
- for (DeclContext::decl_iterator Mem = ClassDecl->decls_begin(),
- MemEnd = ClassDecl->decls_end();
- Mem != MemEnd; ++Mem) {
- if (FieldDecl *F = dyn_cast<FieldDecl>(*Mem)) {
+ for (auto *Mem : ClassDecl->decls()) {
+ if (auto *F = dyn_cast<FieldDecl>(Mem)) {
// C++ [class.bit]p2:
// A declaration for a bit-field that omits the identifier declares an
// unnamed bit-field. Unnamed bit-fields are not members and cannot be
@@ -3601,7 +3728,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
if (Info.isImplicitCopyOrMove())
continue;
- if (IndirectFieldDecl *F = dyn_cast<IndirectFieldDecl>(*Mem)) {
+ if (auto *F = dyn_cast<IndirectFieldDecl>(Mem)) {
if (F->getType()->isIncompleteArrayType()) {
assert(ClassDecl->hasFlexibleArrayMember() &&
"Incomplete array type is not valid");
@@ -3638,13 +3765,12 @@ static void PopulateKeysForFields(FieldDecl *Field, SmallVectorImpl<const void*>
if (const RecordType *RT = Field->getType()->getAs<RecordType>()) {
const RecordDecl *RD = RT->getDecl();
if (RD->isAnonymousStructOrUnion()) {
- for (RecordDecl::field_iterator Field = RD->field_begin(),
- E = RD->field_end(); Field != E; ++Field)
- PopulateKeysForFields(*Field, IdealInits);
+ for (auto *Field : RD->fields())
+ PopulateKeysForFields(Field, IdealInits);
return;
}
}
- IdealInits.push_back(Field);
+ IdealInits.push_back(Field->getCanonicalDecl());
}
static const void *GetKeyForBase(ASTContext &Context, QualType BaseType) {
@@ -3656,7 +3782,7 @@ static const void *GetKeyForMember(ASTContext &Context,
if (!Member->isAnyMemberInitializer())
return GetKeyForBase(Context, QualType(Member->getBaseClass(), 0));
- return Member->getAnyMember();
+ return Member->getAnyMember()->getCanonicalDecl();
}
static void DiagnoseBaseOrMemInitializerOrder(
@@ -3670,9 +3796,8 @@ static void DiagnoseBaseOrMemInitializerOrder(
bool ShouldCheckOrder = false;
for (unsigned InitIndex = 0; InitIndex != Inits.size(); ++InitIndex) {
CXXCtorInitializer *Init = Inits[InitIndex];
- if (SemaRef.Diags.getDiagnosticLevel(diag::warn_initializer_out_of_order,
- Init->getSourceLocation())
- != DiagnosticsEngine::Ignored) {
+ if (!SemaRef.Diags.isIgnored(diag::warn_initializer_out_of_order,
+ Init->getSourceLocation())) {
ShouldCheckOrder = true;
break;
}
@@ -3688,32 +3813,28 @@ static void DiagnoseBaseOrMemInitializerOrder(
const CXXRecordDecl *ClassDecl = Constructor->getParent();
// 1. Virtual bases.
- for (CXXRecordDecl::base_class_const_iterator VBase =
- ClassDecl->vbases_begin(),
- E = ClassDecl->vbases_end(); VBase != E; ++VBase)
- IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, VBase->getType()));
+ for (const auto &VBase : ClassDecl->vbases())
+ IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, VBase.getType()));
// 2. Non-virtual bases.
- for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(),
- E = ClassDecl->bases_end(); Base != E; ++Base) {
- if (Base->isVirtual())
+ for (const auto &Base : ClassDecl->bases()) {
+ if (Base.isVirtual())
continue;
- IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, Base->getType()));
+ IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, Base.getType()));
}
// 3. Direct fields.
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- E = ClassDecl->field_end(); Field != E; ++Field) {
+ for (auto *Field : ClassDecl->fields()) {
if (Field->isUnnamedBitfield())
continue;
- PopulateKeysForFields(*Field, IdealInitKeys);
+ PopulateKeysForFields(Field, IdealInitKeys);
}
unsigned NumIdealInits = IdealInitKeys.size();
unsigned IdealIndex = 0;
- CXXCtorInitializer *PrevInit = 0;
+ CXXCtorInitializer *PrevInit = nullptr;
for (unsigned InitIndex = 0; InitIndex != Inits.size(); ++InitIndex) {
CXXCtorInitializer *Init = Inits[InitIndex];
const void *InitKey = GetKeyForMember(SemaRef.Context, Init);
@@ -3855,13 +3976,12 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
Init->setSourceOrder(i);
if (Init->isAnyMemberInitializer()) {
- FieldDecl *Field = Init->getAnyMember();
- if (CheckRedundantInit(*this, Init, Members[Field]) ||
+ const void *Key = GetKeyForMember(Context, Init);
+ if (CheckRedundantInit(*this, Init, Members[Key]) ||
CheckRedundantUnionInit(*this, Init, MemberUnions))
HadError = true;
} else if (Init->isBaseInitializer()) {
- const void *Key =
- GetKeyForBase(Context, QualType(Init->getBaseClass(), 0));
+ const void *Key = GetKeyForMember(Context, Init);
if (CheckRedundantInit(*this, Init, Members[Key]))
HadError = true;
} else {
@@ -3903,9 +4023,7 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
// emitted, and we currently don't say.
// Non-static data members.
- for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(),
- E = ClassDecl->field_end(); I != E; ++I) {
- FieldDecl *Field = *I;
+ for (auto *Field : ClassDecl->fields()) {
if (Field->isInvalidDecl())
continue;
@@ -3942,13 +4060,12 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
llvm::SmallPtrSet<const RecordType *, 8> DirectVirtualBases;
// Bases.
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
- E = ClassDecl->bases_end(); Base != E; ++Base) {
+ for (const auto &Base : ClassDecl->bases()) {
// Bases are always records in a well-formed non-dependent class.
- const RecordType *RT = Base->getType()->getAs<RecordType>();
+ const RecordType *RT = Base.getType()->getAs<RecordType>();
// Remember direct virtual bases.
- if (Base->isVirtual())
+ if (Base.isVirtual())
DirectVirtualBases.insert(RT);
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl());
@@ -3962,10 +4079,10 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
assert(Dtor && "No dtor found for BaseClassDecl!");
// FIXME: caret should be on the start of the class name
- CheckDestructorAccess(Base->getLocStart(), Dtor,
+ CheckDestructorAccess(Base.getLocStart(), Dtor,
PDiag(diag::err_access_dtor_base)
- << Base->getType()
- << Base->getSourceRange(),
+ << Base.getType()
+ << Base.getSourceRange(),
Context.getTypeDeclType(ClassDecl));
MarkFunctionReferenced(Location, Dtor);
@@ -3973,11 +4090,9 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
}
// Virtual bases.
- for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(),
- E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
-
+ for (const auto &VBase : ClassDecl->vbases()) {
// Bases are always records in a well-formed non-dependent class.
- const RecordType *RT = VBase->getType()->castAs<RecordType>();
+ const RecordType *RT = VBase.getType()->castAs<RecordType>();
// Ignore direct virtual bases.
if (DirectVirtualBases.count(RT))
@@ -3995,13 +4110,13 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
if (CheckDestructorAccess(
ClassDecl->getLocation(), Dtor,
PDiag(diag::err_access_dtor_vbase)
- << Context.getTypeDeclType(ClassDecl) << VBase->getType(),
+ << Context.getTypeDeclType(ClassDecl) << VBase.getType(),
Context.getTypeDeclType(ClassDecl)) ==
AR_accessible) {
CheckDerivedToBaseConversion(
- Context.getTypeDeclType(ClassDecl), VBase->getType(),
+ Context.getTypeDeclType(ClassDecl), VBase.getType(),
diag::err_access_dtor_vbase, 0, ClassDecl->getLocation(),
- SourceRange(), DeclarationName(), 0);
+ SourceRange(), DeclarationName(), nullptr);
}
MarkFunctionReferenced(Location, Dtor);
@@ -4030,7 +4145,7 @@ bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
NonAbstractTypeDiagnoser(unsigned DiagID, AbstractDiagSelID SelID)
: TypeDiagnoser(DiagID == 0), DiagID(DiagID), SelID(SelID) { }
- void diagnose(Sema &S, SourceLocation Loc, QualType T) LLVM_OVERRIDE {
+ void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
if (Suppressed) return;
if (SelID == -1)
S.Diag(Loc, DiagID) << T;
@@ -4172,12 +4287,12 @@ struct CheckAbstractUsage {
}
void Check(FunctionProtoTypeLoc TL, Sema::AbstractDiagSelID Sel) {
- Visit(TL.getResultLoc(), Sema::AbstractReturnType);
- for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
- if (!TL.getArg(I))
+ Visit(TL.getReturnLoc(), Sema::AbstractReturnType);
+ for (unsigned I = 0, E = TL.getNumParams(); I != E; ++I) {
+ if (!TL.getParam(I))
continue;
-
- TypeSourceInfo *TSI = TL.getArg(I)->getTypeSourceInfo();
+
+ TypeSourceInfo *TSI = TL.getParam(I)->getTypeSourceInfo();
if (TSI) Visit(TSI->getTypeLoc(), Sema::AbstractParamType);
}
}
@@ -4267,9 +4382,7 @@ static void CheckAbstractClassUsage(AbstractUsageInfo &Info,
/// Check for invalid uses of an abstract type within a class definition.
static void CheckAbstractClassUsage(AbstractUsageInfo &Info,
CXXRecordDecl *RD) {
- for (CXXRecordDecl::decl_iterator
- I = RD->decls_begin(), E = RD->decls_end(); I != E; ++I) {
- Decl *D = *I;
+ for (auto *D : RD->decls()) {
if (D->isImplicit()) continue;
// Methods and method templates.
@@ -4299,6 +4412,77 @@ static void CheckAbstractClassUsage(AbstractUsageInfo &Info,
}
}
+/// \brief Check class-level dllimport/dllexport attribute.
+static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
+ Attr *ClassAttr = getDLLAttr(Class);
+ if (!ClassAttr)
+ return;
+
+ bool ClassExported = ClassAttr->getKind() == attr::DLLExport;
+
+ // Force declaration of implicit members so they can inherit the attribute.
+ S.ForceDeclarationOfImplicitMembers(Class);
+
+ // FIXME: MSVC's docs say all bases must be exportable, but this doesn't
+ // seem to be true in practice?
+
+ for (Decl *Member : Class->decls()) {
+ VarDecl *VD = dyn_cast<VarDecl>(Member);
+ CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member);
+
+ // Only methods and static fields inherit the attributes.
+ if (!VD && !MD)
+ continue;
+
+ // Don't process deleted methods.
+ if (MD && MD->isDeleted())
+ continue;
+
+ if (MD && MD->isMoveAssignmentOperator() && !ClassExported &&
+ MD->isInlined()) {
+ // Current MSVC versions don't export the move assignment operators, so
+ // don't attempt to import them if we have a definition.
+ continue;
+ }
+
+ if (InheritableAttr *MemberAttr = getDLLAttr(Member)) {
+ if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+ !MemberAttr->isInherited() && !ClassAttr->isInherited()) {
+ S.Diag(MemberAttr->getLocation(),
+ diag::err_attribute_dll_member_of_dll_class)
+ << MemberAttr << ClassAttr;
+ S.Diag(ClassAttr->getLocation(), diag::note_previous_attribute);
+ Member->setInvalidDecl();
+ continue;
+ }
+ } else {
+ auto *NewAttr =
+ cast<InheritableAttr>(ClassAttr->clone(S.getASTContext()));
+ NewAttr->setInherited(true);
+ Member->addAttr(NewAttr);
+ }
+
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member)) {
+ if (ClassExported) {
+ if (MD->isUserProvided()) {
+ // Instantiate non-default methods.
+ S.MarkFunctionReferenced(Class->getLocation(), MD);
+ } else if (!MD->isTrivial() || MD->isExplicitlyDefaulted() ||
+ MD->isCopyAssignmentOperator() ||
+ MD->isMoveAssignmentOperator()) {
+ // Instantiate non-trivial or explicitly defaulted methods, and the
+ // copy assignment / move assignment operators.
+ S.MarkFunctionReferenced(Class->getLocation(), MD);
+ // Resolve its exception specification; CodeGen needs it.
+ auto *FPT = MD->getType()->getAs<FunctionProtoType>();
+ S.ResolveExceptionSpec(Class->getLocation(), FPT);
+ S.ActOnFinishInlineMethodDef(MD);
+ }
+ }
+ }
+ }
+}
+
/// \brief Perform semantic checks on a class definition that has been
/// completing, introducing implicitly-declared members, checking for
/// abstract types, etc.
@@ -4318,9 +4502,7 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
!Record->isAggregate() && !Record->hasUserDeclaredConstructor() &&
!Record->isLambda()) {
bool Complained = false;
- for (RecordDecl::field_iterator F = Record->field_begin(),
- FEnd = Record->field_end();
- F != FEnd; ++F) {
+ for (const auto *F : Record->fields()) {
if (F->hasInClassInitializer() || F->isUnnamedBitfield())
continue;
@@ -4367,7 +4549,8 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
// Warn if the class has virtual methods but non-virtual public destructor.
if (Record->isPolymorphic() && !Record->isDependentType()) {
CXXDestructorDecl *dtor = Record->getDestructor();
- if (!dtor || (!dtor->isVirtual() && dtor->getAccess() == AS_public))
+ if ((!dtor || (!dtor->isVirtual() && dtor->getAccess() == AS_public)) &&
+ !Record->hasAttr<FinalAttr>())
Diag(dtor ? dtor->getLocation() : Record->getLocation(),
diag::warn_non_virtual_dtor) << Context.getRecordType(Record);
}
@@ -4381,27 +4564,25 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
}
if (!Record->isDependentType()) {
- for (CXXRecordDecl::method_iterator M = Record->method_begin(),
- MEnd = Record->method_end();
- M != MEnd; ++M) {
+ for (auto *M : Record->methods()) {
// See if a method overloads virtual methods in a base
// class without overriding any.
if (!M->isStatic())
- DiagnoseHiddenVirtualMethods(*M);
+ DiagnoseHiddenVirtualMethods(M);
// Check whether the explicitly-defaulted special members are valid.
if (!M->isInvalidDecl() && M->isExplicitlyDefaulted())
- CheckExplicitlyDefaultedSpecialMember(*M);
+ CheckExplicitlyDefaultedSpecialMember(M);
// For an explicitly defaulted or deleted special member, we defer
// determining triviality until the class is complete. That time is now!
if (!M->isImplicit() && !M->isUserProvided()) {
- CXXSpecialMember CSM = getSpecialMember(*M);
+ CXXSpecialMember CSM = getSpecialMember(M);
if (CSM != CXXInvalid) {
- M->setTrivial(SpecialMemberIsTrivial(*M, CSM));
+ M->setTrivial(SpecialMemberIsTrivial(M, CSM));
// Inform the class that we've finished declaring this member.
- Record->finishedDefaultedOrDeletedMember(*M);
+ Record->finishedDefaultedOrDeletedMember(M);
}
}
}
@@ -4420,10 +4601,8 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
// destructor for the class is trivial.
if (LangOpts.CPlusPlus11 && !Record->isDependentType() &&
!Record->isLiteral() && !Record->getNumVBases()) {
- for (CXXRecordDecl::method_iterator M = Record->method_begin(),
- MEnd = Record->method_end();
- M != MEnd; ++M) {
- if (M->isConstexpr() && M->isInstance() && !isa<CXXConstructorDecl>(*M)) {
+ for (const auto *M : Record->methods()) {
+ if (M->isConstexpr() && M->isInstance() && !isa<CXXConstructorDecl>(M)) {
switch (Record->getTemplateSpecializationKind()) {
case TSK_ImplicitInstantiation:
case TSK_ExplicitInstantiationDeclaration:
@@ -4446,11 +4625,18 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
}
}
- // Check to see if we're trying to lay out a struct using the ms_struct
- // attribute that is dynamic.
- if (Record->isMsStruct(Context) && Record->isDynamicClass()) {
- Diag(Record->getLocation(), diag::warn_pragma_ms_struct_failed);
- Record->dropAttr<MsStructAttr>();
+ // ms_struct is a request to use the same ABI rules as MSVC. Check
+ // whether this class uses any C++ features that are implemented
+ // completely differently in MSVC, and if so, emit a diagnostic.
+ // That diagnostic defaults to an error, but we allow projects to
+ // map it down to a warning (or ignore it). It's a fairly common
+ // practice among users of the ms_struct pragma to mass-annotate
+ // headers, sweeping up a bunch of types that the project doesn't
+ // really rely on MSVC-compatible layout for. We must therefore
+ // support "ms_struct except for C++ stuff" as a secondary ABI.
+ if (Record->isMsStruct(Context) &&
+ (Record->isPolymorphic() || Record->getNumBases())) {
+ Diag(Record->getLocation(), diag::warn_cxx_ms_struct);
}
// Declare inheriting constructors. We do this eagerly here because:
@@ -4461,16 +4647,47 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
// instantiated (e.g. meta-functions). This doesn't apply to classes that
// have inheriting constructors.
DeclareInheritingConstructors(Record);
+
+ checkDLLAttribute(*this, Record);
+}
+
+/// Look up the special member function that would be called by a special
+/// member function for a subobject of class type.
+///
+/// \param Class The class type of the subobject.
+/// \param CSM The kind of special member function.
+/// \param FieldQuals If the subobject is a field, its cv-qualifiers.
+/// \param ConstRHS True if this is a copy operation with a const object
+/// on its RHS, that is, if the argument to the outer special member
+/// function is 'const' and this is not a field marked 'mutable'.
+static Sema::SpecialMemberOverloadResult *lookupCallFromSpecialMember(
+ Sema &S, CXXRecordDecl *Class, Sema::CXXSpecialMember CSM,
+ unsigned FieldQuals, bool ConstRHS) {
+ unsigned LHSQuals = 0;
+ if (CSM == Sema::CXXCopyAssignment || CSM == Sema::CXXMoveAssignment)
+ LHSQuals = FieldQuals;
+
+ unsigned RHSQuals = FieldQuals;
+ if (CSM == Sema::CXXDefaultConstructor || CSM == Sema::CXXDestructor)
+ RHSQuals = 0;
+ else if (ConstRHS)
+ RHSQuals |= Qualifiers::Const;
+
+ return S.LookupSpecialMember(Class, CSM,
+ RHSQuals & Qualifiers::Const,
+ RHSQuals & Qualifiers::Volatile,
+ false,
+ LHSQuals & Qualifiers::Const,
+ LHSQuals & Qualifiers::Volatile);
}
/// Is the special member function which would be selected to perform the
/// specified operation on the specified class type a constexpr constructor?
static bool specialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl,
Sema::CXXSpecialMember CSM,
- bool ConstArg) {
+ unsigned Quals, bool ConstRHS) {
Sema::SpecialMemberOverloadResult *SMOR =
- S.LookupSpecialMember(ClassDecl, CSM, ConstArg,
- false, false, false, false);
+ lookupCallFromSpecialMember(S, ClassDecl, CSM, Quals, ConstRHS);
if (!SMOR || !SMOR->getMethod())
// A constructor we wouldn't select can't be "involved in initializing"
// anything.
@@ -4540,14 +4757,12 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl,
// sub-objects shall be a constexpr constructor;
// -- the assignment operator selected to copy/move each direct base
// class is a constexpr function, and
- for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(),
- BEnd = ClassDecl->bases_end();
- B != BEnd; ++B) {
- const RecordType *BaseType = B->getType()->getAs<RecordType>();
+ for (const auto &B : ClassDecl->bases()) {
+ const RecordType *BaseType = B.getType()->getAs<RecordType>();
if (!BaseType) continue;
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
- if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, ConstArg))
+ if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg))
return false;
}
@@ -4555,18 +4770,18 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl,
// [...] shall be a constexpr constructor;
// -- every non-static data member and base class sub-object shall be
// initialized
- // -- for each non-stastic data member of X that is of class type (or array
+ // -- for each non-static data member of X that is of class type (or array
// thereof), the assignment operator selected to copy/move that member is
// a constexpr function
- for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
- FEnd = ClassDecl->field_end();
- F != FEnd; ++F) {
+ for (const auto *F : ClassDecl->fields()) {
if (F->isInvalidDecl())
continue;
- if (const RecordType *RecordTy =
- S.Context.getBaseElementType(F->getType())->getAs<RecordType>()) {
+ QualType BaseType = S.Context.getBaseElementType(F->getType());
+ if (const RecordType *RecordTy = BaseType->getAs<RecordType>()) {
CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
- if (!specialMemberIsConstexpr(S, FieldRecDecl, CSM, ConstArg))
+ if (!specialMemberIsConstexpr(S, FieldRecDecl, CSM,
+ BaseType.getCVRQualifiers(),
+ ConstArg && !F->isMutable()))
return false;
}
}
@@ -4598,15 +4813,6 @@ computeImplicitExceptionSpec(Sema &S, SourceLocation Loc, CXXMethodDecl *MD) {
return S.ComputeInheritingCtorExceptionSpec(cast<CXXConstructorDecl>(MD));
}
-static void
-updateExceptionSpec(Sema &S, FunctionDecl *FD, const FunctionProtoType *FPT,
- const Sema::ImplicitExceptionSpecification &ExceptSpec) {
- FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
- ExceptSpec.getEPI(EPI);
- FD->setType(S.Context.getFunctionType(FPT->getResultType(),
- FPT->getArgTypes(), EPI));
-}
-
static FunctionProtoType::ExtProtoInfo getImplicitMethodEPI(Sema &S,
CXXMethodDecl *MD) {
FunctionProtoType::ExtProtoInfo EPI;
@@ -4631,8 +4837,11 @@ void Sema::EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD)
ImplicitExceptionSpecification ExceptSpec =
computeImplicitExceptionSpec(*this, Loc, MD);
+ FunctionProtoType::ExtProtoInfo EPI;
+ ExceptSpec.getEPI(EPI);
+
// Update the type of the special member to use it.
- updateExceptionSpec(*this, MD, FPT, ExceptSpec);
+ UpdateExceptionSpec(MD, EPI);
// A user-provided destructor can be defined outside the class. When that
// happens, be sure to update the exception specification on both
@@ -4640,8 +4849,7 @@ void Sema::EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD)
const FunctionProtoType *CanonicalFPT =
MD->getCanonicalDecl()->getType()->castAs<FunctionProtoType>();
if (CanonicalFPT->getExceptionSpecType() == EST_Unevaluated)
- updateExceptionSpec(*this, MD->getCanonicalDecl(),
- CanonicalFPT, ExceptSpec);
+ UpdateExceptionSpec(MD->getCanonicalDecl(), EPI);
}
void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
@@ -4691,7 +4899,7 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
QualType ReturnType = Context.VoidTy;
if (CSM == CXXCopyAssignment || CSM == CXXMoveAssignment) {
// Check for return type matching.
- ReturnType = Type->getResultType();
+ ReturnType = Type->getReturnType();
QualType ExpectedReturnType =
Context.getLValueReferenceType(Context.getTypeDeclType(RD));
if (!Context.hasSameType(ReturnType, ExpectedReturnType)) {
@@ -4709,7 +4917,7 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
}
// Check for parameter type matching.
- QualType ArgType = ExpectedParams ? Type->getArgType(0) : QualType();
+ QualType ArgType = ExpectedParams ? Type->getParamType(0) : QualType();
bool HasConstParam = false;
if (ExpectedParams && ArgType->isReferenceType()) {
// Argument must be reference to possibly-const T.
@@ -4803,6 +5011,7 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
// [For a] user-provided explicitly-defaulted function [...] if such a
// function is implicitly defined as deleted, the program is ill-formed.
Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) << CSM;
+ ShouldDeleteSpecialMember(MD, CSM, /*Diagnose*/true);
HadError = true;
}
}
@@ -4865,7 +5074,7 @@ struct SpecialMemberDeletionInfo {
bool Diagnose;
// Properties of the special member, computed for convenience.
- bool IsConstructor, IsAssignment, IsMove, ConstArg, VolatileArg;
+ bool IsConstructor, IsAssignment, IsMove, ConstArg;
SourceLocation Loc;
bool AllFieldsAreConst;
@@ -4874,7 +5083,7 @@ struct SpecialMemberDeletionInfo {
Sema::CXXSpecialMember CSM, bool Diagnose)
: S(S), MD(MD), CSM(CSM), Diagnose(Diagnose),
IsConstructor(false), IsAssignment(false), IsMove(false),
- ConstArg(false), VolatileArg(false), Loc(MD->getLocation()),
+ ConstArg(false), Loc(MD->getLocation()),
AllFieldsAreConst(true) {
switch (CSM) {
case Sema::CXXDefaultConstructor:
@@ -4899,8 +5108,9 @@ struct SpecialMemberDeletionInfo {
}
if (MD->getNumParams()) {
- ConstArg = MD->getParamDecl(0)->getType().isConstQualified();
- VolatileArg = MD->getParamDecl(0)->getType().isVolatileQualified();
+ if (const ReferenceType *RT =
+ MD->getParamDecl(0)->getType()->getAs<ReferenceType>())
+ ConstArg = RT->getPointeeType().isConstQualified();
}
}
@@ -4908,21 +5118,9 @@ struct SpecialMemberDeletionInfo {
/// Look up the corresponding special member in the given class.
Sema::SpecialMemberOverloadResult *lookupIn(CXXRecordDecl *Class,
- unsigned Quals) {
- unsigned TQ = MD->getTypeQualifiers();
- // cv-qualifiers on class members don't affect default ctor / dtor calls.
- if (CSM == Sema::CXXDefaultConstructor || CSM == Sema::CXXDestructor)
- Quals = 0;
- // cv-qualifiers on class members affect the type of both '*this' and the
- // argument for an assignment.
- if (IsAssignment)
- TQ |= Quals;
- return S.LookupSpecialMember(Class, CSM,
- ConstArg || (Quals & Qualifiers::Const),
- VolatileArg || (Quals & Qualifiers::Volatile),
- MD->getRefQualifier() == RQ_RValue,
- TQ & Qualifiers::Const,
- TQ & Qualifiers::Volatile);
+ unsigned Quals, bool IsMutable) {
+ return lookupCallFromSpecialMember(S, Class, CSM, Quals,
+ ConstArg && !IsMutable);
}
typedef llvm::PointerUnion<CXXBaseSpecifier*, FieldDecl*> Subobject;
@@ -5017,6 +5215,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject(
CXXRecordDecl *Class, Subobject Subobj, unsigned Quals) {
FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>();
+ bool IsMutable = Field && Field->isMutable();
// C++11 [class.ctor]p5:
// -- any direct or virtual base class, or non-static data member with no
@@ -5034,7 +5233,8 @@ bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject(
// that is deleted or inaccessible
if (!(CSM == Sema::CXXDefaultConstructor &&
Field && Field->hasInClassInitializer()) &&
- shouldDeleteForSubobjectCall(Subobj, lookupIn(Class, Quals), false))
+ shouldDeleteForSubobjectCall(Subobj, lookupIn(Class, Quals, IsMutable),
+ false))
return true;
// C++11 [class.ctor]p5, C++11 [class.copy]p11:
@@ -5122,9 +5322,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) {
bool AllVariantFieldsAreConst = true;
// FIXME: Handle anonymous unions declared within anonymous unions.
- for (CXXRecordDecl::field_iterator UI = FieldRecord->field_begin(),
- UE = FieldRecord->field_end();
- UI != UE; ++UI) {
+ for (auto *UI : FieldRecord->fields()) {
QualType UnionFieldType = S.Context.getBaseElementType(UI->getType());
if (!UnionFieldType.isConstQualified())
@@ -5132,14 +5330,14 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) {
CXXRecordDecl *UnionFieldRecord = UnionFieldType->getAsCXXRecordDecl();
if (UnionFieldRecord &&
- shouldDeleteForClassSubobject(UnionFieldRecord, *UI,
+ shouldDeleteForClassSubobject(UnionFieldRecord, UI,
UnionFieldType.getCVRQualifiers()))
return true;
}
// At least one member in each anonymous union must be non-const
if (CSM == Sema::CXXDefaultConstructor && AllVariantFieldsAreConst &&
- FieldRecord->field_begin() != FieldRecord->field_end()) {
+ !FieldRecord->field_empty()) {
if (Diagnose)
S.Diag(FieldRecord->getLocation(),
diag::note_deleted_default_ctor_all_const)
@@ -5167,7 +5365,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForAllConstMembers() {
// This is a silly definition, because it gives an empty union a deleted
// default constructor. Don't do that.
if (CSM == Sema::CXXDefaultConstructor && inUnion() && AllFieldsAreConst &&
- (MD->getParent()->field_begin() != MD->getParent()->field_end())) {
+ !MD->getParent()->field_empty()) {
if (Diagnose)
S.Diag(MD->getParent()->getLocation(),
diag::note_deleted_default_ctor_all_const)
@@ -5213,32 +5411,30 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
// operator is defined as deleted.
if (MD->isImplicit() &&
(CSM == CXXCopyConstructor || CSM == CXXCopyAssignment)) {
- CXXMethodDecl *UserDeclaredMove = 0;
+ CXXMethodDecl *UserDeclaredMove = nullptr;
// In Microsoft mode, a user-declared move only causes the deletion of the
// corresponding copy operation, not both copy operations.
if (RD->hasUserDeclaredMoveConstructor() &&
- (!getLangOpts().MicrosoftMode || CSM == CXXCopyConstructor)) {
+ (!getLangOpts().MSVCCompat || CSM == CXXCopyConstructor)) {
if (!Diagnose) return true;
// Find any user-declared move constructor.
- for (CXXRecordDecl::ctor_iterator I = RD->ctor_begin(),
- E = RD->ctor_end(); I != E; ++I) {
+ for (auto *I : RD->ctors()) {
if (I->isMoveConstructor()) {
- UserDeclaredMove = *I;
+ UserDeclaredMove = I;
break;
}
}
assert(UserDeclaredMove);
} else if (RD->hasUserDeclaredMoveAssignment() &&
- (!getLangOpts().MicrosoftMode || CSM == CXXCopyAssignment)) {
+ (!getLangOpts().MSVCCompat || CSM == CXXCopyAssignment)) {
if (!Diagnose) return true;
// Find any user-declared move assignment operator.
- for (CXXRecordDecl::method_iterator I = RD->method_begin(),
- E = RD->method_end(); I != E; ++I) {
+ for (auto *I : RD->methods()) {
if (I->isMoveAssignmentOperator()) {
- UserDeclaredMove = *I;
+ UserDeclaredMove = I;
break;
}
}
@@ -5261,7 +5457,7 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
// -- for a virtual destructor, lookup of the non-array deallocation function
// results in an ambiguity or in a function that is deleted or inaccessible
if (CSM == CXXDestructor && MD->isVirtual()) {
- FunctionDecl *OperatorDelete = 0;
+ FunctionDecl *OperatorDelete = nullptr;
DeclarationName Name =
Context.DeclarationNames.getCXXOperatorName(OO_Delete);
if (FindDeallocationFunction(MD->getLocation(), MD->getParent(), Name,
@@ -5274,26 +5470,22 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
SpecialMemberDeletionInfo SMI(*this, MD, CSM, Diagnose);
- for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(),
- BE = RD->bases_end(); BI != BE; ++BI)
- if (!BI->isVirtual() &&
- SMI.shouldDeleteForBase(BI))
+ for (auto &BI : RD->bases())
+ if (!BI.isVirtual() &&
+ SMI.shouldDeleteForBase(&BI))
return true;
// Per DR1611, do not consider virtual bases of constructors of abstract
// classes, since we are not going to construct them.
if (!RD->isAbstract() || !SMI.IsConstructor) {
- for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(),
- BE = RD->vbases_end();
- BI != BE; ++BI)
- if (SMI.shouldDeleteForBase(BI))
+ for (auto &BI : RD->vbases())
+ if (SMI.shouldDeleteForBase(&BI))
return true;
}
- for (CXXRecordDecl::field_iterator FI = RD->field_begin(),
- FE = RD->field_end(); FI != FE; ++FI)
+ for (auto *FI : RD->fields())
if (!FI->isInvalidDecl() && !FI->isUnnamedBitfield() &&
- SMI.shouldDeleteForField(*FI))
+ SMI.shouldDeleteForField(FI))
return true;
if (SMI.shouldDeleteForAllConstMembers())
@@ -5312,9 +5504,9 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
/// member that was most likely to be intended to be trivial, if any.
static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
Sema::CXXSpecialMember CSM, unsigned Quals,
- CXXMethodDecl **Selected) {
+ bool ConstRHS, CXXMethodDecl **Selected) {
if (Selected)
- *Selected = 0;
+ *Selected = nullptr;
switch (CSM) {
case Sema::CXXInvalid:
@@ -5333,14 +5525,13 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
// If there's a default constructor which could have been trivial, dig it
// out. Otherwise, if there's any user-provided default constructor, point
// to that as an example of why there's not a trivial one.
- CXXConstructorDecl *DefCtor = 0;
+ CXXConstructorDecl *DefCtor = nullptr;
if (RD->needsImplicitDefaultConstructor())
S.DeclareImplicitDefaultConstructor(RD);
- for (CXXRecordDecl::ctor_iterator CI = RD->ctor_begin(),
- CE = RD->ctor_end(); CI != CE; ++CI) {
+ for (auto *CI : RD->ctors()) {
if (!CI->isDefaultConstructor())
continue;
- DefCtor = *CI;
+ DefCtor = CI;
if (!DefCtor->isUserProvided())
break;
}
@@ -5403,11 +5594,7 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
case Sema::CXXMoveAssignment:
NeedOverloadResolution:
Sema::SpecialMemberOverloadResult *SMOR =
- S.LookupSpecialMember(RD, CSM,
- Quals & Qualifiers::Const,
- Quals & Qualifiers::Volatile,
- /*RValueThis*/false, /*ConstThis*/false,
- /*VolatileThis*/false);
+ lookupCallFromSpecialMember(S, RD, CSM, Quals, ConstRHS);
// The standard doesn't describe how to behave if the lookup is ambiguous.
// We treat it as not making the member non-trivial, just like the standard
@@ -5433,10 +5620,9 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
}
static CXXConstructorDecl *findUserDeclaredCtor(CXXRecordDecl *RD) {
- for (CXXRecordDecl::ctor_iterator CI = RD->ctor_begin(), CE = RD->ctor_end();
- CI != CE; ++CI)
+ for (auto *CI : RD->ctors())
if (!CI->isImplicit())
- return *CI;
+ return CI;
// Look for constructor templates.
typedef CXXRecordDecl::specific_decl_iterator<FunctionTemplateDecl> tmpl_iter;
@@ -5446,7 +5632,7 @@ static CXXConstructorDecl *findUserDeclaredCtor(CXXRecordDecl *RD) {
return CD;
}
- return 0;
+ return nullptr;
}
/// The kind of subobject we are checking for triviality. The values of this
@@ -5462,7 +5648,7 @@ enum TrivialSubobjectKind {
/// Check whether the special member selected for a given type would be trivial.
static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc,
- QualType SubType,
+ QualType SubType, bool ConstRHS,
Sema::CXXSpecialMember CSM,
TrivialSubobjectKind Kind,
bool Diagnose) {
@@ -5472,10 +5658,13 @@ static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc,
CXXMethodDecl *Selected;
if (findTrivialSpecialMember(S, SubRD, CSM, SubType.getCVRQualifiers(),
- Diagnose ? &Selected : 0))
+ ConstRHS, Diagnose ? &Selected : nullptr))
return true;
if (Diagnose) {
+ if (ConstRHS)
+ SubType.addConst();
+
if (!Selected && CSM == Sema::CXXDefaultConstructor) {
S.Diag(SubobjLoc, diag::note_nontrivial_no_def_ctor)
<< Kind << SubType.getUnqualifiedType();
@@ -5511,8 +5700,7 @@ static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc,
static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD,
Sema::CXXSpecialMember CSM,
bool ConstArg, bool Diagnose) {
- for (CXXRecordDecl::field_iterator FI = RD->field_begin(),
- FE = RD->field_end(); FI != FE; ++FI) {
+ for (const auto *FI : RD->fields()) {
if (FI->isInvalidDecl() || FI->isUnnamedBitfield())
continue;
@@ -5532,7 +5720,7 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD,
// brace-or-equal-initializer
if (CSM == Sema::CXXDefaultConstructor && FI->hasInClassInitializer()) {
if (Diagnose)
- S.Diag(FI->getLocation(), diag::note_nontrivial_in_class_init) << *FI;
+ S.Diag(FI->getLocation(), diag::note_nontrivial_in_class_init) << FI;
return false;
}
@@ -5548,10 +5736,9 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD,
return false;
}
- if (ConstArg && !FI->isMutable())
- FieldType.addConst();
- if (!checkTrivialSubobjectCall(S, FI->getLocation(), FieldType, CSM,
- TSK_Field, Diagnose))
+ bool ConstRHS = ConstArg && !FI->isMutable();
+ if (!checkTrivialSubobjectCall(S, FI->getLocation(), FieldType, ConstRHS,
+ CSM, TSK_Field, Diagnose))
return false;
}
@@ -5562,10 +5749,9 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD,
/// the given kind.
void Sema::DiagnoseNontrivial(const CXXRecordDecl *RD, CXXSpecialMember CSM) {
QualType Ty = Context.getRecordType(RD);
- if (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment)
- Ty.addConst();
- checkTrivialSubobjectCall(*this, RD->getLocation(), Ty, CSM,
+ bool ConstArg = (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment);
+ checkTrivialSubobjectCall(*this, RD->getLocation(), Ty, ConstArg, CSM,
TSK_CompleteObject, /*Diagnose*/true);
}
@@ -5648,12 +5834,9 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
// A [default constructor or destructor] is trivial if
// -- all the direct base classes have trivial [default constructors or
// destructors]
- for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(),
- BE = RD->bases_end(); BI != BE; ++BI)
- if (!checkTrivialSubobjectCall(*this, BI->getLocStart(),
- ConstArg ? BI->getType().withConst()
- : BI->getType(),
- CSM, TSK_BaseClass, Diagnose))
+ for (const auto &BI : RD->bases())
+ if (!checkTrivialSubobjectCall(*this, BI.getLocStart(), BI.getType(),
+ ConstArg, CSM, TSK_BaseClass, Diagnose))
return false;
// C++11 [class.ctor]p5, C++11 [class.dtor]p5:
@@ -5697,8 +5880,7 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
}
// Must have a virtual method.
- for (CXXRecordDecl::method_iterator MI = RD->method_begin(),
- ME = RD->method_end(); MI != ME; ++MI) {
+ for (const auto *MI : RD->methods()) {
if (MI->isVirtual()) {
SourceLocation MLoc = MI->getLocStart();
Diag(MLoc, diag::note_nontrivial_has_virtual) << RD << 0;
@@ -5836,8 +6018,7 @@ void Sema::DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD) {
if (MD->isInvalidDecl())
return;
- if (Diags.getDiagnosticLevel(diag::warn_overloaded_virtual,
- MD->getLocation()) == DiagnosticsEngine::Ignored)
+ if (Diags.isIgnored(diag::warn_overloaded_virtual, MD->getLocation()))
return;
SmallVector<CXXMethodDecl *, 8> OverloadedMethods;
@@ -5937,47 +6118,55 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
}
}
-void Sema::ActOnReenterDeclaratorTemplateScope(Scope *S, DeclaratorDecl *D) {
+unsigned Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) {
if (!D)
- return;
+ return 0;
- int NumParamList = D->getNumTemplateParameterLists();
- for (int i = 0; i < NumParamList; i++) {
- TemplateParameterList* Params = D->getTemplateParameterList(i);
- for (TemplateParameterList::iterator Param = Params->begin(),
- ParamEnd = Params->end();
- Param != ParamEnd; ++Param) {
- NamedDecl *Named = cast<NamedDecl>(*Param);
- if (Named->getDeclName()) {
- S->AddDecl(Named);
- IdResolver.AddDecl(Named);
- }
+ // The order of template parameters is not important here. All names
+ // get added to the same scope.
+ SmallVector<TemplateParameterList *, 4> ParameterLists;
+
+ if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
+ D = TD->getTemplatedDecl();
+
+ if (auto *PSD = dyn_cast<ClassTemplatePartialSpecializationDecl>(D))
+ ParameterLists.push_back(PSD->getTemplateParameters());
+
+ if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
+ for (unsigned i = 0; i < DD->getNumTemplateParameterLists(); ++i)
+ ParameterLists.push_back(DD->getTemplateParameterList(i));
+
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate())
+ ParameterLists.push_back(FTD->getTemplateParameters());
}
}
-}
-void Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) {
- if (!D)
- return;
-
- TemplateParameterList *Params = 0;
- if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D))
- Params = Template->getTemplateParameters();
- else if (ClassTemplatePartialSpecializationDecl *PartialSpec
- = dyn_cast<ClassTemplatePartialSpecializationDecl>(D))
- Params = PartialSpec->getTemplateParameters();
- else
- return;
+ if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
+ for (unsigned i = 0; i < TD->getNumTemplateParameterLists(); ++i)
+ ParameterLists.push_back(TD->getTemplateParameterList(i));
- for (TemplateParameterList::iterator Param = Params->begin(),
- ParamEnd = Params->end();
- Param != ParamEnd; ++Param) {
- NamedDecl *Named = cast<NamedDecl>(*Param);
- if (Named->getDeclName()) {
- S->AddDecl(Named);
- IdResolver.AddDecl(Named);
+ if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TD)) {
+ if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate())
+ ParameterLists.push_back(CTD->getTemplateParameters());
}
}
+
+ unsigned Count = 0;
+ for (TemplateParameterList *Params : ParameterLists) {
+ if (Params->size() > 0)
+ // Ignore explicit specializations; they don't contribute to the template
+ // depth.
+ ++Count;
+ for (NamedDecl *Param : *Params) {
+ if (Param->getDeclName()) {
+ S->AddDecl(Param);
+ IdResolver.AddDecl(Param);
+ }
+ }
+ }
+
+ return Count;
}
void Sema::ActOnStartDelayedMemberDeclarations(Scope *S, Decl *RecordD) {
@@ -5992,6 +6181,18 @@ void Sema::ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *RecordD) {
PopDeclContext();
}
+/// This is used to implement the constant expression evaluation part of the
+/// attribute enable_if extension. There is nothing in standard C++ which would
+/// require reentering parameters.
+void Sema::ActOnReenterCXXMethodParameter(Scope *S, ParmVarDecl *Param) {
+ if (!Param)
+ return;
+
+ S->AddDecl(Param);
+ if (Param->getDeclName())
+ IdResolver.AddDecl(Param);
+}
+
/// ActOnStartDelayedCXXMethodDeclaration - We have completed
/// parsing a top-level (non-nested) C++ class, and we are now
/// parsing those parts of the given Method declaration that could
@@ -6017,7 +6218,7 @@ void Sema::ActOnDelayedCXXMethodParameter(Scope *S, Decl *ParamD) {
// If this parameter has an unparsed default argument, clear it out
// to make way for the parsed default argument.
if (Param->hasUnparsedDefaultArg())
- Param->setDefaultArg(0);
+ Param->setDefaultArg(nullptr);
S->AddDecl(Param);
if (Param->getDeclName())
@@ -6081,6 +6282,15 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
SC = SC_None;
}
+ if (unsigned TypeQuals = D.getDeclSpec().getTypeQualifiers()) {
+ diagnoseIgnoredQualifiers(
+ diag::err_constructor_return_type, TypeQuals, SourceLocation(),
+ D.getDeclSpec().getConstSpecLoc(), D.getDeclSpec().getVolatileSpecLoc(),
+ D.getDeclSpec().getRestrictSpecLoc(),
+ D.getDeclSpec().getAtomicSpecLoc());
+ D.setInvalidType();
+ }
+
DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
if (FTI.TypeQuals != 0) {
if (FTI.TypeQuals & Qualifiers::Const)
@@ -6108,14 +6318,14 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
// case any of the errors above fired) and with "void" as the
// return type, since constructors don't have return types.
const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
- if (Proto->getResultType() == Context.VoidTy && !D.isInvalidType())
+ if (Proto->getReturnType() == Context.VoidTy && !D.isInvalidType())
return R;
FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
EPI.TypeQuals = 0;
EPI.RefQualifier = RQ_None;
-
- return Context.getFunctionType(Context.VoidTy, Proto->getArgTypes(), EPI);
+
+ return Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), EPI);
}
/// CheckConstructor - Checks a fully-formed constructor for
@@ -6170,7 +6380,7 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
Loc = RD->getLocation();
// If we have a virtual destructor, look up the deallocation function
- FunctionDecl *OperatorDelete = 0;
+ FunctionDecl *OperatorDelete = nullptr;
DeclarationName Name =
Context.DeclarationNames.getCXXOperatorName(OO_Delete);
if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete))
@@ -6188,13 +6398,6 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
return false;
}
-static inline bool
-FTIHasSingleVoidArgument(DeclaratorChunk::FunctionTypeInfo &FTI) {
- return (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
- FTI.ArgInfo[0].Param &&
- cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType());
-}
-
/// CheckDestructorDeclarator - Called by ActOnDeclarator to check
/// the well-formednes of the destructor declarator @p D with type @p
/// R. If there are any errors in the declarator, this routine will
@@ -6235,7 +6438,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
SC = SC_None;
}
- if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) {
+ if (!D.isInvalidType()) {
// Destructors don't have return types, but the parser will
// happily parse something like:
//
@@ -6244,9 +6447,19 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
// };
//
// The return type will be eliminated later.
- Diag(D.getIdentifierLoc(), diag::err_destructor_return_type)
- << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
- << SourceRange(D.getIdentifierLoc());
+ if (D.getDeclSpec().hasTypeSpecifier())
+ Diag(D.getIdentifierLoc(), diag::err_destructor_return_type)
+ << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
+ << SourceRange(D.getIdentifierLoc());
+ else if (unsigned TypeQuals = D.getDeclSpec().getTypeQualifiers()) {
+ diagnoseIgnoredQualifiers(diag::err_destructor_return_type, TypeQuals,
+ SourceLocation(),
+ D.getDeclSpec().getConstSpecLoc(),
+ D.getDeclSpec().getVolatileSpecLoc(),
+ D.getDeclSpec().getRestrictSpecLoc(),
+ D.getDeclSpec().getAtomicSpecLoc());
+ D.setInvalidType();
+ }
}
DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
@@ -6273,11 +6486,11 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
}
// Make sure we don't have any parameters.
- if (FTI.NumArgs > 0 && !FTIHasSingleVoidArgument(FTI)) {
+ if (FTIHasNonVoidParameters(FTI)) {
Diag(D.getIdentifierLoc(), diag::err_destructor_with_params);
// Delete the parameters.
- FTI.freeArgs();
+ FTI.freeParams();
D.setInvalidType();
}
@@ -6343,11 +6556,11 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
// Make sure we don't have any parameters.
- if (Proto->getNumArgs() > 0) {
+ if (Proto->getNumParams() > 0) {
Diag(D.getIdentifierLoc(), diag::err_conv_function_with_params);
// Delete the parameters.
- D.getFunctionTypeInfo().freeArgs();
+ D.getFunctionTypeInfo().freeParams();
D.setInvalidType();
} else if (Proto->isVariadic()) {
Diag(D.getIdentifierLoc(), diag::err_conv_function_variadic);
@@ -6356,11 +6569,11 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
// Diagnose "&operator bool()" and other such nonsense. This
// is actually a gcc extension which we don't support.
- if (Proto->getResultType() != ConvType) {
+ if (Proto->getReturnType() != ConvType) {
Diag(D.getIdentifierLoc(), diag::err_conv_function_with_complex_decl)
- << Proto->getResultType();
+ << Proto->getReturnType();
D.setInvalidType();
- ConvType = Proto->getResultType();
+ ConvType = Proto->getReturnType();
}
// C++ [class.conv.fct]p4:
@@ -6464,9 +6677,8 @@ static void DiagnoseNamespaceInlineMismatch(Sema &S, SourceLocation KeywordLoc,
NS->setInline(*IsInline);
// Patch up the lookup table for the containing namespace. This isn't really
// correct, but it's good enough for this particular case.
- for (DeclContext::decl_iterator I = PrevNS->decls_begin(),
- E = PrevNS->decls_end(); I != E; ++I)
- if (NamedDecl *ND = dyn_cast<NamedDecl>(*I))
+ for (auto *I : PrevNS->decls())
+ if (auto *ND = dyn_cast<NamedDecl>(I))
PrevNS->getParent()->makeDeclVisibleInContext(ND);
return;
}
@@ -6477,8 +6689,7 @@ static void DiagnoseNamespaceInlineMismatch(Sema &S, SourceLocation KeywordLoc,
S.Diag(Loc, diag::warn_inline_namespace_reopened_noninline)
<< FixItHint::CreateInsertion(KeywordLoc, "inline ");
else
- S.Diag(Loc, diag::err_inline_namespace_mismatch)
- << IsInline;
+ S.Diag(Loc, diag::err_inline_namespace_mismatch) << *IsInline;
S.Diag(PrevNS->getLocation(), diag::note_previous_definition);
*IsInline = PrevNS->isInline();
@@ -6502,7 +6713,7 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
bool AddToKnown = false;
Scope *DeclRegionScope = NamespcScope->getParent();
- NamespaceDecl *PrevNS = 0;
+ NamespaceDecl *PrevNS = nullptr;
if (II) {
// C++ [namespace.def]p2:
// The identifier in an original-namespace-definition shall not
@@ -6518,7 +6729,7 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
const unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Member |
Decl::IDNS_Type | Decl::IDNS_Using | Decl::IDNS_Tag |
Decl::IDNS_Namespace;
- NamedDecl *PrevDecl = 0;
+ NamedDecl *PrevDecl = nullptr;
DeclContext::lookup_result R = CurContext->getRedeclContext()->lookup(II);
for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
++I) {
@@ -6679,7 +6890,7 @@ NamespaceDecl *Sema::getOrCreateStdNamespace() {
/*Inline=*/false,
SourceLocation(), SourceLocation(),
&PP.getIdentifierTable().get("std"),
- /*PrevDecl=*/0);
+ /*PrevDecl=*/nullptr);
getStdNamespace()->setImplicit(true);
}
@@ -6696,8 +6907,8 @@ bool Sema::isStdInitializerList(QualType Ty, QualType *Element) {
if (!StdNamespace) // If we haven't seen namespace std yet, this can't be it.
return false;
- ClassTemplateDecl *Template = 0;
- const TemplateArgument *Arguments = 0;
+ ClassTemplateDecl *Template = nullptr;
+ const TemplateArgument *Arguments = nullptr;
if (const RecordType *RT = Ty->getAs<RecordType>()) {
@@ -6750,14 +6961,14 @@ static ClassTemplateDecl *LookupStdInitializerList(Sema &S, SourceLocation Loc){
NamespaceDecl *Std = S.getStdNamespace();
if (!Std) {
S.Diag(Loc, diag::err_implied_std_initializer_list_not_found);
- return 0;
+ return nullptr;
}
LookupResult Result(S, &S.PP.getIdentifierTable().get("initializer_list"),
Loc, Sema::LookupOrdinaryName);
if (!S.LookupQualifiedName(Result, Std)) {
S.Diag(Loc, diag::err_implied_std_initializer_list_not_found);
- return 0;
+ return nullptr;
}
ClassTemplateDecl *Template = Result.getAsSingle<ClassTemplateDecl>();
if (!Template) {
@@ -6765,7 +6976,7 @@ static ClassTemplateDecl *LookupStdInitializerList(Sema &S, SourceLocation Loc){
// We found something weird. Complain about the first thing we found.
NamedDecl *Found = *Result.begin();
S.Diag(Found->getLocation(), diag::err_malformed_std_initializer_list);
- return 0;
+ return nullptr;
}
// We found some template called std::initializer_list. Now verify that it's
@@ -6774,7 +6985,7 @@ static ClassTemplateDecl *LookupStdInitializerList(Sema &S, SourceLocation Loc){
if (Params->getMinRequiredArguments() != 1 ||
!isa<TemplateTypeParmDecl>(Params->getParam(0))) {
S.Diag(Template->getLocation(), diag::err_malformed_std_initializer_list);
- return 0;
+ return nullptr;
}
return Template;
@@ -6809,7 +7020,7 @@ bool Sema::isInitListConstructor(const CXXConstructorDecl* Ctor) {
if (const ReferenceType *RT = ArgType->getAs<ReferenceType>())
ArgType = RT->getPointeeType().getUnqualifiedType();
- return isStdInitializerList(ArgType, 0);
+ return isStdInitializerList(ArgType, nullptr);
}
/// \brief Determine whether a using statement is in a context where it will be
@@ -6830,7 +7041,7 @@ namespace {
// Callback to only accept typo corrections that are namespaces.
class NamespaceValidatorCCC : public CorrectionCandidateCallback {
public:
- bool ValidateCandidate(const TypoCorrection &candidate) LLVM_OVERRIDE {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
if (NamedDecl *ND = candidate.getCorrectionDecl())
return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
return false;
@@ -6847,7 +7058,8 @@ static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc,
R.clear();
if (TypoCorrection Corrected = S.CorrectTypo(R.getLookupNameInfo(),
R.getLookupKind(), Sc, &SS,
- Validator)) {
+ Validator,
+ Sema::CTK_ErrorRecovery)) {
if (DeclContext *DC = S.computeDeclContext(SS, false)) {
std::string CorrectedStr(Corrected.getAsString(S.getLangOpts()));
bool DroppedSpecifier = Corrected.WillReplaceSpecifier() &&
@@ -6883,16 +7095,16 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
S = S->getParent();
assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
- UsingDirectiveDecl *UDir = 0;
- NestedNameSpecifier *Qualifier = 0;
+ UsingDirectiveDecl *UDir = nullptr;
+ NestedNameSpecifier *Qualifier = nullptr;
if (SS.isSet())
- Qualifier = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ Qualifier = SS.getScopeRep();
// Lookup namespace name.
LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName);
LookupParsedName(R, S, &SS);
if (R.isAmbiguous())
- return 0;
+ return nullptr;
if (R.empty()) {
R.clear();
@@ -6957,7 +7169,7 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) {
if (Ctx && !Ctx->isFunctionOrMethod())
Ctx->addDecl(UDir);
else
- // Otherwise, it is at block sope. The using-directives will affect lookup
+ // Otherwise, it is at block scope. The using-directives will affect lookup
// only to the end of the scope.
S->PushUsingDirective(UDir);
}
@@ -6993,23 +7205,23 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
if (getLangOpts().CPlusPlus11) break;
- return 0;
-
+ return nullptr;
+
case UnqualifiedId::IK_DestructorName:
Diag(Name.getLocStart(), diag::err_using_decl_destructor)
<< SS.getRange();
- return 0;
-
+ return nullptr;
+
case UnqualifiedId::IK_TemplateId:
Diag(Name.getLocStart(), diag::err_using_decl_template_id)
<< SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc);
- return 0;
+ return nullptr;
}
DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name);
DeclarationName TargetName = TargetNameInfo.getName();
if (!TargetName)
- return 0;
+ return nullptr;
// Warn about access declarations.
if (!HasUsingKeyword) {
@@ -7021,7 +7233,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
if (DiagnoseUnexpandedParameterPack(SS, UPPC_UsingDeclaration) ||
DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC_UsingDeclaration))
- return 0;
+ return nullptr;
NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS,
TargetNameInfo, AttrList,
@@ -7113,7 +7325,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
//
// FIXME: but we might be increasing its access, in which case we
// should redeclare it.
- NamedDecl *NonTag = 0, *Tag = 0;
+ NamedDecl *NonTag = nullptr, *Tag = nullptr;
bool FoundEquivalentDecl = false;
for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
I != E; ++I) {
@@ -7130,22 +7342,17 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
if (FoundEquivalentDecl)
return false;
- if (Target->isFunctionOrFunctionTemplate()) {
- FunctionDecl *FD;
- if (isa<FunctionTemplateDecl>(Target))
- FD = cast<FunctionTemplateDecl>(Target)->getTemplatedDecl();
- else
- FD = cast<FunctionDecl>(Target);
-
- NamedDecl *OldDecl = 0;
- switch (CheckOverload(0, FD, Previous, OldDecl, /*IsForUsingDecl*/ true)) {
+ if (FunctionDecl *FD = Target->getAsFunction()) {
+ NamedDecl *OldDecl = nullptr;
+ switch (CheckOverload(nullptr, FD, Previous, OldDecl,
+ /*IsForUsingDecl*/ true)) {
case Ovl_Overload:
return false;
case Ovl_NonFunction:
Diag(Using->getLocation(), diag::err_using_decl_conflict);
break;
-
+
// We found a decl with the exact signature.
case Ovl_Match:
// If we're in a record, we want to hide the target, so we
@@ -7266,29 +7473,80 @@ void Sema::HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow) {
// be possible for this to happen, because...?
}
+/// Find the base specifier for a base class with the given type.
+static CXXBaseSpecifier *findDirectBaseWithType(CXXRecordDecl *Derived,
+ QualType DesiredBase,
+ bool &AnyDependentBases) {
+ // Check whether the named type is a direct base class.
+ CanQualType CanonicalDesiredBase = DesiredBase->getCanonicalTypeUnqualified();
+ for (auto &Base : Derived->bases()) {
+ CanQualType BaseType = Base.getType()->getCanonicalTypeUnqualified();
+ if (CanonicalDesiredBase == BaseType)
+ return &Base;
+ if (BaseType->isDependentType())
+ AnyDependentBases = true;
+ }
+ return nullptr;
+}
+
namespace {
class UsingValidatorCCC : public CorrectionCandidateCallback {
public:
UsingValidatorCCC(bool HasTypenameKeyword, bool IsInstantiation,
- bool RequireMember)
+ NestedNameSpecifier *NNS, CXXRecordDecl *RequireMemberOf)
: HasTypenameKeyword(HasTypenameKeyword),
- IsInstantiation(IsInstantiation), RequireMember(RequireMember) {}
+ IsInstantiation(IsInstantiation), OldNNS(NNS),
+ RequireMemberOf(RequireMemberOf) {}
- bool ValidateCandidate(const TypoCorrection &Candidate) LLVM_OVERRIDE {
+ bool ValidateCandidate(const TypoCorrection &Candidate) override {
NamedDecl *ND = Candidate.getCorrectionDecl();
// Keywords are not valid here.
if (!ND || isa<NamespaceDecl>(ND))
return false;
- if (RequireMember && !isa<FieldDecl>(ND) && !isa<CXXMethodDecl>(ND) &&
- !isa<TypeDecl>(ND))
- return false;
-
// Completely unqualified names are invalid for a 'using' declaration.
if (Candidate.WillReplaceSpecifier() && !Candidate.getCorrectionSpecifier())
return false;
+ if (RequireMemberOf) {
+ auto *FoundRecord = dyn_cast<CXXRecordDecl>(ND);
+ if (FoundRecord && FoundRecord->isInjectedClassName()) {
+ // No-one ever wants a using-declaration to name an injected-class-name
+ // of a base class, unless they're declaring an inheriting constructor.
+ ASTContext &Ctx = ND->getASTContext();
+ if (!Ctx.getLangOpts().CPlusPlus11)
+ return false;
+ QualType FoundType = Ctx.getRecordType(FoundRecord);
+
+ // Check that the injected-class-name is named as a member of its own
+ // type; we don't want to suggest 'using Derived::Base;', since that
+ // means something else.
+ NestedNameSpecifier *Specifier =
+ Candidate.WillReplaceSpecifier()
+ ? Candidate.getCorrectionSpecifier()
+ : OldNNS;
+ if (!Specifier->getAsType() ||
+ !Ctx.hasSameType(QualType(Specifier->getAsType(), 0), FoundType))
+ return false;
+
+ // Check that this inheriting constructor declaration actually names a
+ // direct base class of the current class.
+ bool AnyDependentBases = false;
+ if (!findDirectBaseWithType(RequireMemberOf,
+ Ctx.getRecordType(FoundRecord),
+ AnyDependentBases) &&
+ !AnyDependentBases)
+ return false;
+ } else {
+ auto *RD = dyn_cast<CXXRecordDecl>(ND->getDeclContext());
+ if (!RD || RequireMemberOf->isProvablyNotDerivedFrom(RD))
+ return false;
+
+ // FIXME: Check that the base class member is accessible?
+ }
+ }
+
if (isa<TypeDecl>(ND))
return HasTypenameKeyword || !IsInstantiation;
@@ -7298,7 +7556,8 @@ public:
private:
bool HasTypenameKeyword;
bool IsInstantiation;
- bool RequireMember;
+ NestedNameSpecifier *OldNNS;
+ CXXRecordDecl *RequireMemberOf;
};
} // end anonymous namespace
@@ -7310,7 +7569,7 @@ private:
NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
SourceLocation UsingLoc,
CXXScopeSpec &SS,
- const DeclarationNameInfo &NameInfo,
+ DeclarationNameInfo NameInfo,
AttributeList *AttrList,
bool IsInstantiation,
bool HasTypenameKeyword,
@@ -7323,7 +7582,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
if (SS.isEmpty()) {
Diag(IdentLoc, diag::err_using_requires_qualname);
- return 0;
+ return nullptr;
}
// Do the redeclaration lookup in the current scope.
@@ -7339,6 +7598,13 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
NamedDecl *D = F.next();
if (!isDeclInScope(D, CurContext, S))
F.erase();
+ // If we found a local extern declaration that's not ordinarily visible,
+ // and this declaration is being added to a non-block scope, ignore it.
+ // We're only checking for scope conflicts here, not also for violations
+ // of the linkage rules.
+ else if (!CurContext->isFunctionOrMethod() && D->isLocalExternDecl() &&
+ !(D->getIdentifierNamespace() & Decl::IDNS_Ordinary))
+ F.erase();
}
F.done();
} else {
@@ -7350,11 +7616,11 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
// Check for invalid redeclarations.
if (CheckUsingDeclRedeclaration(UsingLoc, HasTypenameKeyword,
SS, IdentLoc, Previous))
- return 0;
+ return nullptr;
// Check for bad qualifiers.
- if (CheckUsingDeclQualifier(UsingLoc, SS, IdentLoc))
- return 0;
+ if (CheckUsingDeclQualifier(UsingLoc, SS, NameInfo, IdentLoc))
+ return nullptr;
DeclContext *LookupContext = computeDeclContext(SS);
NamedDecl *D;
@@ -7370,25 +7636,30 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
D = UnresolvedUsingValueDecl::Create(Context, CurContext, UsingLoc,
QualifierLoc, NameInfo);
}
- } else {
- D = UsingDecl::Create(Context, CurContext, UsingLoc, QualifierLoc,
- NameInfo, HasTypenameKeyword);
+ D->setAccess(AS);
+ CurContext->addDecl(D);
+ return D;
}
- D->setAccess(AS);
- CurContext->addDecl(D);
- if (!LookupContext) return D;
- UsingDecl *UD = cast<UsingDecl>(D);
-
- if (RequireCompleteDeclContext(SS, LookupContext)) {
- UD->setInvalidDecl();
+ auto Build = [&](bool Invalid) {
+ UsingDecl *UD =
+ UsingDecl::Create(Context, CurContext, UsingLoc, QualifierLoc, NameInfo,
+ HasTypenameKeyword);
+ UD->setAccess(AS);
+ CurContext->addDecl(UD);
+ UD->setInvalidDecl(Invalid);
return UD;
- }
+ };
+ auto BuildInvalid = [&]{ return Build(true); };
+ auto BuildValid = [&]{ return Build(false); };
+
+ if (RequireCompleteDeclContext(SS, LookupContext))
+ return BuildInvalid();
// The normal rules do not apply to inheriting constructor declarations.
if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) {
- if (CheckInheritingConstructorUsingDecl(UD))
- UD->setInvalidDecl();
+ UsingDecl *UD = BuildValid();
+ CheckInheritingConstructorUsingDecl(UD);
return UD;
}
@@ -7414,31 +7685,53 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
// Try to correct typos if possible.
if (R.empty()) {
- UsingValidatorCCC CCC(HasTypenameKeyword, IsInstantiation,
- CurContext->isRecord());
+ UsingValidatorCCC CCC(HasTypenameKeyword, IsInstantiation, SS.getScopeRep(),
+ dyn_cast<CXXRecordDecl>(CurContext));
if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(),
- R.getLookupKind(), S, &SS, CCC)){
+ R.getLookupKind(), S, &SS, CCC,
+ CTK_ErrorRecovery)){
// We reject any correction for which ND would be NULL.
NamedDecl *ND = Corrected.getCorrectionDecl();
- R.setLookupName(Corrected.getCorrection());
- R.addDecl(ND);
+
// We reject candidates where DroppedSpecifier == true, hence the
// literal '0' below.
diagnoseTypo(Corrected, PDiag(diag::err_no_member_suggest)
<< NameInfo.getName() << LookupContext << 0
<< SS.getRange());
+
+ // If we corrected to an inheriting constructor, handle it as one.
+ auto *RD = dyn_cast<CXXRecordDecl>(ND);
+ if (RD && RD->isInjectedClassName()) {
+ // Fix up the information we'll use to build the using declaration.
+ if (Corrected.WillReplaceSpecifier()) {
+ NestedNameSpecifierLocBuilder Builder;
+ Builder.MakeTrivial(Context, Corrected.getCorrectionSpecifier(),
+ QualifierLoc.getSourceRange());
+ QualifierLoc = Builder.getWithLocInContext(Context);
+ }
+
+ NameInfo.setName(Context.DeclarationNames.getCXXConstructorName(
+ Context.getCanonicalType(Context.getRecordType(RD))));
+ NameInfo.setNamedTypeInfo(nullptr);
+
+ // Build it and process it as an inheriting constructor.
+ UsingDecl *UD = BuildValid();
+ CheckInheritingConstructorUsingDecl(UD);
+ return UD;
+ }
+
+ // FIXME: Pick up all the declarations if we found an overloaded function.
+ R.setLookupName(Corrected.getCorrection());
+ R.addDecl(ND);
} else {
Diag(IdentLoc, diag::err_no_member)
<< NameInfo.getName() << LookupContext << SS.getRange();
- UD->setInvalidDecl();
- return UD;
+ return BuildInvalid();
}
}
- if (R.isAmbiguous()) {
- UD->setInvalidDecl();
- return UD;
- }
+ if (R.isAmbiguous())
+ return BuildInvalid();
if (HasTypenameKeyword) {
// If we asked for a typename and got a non-type decl, error out.
@@ -7447,8 +7740,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
Diag((*I)->getUnderlyingDecl()->getLocation(),
diag::note_using_decl_target);
- UD->setInvalidDecl();
- return UD;
+ return BuildInvalid();
}
} else {
// If we asked for a non-typename and we got a type, error out,
@@ -7457,8 +7749,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
if (IsInstantiation && R.getAsSingle<TypeDecl>()) {
Diag(IdentLoc, diag::err_using_dependent_value_is_type);
Diag(R.getFoundDecl()->getLocation(), diag::note_using_decl_target);
- UD->setInvalidDecl();
- return UD;
+ return BuildInvalid();
}
}
@@ -7467,12 +7758,12 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
if (R.getAsSingle<NamespaceDecl>()) {
Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace)
<< SS.getRange();
- UD->setInvalidDecl();
- return UD;
+ return BuildInvalid();
}
+ UsingDecl *UD = BuildValid();
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
- UsingShadowDecl *PrevDecl = 0;
+ UsingShadowDecl *PrevDecl = nullptr;
if (!CheckUsingShadowDecl(UD, *I, Previous, PrevDecl))
BuildUsingShadowDecl(S, UD, *I, PrevDecl);
}
@@ -7490,28 +7781,20 @@ bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) {
CXXRecordDecl *TargetClass = cast<CXXRecordDecl>(CurContext);
// Check whether the named type is a direct base class.
- CanQualType CanonicalSourceType = SourceType->getCanonicalTypeUnqualified();
- CXXRecordDecl::base_class_iterator BaseIt, BaseE;
- for (BaseIt = TargetClass->bases_begin(), BaseE = TargetClass->bases_end();
- BaseIt != BaseE; ++BaseIt) {
- CanQualType BaseType = BaseIt->getType()->getCanonicalTypeUnqualified();
- if (CanonicalSourceType == BaseType)
- break;
- if (BaseIt->getType()->isDependentType())
- break;
- }
-
- if (BaseIt == BaseE) {
- // Did not find SourceType in the bases.
+ bool AnyDependentBases = false;
+ auto *Base = findDirectBaseWithType(TargetClass, QualType(SourceType, 0),
+ AnyDependentBases);
+ if (!Base && !AnyDependentBases) {
Diag(UD->getUsingLoc(),
diag::err_using_decl_constructor_not_in_direct_base)
<< UD->getNameInfo().getSourceRange()
<< QualType(SourceType, 0) << TargetClass;
+ UD->setInvalidDecl();
return true;
}
- if (!CurContext->isDependentContext())
- BaseIt->setInheritConstructors();
+ if (Base)
+ Base->setInheritConstructors();
return false;
}
@@ -7534,8 +7817,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
if (!CurContext->getRedeclContext()->isRecord())
return false;
- NestedNameSpecifier *Qual
- = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+ NestedNameSpecifier *Qual = SS.getScopeRep();
for (LookupResult::iterator I = Prev.begin(), E = Prev.end(); I != E; ++I) {
NamedDecl *D = *I;
@@ -7580,6 +7862,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
/// scope. If an error is found, diagnoses it and returns true.
bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
const CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
SourceLocation NameLoc) {
DeclContext *NamedContext = computeDeclContext(SS);
@@ -7591,8 +7874,56 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
// If we weren't able to compute a valid scope, it must be a
// dependent class scope.
if (!NamedContext || NamedContext->isRecord()) {
+ auto *RD = dyn_cast<CXXRecordDecl>(NamedContext);
+ if (RD && RequireCompleteDeclContext(const_cast<CXXScopeSpec&>(SS), RD))
+ RD = nullptr;
+
Diag(NameLoc, diag::err_using_decl_can_not_refer_to_class_member)
<< SS.getRange();
+
+ // If we have a complete, non-dependent source type, try to suggest a
+ // way to get the same effect.
+ if (!RD)
+ return true;
+
+ // Find what this using-declaration was referring to.
+ LookupResult R(*this, NameInfo, LookupOrdinaryName);
+ R.setHideTags(false);
+ R.suppressDiagnostics();
+ LookupQualifiedName(R, RD);
+
+ if (R.getAsSingle<TypeDecl>()) {
+ if (getLangOpts().CPlusPlus11) {
+ // Convert 'using X::Y;' to 'using Y = X::Y;'.
+ Diag(SS.getBeginLoc(), diag::note_using_decl_class_member_workaround)
+ << 0 // alias declaration
+ << FixItHint::CreateInsertion(SS.getBeginLoc(),
+ NameInfo.getName().getAsString() +
+ " = ");
+ } else {
+ // Convert 'using X::Y;' to 'typedef X::Y Y;'.
+ SourceLocation InsertLoc =
+ PP.getLocForEndOfToken(NameInfo.getLocEnd());
+ Diag(InsertLoc, diag::note_using_decl_class_member_workaround)
+ << 1 // typedef declaration
+ << FixItHint::CreateReplacement(UsingLoc, "typedef")
+ << FixItHint::CreateInsertion(
+ InsertLoc, " " + NameInfo.getName().getAsString());
+ }
+ } else if (R.getAsSingle<VarDecl>()) {
+ // Don't provide a fixit outside C++11 mode; we don't want to suggest
+ // repeating the type of the static data member here.
+ FixItHint FixIt;
+ if (getLangOpts().CPlusPlus11) {
+ // Convert 'using X::Y;' to 'auto &Y = X::Y;'.
+ FixIt = FixItHint::CreateReplacement(
+ UsingLoc, "auto &" + NameInfo.getName().getAsString() + " = ");
+ }
+
+ Diag(UsingLoc, diag::note_using_decl_class_member_workaround)
+ << 2 // reference declaration
+ << FixIt;
+ }
return true;
}
@@ -7618,7 +7949,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
// but we don't have that level of source info.
Diag(SS.getRange().getBegin(),
diag::err_using_decl_nested_name_specifier_is_not_class)
- << (NestedNameSpecifier*) SS.getScopeRep() << SS.getRange();
+ << SS.getScopeRep() << SS.getRange();
return true;
}
@@ -7643,7 +7974,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
Diag(SS.getRange().getBegin(),
diag::err_using_decl_nested_name_specifier_is_not_base_class)
- << (NestedNameSpecifier*) SS.getScopeRep()
+ << SS.getScopeRep()
<< cast<CXXRecordDecl>(CurContext)
<< SS.getRange();
return true;
@@ -7703,7 +8034,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
Diag(SS.getRange().getBegin(),
diag::err_using_decl_nested_name_specifier_is_not_base_class)
- << (NestedNameSpecifier*) SS.getScopeRep()
+ << SS.getScopeRep()
<< cast<CXXRecordDecl>(CurContext)
<< SS.getRange();
@@ -7724,15 +8055,15 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
"got alias-declaration outside of declaration scope");
if (Type.isInvalid())
- return 0;
+ return nullptr;
bool Invalid = false;
DeclarationNameInfo NameInfo = GetNameFromUnqualifiedId(Name);
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
GetTypeFromParser(Type.get(), &TInfo);
if (DiagnoseClassNameShadow(CurContext, NameInfo))
- return 0;
+ return nullptr;
if (DiagnoseUnexpandedParameterPack(Name.StartLocation, TInfo,
UPPC_DeclarationType)) {
@@ -7771,8 +8102,8 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
NamedDecl *NewND;
if (TemplateParamLists.size()) {
- TypeAliasTemplateDecl *OldDecl = 0;
- TemplateParameterList *OldTemplateParams = 0;
+ TypeAliasTemplateDecl *OldDecl = nullptr;
+ TemplateParameterList *OldTemplateParams = nullptr;
if (TemplateParamLists.size() != 1) {
Diag(UsingLoc, diag::err_alias_template_extra_headers)
@@ -7827,7 +8158,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
// and check the parameter list.
if (CheckTemplateParameterList(TemplateParams, OldTemplateParams,
TPC_TypeAliasTemplate))
- return 0;
+ return nullptr;
TypeAliasTemplateDecl *NewDecl =
TypeAliasTemplateDecl::Create(Context, CurContext, UsingLoc,
@@ -7871,7 +8202,7 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S,
= LookupSingleName(S, Alias, AliasLoc, LookupOrdinaryName,
ForRedeclaration);
if (PrevDecl && !isDeclInScope(PrevDecl, CurContext, S))
- PrevDecl = 0;
+ PrevDecl = nullptr;
if (PrevDecl) {
if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(PrevDecl)) {
@@ -7881,23 +8212,23 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S,
// declaration to maintain better source information.
if (!R.isAmbiguous() && !R.empty() &&
AD->getNamespace()->Equals(getNamespaceDecl(R.getFoundDecl())))
- return 0;
+ return nullptr;
}
unsigned DiagID = isa<NamespaceDecl>(PrevDecl) ? diag::err_redefinition :
diag::err_redefinition_different_kind;
Diag(AliasLoc, DiagID) << Alias;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
- return 0;
+ return nullptr;
}
if (R.isAmbiguous())
- return 0;
+ return nullptr;
if (R.empty()) {
if (!TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, Ident)) {
Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange();
- return 0;
+ return nullptr;
}
}
@@ -7923,40 +8254,34 @@ Sema::ComputeDefaultedDefaultCtorExceptionSpec(SourceLocation Loc,
return ExceptSpec;
// Direct base-class constructors.
- for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(),
- BEnd = ClassDecl->bases_end();
- B != BEnd; ++B) {
- if (B->isVirtual()) // Handled below.
+ for (const auto &B : ClassDecl->bases()) {
+ if (B.isVirtual()) // Handled below.
continue;
- if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+ if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) {
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl);
// If this is a deleted function, add it anyway. This might be conformant
// with the standard. This might not. I'm not sure. It might not matter.
if (Constructor)
- ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
+ ExceptSpec.CalledDecl(B.getLocStart(), Constructor);
}
}
// Virtual base-class constructors.
- for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(),
- BEnd = ClassDecl->vbases_end();
- B != BEnd; ++B) {
- if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+ for (const auto &B : ClassDecl->vbases()) {
+ if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) {
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl);
// If this is a deleted function, add it anyway. This might be conformant
// with the standard. This might not. I'm not sure. It might not matter.
if (Constructor)
- ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
+ ExceptSpec.CalledDecl(B.getLocStart(), Constructor);
}
}
// Field constructors.
- for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
- FEnd = ClassDecl->field_end();
- F != FEnd; ++F) {
+ for (const auto *F : ClassDecl->fields()) {
if (F->hasInClassInitializer()) {
if (Expr *E = F->getInClassInitializer())
ExceptSpec.CalledExpr(E);
@@ -8012,40 +8337,34 @@ Sema::ComputeInheritingCtorExceptionSpec(CXXConstructorDecl *CD) {
ExceptSpec.CalledDecl(CD->getLocStart(), InheritedCD);
// Direct base-class constructors.
- for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(),
- BEnd = ClassDecl->bases_end();
- B != BEnd; ++B) {
- if (B->isVirtual()) // Handled below.
+ for (const auto &B : ClassDecl->bases()) {
+ if (B.isVirtual()) // Handled below.
continue;
- if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+ if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) {
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
if (BaseClassDecl == InheritedDecl)
continue;
CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl);
if (Constructor)
- ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
+ ExceptSpec.CalledDecl(B.getLocStart(), Constructor);
}
}
// Virtual base-class constructors.
- for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(),
- BEnd = ClassDecl->vbases_end();
- B != BEnd; ++B) {
- if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+ for (const auto &B : ClassDecl->vbases()) {
+ if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) {
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
if (BaseClassDecl == InheritedDecl)
continue;
CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl);
if (Constructor)
- ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
+ ExceptSpec.CalledDecl(B.getLocStart(), Constructor);
}
}
// Field constructors.
- for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
- FEnd = ClassDecl->field_end();
- F != FEnd; ++F) {
+ for (const auto *F : ClassDecl->fields()) {
if (F->hasInClassInitializer()) {
if (Expr *E = F->getInClassInitializer())
ExceptSpec.CalledExpr(E);
@@ -8107,7 +8426,7 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
DeclaringSpecialMember DSM(*this, ClassDecl, CXXDefaultConstructor);
if (DSM.isAlreadyBeingDeclared())
- return 0;
+ return nullptr;
bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl,
CXXDefaultConstructor,
@@ -8121,9 +8440,9 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
= Context.DeclarationNames.getCXXConstructorName(ClassType);
DeclarationNameInfo NameInfo(Name, ClassLoc);
CXXConstructorDecl *DefaultCon = CXXConstructorDecl::Create(
- Context, ClassDecl, ClassLoc, NameInfo, /*Type*/QualType(), /*TInfo=*/0,
- /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true,
- Constexpr);
+ Context, ClassDecl, ClassLoc, NameInfo, /*Type*/QualType(),
+ /*TInfo=*/nullptr, /*isExplicit=*/false, /*isInline=*/true,
+ /*isImplicitlyDeclared=*/true, Constexpr);
DefaultCon->setAccess(AS_public);
DefaultCon->setDefaulted();
DefaultCon->setImplicit();
@@ -8169,7 +8488,9 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
return;
}
- SourceLocation Loc = Constructor->getLocation();
+ SourceLocation Loc = Constructor->getLocEnd().isValid()
+ ? Constructor->getLocEnd()
+ : Constructor->getLocation();
Constructor->setBody(new (Context) CompoundStmt(Loc));
Constructor->markUsed(Context);
@@ -8209,7 +8530,7 @@ private:
/// Information about an inheriting constructor.
struct InheritingConstructor {
InheritingConstructor()
- : DeclaredInDerived(false), BaseCtor(0), DerivedCtor(0) {}
+ : DeclaredInDerived(false), BaseCtor(nullptr), DerivedCtor(nullptr) {}
/// If \c true, a constructor with this signature is already declared
/// in the derived class.
@@ -8256,10 +8577,8 @@ private:
/// Process all constructors for a class.
void visitAll(const CXXRecordDecl *RD, VisitFn Callback) {
- for (CXXRecordDecl::ctor_iterator CtorIt = RD->ctor_begin(),
- CtorE = RD->ctor_end();
- CtorIt != CtorE; ++CtorIt)
- (this->*Callback)(*CtorIt);
+ for (const auto *Ctor : RD->ctors())
+ (this->*Callback)(Ctor);
for (CXXRecordDecl::specific_decl_iterator<FunctionTemplateDecl>
I(RD->decls_begin()), E(RD->decls_end());
I != E; ++I) {
@@ -8278,7 +8597,7 @@ private:
void inherit(const CXXConstructorDecl *Ctor) {
const FunctionProtoType *CtorType =
Ctor->getType()->castAs<FunctionProtoType>();
- ArrayRef<QualType> ArgTypes(CtorType->getArgTypes());
+ ArrayRef<QualType> ArgTypes(CtorType->getParamTypes());
FunctionProtoType::ExtProtoInfo EPI = CtorType->getExtProtoInfo();
SourceLocation UsingLoc = getUsingLoc(Ctor->getParent());
@@ -8306,7 +8625,7 @@ private:
do
declareCtor(UsingLoc, Ctor,
SemaRef.Context.getFunctionType(
- Ctor->getResultType(), ArgTypes.slice(0, Params), EPI));
+ Ctor->getReturnType(), ArgTypes.slice(0, Params), EPI));
while (Params > MinParams &&
Ctor->getParamDecl(--Params)->hasDefaultArg());
}
@@ -8392,7 +8711,7 @@ private:
Context.getCanonicalType(Context.getRecordType(Derived)));
DeclarationNameInfo NameInfo(Name, UsingLoc);
- TemplateParameterList *TemplateParams = 0;
+ TemplateParameterList *TemplateParams = nullptr;
if (const FunctionTemplateDecl *FTD =
BaseCtor->getDescribedFunctionTemplate()) {
TemplateParams = FTD->getTemplateParameters();
@@ -8420,21 +8739,21 @@ private:
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.ExceptionSpecType = EST_Unevaluated;
EPI.ExceptionSpecDecl = DerivedCtor;
- DerivedCtor->setType(Context.getFunctionType(FPT->getResultType(),
- FPT->getArgTypes(), EPI));
+ DerivedCtor->setType(Context.getFunctionType(FPT->getReturnType(),
+ FPT->getParamTypes(), EPI));
// Build the parameter declarations.
SmallVector<ParmVarDecl *, 16> ParamDecls;
- for (unsigned I = 0, N = FPT->getNumArgs(); I != N; ++I) {
+ for (unsigned I = 0, N = FPT->getNumParams(); I != N; ++I) {
TypeSourceInfo *TInfo =
- Context.getTrivialTypeSourceInfo(FPT->getArgType(I), UsingLoc);
+ Context.getTrivialTypeSourceInfo(FPT->getParamType(I), UsingLoc);
ParmVarDecl *PD = ParmVarDecl::Create(
- Context, DerivedCtor, UsingLoc, UsingLoc, /*IdentifierInfo=*/0,
- FPT->getArgType(I), TInfo, SC_None, /*DefaultArg=*/0);
+ Context, DerivedCtor, UsingLoc, UsingLoc, /*IdentifierInfo=*/nullptr,
+ FPT->getParamType(I), TInfo, SC_None, /*DefaultArg=*/nullptr);
PD->setScopeInfo(0, I);
PD->setImplicit();
ParamDecls.push_back(PD);
- ProtoLoc.setArg(I, PD);
+ ProtoLoc.setParam(I, PD);
}
// Set up the new constructor.
@@ -8475,11 +8794,9 @@ void Sema::DeclareInheritingConstructors(CXXRecordDecl *ClassDecl) {
// Find base classes from which we might inherit constructors.
SmallVector<CXXRecordDecl*, 4> InheritedBases;
- for (CXXRecordDecl::base_class_iterator BaseIt = ClassDecl->bases_begin(),
- BaseE = ClassDecl->bases_end();
- BaseIt != BaseE; ++BaseIt)
- if (BaseIt->getInheritConstructors())
- InheritedBases.push_back(BaseIt->getType()->getAsCXXRecordDecl());
+ for (const auto &BaseIt : ClassDecl->bases())
+ if (BaseIt.getInheritConstructors())
+ InheritedBases.push_back(BaseIt.getType()->getAsCXXRecordDecl());
// Go no further if we're not inheriting any constructors.
if (InheritedBases.empty())
@@ -8532,30 +8849,24 @@ Sema::ComputeDefaultedDtorExceptionSpec(CXXMethodDecl *MD) {
return ExceptSpec;
// Direct base-class destructors.
- for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(),
- BEnd = ClassDecl->bases_end();
- B != BEnd; ++B) {
- if (B->isVirtual()) // Handled below.
+ for (const auto &B : ClassDecl->bases()) {
+ if (B.isVirtual()) // Handled below.
continue;
- if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
- ExceptSpec.CalledDecl(B->getLocStart(),
+ if (const RecordType *BaseType = B.getType()->getAs<RecordType>())
+ ExceptSpec.CalledDecl(B.getLocStart(),
LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
}
// Virtual base-class destructors.
- for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(),
- BEnd = ClassDecl->vbases_end();
- B != BEnd; ++B) {
- if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
- ExceptSpec.CalledDecl(B->getLocStart(),
+ for (const auto &B : ClassDecl->vbases()) {
+ if (const RecordType *BaseType = B.getType()->getAs<RecordType>())
+ ExceptSpec.CalledDecl(B.getLocStart(),
LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
}
// Field destructors.
- for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
- FEnd = ClassDecl->field_end();
- F != FEnd; ++F) {
+ for (const auto *F : ClassDecl->fields()) {
if (const RecordType *RecordTy
= Context.getBaseElementType(F->getType())->getAs<RecordType>())
ExceptSpec.CalledDecl(F->getLocation(),
@@ -8574,7 +8885,7 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
DeclaringSpecialMember DSM(*this, ClassDecl, CXXDestructor);
if (DSM.isAlreadyBeingDeclared())
- return 0;
+ return nullptr;
// Create the actual destructor declaration.
CanQualType ClassType
@@ -8585,7 +8896,7 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
DeclarationNameInfo NameInfo(Name, ClassLoc);
CXXDestructorDecl *Destructor
= CXXDestructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo,
- QualType(), 0, /*isInline=*/true,
+ QualType(), nullptr, /*isInline=*/true,
/*isImplicitlyDeclared=*/true);
Destructor->setAccess(AS_public);
Destructor->setDefaulted();
@@ -8641,7 +8952,9 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
return;
}
- SourceLocation Loc = Destructor->getLocation();
+ SourceLocation Loc = Destructor->getLocEnd().isValid()
+ ? Destructor->getLocEnd()
+ : Destructor->getLocation();
Destructor->setBody(new (Context) CompoundStmt(Loc));
Destructor->markUsed(Context);
MarkVTableUsed(CurrentLocation, ClassDecl);
@@ -8719,8 +9032,8 @@ class RefBuilder: public ExprBuilder {
QualType VarType;
public:
- virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
- return assertNotNull(S.BuildDeclRefExpr(Var, VarType, VK_LValue, Loc).take());
+ virtual Expr *build(Sema &S, SourceLocation Loc) const override {
+ return assertNotNull(S.BuildDeclRefExpr(Var, VarType, VK_LValue, Loc).get());
}
RefBuilder(VarDecl *Var, QualType VarType)
@@ -8729,8 +9042,8 @@ public:
class ThisBuilder: public ExprBuilder {
public:
- virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
- return assertNotNull(S.ActOnCXXThis(Loc).takeAs<Expr>());
+ virtual Expr *build(Sema &S, SourceLocation Loc) const override {
+ return assertNotNull(S.ActOnCXXThis(Loc).getAs<Expr>());
}
};
@@ -8741,10 +9054,10 @@ class CastBuilder: public ExprBuilder {
const CXXCastPath &Path;
public:
- virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ virtual Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(S.ImpCastExprToType(Builder.build(S, Loc), Type,
CK_UncheckedDerivedToBase, Kind,
- &Path).take());
+ &Path).get());
}
CastBuilder(const ExprBuilder &Builder, QualType Type, ExprValueKind Kind,
@@ -8756,9 +9069,9 @@ class DerefBuilder: public ExprBuilder {
const ExprBuilder &Builder;
public:
- virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ virtual Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(
- S.CreateBuiltinUnaryOp(Loc, UO_Deref, Builder.build(S, Loc)).take());
+ S.CreateBuiltinUnaryOp(Loc, UO_Deref, Builder.build(S, Loc)).get());
}
DerefBuilder(const ExprBuilder &Builder) : Builder(Builder) {}
@@ -8772,10 +9085,10 @@ class MemberBuilder: public ExprBuilder {
LookupResult &MemberLookup;
public:
- virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ virtual Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(S.BuildMemberReferenceExpr(
- Builder.build(S, Loc), Type, Loc, IsArrow, SS, SourceLocation(), 0,
- MemberLookup, 0).take());
+ Builder.build(S, Loc), Type, Loc, IsArrow, SS, SourceLocation(),
+ nullptr, MemberLookup, nullptr).get());
}
MemberBuilder(const ExprBuilder &Builder, QualType Type, bool IsArrow,
@@ -8788,7 +9101,7 @@ class MoveCastBuilder: public ExprBuilder {
const ExprBuilder &Builder;
public:
- virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ virtual Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(CastForMoving(S, Builder.build(S, Loc)));
}
@@ -8799,9 +9112,9 @@ class LvalueConvBuilder: public ExprBuilder {
const ExprBuilder &Builder;
public:
- virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ virtual Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(
- S.DefaultLvalueConversion(Builder.build(S, Loc)).take());
+ S.DefaultLvalueConversion(Builder.build(S, Loc)).get());
}
LvalueConvBuilder(const ExprBuilder &Builder) : Builder(Builder) {}
@@ -8812,10 +9125,9 @@ class SubscriptBuilder: public ExprBuilder {
const ExprBuilder &Index;
public:
- virtual Expr *build(Sema &S, SourceLocation Loc) const
- LLVM_OVERRIDE {
+ virtual Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(S.CreateBuiltinArraySubscriptExpr(
- Base.build(S, Loc), Loc, Index.build(S, Loc), Loc).take());
+ Base.build(S, Loc), Loc, Index.build(S, Loc), Loc).get());
}
SubscriptBuilder(const ExprBuilder &Base, const ExprBuilder &Index)
@@ -8867,17 +9179,17 @@ buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T,
return StmtError();
ExprResult MemCpyRef = S.BuildDeclRefExpr(MemCpy, S.Context.BuiltinFnTy,
- VK_RValue, Loc, 0);
+ VK_RValue, Loc, nullptr);
assert(MemCpyRef.isUsable() && "Builtin reference cannot fail");
Expr *CallArgs[] = {
To, From, IntegerLiteral::Create(S.Context, Size, SizeType, Loc)
};
- ExprResult Call = S.ActOnCallExpr(/*Scope=*/0, MemCpyRef.take(),
+ ExprResult Call = S.ActOnCallExpr(/*Scope=*/nullptr, MemCpyRef.get(),
Loc, CallArgs, Loc);
assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!");
- return S.Owned(Call.takeAs<Stmt>());
+ return Call.getAs<Stmt>();
}
/// \brief Builds a statement that copies/moves the given entity from \p From to
@@ -8976,7 +9288,7 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
CXXScopeSpec SS;
const Type *CanonicalT = S.Context.getCanonicalType(T.getTypePtr());
SS.MakeTrivial(S.Context,
- NestedNameSpecifier::Create(S.Context, 0, false,
+ NestedNameSpecifier::Create(S.Context, nullptr, false,
CanonicalT),
Loc);
@@ -8984,9 +9296,9 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
ExprResult OpEqualRef
= S.BuildMemberReferenceExpr(To.build(S, Loc), T, Loc, /*isArrow=*/false,
SS, /*TemplateKWLoc=*/SourceLocation(),
- /*FirstQualifierInScope=*/0,
+ /*FirstQualifierInScope=*/nullptr,
OpLookup,
- /*TemplateArgs=*/0,
+ /*TemplateArgs=*/nullptr,
/*SuppressQualifierCheck=*/true);
if (OpEqualRef.isInvalid())
return StmtError();
@@ -8994,8 +9306,8 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
// Build the call to the assignment operator.
Expr *FromInst = From.build(S, Loc);
- ExprResult Call = S.BuildCallToMemberFunction(/*Scope=*/0,
- OpEqualRef.takeAs<Expr>(),
+ ExprResult Call = S.BuildCallToMemberFunction(/*Scope=*/nullptr,
+ OpEqualRef.getAs<Expr>(),
Loc, FromInst, Loc);
if (Call.isInvalid())
return StmtError();
@@ -9004,7 +9316,7 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
// bail out. We'll replace the whole shebang with a memcpy.
CXXMemberCallExpr *CE = dyn_cast<CXXMemberCallExpr>(Call.get());
if (CE && CE->getMethodDecl()->isTrivial() && Depth)
- return StmtResult((Stmt*)0);
+ return StmtResult((Stmt*)nullptr);
// Convert to an expression-statement, and clean up any produced
// temporaries.
@@ -9033,7 +9345,7 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
QualType SizeType = S.Context.getSizeType();
// Create the iteration variable.
- IdentifierInfo *IterationVarName = 0;
+ IdentifierInfo *IterationVarName = nullptr;
{
SmallString<8> Str;
llvm::raw_svector_ostream OS(Str);
@@ -9093,8 +9405,8 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
// Construct the loop that copies all elements of this array.
return S.ActOnForStmt(Loc, Loc, InitStmt,
S.MakeFullExpr(Comparison),
- 0, S.MakeFullDiscardedValueExpr(Increment),
- Loc, Copy.take());
+ nullptr, S.MakeFullDiscardedValueExpr(Increment),
+ Loc, Copy.get());
}
static StmtResult
@@ -9127,8 +9439,9 @@ Sema::ComputeDefaultedCopyAssignmentExceptionSpec(CXXMethodDecl *MD) {
return ExceptSpec;
const FunctionProtoType *T = MD->getType()->castAs<FunctionProtoType>();
- assert(T->getNumArgs() == 1 && "not a copy assignment op");
- unsigned ArgQuals = T->getArgType(0).getNonReferenceType().getCVRQualifiers();
+ assert(T->getNumParams() == 1 && "not a copy assignment op");
+ unsigned ArgQuals =
+ T->getParamType(0).getNonReferenceType().getCVRQualifiers();
// C++ [except.spec]p14:
// An implicitly declared special member function (Clause 12) shall have an
@@ -9140,33 +9453,26 @@ Sema::ComputeDefaultedCopyAssignmentExceptionSpec(CXXMethodDecl *MD) {
// Based on a similar decision made for constness in C++0x, we're erring on
// the side of assuming such calls to be made regardless of whether they
// actually happen.
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
- BaseEnd = ClassDecl->bases_end();
- Base != BaseEnd; ++Base) {
- if (Base->isVirtual())
+ for (const auto &Base : ClassDecl->bases()) {
+ if (Base.isVirtual())
continue;
CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
if (CXXMethodDecl *CopyAssign = LookupCopyingAssignment(BaseClassDecl,
ArgQuals, false, 0))
- ExceptSpec.CalledDecl(Base->getLocStart(), CopyAssign);
+ ExceptSpec.CalledDecl(Base.getLocStart(), CopyAssign);
}
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
- BaseEnd = ClassDecl->vbases_end();
- Base != BaseEnd; ++Base) {
+ for (const auto &Base : ClassDecl->vbases()) {
CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
if (CXXMethodDecl *CopyAssign = LookupCopyingAssignment(BaseClassDecl,
ArgQuals, false, 0))
- ExceptSpec.CalledDecl(Base->getLocStart(), CopyAssign);
+ ExceptSpec.CalledDecl(Base.getLocStart(), CopyAssign);
}
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- FieldEnd = ClassDecl->field_end();
- Field != FieldEnd;
- ++Field) {
+ for (const auto *Field : ClassDecl->fields()) {
QualType FieldType = Context.getBaseElementType(Field->getType());
if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
if (CXXMethodDecl *CopyAssign =
@@ -9189,7 +9495,7 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
DeclaringSpecialMember DSM(*this, ClassDecl, CXXCopyAssignment);
if (DSM.isAlreadyBeingDeclared())
- return 0;
+ return nullptr;
QualType ArgType = Context.getTypeDeclType(ClassDecl);
QualType RetType = Context.getLValueReferenceType(ArgType);
@@ -9209,8 +9515,8 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
DeclarationNameInfo NameInfo(Name, ClassLoc);
CXXMethodDecl *CopyAssignment =
CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(),
- /*TInfo=*/ 0, /*StorageClass=*/ SC_None,
- /*isInline=*/ true, Constexpr, SourceLocation());
+ /*TInfo=*/nullptr, /*StorageClass=*/SC_None,
+ /*isInline=*/true, Constexpr, SourceLocation());
CopyAssignment->setAccess(AS_public);
CopyAssignment->setDefaulted();
CopyAssignment->setImplicit();
@@ -9222,9 +9528,10 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
// Add the parameter to the operator.
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment,
- ClassLoc, ClassLoc, /*Id=*/0,
- ArgType, /*TInfo=*/0,
- SC_None, 0);
+ ClassLoc, ClassLoc,
+ /*Id=*/nullptr, ArgType,
+ /*TInfo=*/nullptr, SC_None,
+ nullptr);
CopyAssignment->setParams(FromParam);
AddOverriddenMethods(ClassDecl, CopyAssignment);
@@ -9255,7 +9562,7 @@ static void diagnoseDeprecatedCopyOperation(Sema &S, CXXMethodDecl *CopyOp,
assert(CopyOp->isImplicit());
CXXRecordDecl *RD = CopyOp->getParent();
- CXXMethodDecl *UserDeclaredOperation = 0;
+ CXXMethodDecl *UserDeclaredOperation = nullptr;
// In Microsoft mode, assignment operations don't affect constructors and
// vice versa.
@@ -9263,24 +9570,22 @@ static void diagnoseDeprecatedCopyOperation(Sema &S, CXXMethodDecl *CopyOp,
UserDeclaredOperation = RD->getDestructor();
} else if (!isa<CXXConstructorDecl>(CopyOp) &&
RD->hasUserDeclaredCopyConstructor() &&
- !S.getLangOpts().MicrosoftMode) {
+ !S.getLangOpts().MSVCCompat) {
// Find any user-declared copy constructor.
- for (CXXRecordDecl::ctor_iterator I = RD->ctor_begin(),
- E = RD->ctor_end(); I != E; ++I) {
+ for (auto *I : RD->ctors()) {
if (I->isCopyConstructor()) {
- UserDeclaredOperation = *I;
+ UserDeclaredOperation = I;
break;
}
}
assert(UserDeclaredOperation);
} else if (isa<CXXConstructorDecl>(CopyOp) &&
RD->hasUserDeclaredCopyAssignment() &&
- !S.getLangOpts().MicrosoftMode) {
+ !S.getLangOpts().MSVCCompat) {
// Find any user-declared move assignment operator.
- for (CXXRecordDecl::method_iterator I = RD->method_begin(),
- E = RD->method_end(); I != E; ++I) {
+ for (auto *I : RD->methods()) {
if (I->isCopyAssignmentOperator()) {
- UserDeclaredOperation = *I;
+ UserDeclaredOperation = I;
break;
}
}
@@ -9349,8 +9654,10 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
}
// Our location for everything implicitly-generated.
- SourceLocation Loc = CopyAssignOperator->getLocation();
-
+ SourceLocation Loc = CopyAssignOperator->getLocEnd().isValid()
+ ? CopyAssignOperator->getLocEnd()
+ : CopyAssignOperator->getLocation();
+
// Builds a DeclRefExpr for the "other" object.
RefBuilder OtherRef(Other, OtherRefType);
@@ -9359,18 +9666,17 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
// Assign base classes.
bool Invalid = false;
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
- E = ClassDecl->bases_end(); Base != E; ++Base) {
+ for (auto &Base : ClassDecl->bases()) {
// Form the assignment:
// static_cast<Base*>(this)->Base::operator=(static_cast<Base&>(other));
- QualType BaseType = Base->getType().getUnqualifiedType();
+ QualType BaseType = Base.getType().getUnqualifiedType();
if (!BaseType->isRecordType()) {
Invalid = true;
continue;
}
CXXCastPath BasePath;
- BasePath.push_back(Base);
+ BasePath.push_back(&Base);
// Construct the "from" expression, which is an implicit cast to the
// appropriately-qualified base type.
@@ -9397,13 +9703,11 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
}
// Success! Record the copy.
- Statements.push_back(Copy.takeAs<Expr>());
+ Statements.push_back(Copy.getAs<Expr>());
}
// Assign non-static members.
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- FieldEnd = ClassDecl->field_end();
- Field != FieldEnd; ++Field) {
+ for (auto *Field : ClassDecl->fields()) {
if (Field->isUnnamedBitfield())
continue;
@@ -9450,7 +9754,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
CXXScopeSpec SS; // Intentionally empty
LookupResult MemberLookup(*this, Field->getDeclName(), Loc,
LookupMemberName);
- MemberLookup.addDecl(*Field);
+ MemberLookup.addDecl(Field);
MemberLookup.resolveKind();
MemberBuilder From(OtherRef, OtherRefType, /*IsArrow=*/false, MemberLookup);
@@ -9470,18 +9774,18 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
}
// Success! Record the copy.
- Statements.push_back(Copy.takeAs<Stmt>());
+ Statements.push_back(Copy.getAs<Stmt>());
}
if (!Invalid) {
// Add a "return *this;"
ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This.build(*this, Loc));
- StmtResult Return = ActOnReturnStmt(Loc, ThisObj.get());
+ StmtResult Return = BuildReturnStmt(Loc, ThisObj.get());
if (Return.isInvalid())
Invalid = true;
else {
- Statements.push_back(Return.takeAs<Stmt>());
+ Statements.push_back(Return.getAs<Stmt>());
if (Trap.hasErrorOccurred()) {
Diag(CurrentLocation, diag::note_member_synthesized_at)
@@ -9503,7 +9807,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
/*isStmtExpr=*/false);
assert(!Body.isInvalid() && "Compound statement creation cannot fail");
}
- CopyAssignOperator->setBody(Body.takeAs<Stmt>());
+ CopyAssignOperator->setBody(Body.getAs<Stmt>());
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(CopyAssignOperator);
@@ -9530,33 +9834,26 @@ Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXMethodDecl *MD) {
// actually happen.
// Note that a move constructor is not implicitly declared when there are
// virtual bases, but it can still be user-declared and explicitly defaulted.
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
- BaseEnd = ClassDecl->bases_end();
- Base != BaseEnd; ++Base) {
- if (Base->isVirtual())
+ for (const auto &Base : ClassDecl->bases()) {
+ if (Base.isVirtual())
continue;
CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(BaseClassDecl,
0, false, 0))
- ExceptSpec.CalledDecl(Base->getLocStart(), MoveAssign);
+ ExceptSpec.CalledDecl(Base.getLocStart(), MoveAssign);
}
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
- BaseEnd = ClassDecl->vbases_end();
- Base != BaseEnd; ++Base) {
+ for (const auto &Base : ClassDecl->vbases()) {
CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(BaseClassDecl,
0, false, 0))
- ExceptSpec.CalledDecl(Base->getLocStart(), MoveAssign);
+ ExceptSpec.CalledDecl(Base.getLocStart(), MoveAssign);
}
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- FieldEnd = ClassDecl->field_end();
- Field != FieldEnd;
- ++Field) {
+ for (const auto *Field : ClassDecl->fields()) {
QualType FieldType = Context.getBaseElementType(Field->getType());
if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
if (CXXMethodDecl *MoveAssign =
@@ -9575,7 +9872,7 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {
DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveAssignment);
if (DSM.isAlreadyBeingDeclared())
- return 0;
+ return nullptr;
// Note: The following rules are largely analoguous to the move
// constructor rules.
@@ -9595,7 +9892,7 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {
DeclarationNameInfo NameInfo(Name, ClassLoc);
CXXMethodDecl *MoveAssignment =
CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(),
- /*TInfo=*/0, /*StorageClass=*/SC_None,
+ /*TInfo=*/nullptr, /*StorageClass=*/SC_None,
/*isInline=*/true, Constexpr, SourceLocation());
MoveAssignment->setAccess(AS_public);
MoveAssignment->setDefaulted();
@@ -9608,9 +9905,10 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {
// Add the parameter to the operator.
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveAssignment,
- ClassLoc, ClassLoc, /*Id=*/0,
- ArgType, /*TInfo=*/0,
- SC_None, 0);
+ ClassLoc, ClassLoc,
+ /*Id=*/nullptr, ArgType,
+ /*TInfo=*/nullptr, SC_None,
+ nullptr);
MoveAssignment->setParams(FromParam);
AddOverriddenMethods(ClassDecl, MoveAssignment);
@@ -9654,10 +9952,8 @@ static void checkMoveAssignmentForRepeatedMove(Sema &S, CXXRecordDecl *Class,
typedef llvm::DenseMap<CXXRecordDecl*, CXXBaseSpecifier*> VBaseMap;
VBaseMap VBases;
- for (CXXRecordDecl::base_class_iterator BI = Class->bases_begin(),
- BE = Class->bases_end();
- BI != BE; ++BI) {
- Worklist.push_back(&*BI);
+ for (auto &BI : Class->bases()) {
+ Worklist.push_back(&BI);
while (!Worklist.empty()) {
CXXBaseSpecifier *BaseSpec = Worklist.pop_back_val();
CXXRecordDecl *Base = BaseSpec->getType()->getAsCXXRecordDecl();
@@ -9689,22 +9985,22 @@ static void checkMoveAssignmentForRepeatedMove(Sema &S, CXXRecordDecl *Class,
// only happens in one base, we'll diagnose it when synthesizing
// that base class's move assignment operator.)
CXXBaseSpecifier *&Existing =
- VBases.insert(std::make_pair(Base->getCanonicalDecl(), BI))
+ VBases.insert(std::make_pair(Base->getCanonicalDecl(), &BI))
.first->second;
- if (Existing && Existing != BI) {
+ if (Existing && Existing != &BI) {
S.Diag(CurrentLocation, diag::warn_vbase_moved_multiple_times)
<< Class << Base;
S.Diag(Existing->getLocStart(), diag::note_vbase_moved_here)
<< (Base->getCanonicalDecl() ==
Existing->getType()->getAsCXXRecordDecl()->getCanonicalDecl())
<< Base << Existing->getType() << Existing->getSourceRange();
- S.Diag(BI->getLocStart(), diag::note_vbase_moved_here)
+ S.Diag(BI.getLocStart(), diag::note_vbase_moved_here)
<< (Base->getCanonicalDecl() ==
- BI->getType()->getAsCXXRecordDecl()->getCanonicalDecl())
- << Base << BI->getType() << BaseSpec->getSourceRange();
+ BI.getType()->getAsCXXRecordDecl()->getCanonicalDecl())
+ << Base << BI.getType() << BaseSpec->getSourceRange();
// Only diagnose each vbase once.
- Existing = 0;
+ Existing = nullptr;
}
} else {
// Only walk over bases that have defaulted move assignment operators.
@@ -9714,10 +10010,8 @@ static void checkMoveAssignmentForRepeatedMove(Sema &S, CXXRecordDecl *Class,
continue;
// We're going to move the base classes of Base. Add them to the list.
- for (CXXRecordDecl::base_class_iterator BI = Base->bases_begin(),
- BE = Base->bases_end();
- BI != BE; ++BI)
- Worklist.push_back(&*BI);
+ for (auto &BI : Base->bases())
+ Worklist.push_back(&BI);
}
}
}
@@ -9767,7 +10061,9 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
"Bad argument type of defaulted move assignment");
// Our location for everything implicitly-generated.
- SourceLocation Loc = MoveAssignOperator->getLocation();
+ SourceLocation Loc = MoveAssignOperator->getLocEnd().isValid()
+ ? MoveAssignOperator->getLocEnd()
+ : MoveAssignOperator->getLocation();
// Builds a reference to the "other" object.
RefBuilder OtherRef(Other, OtherRefType);
@@ -9779,8 +10075,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
// Assign base classes.
bool Invalid = false;
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
- E = ClassDecl->bases_end(); Base != E; ++Base) {
+ for (auto &Base : ClassDecl->bases()) {
// C++11 [class.copy]p28:
// It is unspecified whether subobjects representing virtual base classes
// are assigned more than once by the implicitly-defined copy assignment
@@ -9791,14 +10086,14 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
// Form the assignment:
// static_cast<Base*>(this)->Base::operator=(static_cast<Base&&>(other));
- QualType BaseType = Base->getType().getUnqualifiedType();
+ QualType BaseType = Base.getType().getUnqualifiedType();
if (!BaseType->isRecordType()) {
Invalid = true;
continue;
}
CXXCastPath BasePath;
- BasePath.push_back(Base);
+ BasePath.push_back(&Base);
// Construct the "from" expression, which is an implicit cast to the
// appropriately-qualified base type.
@@ -9826,13 +10121,11 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
}
// Success! Record the move.
- Statements.push_back(Move.takeAs<Expr>());
+ Statements.push_back(Move.getAs<Expr>());
}
// Assign non-static members.
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- FieldEnd = ClassDecl->field_end();
- Field != FieldEnd; ++Field) {
+ for (auto *Field : ClassDecl->fields()) {
if (Field->isUnnamedBitfield())
continue;
@@ -9878,7 +10171,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
// Build references to the field in the object we're copying from and to.
LookupResult MemberLookup(*this, Field->getDeclName(), Loc,
LookupMemberName);
- MemberLookup.addDecl(*Field);
+ MemberLookup.addDecl(Field);
MemberLookup.resolveKind();
MemberBuilder From(MoveOther, OtherRefType,
/*IsArrow=*/false, MemberLookup);
@@ -9902,18 +10195,19 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
}
// Success! Record the copy.
- Statements.push_back(Move.takeAs<Stmt>());
+ Statements.push_back(Move.getAs<Stmt>());
}
if (!Invalid) {
// Add a "return *this;"
- ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This.build(*this, Loc));
-
- StmtResult Return = ActOnReturnStmt(Loc, ThisObj.get());
+ ExprResult ThisObj =
+ CreateBuiltinUnaryOp(Loc, UO_Deref, This.build(*this, Loc));
+
+ StmtResult Return = BuildReturnStmt(Loc, ThisObj.get());
if (Return.isInvalid())
Invalid = true;
else {
- Statements.push_back(Return.takeAs<Stmt>());
+ Statements.push_back(Return.getAs<Stmt>());
if (Trap.hasErrorOccurred()) {
Diag(CurrentLocation, diag::note_member_synthesized_at)
@@ -9935,7 +10229,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
/*isStmtExpr=*/false);
assert(!Body.isInvalid() && "Compound statement creation cannot fail");
}
- MoveAssignOperator->setBody(Body.takeAs<Stmt>());
+ MoveAssignOperator->setBody(Body.getAs<Stmt>());
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(MoveAssignOperator);
@@ -9951,40 +10245,31 @@ Sema::ComputeDefaultedCopyCtorExceptionSpec(CXXMethodDecl *MD) {
return ExceptSpec;
const FunctionProtoType *T = MD->getType()->castAs<FunctionProtoType>();
- assert(T->getNumArgs() >= 1 && "not a copy ctor");
- unsigned Quals = T->getArgType(0).getNonReferenceType().getCVRQualifiers();
+ assert(T->getNumParams() >= 1 && "not a copy ctor");
+ unsigned Quals = T->getParamType(0).getNonReferenceType().getCVRQualifiers();
// C++ [except.spec]p14:
// An implicitly declared special member function (Clause 12) shall have an
// exception-specification. [...]
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
- BaseEnd = ClassDecl->bases_end();
- Base != BaseEnd;
- ++Base) {
+ for (const auto &Base : ClassDecl->bases()) {
// Virtual bases are handled below.
- if (Base->isVirtual())
+ if (Base.isVirtual())
continue;
CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
if (CXXConstructorDecl *CopyConstructor =
LookupCopyingConstructor(BaseClassDecl, Quals))
- ExceptSpec.CalledDecl(Base->getLocStart(), CopyConstructor);
+ ExceptSpec.CalledDecl(Base.getLocStart(), CopyConstructor);
}
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
- BaseEnd = ClassDecl->vbases_end();
- Base != BaseEnd;
- ++Base) {
+ for (const auto &Base : ClassDecl->vbases()) {
CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
if (CXXConstructorDecl *CopyConstructor =
LookupCopyingConstructor(BaseClassDecl, Quals))
- ExceptSpec.CalledDecl(Base->getLocStart(), CopyConstructor);
+ ExceptSpec.CalledDecl(Base.getLocStart(), CopyConstructor);
}
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- FieldEnd = ClassDecl->field_end();
- Field != FieldEnd;
- ++Field) {
+ for (const auto *Field : ClassDecl->fields()) {
QualType FieldType = Context.getBaseElementType(Field->getType());
if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
if (CXXConstructorDecl *CopyConstructor =
@@ -10006,7 +10291,7 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
DeclaringSpecialMember DSM(*this, ClassDecl, CXXCopyConstructor);
if (DSM.isAlreadyBeingDeclared())
- return 0;
+ return nullptr;
QualType ClassType = Context.getTypeDeclType(ClassDecl);
QualType ArgType = ClassType;
@@ -10028,7 +10313,7 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
// An implicitly-declared copy constructor is an inline public
// member of its class.
CXXConstructorDecl *CopyConstructor = CXXConstructorDecl::Create(
- Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/0,
+ Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr,
/*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true,
Constexpr);
CopyConstructor->setAccess(AS_public);
@@ -10043,9 +10328,9 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
// Add the parameter to the constructor.
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor,
ClassLoc, ClassLoc,
- /*IdentifierInfo=*/0,
- ArgType, /*TInfo=*/0,
- SC_None, 0);
+ /*IdentifierInfo=*/nullptr,
+ ArgType, /*TInfo=*/nullptr,
+ SC_None, nullptr);
CopyConstructor->setParams(FromParam);
CopyConstructor->setTrivial(
@@ -10093,13 +10378,17 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
<< CXXCopyConstructor << Context.getTagDeclType(ClassDecl);
CopyConstructor->setInvalidDecl();
} else {
+ SourceLocation Loc = CopyConstructor->getLocEnd().isValid()
+ ? CopyConstructor->getLocEnd()
+ : CopyConstructor->getLocation();
Sema::CompoundScopeRAII CompoundScope(*this);
- CopyConstructor->setBody(ActOnCompoundStmt(
- CopyConstructor->getLocation(), CopyConstructor->getLocation(), None,
- /*isStmtExpr=*/ false).takeAs<Stmt>());
+ CopyConstructor->setBody(
+ ActOnCompoundStmt(Loc, Loc, None, /*isStmtExpr=*/false).getAs<Stmt>());
}
CopyConstructor->markUsed(Context);
+ MarkVTableUsed(CurrentLocation, ClassDecl);
+
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(CopyConstructor);
}
@@ -10117,42 +10406,36 @@ Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXMethodDecl *MD) {
return ExceptSpec;
// Direct base-class constructors.
- for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(),
- BEnd = ClassDecl->bases_end();
- B != BEnd; ++B) {
- if (B->isVirtual()) // Handled below.
+ for (const auto &B : ClassDecl->bases()) {
+ if (B.isVirtual()) // Handled below.
continue;
- if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+ if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) {
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
CXXConstructorDecl *Constructor =
LookupMovingConstructor(BaseClassDecl, 0);
// If this is a deleted function, add it anyway. This might be conformant
// with the standard. This might not. I'm not sure. It might not matter.
if (Constructor)
- ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
+ ExceptSpec.CalledDecl(B.getLocStart(), Constructor);
}
}
// Virtual base-class constructors.
- for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(),
- BEnd = ClassDecl->vbases_end();
- B != BEnd; ++B) {
- if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+ for (const auto &B : ClassDecl->vbases()) {
+ if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) {
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
CXXConstructorDecl *Constructor =
LookupMovingConstructor(BaseClassDecl, 0);
// If this is a deleted function, add it anyway. This might be conformant
// with the standard. This might not. I'm not sure. It might not matter.
if (Constructor)
- ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
+ ExceptSpec.CalledDecl(B.getLocStart(), Constructor);
}
}
// Field constructors.
- for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
- FEnd = ClassDecl->field_end();
- F != FEnd; ++F) {
+ for (const auto *F : ClassDecl->fields()) {
QualType FieldType = Context.getBaseElementType(F->getType());
if (CXXRecordDecl *FieldRecDecl = FieldType->getAsCXXRecordDecl()) {
CXXConstructorDecl *Constructor =
@@ -10176,7 +10459,7 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveConstructor);
if (DSM.isAlreadyBeingDeclared())
- return 0;
+ return nullptr;
QualType ClassType = Context.getTypeDeclType(ClassDecl);
QualType ArgType = Context.getRValueReferenceType(ClassType);
@@ -10195,7 +10478,7 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
// An implicitly-declared copy/move constructor is an inline public
// member of its class.
CXXConstructorDecl *MoveConstructor = CXXConstructorDecl::Create(
- Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/0,
+ Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr,
/*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true,
Constexpr);
MoveConstructor->setAccess(AS_public);
@@ -10210,9 +10493,9 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
// Add the parameter to the constructor.
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveConstructor,
ClassLoc, ClassLoc,
- /*IdentifierInfo=*/0,
- ArgType, /*TInfo=*/0,
- SC_None, 0);
+ /*IdentifierInfo=*/nullptr,
+ ArgType, /*TInfo=*/nullptr,
+ SC_None, nullptr);
MoveConstructor->setParams(FromParam);
MoveConstructor->setTrivial(
@@ -10255,13 +10538,16 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
<< CXXMoveConstructor << Context.getTagDeclType(ClassDecl);
MoveConstructor->setInvalidDecl();
} else {
+ SourceLocation Loc = MoveConstructor->getLocEnd().isValid()
+ ? MoveConstructor->getLocEnd()
+ : MoveConstructor->getLocation();
Sema::CompoundScopeRAII CompoundScope(*this);
MoveConstructor->setBody(ActOnCompoundStmt(
- MoveConstructor->getLocation(), MoveConstructor->getLocation(), None,
- /*isStmtExpr=*/ false).takeAs<Stmt>());
+ Loc, Loc, None, /*isStmtExpr=*/ false).getAs<Stmt>());
}
MoveConstructor->markUsed(Context);
+ MarkVTableUsed(CurrentLocation, ClassDecl);
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(MoveConstructor);
@@ -10281,19 +10567,17 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
// cache the deduced template arguments for this specialization
// so that we can use them to retrieve the corresponding call-operator
// and static-invoker.
- const TemplateArgumentList *DeducedTemplateArgs = 0;
-
-
+ const TemplateArgumentList *DeducedTemplateArgs = nullptr;
+
// Retrieve the corresponding call-operator specialization.
if (Lambda->isGenericLambda()) {
assert(Conv->isFunctionTemplateSpecialization());
FunctionTemplateDecl *CallOpTemplate =
CallOp->getDescribedFunctionTemplate();
DeducedTemplateArgs = Conv->getTemplateSpecializationArgs();
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
FunctionDecl *CallOpSpec = CallOpTemplate->findSpecialization(
- DeducedTemplateArgs->data(),
- DeducedTemplateArgs->size(),
+ DeducedTemplateArgs->asArray(),
InsertPos);
assert(CallOpSpec &&
"Conversion operator must have a corresponding call operator");
@@ -10309,7 +10593,7 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
SynthesizedFunctionScope Scope(*this, Conv);
DiagnosticErrorTrap Trap(Diags);
- // Retreive the static invoker...
+ // Retrieve the static invoker...
CXXMethodDecl *Invoker = Lambda->getLambdaStaticInvoker();
// ... and get the corresponding specialization for a generic lambda.
if (Lambda->isGenericLambda()) {
@@ -10317,10 +10601,9 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
"Must have deduced template arguments from Conversion Operator");
FunctionTemplateDecl *InvokeTemplate =
Invoker->getDescribedFunctionTemplate();
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
FunctionDecl *InvokeSpec = InvokeTemplate->findSpecialization(
- DeducedTemplateArgs->data(),
- DeducedTemplateArgs->size(),
+ DeducedTemplateArgs->asArray(),
InsertPos);
assert(InvokeSpec &&
"Must have a corresponding static invoker specialization");
@@ -10328,9 +10611,9 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
}
// Construct the body of the conversion function { return __invoke; }.
Expr *FunctionRef = BuildDeclRefExpr(Invoker, Invoker->getType(),
- VK_LValue, Conv->getLocation()).take();
+ VK_LValue, Conv->getLocation()).get();
assert(FunctionRef && "Can't refer to __invoke function?");
- Stmt *Return = ActOnReturnStmt(Conv->getLocation(), FunctionRef).take();
+ Stmt *Return = BuildReturnStmt(Conv->getLocation(), FunctionRef).get();
Conv->setBody(new (Context) CompoundStmt(Context, Return,
Conv->getLocation(),
Conv->getLocation()));
@@ -10364,8 +10647,8 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion(
DiagnosticErrorTrap Trap(Diags);
// Copy-initialize the lambda object as needed to capture it.
- Expr *This = ActOnCXXThis(CurrentLocation).take();
- Expr *DerefThis =CreateBuiltinUnaryOp(CurrentLocation, UO_Deref, This).take();
+ Expr *This = ActOnCXXThis(CurrentLocation).get();
+ Expr *DerefThis =CreateBuiltinUnaryOp(CurrentLocation, UO_Deref, This).get();
ExprResult BuildBlock = BuildBlockForLambdaConversion(CurrentLocation,
Conv->getLocation(),
@@ -10378,7 +10661,7 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion(
if (!BuildBlock.isInvalid() && !getLangOpts().ObjCAutoRefCount)
BuildBlock = ImplicitCastExpr::Create(Context, BuildBlock.get()->getType(),
CK_CopyAndAutoreleaseBlockObject,
- BuildBlock.get(), 0, VK_RValue);
+ BuildBlock.get(), nullptr, VK_RValue);
if (BuildBlock.isInvalid()) {
Diag(CurrentLocation, diag::note_lambda_to_block_conv);
@@ -10388,7 +10671,7 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion(
// Create the return statement that returns the block from the conversion
// function.
- StmtResult Return = ActOnReturnStmt(Conv->getLocation(), BuildBlock.get());
+ StmtResult Return = BuildReturnStmt(Conv->getLocation(), BuildBlock.get());
if (Return.isInvalid()) {
Diag(CurrentLocation, diag::note_lambda_to_block_conv);
Conv->setInvalidDecl();
@@ -10396,7 +10679,7 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion(
}
// Set the body of the conversion function.
- Stmt *ReturnS = Return.take();
+ Stmt *ReturnS = Return.get();
Conv->setBody(new (Context) CompoundStmt(Context, ReturnS,
Conv->getLocation(),
Conv->getLocation()));
@@ -10432,6 +10715,7 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
MultiExprArg ExprArgs,
bool HadMultipleCandidates,
bool IsListInitialization,
+ bool IsStdInitListInitialization,
bool RequiresZeroInit,
unsigned ConstructKind,
SourceRange ParenRange) {
@@ -10455,7 +10739,8 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor,
Elidable, ExprArgs, HadMultipleCandidates,
- IsListInitialization, RequiresZeroInit,
+ IsListInitialization,
+ IsStdInitListInitialization, RequiresZeroInit,
ConstructKind, ParenRange);
}
@@ -10467,16 +10752,17 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
MultiExprArg ExprArgs,
bool HadMultipleCandidates,
bool IsListInitialization,
+ bool IsStdInitListInitialization,
bool RequiresZeroInit,
unsigned ConstructKind,
SourceRange ParenRange) {
MarkFunctionReferenced(ConstructLoc, Constructor);
- return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc,
- Constructor, Elidable, ExprArgs,
- HadMultipleCandidates,
- IsListInitialization, RequiresZeroInit,
- static_cast<CXXConstructExpr::ConstructionKind>(ConstructKind),
- ParenRange));
+ return CXXConstructExpr::Create(
+ Context, DeclInitType, ConstructLoc, Constructor, Elidable, ExprArgs,
+ HadMultipleCandidates, IsListInitialization, IsStdInitListInitialization,
+ RequiresZeroInit,
+ static_cast<CXXConstructExpr::ConstructionKind>(ConstructKind),
+ ParenRange);
}
void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) {
@@ -10495,6 +10781,7 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) {
<< VD->getType());
DiagnoseUseOfDecl(Destructor, VD->getLocation());
+ if (Destructor->isTrivial()) return;
if (!VD->hasGlobalStorage()) return;
// Emit warning for non-trivial dtor in global scope (a real global,
@@ -10525,11 +10812,11 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
const FunctionProtoType *Proto
= Constructor->getType()->getAs<FunctionProtoType>();
assert(Proto && "Constructor without a prototype?");
- unsigned NumArgsInProto = Proto->getNumArgs();
-
+ unsigned NumParams = Proto->getNumParams();
+
// If too few arguments are available, we'll fill in the rest with defaults.
- if (NumArgs < NumArgsInProto)
- ConvertedArgs.reserve(NumArgsInProto);
+ if (NumArgs < NumParams)
+ ConvertedArgs.reserve(NumParams);
else
ConvertedArgs.reserve(NumArgs);
@@ -10580,8 +10867,8 @@ CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl,
CanQualType ExpectedFirstParamType,
unsigned DependentParamTypeDiag,
unsigned InvalidParamTypeDiag) {
- QualType ResultType =
- FnDecl->getType()->getAs<FunctionType>()->getResultType();
+ QualType ResultType =
+ FnDecl->getType()->getAs<FunctionType>()->getReturnType();
// Check that the result type is not dependent.
if (ResultType->isDependentType())
@@ -10706,10 +10993,8 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
diag::err_operator_overload_static) << FnDecl->getDeclName();
} else {
bool ClassOrEnumParam = false;
- for (FunctionDecl::param_iterator Param = FnDecl->param_begin(),
- ParamEnd = FnDecl->param_end();
- Param != ParamEnd; ++Param) {
- QualType ParamType = (*Param)->getType().getNonReferenceType();
+ for (auto Param : FnDecl->params()) {
+ QualType ParamType = Param->getType().getNonReferenceType();
if (ParamType->isDependentType() || ParamType->isRecordType() ||
ParamType->isEnumeralType()) {
ClassOrEnumParam = true;
@@ -10730,12 +11015,11 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
// Only the function-call operator allows default arguments
// (C++ [over.call]p1).
if (Op != OO_Call) {
- for (FunctionDecl::param_iterator Param = FnDecl->param_begin();
- Param != FnDecl->param_end(); ++Param) {
- if ((*Param)->hasDefaultArg())
- return Diag((*Param)->getLocation(),
+ for (auto Param : FnDecl->params()) {
+ if (Param->hasDefaultArg())
+ return Diag(Param->getLocation(),
diag::err_operator_overload_default_arg)
- << FnDecl->getDeclName() << (*Param)->getDefaultArgRange();
+ << FnDecl->getDeclName() << Param->getDefaultArgRange();
}
}
@@ -10802,11 +11086,10 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
// increment operator ++ for objects of that type.
if ((Op == OO_PlusPlus || Op == OO_MinusMinus) && NumParams == 2) {
ParmVarDecl *LastParam = FnDecl->getParamDecl(FnDecl->getNumParams() - 1);
- bool ParamIsInt = false;
- if (const BuiltinType *BT = LastParam->getType()->getAs<BuiltinType>())
- ParamIsInt = BT->getKind() == BuiltinType::Int;
+ QualType ParamType = LastParam->getType();
- if (!ParamIsInt)
+ if (!ParamType->isSpecificBuiltinType(BuiltinType::Int) &&
+ !ParamType->isDependentType())
return Diag(LastParam->getLocation(),
diag::err_operator_overload_post_incdec_must_be_int)
<< LastParam->getType() << (Op == OO_MinusMinus);
@@ -10939,13 +11222,11 @@ FinishedParams:
// A parameter-declaration-clause containing a default argument is not
// equivalent to any of the permitted forms.
- for (FunctionDecl::param_iterator Param = FnDecl->param_begin(),
- ParamEnd = FnDecl->param_end();
- Param != ParamEnd; ++Param) {
- if ((*Param)->hasDefaultArg()) {
- Diag((*Param)->getDefaultArgRange().getBegin(),
+ for (auto Param : FnDecl->params()) {
+ if (Param->hasDefaultArg()) {
+ Diag(Param->getDefaultArgRange().getBegin(),
diag::err_literal_operator_default_argument)
- << (*Param)->getDefaultArgRange();
+ << Param->getDefaultArgRange();
break;
}
}
@@ -10965,29 +11246,36 @@ FinishedParams:
/// ActOnStartLinkageSpecification - Parsed the beginning of a C++
/// linkage specification, including the language and (if present)
-/// the '{'. ExternLoc is the location of the 'extern', LangLoc is
-/// the location of the language string literal, which is provided
-/// by Lang/StrSize. LBraceLoc, if valid, provides the location of
+/// the '{'. ExternLoc is the location of the 'extern', Lang is the
+/// language string literal. LBraceLoc, if valid, provides the location of
/// the '{' brace. Otherwise, this linkage specification does not
/// have any braces.
Decl *Sema::ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc,
- SourceLocation LangLoc,
- StringRef Lang,
+ Expr *LangStr,
SourceLocation LBraceLoc) {
+ StringLiteral *Lit = cast<StringLiteral>(LangStr);
+ if (!Lit->isAscii()) {
+ Diag(LangStr->getExprLoc(), diag::err_language_linkage_spec_not_ascii)
+ << LangStr->getSourceRange();
+ return nullptr;
+ }
+
+ StringRef Lang = Lit->getString();
LinkageSpecDecl::LanguageIDs Language;
- if (Lang == "\"C\"")
+ if (Lang == "C")
Language = LinkageSpecDecl::lang_c;
- else if (Lang == "\"C++\"")
+ else if (Lang == "C++")
Language = LinkageSpecDecl::lang_cxx;
else {
- Diag(LangLoc, diag::err_bad_language);
- return 0;
+ Diag(LangStr->getExprLoc(), diag::err_language_linkage_spec_unknown)
+ << LangStr->getSourceRange();
+ return nullptr;
}
// FIXME: Add all the various semantics of linkage specifications
- LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext,
- ExternLoc, LangLoc, Language,
+ LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext, ExternLoc,
+ LangStr->getExprLoc(), Language,
LBraceLoc.isValid());
CurContext->addDecl(D);
PushDeclContext(S, D);
@@ -11001,13 +11289,11 @@ Decl *Sema::ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc,
Decl *Sema::ActOnFinishLinkageSpecification(Scope *S,
Decl *LinkageSpec,
SourceLocation RBraceLoc) {
- if (LinkageSpec) {
- if (RBraceLoc.isValid()) {
- LinkageSpecDecl* LSDecl = cast<LinkageSpecDecl>(LinkageSpec);
- LSDecl->setRBraceLoc(RBraceLoc);
- }
- PopDeclContext();
+ if (RBraceLoc.isValid()) {
+ LinkageSpecDecl* LSDecl = cast<LinkageSpecDecl>(LinkageSpec);
+ LSDecl->setRBraceLoc(RBraceLoc);
}
+ PopDeclContext();
return LinkageSpec;
}
@@ -11128,7 +11414,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
else {
// If the constructor used was non-trivial, set this as the
// "initializer".
- CXXConstructExpr *construct = result.takeAs<CXXConstructExpr>();
+ CXXConstructExpr *construct = result.getAs<CXXConstructExpr>();
if (!construct->getConstructor()->isTrivial()) {
Expr *init = MaybeCreateExprWithCleanups(construct);
ExDecl->setInit(init);
@@ -11165,13 +11451,17 @@ Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
LookupOrdinaryName,
ForRedeclaration)) {
// The scope should be freshly made just for us. There is just no way
- // it contains any previous declaration.
+ // it contains any previous declaration, except for function parameters in
+ // a function-try-block's catch statement.
assert(!S->isDeclScope(PrevDecl));
- if (PrevDecl->isTemplateParameter()) {
+ if (isDeclInScope(PrevDecl, CurContext, S)) {
+ Diag(D.getIdentifierLoc(), diag::err_redefinition)
+ << D.getIdentifier();
+ Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+ Invalid = true;
+ } else if (PrevDecl->isTemplateParameter())
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
- PrevDecl = 0;
- }
}
if (D.getCXXScopeSpec().isSet() && !Invalid) {
@@ -11201,10 +11491,11 @@ Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc,
Expr *AssertExpr,
Expr *AssertMessageExpr,
SourceLocation RParenLoc) {
- StringLiteral *AssertMessage = cast<StringLiteral>(AssertMessageExpr);
+ StringLiteral *AssertMessage =
+ AssertMessageExpr ? cast<StringLiteral>(AssertMessageExpr) : nullptr;
if (DiagnoseUnexpandedParameterPack(AssertExpr, UPPC_StaticAssertExpression))
- return 0;
+ return nullptr;
return BuildStaticAssertDeclaration(StaticAssertLoc, AssertExpr,
AssertMessage, RParenLoc, false);
@@ -11215,6 +11506,7 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
StringLiteral *AssertMessage,
SourceLocation RParenLoc,
bool Failed) {
+ assert(AssertExpr != nullptr && "Expected non-null condition");
if (!AssertExpr->isTypeDependent() && !AssertExpr->isValueDependent() &&
!Failed) {
// In a static_assert-declaration, the constant-expression shall be a
@@ -11232,9 +11524,10 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
if (!Failed && !Cond) {
SmallString<256> MsgBuffer;
llvm::raw_svector_ostream Msg(MsgBuffer);
- AssertMessage->printPretty(Msg, 0, getPrintingPolicy());
+ if (AssertMessage)
+ AssertMessage->printPretty(Msg, nullptr, getPrintingPolicy());
Diag(StaticAssertLoc, diag::err_static_assert_failed)
- << Msg.str() << AssertExpr->getSourceRange();
+ << !AssertMessage << Msg.str() << AssertExpr->getSourceRange();
Failed = true;
}
}
@@ -11273,9 +11566,10 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart,
// a tag in front.
if (const RecordType *RT = T->getAs<RecordType>()) {
RecordDecl *RD = RT->getDecl();
-
- std::string InsertionText = std::string(" ") + RD->getKindName();
-
+
+ SmallString<16> InsertionText(" ");
+ InsertionText += RD->getKindName();
+
Diag(TypeRange.getBegin(),
getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_unelaborated_friend_type :
@@ -11314,7 +11608,9 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart,
// If the type specifier in a friend declaration designates a (possibly
// cv-qualified) class type, that class is declared as a friend; otherwise,
// the friend declaration is ignored.
- return FriendDecl::Create(Context, CurContext, LocStart, TSInfo, FriendLoc);
+ return FriendDecl::Create(Context, CurContext,
+ TSInfo->getTypeLoc().getLocStart(), TSInfo,
+ FriendLoc);
}
/// Handle a friend tag declaration where the scope specifier was
@@ -11333,19 +11629,18 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
if (TemplateParameterList *TemplateParams =
MatchTemplateParametersToScopeSpecifier(
- TagLoc, NameLoc, SS, TempParamLists, /*friend*/ true,
+ TagLoc, NameLoc, SS, nullptr, TempParamLists, /*friend*/ true,
isExplicitSpecialization, Invalid)) {
if (TemplateParams->size() > 0) {
// This is a declaration of a class template.
if (Invalid)
- return 0;
+ return nullptr;
- return CheckClassTemplate(S, TagSpec, TUK_Friend, TagLoc,
- SS, Name, NameLoc, Attr,
- TemplateParams, AS_public,
+ return CheckClassTemplate(S, TagSpec, TUK_Friend, TagLoc, SS, Name,
+ NameLoc, Attr, TemplateParams, AS_public,
/*ModulePrivateLoc=*/SourceLocation(),
- TempParamLists.size() - 1,
- TempParamLists.data()).take();
+ FriendLoc, TempParamLists.size() - 1,
+ TempParamLists.data()).get();
} else {
// The "template<>" header is extraneous.
Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams)
@@ -11354,7 +11649,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
}
}
- if (Invalid) return 0;
+ if (Invalid) return nullptr;
bool isAllExplicitSpecializations = true;
for (unsigned I = TempParamLists.size(); I-- > 0; ) {
@@ -11374,21 +11669,22 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
bool Owned = false;
bool IsDependent = false;
return ActOnTag(S, TagSpec, TUK_Friend, TagLoc, SS, Name, NameLoc,
- Attr, AS_public,
+ Attr, AS_public,
/*ModulePrivateLoc=*/SourceLocation(),
- MultiTemplateParamsArg(), Owned, IsDependent,
+ MultiTemplateParamsArg(), Owned, IsDependent,
/*ScopedEnumKWLoc=*/SourceLocation(),
/*ScopedEnumUsesClassTag=*/false,
- /*UnderlyingType=*/TypeResult());
+ /*UnderlyingType=*/TypeResult(),
+ /*IsTypeSpecifier=*/false);
}
-
+
NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
ElaboratedTypeKeyword Keyword
= TypeWithKeyword::getKeywordForTagTypeKind(Kind);
QualType T = CheckTypenameType(Keyword, TagLoc, QualifierLoc,
*Name, NameLoc);
if (T.isNull())
- return 0;
+ return nullptr;
TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
if (isa<DependentNameType>(T)) {
@@ -11468,10 +11764,10 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
TypeSourceInfo *TSI = GetTypeForDeclarator(TheDeclarator, S);
QualType T = TSI->getType();
if (TheDeclarator.isInvalidType())
- return 0;
+ return nullptr;
if (DiagnoseUnexpandedParameterPack(Loc, TSI, UPPC_FriendDeclaration))
- return 0;
+ return nullptr;
// This is definitely an error in C++98. It's probably meant to
// be forbidden in C++0x, too, but the specification is just
@@ -11490,7 +11786,7 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
if (TempParams.size() && !T->isElaboratedTypeSpecifier()) {
Diag(Loc, diag::err_tagless_friend_type_template)
<< DS.getSourceRange();
- return 0;
+ return nullptr;
}
// C++98 [class.friend]p1: A friend of a class is a function
@@ -11515,8 +11811,8 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
D = CheckFriendTypeDecl(Loc, DS.getFriendSpecLoc(), TSI);
if (!D)
- return 0;
-
+ return nullptr;
+
D->setAccess(AS_public);
CurContext->addDecl(D);
@@ -11548,7 +11844,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
// It might be worthwhile to try to recover by creating an
// appropriate declaration.
- return 0;
+ return nullptr;
}
// C++ [namespace.memdef]p3
@@ -11575,7 +11871,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
if (DiagnoseUnexpandedParameterPack(Loc, TInfo, UPPC_FriendDeclaration) ||
DiagnoseUnexpandedParameterPack(NameInfo, UPPC_FriendDeclaration) ||
DiagnoseUnexpandedParameterPack(SS, UPPC_FriendDeclaration))
- return 0;
+ return nullptr;
// The context we found the declaration in, or in which we should
// create the declaration.
@@ -11588,7 +11884,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
// - There's no scope specifier and we're in a local class. Only look
// for functions declared in the immediately-enclosing block scope.
// We recover from invalid scope qualifiers as if they just weren't there.
- FunctionDecl *FunctionContainingLocalClass = 0;
+ FunctionDecl *FunctionContainingLocalClass = nullptr;
if ((SS.isInvalid() || !SS.isSet()) &&
(FunctionContainingLocalClass =
cast<CXXRecordDecl>(CurContext)->isLocalClass())) {
@@ -11681,9 +11977,9 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
// or function template.
} else if (!SS.getScopeRep()->isDependent()) {
DC = computeDeclContext(SS);
- if (!DC) return 0;
+ if (!DC) return nullptr;
- if (RequireCompleteDeclContext(SS, DC)) return 0;
+ if (RequireCompleteDeclContext(SS, DC)) return nullptr;
LookupQualifiedName(Previous, DC);
@@ -11703,7 +11999,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
D.setInvalidType();
Diag(Loc, diag::err_qualified_friend_not_found)
<< Name << TInfo->getType();
- return 0;
+ return nullptr;
}
// C++ [class.friend]p1: A friend of a class is a function or
@@ -11755,7 +12051,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
Diag(Loc, diag::err_introducing_special_friend) <<
(D.getName().getKind() == UnqualifiedId::IK_ConstructorName ? 0 :
D.getName().getKind() == UnqualifiedId::IK_DestructorName ? 1 : 2);
- return 0;
+ return nullptr;
}
}
@@ -11771,7 +12067,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
bool AddToScope = true;
NamedDecl *ND = ActOnFunctionDeclarator(DCScope, D, DC, TInfo, Previous,
TemplateParams, AddToScope);
- if (!ND) return 0;
+ if (!ND) return nullptr;
assert(ND->getLexicalDeclContext() == CurContext);
@@ -11841,16 +12137,25 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
if (const FunctionDecl *Prev = Fn->getPreviousDecl()) {
// Don't consider the implicit declaration we generate for explicit
// specializations. FIXME: Do not generate these implicit declarations.
- if ((Prev->getTemplateSpecializationKind() != TSK_ExplicitSpecialization
- || Prev->getPreviousDecl()) && !Prev->isDefined()) {
+ if ((Prev->getTemplateSpecializationKind() != TSK_ExplicitSpecialization ||
+ Prev->getPreviousDecl()) &&
+ !Prev->isDefined()) {
Diag(DelLoc, diag::err_deleted_decl_not_first);
- Diag(Prev->getLocation(), diag::note_previous_declaration);
+ Diag(Prev->getLocation().isInvalid() ? DelLoc : Prev->getLocation(),
+ Prev->isImplicit() ? diag::note_previous_implicit_declaration
+ : diag::note_previous_declaration);
}
// If the declaration wasn't the first, we delete the function anyway for
// recovery.
Fn = Fn->getCanonicalDecl();
}
+ // dllimport/dllexport cannot be deleted.
+ if (const InheritableAttr *DLLAttr = getDLLAttr(Fn)) {
+ Diag(Fn->getLocation(), diag::err_attribute_dll_deleted) << DLLAttr;
+ Fn->setInvalidDecl();
+ }
+
if (Fn->isDeleted())
return;
@@ -11871,6 +12176,11 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
}
}
+ // C++11 [basic.start.main]p3:
+ // A program that defines main as deleted [...] is ill-formed.
+ if (Fn->isMain())
+ Diag(DelLoc, diag::err_deleted_main);
+
Fn->setDeletedAsWritten();
}
@@ -11977,6 +12287,13 @@ bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
if (NewCC == OldCC)
return false;
+ // If the calling conventions mismatch because the new function is static,
+ // suppress the calling convention mismatch error; the error about static
+ // function override (err_static_overrides_virtual from
+ // Sema::CheckFunctionDeclaration) is more clear.
+ if (New->getStorageClass() == SC_Static)
+ return false;
+
Diag(New->getLocation(),
diag::err_conflicting_overriding_cc_attributes)
<< New->getDeclName() << New->getType() << Old->getType();
@@ -11986,8 +12303,8 @@ bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
const CXXMethodDecl *Old) {
- QualType NewTy = New->getType()->getAs<FunctionType>()->getResultType();
- QualType OldTy = Old->getType()->getAs<FunctionType>()->getResultType();
+ QualType NewTy = New->getType()->getAs<FunctionType>()->getReturnType();
+ QualType OldTy = Old->getType()->getAs<FunctionType>()->getReturnType();
if (Context.hasSameType(NewTy, OldTy) ||
NewTy->isDependentType() || OldTy->isDependentType())
@@ -12015,8 +12332,10 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
if (NewClassTy.isNull()) {
Diag(New->getLocation(),
diag::err_different_return_type_for_overriding_virtual_function)
- << New->getDeclName() << NewTy << OldTy;
- Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+ << New->getDeclName() << NewTy << OldTy
+ << New->getReturnTypeSourceRange();
+ Diag(Old->getLocation(), diag::note_overridden_virtual_function)
+ << Old->getReturnTypeSourceRange();
return true;
}
@@ -12036,24 +12355,27 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
if (!Context.hasSameUnqualifiedType(NewClassTy, OldClassTy)) {
// Check if the new class derives from the old class.
if (!IsDerivedFrom(NewClassTy, OldClassTy)) {
- Diag(New->getLocation(),
- diag::err_covariant_return_not_derived)
- << New->getDeclName() << NewTy << OldTy;
- Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+ Diag(New->getLocation(), diag::err_covariant_return_not_derived)
+ << New->getDeclName() << NewTy << OldTy
+ << New->getReturnTypeSourceRange();
+ Diag(Old->getLocation(), diag::note_overridden_virtual_function)
+ << Old->getReturnTypeSourceRange();
return true;
}
// Check if we the conversion from derived to base is valid.
- if (CheckDerivedToBaseConversion(NewClassTy, OldClassTy,
- diag::err_covariant_return_inaccessible_base,
- diag::err_covariant_return_ambiguous_derived_to_base_conv,
- // FIXME: Should this point to the return type?
- New->getLocation(), SourceRange(), New->getDeclName(), 0)) {
+ if (CheckDerivedToBaseConversion(
+ NewClassTy, OldClassTy,
+ diag::err_covariant_return_inaccessible_base,
+ diag::err_covariant_return_ambiguous_derived_to_base_conv,
+ New->getLocation(), New->getReturnTypeSourceRange(),
+ New->getDeclName(), nullptr)) {
// FIXME: this note won't trigger for delayed access control
// diagnostics, and it's impossible to get an undelayed error
// here from access control during the original parse because
// the ParsingDeclSpec/ParsingDeclarator are still in scope.
- Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+ Diag(Old->getLocation(), diag::note_overridden_virtual_function)
+ << Old->getReturnTypeSourceRange();
return true;
}
}
@@ -12062,8 +12384,10 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
if (NewTy.getLocalCVRQualifiers() != OldTy.getLocalCVRQualifiers()) {
Diag(New->getLocation(),
diag::err_covariant_return_type_different_qualifications)
- << New->getDeclName() << NewTy << OldTy;
- Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+ << New->getDeclName() << NewTy << OldTy
+ << New->getReturnTypeSourceRange();
+ Diag(Old->getLocation(), diag::note_overridden_virtual_function)
+ << Old->getReturnTypeSourceRange();
return true;
};
@@ -12072,8 +12396,10 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
if (NewClassTy.isMoreQualifiedThan(OldClassTy)) {
Diag(New->getLocation(),
diag::err_covariant_return_type_class_type_more_qualified)
- << New->getDeclName() << NewTy << OldTy;
- Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+ << New->getDeclName() << NewTy << OldTy
+ << New->getReturnTypeSourceRange();
+ Diag(Old->getLocation(), diag::note_overridden_virtual_function)
+ << Old->getReturnTypeSourceRange();
return true;
};
@@ -12118,13 +12444,16 @@ static bool isStaticDataMember(const Decl *D) {
/// class X.
void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) {
// If there is no declaration, there was an error parsing it.
- if (D == 0 || D->isInvalidDecl()) return;
+ if (!D || D->isInvalidDecl())
+ return;
+
+ // We will always have a nested name specifier here, but this declaration
+ // might not be out of line if the specifier names the current namespace:
+ // extern int n;
+ // int ::n = 0;
+ if (D->isOutOfLine())
+ EnterDeclaratorContext(S, D->getDeclContext());
- // We should only get called for declarations with scope specifiers, like:
- // int foo::bar;
- assert(D->isOutOfLine());
- EnterDeclaratorContext(S, D->getDeclContext());
-
// If we are parsing the initializer for a static data member, push a
// new expression evaluation context that is associated with this static
// data member.
@@ -12136,13 +12465,14 @@ void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) {
/// initializer for the out-of-line declaration 'D'.
void Sema::ActOnCXXExitDeclInitializer(Scope *S, Decl *D) {
// If there is no declaration, there was an error parsing it.
- if (D == 0 || D->isInvalidDecl()) return;
+ if (!D || D->isInvalidDecl())
+ return;
if (isStaticDataMember(D))
- PopExpressionEvaluationContext();
+ PopExpressionEvaluationContext();
- assert(D->isOutOfLine());
- ExitDeclaratorContext(S);
+ if (D->isOutOfLine())
+ ExitDeclaratorContext(S);
}
/// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a
@@ -12216,6 +12546,20 @@ void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
// Otherwise, we can early exit.
return;
}
+ } else {
+ // The Microsoft ABI requires that we perform the destructor body
+ // checks (i.e. operator delete() lookup) when the vtable is marked used, as
+ // the deleting destructor is emitted with the vtable, not with the
+ // destructor definition as in the Itanium ABI.
+ // If it has a definition, we do the check at that point instead.
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+ Class->hasUserDeclaredDestructor() &&
+ !Class->getDestructor()->isDefined() &&
+ !Class->getDestructor()->isDeleted()) {
+ CXXDestructorDecl *DD = Class->getDestructor();
+ ContextRAII SavedContext(*this, DD);
+ CheckDestructor(DD);
+ }
}
// Local classes need to have their virtual members marked
@@ -12267,11 +12611,9 @@ bool Sema::DefineUsedVTables() {
bool IsExplicitInstantiationDeclaration
= Class->getTemplateSpecializationKind()
== TSK_ExplicitInstantiationDeclaration;
- for (TagDecl::redecl_iterator R = Class->redecls_begin(),
- REnd = Class->redecls_end();
- R != REnd; ++R) {
+ for (auto R : Class->redecls()) {
TemplateSpecializationKind TSK
- = cast<CXXRecordDecl>(*R)->getTemplateSpecializationKind();
+ = cast<CXXRecordDecl>(R)->getTemplateSpecializationKind();
if (TSK == TSK_ExplicitInstantiationDeclaration)
IsExplicitInstantiationDeclaration = true;
else if (TSK == TSK_ExplicitInstantiationDefinition) {
@@ -12303,7 +12645,7 @@ bool Sema::DefineUsedVTables() {
// Optionally warn if we're emitting a weak vtable.
if (Class->isExternallyVisible() &&
Class->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {
- const FunctionDecl *KeyFunctionDef = 0;
+ const FunctionDecl *KeyFunctionDef = nullptr;
if (!KeyFunction ||
(KeyFunction->hasBody(KeyFunctionDef) &&
KeyFunctionDef->isInlined()))
@@ -12320,10 +12662,9 @@ bool Sema::DefineUsedVTables() {
void Sema::MarkVirtualMemberExceptionSpecsNeeded(SourceLocation Loc,
const CXXRecordDecl *RD) {
- for (CXXRecordDecl::method_iterator I = RD->method_begin(),
- E = RD->method_end(); I != E; ++I)
- if ((*I)->isVirtual() && !(*I)->isPure())
- ResolveExceptionSpec(Loc, (*I)->getType()->castAs<FunctionProtoType>());
+ for (const auto *I : RD->methods())
+ if (I->isVirtual() && !I->isPure())
+ ResolveExceptionSpec(Loc, I->getType()->castAs<FunctionProtoType>());
}
void Sema::MarkVirtualMembersReferenced(SourceLocation Loc,
@@ -12351,10 +12692,9 @@ void Sema::MarkVirtualMembersReferenced(SourceLocation Loc,
if (RD->getNumVBases() == 0)
return;
- for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
- e = RD->bases_end(); i != e; ++i) {
+ for (const auto &I : RD->bases()) {
const CXXRecordDecl *Base =
- cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
if (Base->getNumVBases() == 0)
continue;
MarkVirtualMembersReferenced(Loc, Base);
@@ -12394,7 +12734,7 @@ void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {
Member =
new (Context) CXXCtorInitializer(Context, Field, SourceLocation(),
SourceLocation(),
- MemberInit.takeAs<Expr>(),
+ MemberInit.getAs<Expr>(),
SourceLocation());
AllToInit.push_back(Member);
@@ -12430,7 +12770,7 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
// Target may not be determinable yet, for instance if this is a dependent
// call in an uninstantiated template.
if (Target) {
- const FunctionDecl *FNTarget = 0;
+ const FunctionDecl *FNTarget = nullptr;
(void)Target->hasBody(FNTarget);
Target = const_cast<CXXConstructorDecl*>(
cast_or_null<CXXConstructorDecl>(FNTarget));
@@ -12438,7 +12778,7 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
CXXConstructorDecl *Canonical = Ctor->getCanonicalDecl(),
// Avoid dereferencing a null pointer here.
- *TCanonical = Target ? Target->getCanonicalDecl() : 0;
+ *TCanonical = Target? Target->getCanonicalDecl() : nullptr;
if (!Current.insert(Canonical))
return;
@@ -12463,7 +12803,7 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
CXXConstructorDecl *C = Target;
while (C->getCanonicalDecl() != Canonical) {
- const FunctionDecl *FNTarget = 0;
+ const FunctionDecl *FNTarget = nullptr;
(void)C->getTargetConstructor()->hasBody(FNTarget);
assert(FNTarget && "Ctor cycle through bodiless function");
@@ -12534,7 +12874,7 @@ bool Sema::checkThisInStaticMemberFunctionType(CXXMethodDecl *Method) {
// If the return type came after the cv-qualifier-seq, check it now.
if (Proto->hasTrailingReturn() &&
- !Finder.TraverseTypeLoc(ProtoTL.getResultLoc()))
+ !Finder.TraverseTypeLoc(ProtoTL.getReturnLoc()))
return true;
// Check the exception specification.
@@ -12571,10 +12911,8 @@ bool Sema::checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method) {
return true;
case EST_Dynamic:
- for (FunctionProtoType::exception_iterator E = Proto->exception_begin(),
- EEnd = Proto->exception_end();
- E != EEnd; ++E) {
- if (!Finder.TraverseType(*E))
+ for (const auto &E : Proto->exceptions()) {
+ if (!Finder.TraverseType(E))
return true;
}
break;
@@ -12587,45 +12925,36 @@ bool Sema::checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method) {
FindCXXThisExpr Finder(*this);
// Check attributes.
- for (Decl::attr_iterator A = Method->attr_begin(), AEnd = Method->attr_end();
- A != AEnd; ++A) {
+ for (const auto *A : Method->attrs()) {
// FIXME: This should be emitted by tblgen.
- Expr *Arg = 0;
+ Expr *Arg = nullptr;
ArrayRef<Expr *> Args;
- if (GuardedByAttr *G = dyn_cast<GuardedByAttr>(*A))
+ if (const auto *G = dyn_cast<GuardedByAttr>(A))
Arg = G->getArg();
- else if (PtGuardedByAttr *G = dyn_cast<PtGuardedByAttr>(*A))
+ else if (const auto *G = dyn_cast<PtGuardedByAttr>(A))
Arg = G->getArg();
- else if (AcquiredAfterAttr *AA = dyn_cast<AcquiredAfterAttr>(*A))
+ else if (const auto *AA = dyn_cast<AcquiredAfterAttr>(A))
Args = ArrayRef<Expr *>(AA->args_begin(), AA->args_size());
- else if (AcquiredBeforeAttr *AB = dyn_cast<AcquiredBeforeAttr>(*A))
+ else if (const auto *AB = dyn_cast<AcquiredBeforeAttr>(A))
Args = ArrayRef<Expr *>(AB->args_begin(), AB->args_size());
- else if (ExclusiveLockFunctionAttr *ELF
- = dyn_cast<ExclusiveLockFunctionAttr>(*A))
- Args = ArrayRef<Expr *>(ELF->args_begin(), ELF->args_size());
- else if (SharedLockFunctionAttr *SLF
- = dyn_cast<SharedLockFunctionAttr>(*A))
- Args = ArrayRef<Expr *>(SLF->args_begin(), SLF->args_size());
- else if (ExclusiveTrylockFunctionAttr *ETLF
- = dyn_cast<ExclusiveTrylockFunctionAttr>(*A)) {
+ else if (const auto *ETLF = dyn_cast<ExclusiveTrylockFunctionAttr>(A)) {
Arg = ETLF->getSuccessValue();
Args = ArrayRef<Expr *>(ETLF->args_begin(), ETLF->args_size());
- } else if (SharedTrylockFunctionAttr *STLF
- = dyn_cast<SharedTrylockFunctionAttr>(*A)) {
+ } else if (const auto *STLF = dyn_cast<SharedTrylockFunctionAttr>(A)) {
Arg = STLF->getSuccessValue();
Args = ArrayRef<Expr *>(STLF->args_begin(), STLF->args_size());
- } else if (UnlockFunctionAttr *UF = dyn_cast<UnlockFunctionAttr>(*A))
- Args = ArrayRef<Expr *>(UF->args_begin(), UF->args_size());
- else if (LockReturnedAttr *LR = dyn_cast<LockReturnedAttr>(*A))
+ } else if (const auto *LR = dyn_cast<LockReturnedAttr>(A))
Arg = LR->getArg();
- else if (LocksExcludedAttr *LE = dyn_cast<LocksExcludedAttr>(*A))
+ else if (const auto *LE = dyn_cast<LocksExcludedAttr>(A))
Args = ArrayRef<Expr *>(LE->args_begin(), LE->args_size());
- else if (ExclusiveLocksRequiredAttr *ELR
- = dyn_cast<ExclusiveLocksRequiredAttr>(*A))
- Args = ArrayRef<Expr *>(ELR->args_begin(), ELR->args_size());
- else if (SharedLocksRequiredAttr *SLR
- = dyn_cast<SharedLocksRequiredAttr>(*A))
- Args = ArrayRef<Expr *>(SLR->args_begin(), SLR->args_size());
+ else if (const auto *RC = dyn_cast<RequiresCapabilityAttr>(A))
+ Args = ArrayRef<Expr *>(RC->args_begin(), RC->args_size());
+ else if (const auto *AC = dyn_cast<AcquireCapabilityAttr>(A))
+ Args = ArrayRef<Expr *>(AC->args_begin(), AC->args_size());
+ else if (const auto *AC = dyn_cast<TryAcquireCapabilityAttr>(A))
+ Args = ArrayRef<Expr *>(AC->args_begin(), AC->args_size());
+ else if (const auto *RC = dyn_cast<ReleaseCapabilityAttr>(A))
+ Args = ArrayRef<Expr *>(RC->args_begin(), RC->args_size());
if (Arg && !Finder.TraverseStmt(Arg))
return true;
@@ -12686,9 +13015,9 @@ Sema::checkExceptionSpecification(ExceptionSpecificationType EST,
}
if (!NoexceptExpr->isValueDependent())
- NoexceptExpr = VerifyIntegerConstantExpression(NoexceptExpr, 0,
+ NoexceptExpr = VerifyIntegerConstantExpression(NoexceptExpr, nullptr,
diag::err_noexcept_needs_constant_expression,
- /*AllowFold*/ false).take();
+ /*AllowFold*/ false).get();
EPI.NoexceptExpr = NoexceptExpr;
}
return;
@@ -12746,7 +13075,7 @@ MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record,
IdentifierInfo *II = D.getIdentifier();
if (!II) {
Diag(DeclStart, diag::err_anonymous_property);
- return NULL;
+ return nullptr;
}
SourceLocation Loc = D.getIdentifierLoc();
@@ -12771,7 +13100,7 @@ MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record,
<< DeclSpec::getSpecifierName(TSCS);
// Check to see if this name was declared as a member previously
- NamedDecl *PrevDecl = 0;
+ NamedDecl *PrevDecl = nullptr;
LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration);
LookupName(Previous, S);
switch (Previous.getResultKind()) {
@@ -12794,18 +13123,16 @@ MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record,
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
// Just pretend that we didn't see the previous declaration.
- PrevDecl = 0;
+ PrevDecl = nullptr;
}
if (PrevDecl && !isDeclInScope(PrevDecl, Record, S))
- PrevDecl = 0;
+ PrevDecl = nullptr;
SourceLocation TSSL = D.getLocStart();
- MSPropertyDecl *NewPD;
const AttributeList::PropertyData &Data = MSPropertyAttr->getPropertyData();
- NewPD = new (Context) MSPropertyDecl(Record, Loc,
- II, T, TInfo, TSSL,
- Data.GetterId, Data.SetterId);
+ MSPropertyDecl *NewPD = MSPropertyDecl::Create(
+ Context, Record, Loc, II, T, TInfo, TSSL, Data.GetterId, Data.SetterId);
ProcessDeclAttributes(TUScope, NewPD, D);
NewPD->setAccess(AS);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
index f44fb32..b5205b3 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
@@ -15,11 +15,11 @@
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
+#include "clang/AST/DataRecursiveASTVisitor.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/Sema/Lookup.h"
@@ -48,8 +48,8 @@ bool Sema::checkInitMethod(ObjCMethodDecl *method,
// We ignore protocols here. Should we? What about Class?
- const ObjCObjectType *result = method->getResultType()
- ->castAs<ObjCObjectPointerType>()->getObjectType();
+ const ObjCObjectType *result =
+ method->getReturnType()->castAs<ObjCObjectPointerType>()->getObjectType();
if (result->isObjCId()) {
return false;
@@ -70,7 +70,7 @@ bool Sema::checkInitMethod(ObjCMethodDecl *method,
} else {
// If this method was declared in a protocol, we can't check
// anything unless we have a receiver type that's an interface.
- const ObjCInterfaceDecl *receiverClass = 0;
+ const ObjCInterfaceDecl *receiverClass = nullptr;
if (isa<ObjCProtocolDecl>(method->getDeclContext())) {
if (receiverTypeIfCall.isNull())
return false;
@@ -97,8 +97,9 @@ bool Sema::checkInitMethod(ObjCMethodDecl *method,
// If we're in a system header, and this is not a call, just make
// the method unusable.
if (receiverTypeIfCall.isNull() && getSourceManager().isInSystemHeader(loc)) {
- method->addAttr(new (Context) UnavailableAttr(loc, Context,
- "init method returns a type unrelated to its receiver type"));
+ method->addAttr(UnavailableAttr::CreateImplicit(Context,
+ "init method returns a type unrelated to its receiver type",
+ loc));
return true;
}
@@ -116,10 +117,10 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
// implies a related result type, and the original (overridden) method has
// a suitable return type, but the new (overriding) method does not have
// a suitable return type.
- QualType ResultType = NewMethod->getResultType();
+ QualType ResultType = NewMethod->getReturnType();
SourceRange ResultTypeRange;
- if (const TypeSourceInfo *ResultTypeInfo
- = NewMethod->getResultTypeSourceInfo())
+ if (const TypeSourceInfo *ResultTypeInfo =
+ NewMethod->getReturnTypeSourceInfo())
ResultTypeRange = ResultTypeInfo->getTypeLoc().getSourceRange();
// Figure out which class this method is part of, if any.
@@ -207,19 +208,19 @@ bool Sema::CheckARCMethodDecl(ObjCMethodDecl *method) {
return false;
case OMF_dealloc:
- if (!Context.hasSameType(method->getResultType(), Context.VoidTy)) {
+ if (!Context.hasSameType(method->getReturnType(), Context.VoidTy)) {
SourceRange ResultTypeRange;
- if (const TypeSourceInfo *ResultTypeInfo
- = method->getResultTypeSourceInfo())
+ if (const TypeSourceInfo *ResultTypeInfo =
+ method->getReturnTypeSourceInfo())
ResultTypeRange = ResultTypeInfo->getTypeLoc().getSourceRange();
if (ResultTypeRange.isInvalid())
- Diag(method->getLocation(), diag::error_dealloc_bad_result_type)
- << method->getResultType()
- << FixItHint::CreateInsertion(method->getSelectorLoc(0), "(void)");
+ Diag(method->getLocation(), diag::error_dealloc_bad_result_type)
+ << method->getReturnType()
+ << FixItHint::CreateInsertion(method->getSelectorLoc(0), "(void)");
else
- Diag(method->getLocation(), diag::error_dealloc_bad_result_type)
- << method->getResultType()
- << FixItHint::CreateReplacement(ResultTypeRange, "void");
+ Diag(method->getLocation(), diag::error_dealloc_bad_result_type)
+ << method->getReturnType()
+ << FixItHint::CreateReplacement(ResultTypeRange, "void");
return true;
}
return false;
@@ -229,8 +230,7 @@ bool Sema::CheckARCMethodDecl(ObjCMethodDecl *method) {
if (checkInitMethod(method, QualType()))
return true;
- method->addAttr(new (Context) NSConsumesSelfAttr(SourceLocation(),
- Context));
+ method->addAttr(NSConsumesSelfAttr::CreateImplicit(Context));
// Don't add a second copy of this attribute, but otherwise don't
// let it be suppressed.
@@ -249,8 +249,7 @@ bool Sema::CheckARCMethodDecl(ObjCMethodDecl *method) {
break;
}
- method->addAttr(new (Context) NSReturnsRetainedAttr(SourceLocation(),
- Context));
+ method->addAttr(NSReturnsRetainedAttr::CreateImplicit(Context));
return false;
}
@@ -304,7 +303,7 @@ HasExplicitOwnershipAttr(Sema &S, ParmVarDecl *Param) {
/// ActOnStartOfObjCMethodDef - This routine sets up parameters; invisible
/// and user declared, in the method definition's AST.
void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
- assert((getCurMethodDecl() == 0) && "Methodparsing confused");
+ assert((getCurMethodDecl() == nullptr) && "Methodparsing confused");
ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D);
// If we don't have a valid method decl, simply return.
@@ -329,17 +328,15 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
/*CheckParameterNames=*/false);
// Introduce all of the other parameters into this scope.
- for (ObjCMethodDecl::param_iterator PI = MDecl->param_begin(),
- E = MDecl->param_end(); PI != E; ++PI) {
- ParmVarDecl *Param = (*PI);
+ for (auto *Param : MDecl->params()) {
if (!Param->isInvalidDecl() &&
getLangOpts().ObjCAutoRefCount &&
!HasExplicitOwnershipAttr(*this, Param))
Diag(Param->getLocation(), diag::warn_arc_strong_pointer_objc_pointer) <<
Param->getType();
- if ((*PI)->getIdentifier())
- PushOnScopeChains(*PI, FnBodyScope);
+ if (Param->getIdentifier())
+ PushOnScopeChains(Param, FnBodyScope);
}
// In ARC, disallow definition of retain/release/autorelease/retainCount
@@ -378,11 +375,16 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
dyn_cast<ObjCImplDecl>(MDecl->getDeclContext());
ObjCContainerDecl *ContDeclOfMethodDecl =
dyn_cast<ObjCContainerDecl>(IMD->getDeclContext());
- ObjCImplDecl *ImplDeclOfMethodDecl = 0;
+ ObjCImplDecl *ImplDeclOfMethodDecl = nullptr;
if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ContDeclOfMethodDecl))
ImplDeclOfMethodDecl = OID->getImplementation();
- else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ContDeclOfMethodDecl))
- ImplDeclOfMethodDecl = CD->getImplementation();
+ else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ContDeclOfMethodDecl)) {
+ if (CD->IsClassExtension()) {
+ if (ObjCInterfaceDecl *OID = CD->getClassInterface())
+ ImplDeclOfMethodDecl = OID->getImplementation();
+ } else
+ ImplDeclOfMethodDecl = CD->getImplementation();
+ }
// No need to issue deprecated warning if deprecated mehod in class/category
// is being implemented in its own implementation (no overriding is involved).
if (!ImplDeclOfMethodDecl || ImplDeclOfMethodDecl != ImplDeclOfMethodDef)
@@ -391,6 +393,17 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
MDecl->getLocation(), 0);
}
+ if (MDecl->getMethodFamily() == OMF_init) {
+ if (MDecl->isDesignatedInitializerForTheInterface()) {
+ getCurFunction()->ObjCIsDesignatedInit = true;
+ getCurFunction()->ObjCWarnForNoDesignatedInitChain =
+ IC->getSuperClass() != nullptr;
+ } else if (IC->hasDesignatedInitializers()) {
+ getCurFunction()->ObjCIsSecondaryInit = true;
+ getCurFunction()->ObjCWarnForNoInitDelegation = true;
+ }
+ }
+
// If this is "dealloc" or "finalize", set some bit here.
// Then in ActOnSuperMessage() (SemaExprObjC), set it back to false.
// Finally, in ActOnFinishFunctionBody() (SemaDecl), warn if flag is set.
@@ -424,11 +437,11 @@ namespace {
// function will reject corrections to that class.
class ObjCInterfaceValidatorCCC : public CorrectionCandidateCallback {
public:
- ObjCInterfaceValidatorCCC() : CurrentIDecl(0) {}
+ ObjCInterfaceValidatorCCC() : CurrentIDecl(nullptr) {}
explicit ObjCInterfaceValidatorCCC(ObjCInterfaceDecl *IDecl)
: CurrentIDecl(IDecl) {}
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
ObjCInterfaceDecl *ID = candidate.getCorrectionDeclAs<ObjCInterfaceDecl>();
return ID && !declaresSameEntity(ID, CurrentIDecl);
}
@@ -510,7 +523,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
ObjCInterfaceValidatorCCC Validator(IDecl);
if (TypoCorrection Corrected = CorrectTypo(
DeclarationNameInfo(SuperName, SuperLoc), LookupOrdinaryName, TUScope,
- NULL, Validator)) {
+ nullptr, Validator, CTK_ErrorRecovery)) {
diagnoseTypo(Corrected, PDiag(diag::err_undef_superclass_suggest)
<< SuperName << ClassName);
PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>();
@@ -529,7 +542,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
if (SuperClassDecl)
(void)DiagnoseUseOfDecl(SuperClassDecl, SuperLoc);
- if (PrevDecl && SuperClassDecl == 0) {
+ if (PrevDecl && !SuperClassDecl) {
// The previous declaration was not a class decl. Check if we have a
// typedef. If we do, get the underlying class type.
if (const TypedefNameDecl *TDecl =
@@ -568,7 +581,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
SuperClassDecl->getDeclName(),
ClassName,
SourceRange(AtInterfaceLoc, ClassLoc))) {
- SuperClassDecl = 0;
+ SuperClassDecl = nullptr;
}
}
IDecl->setSuperClass(SuperClassDecl);
@@ -607,9 +620,8 @@ void Sema::ActOnTypedefedProtocols(SmallVectorImpl<Decl *> &ProtocolRefs,
QualType T = TDecl->getUnderlyingType();
if (T->isObjCObjectType())
if (const ObjCObjectType *OPT = T->getAs<ObjCObjectType>())
- for (ObjCObjectType::qual_iterator I = OPT->qual_begin(),
- E = OPT->qual_end(); I != E; ++I)
- ProtocolRefs.push_back(*I);
+ for (auto *I : OPT->quals())
+ ProtocolRefs.push_back(I);
}
}
@@ -626,7 +638,7 @@ Decl *Sema::ActOnCompatibilityAlias(SourceLocation AtLoc,
if (ADecl) {
Diag(AliasLocation, diag::err_conflicting_aliasing_type) << AliasName;
Diag(ADecl->getLocation(), diag::note_previous_declaration);
- return 0;
+ return nullptr;
}
// Check for class declaration
NamedDecl *CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation,
@@ -643,11 +655,11 @@ Decl *Sema::ActOnCompatibilityAlias(SourceLocation AtLoc,
}
}
ObjCInterfaceDecl *CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDeclU);
- if (CDecl == 0) {
+ if (!CDecl) {
Diag(ClassLocation, diag::warn_undef_interface) << ClassName;
if (CDeclU)
Diag(CDeclU->getLocation(), diag::note_previous_declaration);
- return 0;
+ return nullptr;
}
// Everything checked out, instantiate a new alias declaration AST.
@@ -701,8 +713,8 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
assert(ProtocolName && "Missing protocol identifier");
ObjCProtocolDecl *PrevDecl = LookupProtocol(ProtocolName, ProtocolLoc,
ForRedeclaration);
- ObjCProtocolDecl *PDecl = 0;
- if (ObjCProtocolDecl *Def = PrevDecl? PrevDecl->getDefinition() : 0) {
+ ObjCProtocolDecl *PDecl = nullptr;
+ if (ObjCProtocolDecl *Def = PrevDecl? PrevDecl->getDefinition() : nullptr) {
// If we already have a definition, complain.
Diag(ProtocolLoc, diag::warn_duplicate_protocol_def) << ProtocolName;
Diag(Def->getLocation(), diag::note_previous_definition);
@@ -713,7 +725,7 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
// FIXME: Can we turn this into an error?
PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName,
ProtocolLoc, AtProtoInterfaceLoc,
- /*PrevDecl=*/0);
+ /*PrevDecl=*/nullptr);
PDecl->startDefinition();
} else {
if (PrevDecl) {
@@ -751,6 +763,21 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
return ActOnObjCContainerStartDefinition(PDecl);
}
+static bool NestedProtocolHasNoDefinition(ObjCProtocolDecl *PDecl,
+ ObjCProtocolDecl *&UndefinedProtocol) {
+ if (!PDecl->hasDefinition() || PDecl->getDefinition()->isHidden()) {
+ UndefinedProtocol = PDecl;
+ return true;
+ }
+
+ for (auto *PI : PDecl->protocols())
+ if (NestedProtocolHasNoDefinition(PI, UndefinedProtocol)) {
+ UndefinedProtocol = PI;
+ return true;
+ }
+ return false;
+}
+
/// FindProtocolDeclaration - This routine looks up protocols and
/// issues an error if they are not declared. It returns list of
/// protocol declarations in its 'Protocols' argument.
@@ -766,7 +793,8 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations,
DeclFilterCCC<ObjCProtocolDecl> Validator;
TypoCorrection Corrected = CorrectTypo(
DeclarationNameInfo(ProtocolId[i].first, ProtocolId[i].second),
- LookupObjCProtocolName, TUScope, NULL, Validator);
+ LookupObjCProtocolName, TUScope, nullptr, Validator,
+ CTK_ErrorRecovery);
if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>()))
diagnoseTypo(Corrected, PDiag(diag::err_undeclared_protocol_suggest)
<< ProtocolId[i].first);
@@ -786,10 +814,15 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations,
// If this is a forward declaration and we are supposed to warn in this
// case, do it.
// FIXME: Recover nicely in the hidden case.
+ ObjCProtocolDecl *UndefinedProtocol;
+
if (WarnOnDeclarations &&
- (!PDecl->hasDefinition() || PDecl->getDefinition()->isHidden()))
+ NestedProtocolHasNoDefinition(PDecl, UndefinedProtocol)) {
Diag(ProtocolId[i].second, diag::warn_undef_protocolref)
<< ProtocolId[i].first;
+ Diag(UndefinedProtocol->getLocation(), diag::note_protocol_decl_undefined)
+ << UndefinedProtocol;
+ }
Protocols.push_back(PDecl);
}
}
@@ -803,19 +836,16 @@ void Sema::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
return; // Possibly due to previous error
llvm::DenseMap<Selector, const ObjCMethodDecl*> MethodMap;
- for (ObjCInterfaceDecl::method_iterator i = ID->meth_begin(),
- e = ID->meth_end(); i != e; ++i) {
- ObjCMethodDecl *MD = *i;
+ for (auto *MD : ID->methods())
MethodMap[MD->getSelector()] = MD;
- }
if (MethodMap.empty())
return;
- for (ObjCCategoryDecl::method_iterator i = CAT->meth_begin(),
- e = CAT->meth_end(); i != e; ++i) {
- ObjCMethodDecl *Method = *i;
+ for (const auto *Method : CAT->methods()) {
const ObjCMethodDecl *&PrevMethod = MethodMap[Method->getSelector()];
- if (PrevMethod && !MatchTwoMethodDeclarations(Method, PrevMethod)) {
+ if (PrevMethod &&
+ (PrevMethod->isInstanceMethod() == Method->isInstanceMethod()) &&
+ !MatchTwoMethodDeclarations(Method, PrevMethod)) {
Diag(Method->getLocation(), diag::err_duplicate_method_decl)
<< Method->getDeclName();
Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
@@ -871,7 +901,7 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
if (!IDecl
|| RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl),
diag::err_category_forward_interface,
- CategoryName == 0)) {
+ CategoryName == nullptr)) {
// Create an invalid ObjCCategoryDecl to serve as context for
// the enclosing method declarations. We mark the decl invalid
// to make it clear that this isn't a valid AST.
@@ -928,7 +958,7 @@ Decl *Sema::ActOnStartCategoryImplementation(
IdentifierInfo *ClassName, SourceLocation ClassLoc,
IdentifierInfo *CatName, SourceLocation CatLoc) {
ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true);
- ObjCCategoryDecl *CatIDecl = 0;
+ ObjCCategoryDecl *CatIDecl = nullptr;
if (IDecl && IDecl->hasDefinition()) {
CatIDecl = IDecl->FindCategoryDeclaration(CatName);
if (!CatIDecl) {
@@ -987,7 +1017,7 @@ Decl *Sema::ActOnStartClassImplementation(
IdentifierInfo *ClassName, SourceLocation ClassLoc,
IdentifierInfo *SuperClassname,
SourceLocation SuperClassLoc) {
- ObjCInterfaceDecl *IDecl = 0;
+ ObjCInterfaceDecl *IDecl = nullptr;
// Check for another declaration kind with the same name.
NamedDecl *PrevDecl
= LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName,
@@ -1004,7 +1034,8 @@ Decl *Sema::ActOnStartClassImplementation(
ObjCInterfaceValidatorCCC Validator;
TypoCorrection Corrected =
CorrectTypo(DeclarationNameInfo(ClassName, ClassLoc),
- LookupOrdinaryName, TUScope, NULL, Validator);
+ LookupOrdinaryName, TUScope, nullptr, Validator,
+ CTK_NonError);
if (Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {
// Suggest the (potentially) correct interface name. Don't provide a
// code-modification hint or use the typo name for recovery, because
@@ -1018,7 +1049,7 @@ Decl *Sema::ActOnStartClassImplementation(
}
// Check that super class name is valid class name
- ObjCInterfaceDecl* SDecl = 0;
+ ObjCInterfaceDecl *SDecl = nullptr;
if (SuperClassname) {
// Check if a different kind of symbol declared in this scope.
PrevDecl = LookupSingleName(TUScope, SuperClassname, SuperClassLoc,
@@ -1030,7 +1061,7 @@ Decl *Sema::ActOnStartClassImplementation(
} else {
SDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
if (SDecl && !SDecl->hasDefinition())
- SDecl = 0;
+ SDecl = nullptr;
if (!SDecl)
Diag(SuperClassLoc, diag::err_undef_superclass)
<< SuperClassname << ClassName;
@@ -1051,7 +1082,7 @@ Decl *Sema::ActOnStartClassImplementation(
// FIXME: Do we support attributes on the @implementation? If so we should
// copy them over.
IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassImplLoc,
- ClassName, /*PrevDecl=*/0, ClassLoc,
+ ClassName, /*PrevDecl=*/nullptr, ClassLoc,
true);
IDecl->startDefinition();
if (SDecl) {
@@ -1154,11 +1185,7 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
continue;
}
// Check class extensions (unnamed categories) for duplicate ivars.
- for (ObjCInterfaceDecl::visible_extensions_iterator
- Ext = IDecl->visible_extensions_begin(),
- ExtEnd = IDecl->visible_extensions_end();
- Ext != ExtEnd; ++Ext) {
- ObjCCategoryDecl *CDecl = *Ext;
+ for (const auto *CDecl : IDecl->visible_extensions()) {
if (const ObjCIvarDecl *ClsExtIvar =
CDecl->getIvarDecl(ImplIvar->getIdentifier())) {
Diag(ImplIvar->getLocation(), diag::err_duplicate_ivar_declaration);
@@ -1209,13 +1236,16 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
}
if (numIvars > 0)
- Diag(ivars[j]->getLocation(), diag::err_inconsistant_ivar_count);
+ Diag(ivars[j]->getLocation(), diag::err_inconsistent_ivar_count);
else if (IVI != IVE)
- Diag(IVI->getLocation(), diag::err_inconsistant_ivar_count);
+ Diag(IVI->getLocation(), diag::err_inconsistent_ivar_count);
}
-void Sema::WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method,
- bool &IncompleteImpl, unsigned DiagID) {
+static void WarnUndefinedMethod(Sema &S, SourceLocation ImpLoc,
+ ObjCMethodDecl *method,
+ bool &IncompleteImpl,
+ unsigned DiagID,
+ NamedDecl *NeededFor = nullptr) {
// No point warning no definition of method which is 'unavailable'.
switch (method->getAvailability()) {
case AR_Available:
@@ -1233,13 +1263,17 @@ void Sema::WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method,
// warning, but some users strongly voiced that they would prefer
// separate warnings. We will give that approach a try, as that
// matches what we do with protocols.
-
- Diag(ImpLoc, DiagID) << method->getDeclName();
+ {
+ const Sema::SemaDiagnosticBuilder &B = S.Diag(ImpLoc, DiagID);
+ B << method;
+ if (NeededFor)
+ B << NeededFor;
+ }
// Issue a note to the original declaration.
SourceLocation MethodLoc = method->getLocStart();
if (MethodLoc.isValid())
- Diag(MethodLoc, diag::note_method_declared_at) << method;
+ S.Diag(MethodLoc, diag::note_method_declared_at) << method;
}
/// Determines if type B can be substituted for type A. Returns true if we can
@@ -1323,21 +1357,21 @@ static bool CheckMethodOverrideReturn(Sema &S,
(MethodDecl->getObjCDeclQualifier() !=
MethodImpl->getObjCDeclQualifier())) {
if (Warn) {
- S.Diag(MethodImpl->getLocation(),
- (IsOverridingMode ?
- diag::warn_conflicting_overriding_ret_type_modifiers
- : diag::warn_conflicting_ret_type_modifiers))
+ S.Diag(MethodImpl->getLocation(),
+ (IsOverridingMode
+ ? diag::warn_conflicting_overriding_ret_type_modifiers
+ : diag::warn_conflicting_ret_type_modifiers))
<< MethodImpl->getDeclName()
- << getTypeRange(MethodImpl->getResultTypeSourceInfo());
- S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration)
- << getTypeRange(MethodDecl->getResultTypeSourceInfo());
+ << getTypeRange(MethodImpl->getReturnTypeSourceInfo());
+ S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration)
+ << getTypeRange(MethodDecl->getReturnTypeSourceInfo());
}
else
return false;
}
-
- if (S.Context.hasSameUnqualifiedType(MethodImpl->getResultType(),
- MethodDecl->getResultType()))
+
+ if (S.Context.hasSameUnqualifiedType(MethodImpl->getReturnType(),
+ MethodDecl->getReturnType()))
return true;
if (!Warn)
return false;
@@ -1349,9 +1383,9 @@ static bool CheckMethodOverrideReturn(Sema &S,
// Mismatches between ObjC pointers go into a different warning
// category, and sometimes they're even completely whitelisted.
if (const ObjCObjectPointerType *ImplPtrTy =
- MethodImpl->getResultType()->getAs<ObjCObjectPointerType>()) {
+ MethodImpl->getReturnType()->getAs<ObjCObjectPointerType>()) {
if (const ObjCObjectPointerType *IfacePtrTy =
- MethodDecl->getResultType()->getAs<ObjCObjectPointerType>()) {
+ MethodDecl->getReturnType()->getAs<ObjCObjectPointerType>()) {
// Allow non-matching return types as long as they don't violate
// the principle of substitutability. Specifically, we permit
// return types that are subclasses of the declared return type,
@@ -1366,14 +1400,13 @@ static bool CheckMethodOverrideReturn(Sema &S,
}
S.Diag(MethodImpl->getLocation(), DiagID)
- << MethodImpl->getDeclName()
- << MethodDecl->getResultType()
- << MethodImpl->getResultType()
- << getTypeRange(MethodImpl->getResultTypeSourceInfo());
- S.Diag(MethodDecl->getLocation(),
- IsOverridingMode ? diag::note_previous_declaration
- : diag::note_previous_definition)
- << getTypeRange(MethodDecl->getResultTypeSourceInfo());
+ << MethodImpl->getDeclName() << MethodDecl->getReturnType()
+ << MethodImpl->getReturnType()
+ << getTypeRange(MethodImpl->getReturnTypeSourceInfo());
+ S.Diag(MethodDecl->getLocation(), IsOverridingMode
+ ? diag::note_previous_declaration
+ : diag::note_previous_definition)
+ << getTypeRange(MethodDecl->getReturnTypeSourceInfo());
return false;
}
@@ -1505,7 +1538,7 @@ static bool checkMethodFamilyMismatch(Sema &S, ObjCMethodDecl *impl,
// The only reason these methods don't fall within their families is
// due to unusual result types.
- if (unmatched->getResultType()->isObjCObjectPointerType()) {
+ if (unmatched->getReturnType()->isObjCObjectPointerType()) {
reasonSelector = R_UnrelatedReturn;
} else {
reasonSelector = R_NonObjectReturn;
@@ -1615,22 +1648,75 @@ void Sema::WarnExactTypedMethods(ObjCMethodDecl *ImpMethodDecl,
/// we used an immutable set to keep the table then it wouldn't add significant
/// memory cost and it would be handy for lookups.
+typedef llvm::DenseSet<IdentifierInfo*> ProtocolNameSet;
+typedef std::unique_ptr<ProtocolNameSet> LazyProtocolNameSet;
+
+static void findProtocolsWithExplicitImpls(const ObjCProtocolDecl *PDecl,
+ ProtocolNameSet &PNS) {
+ if (PDecl->hasAttr<ObjCExplicitProtocolImplAttr>())
+ PNS.insert(PDecl->getIdentifier());
+ for (const auto *PI : PDecl->protocols())
+ findProtocolsWithExplicitImpls(PI, PNS);
+}
+
+/// Recursively populates a set with all conformed protocols in a class
+/// hierarchy that have the 'objc_protocol_requires_explicit_implementation'
+/// attribute.
+static void findProtocolsWithExplicitImpls(const ObjCInterfaceDecl *Super,
+ ProtocolNameSet &PNS) {
+ if (!Super)
+ return;
+
+ for (const auto *I : Super->all_referenced_protocols())
+ findProtocolsWithExplicitImpls(I, PNS);
+
+ findProtocolsWithExplicitImpls(Super->getSuperClass(), PNS);
+}
+
/// CheckProtocolMethodDefs - This routine checks unimplemented methods
/// Declared in protocol, and those referenced by it.
-void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc,
- ObjCProtocolDecl *PDecl,
- bool& IncompleteImpl,
- const SelectorSet &InsMap,
- const SelectorSet &ClsMap,
- ObjCContainerDecl *CDecl) {
+static void CheckProtocolMethodDefs(Sema &S,
+ SourceLocation ImpLoc,
+ ObjCProtocolDecl *PDecl,
+ bool& IncompleteImpl,
+ const Sema::SelectorSet &InsMap,
+ const Sema::SelectorSet &ClsMap,
+ ObjCContainerDecl *CDecl,
+ LazyProtocolNameSet &ProtocolsExplictImpl) {
ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl);
ObjCInterfaceDecl *IDecl = C ? C->getClassInterface()
: dyn_cast<ObjCInterfaceDecl>(CDecl);
assert (IDecl && "CheckProtocolMethodDefs - IDecl is null");
ObjCInterfaceDecl *Super = IDecl->getSuperClass();
- ObjCInterfaceDecl *NSIDecl = 0;
- if (getLangOpts().ObjCRuntime.isNeXTFamily()) {
+ ObjCInterfaceDecl *NSIDecl = nullptr;
+
+ // If this protocol is marked 'objc_protocol_requires_explicit_implementation'
+ // then we should check if any class in the super class hierarchy also
+ // conforms to this protocol, either directly or via protocol inheritance.
+ // If so, we can skip checking this protocol completely because we
+ // know that a parent class already satisfies this protocol.
+ //
+ // Note: we could generalize this logic for all protocols, and merely
+ // add the limit on looking at the super class chain for just
+ // specially marked protocols. This may be a good optimization. This
+ // change is restricted to 'objc_protocol_requires_explicit_implementation'
+ // protocols for now for controlled evaluation.
+ if (PDecl->hasAttr<ObjCExplicitProtocolImplAttr>()) {
+ if (!ProtocolsExplictImpl) {
+ ProtocolsExplictImpl.reset(new ProtocolNameSet);
+ findProtocolsWithExplicitImpls(Super, *ProtocolsExplictImpl);
+ }
+ if (ProtocolsExplictImpl->find(PDecl->getIdentifier()) !=
+ ProtocolsExplictImpl->end())
+ return;
+
+ // If no super class conforms to the protocol, we should not search
+ // for methods in the super class to implicitly satisfy the protocol.
+ Super = nullptr;
+ }
+
+ if (S.getLangOpts().ObjCRuntime.isNeXTFamily()) {
// check to see if class implements forwardInvocation method and objects
// of this class are derived from 'NSProxy' so that to forward requests
// from one object to another.
@@ -1638,12 +1724,12 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc,
// implemented in the class, we should not issue "Method definition not
// found" warnings.
// FIXME: Use a general GetUnarySelector method for this.
- IdentifierInfo* II = &Context.Idents.get("forwardInvocation");
- Selector fISelector = Context.Selectors.getSelector(1, &II);
+ IdentifierInfo* II = &S.Context.Idents.get("forwardInvocation");
+ Selector fISelector = S.Context.Selectors.getSelector(1, &II);
if (InsMap.count(fISelector))
// Is IDecl derived from 'NSProxy'? If so, no instance methods
// need be implemented in the implementation.
- NSIDecl = IDecl->lookupInheritedClass(&Context.Idents.get("NSProxy"));
+ NSIDecl = IDecl->lookupInheritedClass(&S.Context.Idents.get("NSProxy"));
}
// If this is a forward protocol declaration, get its definition.
@@ -1658,13 +1744,15 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc,
// check unimplemented instance methods.
if (!NSIDecl)
- for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(),
- E = PDecl->instmeth_end(); I != E; ++I) {
- ObjCMethodDecl *method = *I;
+ for (auto *method : PDecl->instance_methods()) {
if (method->getImplementationControl() != ObjCMethodDecl::Optional &&
!method->isPropertyAccessor() &&
!InsMap.count(method->getSelector()) &&
- (!Super || !Super->lookupInstanceMethod(method->getSelector()))) {
+ (!Super || !Super->lookupMethod(method->getSelector(),
+ true /* instance */,
+ false /* shallowCategory */,
+ true /* followsSuper */,
+ nullptr /* category */))) {
// If a method is not implemented in the category implementation but
// has been declared in its primary class, superclass,
// or in one of their protocols, no need to issue the warning.
@@ -1675,44 +1763,45 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc,
// have been synthesized due to a property declared in the class which
// uses the protocol.
if (ObjCMethodDecl *MethodInClass =
- IDecl->lookupInstanceMethod(method->getSelector(),
- true /*shallowCategoryLookup*/))
+ IDecl->lookupMethod(method->getSelector(),
+ true /* instance */,
+ true /* shallowCategoryLookup */,
+ false /* followSuper */))
if (C || MethodInClass->isPropertyAccessor())
continue;
unsigned DIAG = diag::warn_unimplemented_protocol_method;
- if (Diags.getDiagnosticLevel(DIAG, ImpLoc)
- != DiagnosticsEngine::Ignored) {
- WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG);
- Diag(CDecl->getLocation(), diag::note_required_for_protocol_at)
- << PDecl->getDeclName();
+ if (!S.Diags.isIgnored(DIAG, ImpLoc)) {
+ WarnUndefinedMethod(S, ImpLoc, method, IncompleteImpl, DIAG,
+ PDecl);
}
}
}
// check unimplemented class methods
- for (ObjCProtocolDecl::classmeth_iterator
- I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();
- I != E; ++I) {
- ObjCMethodDecl *method = *I;
+ for (auto *method : PDecl->class_methods()) {
if (method->getImplementationControl() != ObjCMethodDecl::Optional &&
!ClsMap.count(method->getSelector()) &&
- (!Super || !Super->lookupClassMethod(method->getSelector()))) {
+ (!Super || !Super->lookupMethod(method->getSelector(),
+ false /* class method */,
+ false /* shallowCategoryLookup */,
+ true /* followSuper */,
+ nullptr /* category */))) {
// See above comment for instance method lookups.
- if (C && IDecl->lookupClassMethod(method->getSelector(),
- true /*shallowCategoryLookup*/))
+ if (C && IDecl->lookupMethod(method->getSelector(),
+ false /* class */,
+ true /* shallowCategoryLookup */,
+ false /* followSuper */))
continue;
+
unsigned DIAG = diag::warn_unimplemented_protocol_method;
- if (Diags.getDiagnosticLevel(DIAG, ImpLoc) !=
- DiagnosticsEngine::Ignored) {
- WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG);
- Diag(IDecl->getLocation(), diag::note_required_for_protocol_at) <<
- PDecl->getDeclName();
+ if (!S.Diags.isIgnored(DIAG, ImpLoc)) {
+ WarnUndefinedMethod(S, ImpLoc, method, IncompleteImpl, DIAG, PDecl);
}
}
}
// Check on this protocols's referenced protocols, recursively.
- for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
- E = PDecl->protocol_end(); PI != E; ++PI)
- CheckProtocolMethodDefs(ImpLoc, *PI, IncompleteImpl, InsMap, ClsMap, CDecl);
+ for (auto *PI : PDecl->protocols())
+ CheckProtocolMethodDefs(S, ImpLoc, PI, IncompleteImpl, InsMap, ClsMap,
+ CDecl, ProtocolsExplictImpl);
}
/// MatchAllMethodDeclarations - Check methods declared in interface
@@ -1729,56 +1818,50 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap,
bool WarnCategoryMethodImpl) {
// Check and see if instance methods in class interface have been
// implemented in the implementation class. If so, their types match.
- for (ObjCInterfaceDecl::instmeth_iterator I = CDecl->instmeth_begin(),
- E = CDecl->instmeth_end(); I != E; ++I) {
- if (!InsMapSeen.insert((*I)->getSelector()))
+ for (auto *I : CDecl->instance_methods()) {
+ if (!InsMapSeen.insert(I->getSelector()))
continue;
- if (!(*I)->isPropertyAccessor() &&
- !InsMap.count((*I)->getSelector())) {
+ if (!I->isPropertyAccessor() &&
+ !InsMap.count(I->getSelector())) {
if (ImmediateClass)
- WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl,
+ WarnUndefinedMethod(*this, IMPDecl->getLocation(), I, IncompleteImpl,
diag::warn_undef_method_impl);
continue;
} else {
ObjCMethodDecl *ImpMethodDecl =
- IMPDecl->getInstanceMethod((*I)->getSelector());
- assert(CDecl->getInstanceMethod((*I)->getSelector()) &&
+ IMPDecl->getInstanceMethod(I->getSelector());
+ assert(CDecl->getInstanceMethod(I->getSelector()) &&
"Expected to find the method through lookup as well");
- ObjCMethodDecl *MethodDecl = *I;
// ImpMethodDecl may be null as in a @dynamic property.
if (ImpMethodDecl) {
if (!WarnCategoryMethodImpl)
- WarnConflictingTypedMethods(ImpMethodDecl, MethodDecl,
+ WarnConflictingTypedMethods(ImpMethodDecl, I,
isa<ObjCProtocolDecl>(CDecl));
- else if (!MethodDecl->isPropertyAccessor())
- WarnExactTypedMethods(ImpMethodDecl, MethodDecl,
- isa<ObjCProtocolDecl>(CDecl));
+ else if (!I->isPropertyAccessor())
+ WarnExactTypedMethods(ImpMethodDecl, I, isa<ObjCProtocolDecl>(CDecl));
}
}
}
// Check and see if class methods in class interface have been
// implemented in the implementation class. If so, their types match.
- for (ObjCInterfaceDecl::classmeth_iterator I = CDecl->classmeth_begin(),
- E = CDecl->classmeth_end();
- I != E; ++I) {
- if (!ClsMapSeen.insert((*I)->getSelector()))
+ for (auto *I : CDecl->class_methods()) {
+ if (!ClsMapSeen.insert(I->getSelector()))
continue;
- if (!ClsMap.count((*I)->getSelector())) {
+ if (!ClsMap.count(I->getSelector())) {
if (ImmediateClass)
- WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl,
+ WarnUndefinedMethod(*this, IMPDecl->getLocation(), I, IncompleteImpl,
diag::warn_undef_method_impl);
} else {
ObjCMethodDecl *ImpMethodDecl =
- IMPDecl->getClassMethod((*I)->getSelector());
- assert(CDecl->getClassMethod((*I)->getSelector()) &&
+ IMPDecl->getClassMethod(I->getSelector());
+ assert(CDecl->getClassMethod(I->getSelector()) &&
"Expected to find the method through lookup as well");
- ObjCMethodDecl *MethodDecl = *I;
if (!WarnCategoryMethodImpl)
- WarnConflictingTypedMethods(ImpMethodDecl, MethodDecl,
+ WarnConflictingTypedMethods(ImpMethodDecl, I,
isa<ObjCProtocolDecl>(CDecl));
else
- WarnExactTypedMethods(ImpMethodDecl, MethodDecl,
+ WarnExactTypedMethods(ImpMethodDecl, I,
isa<ObjCProtocolDecl>(CDecl));
}
}
@@ -1786,10 +1869,9 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap,
if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl> (CDecl)) {
// Also, check for methods declared in protocols inherited by
// this protocol.
- for (ObjCProtocolDecl::protocol_iterator
- PI = PD->protocol_begin(), E = PD->protocol_end(); PI != E; ++PI)
+ for (auto *PI : PD->protocols())
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
- IMPDecl, (*PI), IncompleteImpl, false,
+ IMPDecl, PI, IncompleteImpl, false,
WarnCategoryMethodImpl);
}
@@ -1798,35 +1880,24 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap,
// i.e. when WarnCategoryMethodImpl is false, check declarations in class
// extension; as well as those in categories.
if (!WarnCategoryMethodImpl) {
- for (ObjCInterfaceDecl::visible_categories_iterator
- Cat = I->visible_categories_begin(),
- CatEnd = I->visible_categories_end();
- Cat != CatEnd; ++Cat) {
+ for (auto *Cat : I->visible_categories())
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
- IMPDecl, *Cat, IncompleteImpl, false,
+ IMPDecl, Cat, IncompleteImpl, false,
WarnCategoryMethodImpl);
- }
} else {
// Also methods in class extensions need be looked at next.
- for (ObjCInterfaceDecl::visible_extensions_iterator
- Ext = I->visible_extensions_begin(),
- ExtEnd = I->visible_extensions_end();
- Ext != ExtEnd; ++Ext) {
+ for (auto *Ext : I->visible_extensions())
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
- IMPDecl, *Ext, IncompleteImpl, false,
+ IMPDecl, Ext, IncompleteImpl, false,
WarnCategoryMethodImpl);
- }
}
// Check for any implementation of a methods declared in protocol.
- for (ObjCInterfaceDecl::all_protocol_iterator
- PI = I->all_referenced_protocol_begin(),
- E = I->all_referenced_protocol_end(); PI != E; ++PI)
+ for (auto *PI : I->all_referenced_protocols())
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
- IMPDecl,
- (*PI), IncompleteImpl, false,
+ IMPDecl, PI, IncompleteImpl, false,
WarnCategoryMethodImpl);
-
+
// FIXME. For now, we are not checking for extact match of methods
// in category implementation and its primary class's super class.
if (!WarnCategoryMethodImpl && I->getSuperClass())
@@ -1841,20 +1912,6 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap,
/// warns each time an exact match is found.
void Sema::CheckCategoryVsClassMethodMatches(
ObjCCategoryImplDecl *CatIMPDecl) {
- SelectorSet InsMap, ClsMap;
-
- for (ObjCImplementationDecl::instmeth_iterator
- I = CatIMPDecl->instmeth_begin(),
- E = CatIMPDecl->instmeth_end(); I!=E; ++I)
- InsMap.insert((*I)->getSelector());
-
- for (ObjCImplementationDecl::classmeth_iterator
- I = CatIMPDecl->classmeth_begin(),
- E = CatIMPDecl->classmeth_end(); I != E; ++I)
- ClsMap.insert((*I)->getSelector());
- if (InsMap.empty() && ClsMap.empty())
- return;
-
// Get category's primary class.
ObjCCategoryDecl *CatDecl = CatIMPDecl->getCategoryDecl();
if (!CatDecl)
@@ -1862,6 +1919,28 @@ void Sema::CheckCategoryVsClassMethodMatches(
ObjCInterfaceDecl *IDecl = CatDecl->getClassInterface();
if (!IDecl)
return;
+ ObjCInterfaceDecl *SuperIDecl = IDecl->getSuperClass();
+ SelectorSet InsMap, ClsMap;
+
+ for (const auto *I : CatIMPDecl->instance_methods()) {
+ Selector Sel = I->getSelector();
+ // When checking for methods implemented in the category, skip over
+ // those declared in category class's super class. This is because
+ // the super class must implement the method.
+ if (SuperIDecl && SuperIDecl->lookupMethod(Sel, true))
+ continue;
+ InsMap.insert(Sel);
+ }
+
+ for (const auto *I : CatIMPDecl->class_methods()) {
+ Selector Sel = I->getSelector();
+ if (SuperIDecl && SuperIDecl->lookupMethod(Sel, false))
+ continue;
+ ClsMap.insert(Sel);
+ }
+ if (InsMap.empty() && ClsMap.empty())
+ return;
+
SelectorSet InsMapSeen, ClsMapSeen;
bool IncompleteImpl = false;
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
@@ -1876,24 +1955,22 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
SelectorSet InsMap;
// Check and see if instance methods in class interface have been
// implemented in the implementation class.
- for (ObjCImplementationDecl::instmeth_iterator
- I = IMPDecl->instmeth_begin(), E = IMPDecl->instmeth_end(); I!=E; ++I)
- InsMap.insert((*I)->getSelector());
+ for (const auto *I : IMPDecl->instance_methods())
+ InsMap.insert(I->getSelector());
// Check and see if properties declared in the interface have either 1)
// an implementation or 2) there is a @synthesize/@dynamic implementation
// of the property in the @implementation.
- if (const ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl))
- if (!(LangOpts.ObjCDefaultSynthProperties &&
- LangOpts.ObjCRuntime.isNonFragile()) ||
- IDecl->isObjCRequiresPropertyDefs())
- DiagnoseUnimplementedProperties(S, IMPDecl, CDecl);
-
+ if (const ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
+ bool SynthesizeProperties = LangOpts.ObjCDefaultSynthProperties &&
+ LangOpts.ObjCRuntime.isNonFragile() &&
+ !IDecl->isObjCRequiresPropertyDefs();
+ DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, SynthesizeProperties);
+ }
+
SelectorSet ClsMap;
- for (ObjCImplementationDecl::classmeth_iterator
- I = IMPDecl->classmeth_begin(),
- E = IMPDecl->classmeth_end(); I != E; ++I)
- ClsMap.insert((*I)->getSelector());
+ for (const auto *I : IMPDecl->class_methods())
+ ClsMap.insert(I->getSelector());
// Check for type conflict of methods declared in a class/protocol and
// its implementation; if any.
@@ -1913,28 +1990,25 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
// Check and see if class methods in class interface have been
// implemented in the implementation class.
+ LazyProtocolNameSet ExplicitImplProtocols;
+
if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {
- for (ObjCInterfaceDecl::all_protocol_iterator
- PI = I->all_referenced_protocol_begin(),
- E = I->all_referenced_protocol_end(); PI != E; ++PI)
- CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl,
- InsMap, ClsMap, I);
+ for (auto *PI : I->all_referenced_protocols())
+ CheckProtocolMethodDefs(*this, IMPDecl->getLocation(), PI, IncompleteImpl,
+ InsMap, ClsMap, I, ExplicitImplProtocols);
// Check class extensions (unnamed categories)
- for (ObjCInterfaceDecl::visible_extensions_iterator
- Ext = I->visible_extensions_begin(),
- ExtEnd = I->visible_extensions_end();
- Ext != ExtEnd; ++Ext) {
- ImplMethodsVsClassMethods(S, IMPDecl, *Ext, IncompleteImpl);
- }
+ for (auto *Ext : I->visible_extensions())
+ ImplMethodsVsClassMethods(S, IMPDecl, Ext, IncompleteImpl);
} else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {
// For extended class, unimplemented methods in its protocols will
// be reported in the primary class.
if (!C->IsClassExtension()) {
- for (ObjCCategoryDecl::protocol_iterator PI = C->protocol_begin(),
- E = C->protocol_end(); PI != E; ++PI)
- CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl,
- InsMap, ClsMap, CDecl);
- DiagnoseUnimplementedProperties(S, IMPDecl, CDecl);
+ for (auto *P : C->protocols())
+ CheckProtocolMethodDefs(*this, IMPDecl->getLocation(), P,
+ IncompleteImpl, InsMap, ClsMap, CDecl,
+ ExplicitImplProtocols);
+ DiagnoseUnimplementedProperties(S, IMPDecl, CDecl,
+ /* SynthesizeProperties */ false);
}
} else
llvm_unreachable("invalid ObjCContainerDecl type.");
@@ -2103,8 +2177,8 @@ static bool tryMatchRecordTypes(ASTContext &Context,
bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *left,
const ObjCMethodDecl *right,
MethodMatchStrategy strategy) {
- if (!matchTypes(Context, strategy,
- left->getResultType(), right->getResultType()))
+ if (!matchTypes(Context, strategy, left->getReturnType(),
+ right->getReturnType()))
return false;
// If either is hidden, it is not considered to match.
@@ -2145,9 +2219,9 @@ void Sema::addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method) {
List->setBits(List->getBits()+1);
// If the list is empty, make it a singleton list.
- if (List->Method == 0) {
+ if (List->Method == nullptr) {
List->Method = Method;
- List->setNext(0);
+ List->setNext(nullptr);
return;
}
@@ -2187,7 +2261,7 @@ void Sema::addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method) {
// We have a new signature for an existing method - add it.
// This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
ObjCMethodList *Mem = BumpAlloc.Allocate<ObjCMethodList>();
- Previous->setNext(new (Mem) ObjCMethodList(Method, 0));
+ Previous->setNext(new (Mem) ObjCMethodList(Method, nullptr));
}
/// \brief Read the contents of the method pool for a given selector from
@@ -2233,7 +2307,7 @@ static bool isAcceptableMethodMismatch(ObjCMethodDecl *chosen,
// Don't complain about mismatches for -length if the method we
// chose has an integral result type.
- return (chosen->getResultType()->isIntegerType());
+ return (chosen->getReturnType()->isIntegerType());
}
ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R,
@@ -2244,7 +2318,7 @@ ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R,
GlobalMethodPool::iterator Pos = MethodPool.find(Sel);
if (Pos == MethodPool.end())
- return 0;
+ return nullptr;
// Gather the non-hidden methods.
ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second;
@@ -2262,7 +2336,7 @@ ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R,
// If there aren't any visible methods, we're done.
// FIXME: Recover if there are any known-but-hidden methods?
if (Methods.empty())
- return 0;
+ return nullptr;
if (Methods.size() == 1)
return Methods[0];
@@ -2273,10 +2347,8 @@ ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R,
// We support a warning which complains about *any* difference in
// method signature.
bool strictSelectorMatch =
- (receiverIdOrClass && warn &&
- (Diags.getDiagnosticLevel(diag::warn_strict_multiple_method_decl,
- R.getBegin())
- != DiagnosticsEngine::Ignored));
+ receiverIdOrClass && warn &&
+ !Diags.isIgnored(diag::warn_strict_multiple_method_decl, R.getBegin());
if (strictSelectorMatch) {
for (unsigned I = 1, N = Methods.size(); I != N; ++I) {
if (!MatchTwoMethodDeclarations(Methods[0], Methods[I], MMS_strict)) {
@@ -2324,15 +2396,19 @@ ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R,
ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) {
GlobalMethodPool::iterator Pos = MethodPool.find(Sel);
if (Pos == MethodPool.end())
- return 0;
+ return nullptr;
GlobalMethods &Methods = Pos->second;
-
- if (Methods.first.Method && Methods.first.Method->isDefined())
- return Methods.first.Method;
- if (Methods.second.Method && Methods.second.Method->isDefined())
- return Methods.second.Method;
- return 0;
+ for (const ObjCMethodList *Method = &Methods.first; Method;
+ Method = Method->getNext())
+ if (Method->Method && Method->Method->isDefined())
+ return Method->Method;
+
+ for (const ObjCMethodList *Method = &Methods.second; Method;
+ Method = Method->getNext())
+ if (Method->Method && Method->Method->isDefined())
+ return Method->Method;
+ return nullptr;
}
static void
@@ -2364,7 +2440,8 @@ static bool HelperIsMethodInObjCType(Sema &S, Selector Sel,
return true;
if (S.LookupMethodInObjectType(Sel, ObjectType, true/*Instance method*/))
return true;
- return S.LookupMethodInObjectType(Sel, ObjectType, false/*Class method*/) != 0;
+ return S.LookupMethodInObjectType(Sel, ObjectType, false/*Class method*/) !=
+ nullptr;
}
const ObjCMethodDecl *
@@ -2376,7 +2453,7 @@ Sema::SelectorsForTypoCorrection(Selector Sel,
if (ObjectType.isNull())
ObjectIsId = ObjectIsClass = false;
else if (!ObjectType->isObjCObjectPointerType())
- return 0;
+ return nullptr;
else if (const ObjCObjectPointerType *ObjCPtr =
ObjectType->getAsObjCInterfacePointerType()) {
ObjectType = QualType(ObjCPtr->getInterfaceType(), 0);
@@ -2387,8 +2464,8 @@ Sema::SelectorsForTypoCorrection(Selector Sel,
else if (ObjectType->isObjCClassType() || ObjectType->isObjCQualifiedClassType())
ObjectIsId = false;
else
- return 0;
-
+ return nullptr;
+
for (GlobalMethodPool::iterator b = MethodPool.begin(),
e = MethodPool.end(); b != e; b++) {
// instance methods
@@ -2420,52 +2497,7 @@ Sema::SelectorsForTypoCorrection(Selector Sel,
HelperSelectorsForTypoCorrection(SelectedMethods,
Sel.getAsString(), Methods[i]);
}
- return (SelectedMethods.size() == 1) ? SelectedMethods[0] : NULL;
-}
-
-static void
-HelperToDiagnoseMismatchedMethodsInGlobalPool(Sema &S,
- ObjCMethodList &MethList) {
- ObjCMethodList *M = &MethList;
- ObjCMethodDecl *TargetMethod = M->Method;
- while (TargetMethod &&
- isa<ObjCImplDecl>(TargetMethod->getDeclContext())) {
- M = M->getNext();
- TargetMethod = M ? M->Method : 0;
- }
- if (!TargetMethod)
- return;
- bool FirstTime = true;
- for (M = M->getNext(); M; M=M->getNext()) {
- ObjCMethodDecl *MatchingMethodDecl = M->Method;
- if (isa<ObjCImplDecl>(MatchingMethodDecl->getDeclContext()))
- continue;
- if (!S.MatchTwoMethodDeclarations(TargetMethod,
- MatchingMethodDecl, Sema::MMS_loose)) {
- if (FirstTime) {
- FirstTime = false;
- S.Diag(TargetMethod->getLocation(), diag::warning_multiple_selectors)
- << TargetMethod->getSelector();
- }
- S.Diag(MatchingMethodDecl->getLocation(), diag::note_also_found);
- }
- }
-}
-
-void Sema::DiagnoseMismatchedMethodsInGlobalPool() {
- unsigned DIAG = diag::warning_multiple_selectors;
- if (Diags.getDiagnosticLevel(DIAG, SourceLocation())
- == DiagnosticsEngine::Ignored)
- return;
- for (GlobalMethodPool::iterator b = MethodPool.begin(),
- e = MethodPool.end(); b != e; b++) {
- // first, instance methods
- ObjCMethodList &InstMethList = b->second.first;
- HelperToDiagnoseMismatchedMethodsInGlobalPool(*this, InstMethList);
- // second, class methods
- ObjCMethodList &ClsMethList = b->second.second;
- HelperToDiagnoseMismatchedMethodsInGlobalPool(*this, ClsMethList);
- }
+ return (SelectedMethods.size() == 1) ? SelectedMethods[0] : nullptr;
}
/// DiagnoseDuplicateIvars -
@@ -2475,9 +2507,7 @@ void Sema::DiagnoseMismatchedMethodsInGlobalPool() {
/// class's \@implementation is seen.
void Sema::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID,
ObjCInterfaceDecl *SID) {
- for (ObjCInterfaceDecl::ivar_iterator IVI = ID->ivar_begin(),
- IVE = ID->ivar_end(); IVI != IVE; ++IVI) {
- ObjCIvarDecl* Ivar = *IVI;
+ for (auto *Ivar : ID->ivars()) {
if (Ivar->isInvalidDecl())
continue;
if (IdentifierInfo *II = Ivar->getIdentifier()) {
@@ -2516,7 +2546,7 @@ Sema::ObjCContainerKind Sema::getObjCContainerKind() const {
Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
ArrayRef<DeclGroupPtrTy> allTUVars) {
if (getObjCContainerKind() == Sema::OCK_None)
- return 0;
+ return nullptr;
assert(AtEnd.isValid() && "Invalid location for '@end'");
@@ -2603,10 +2633,8 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
// ProcessPropertyDecl is responsible for diagnosing conflicts with any
// user-defined setter/getter. It also synthesizes setter/getter methods
// and adds them to the DeclContext and global method pools.
- for (ObjCContainerDecl::prop_iterator I = CDecl->prop_begin(),
- E = CDecl->prop_end();
- I != E; ++I)
- ProcessPropertyDecl(*I, CDecl);
+ for (auto *I : CDecl->properties())
+ ProcessPropertyDecl(I, CDecl);
CDecl->setAtEndRange(AtEnd);
}
if (ObjCImplementationDecl *IC=dyn_cast<ObjCImplementationDecl>(ClassDecl)) {
@@ -2617,13 +2645,8 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
// of the other class extensions. Mark them as synthesized as
// property will be synthesized when property with same name is
// seen in the @implementation.
- for (ObjCInterfaceDecl::visible_extensions_iterator
- Ext = IDecl->visible_extensions_begin(),
- ExtEnd = IDecl->visible_extensions_end();
- Ext != ExtEnd; ++Ext) {
- for (ObjCContainerDecl::prop_iterator I = Ext->prop_begin(),
- E = Ext->prop_end(); I != E; ++I) {
- ObjCPropertyDecl *Property = *I;
+ for (const auto *Ext : IDecl->visible_extensions()) {
+ for (const auto *Property : Ext->properties()) {
// Skip over properties declared @dynamic
if (const ObjCPropertyImplDecl *PIDecl
= IC->FindPropertyImplDecl(Property->getIdentifier()))
@@ -2631,10 +2654,7 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
== ObjCPropertyImplDecl::Dynamic)
continue;
- for (ObjCInterfaceDecl::visible_extensions_iterator
- Ext = IDecl->visible_extensions_begin(),
- ExtEnd = IDecl->visible_extensions_end();
- Ext != ExtEnd; ++Ext) {
+ for (const auto *Ext : IDecl->visible_extensions()) {
if (ObjCMethodDecl *GetterMethod
= Ext->getInstanceMethod(Property->getGetterName()))
GetterMethod->setPropertyAccessor(true);
@@ -2648,14 +2668,17 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
ImplMethodsVsClassMethods(S, IC, IDecl);
AtomicPropertySetterGetterRules(IC, IDecl);
DiagnoseOwningPropertyGetterSynthesis(IC);
-
+ DiagnoseUnusedBackingIvarInAccessor(S, IC);
+ if (IDecl->hasDesignatedInitializers())
+ DiagnoseMissingDesignatedInitOverrides(IC, IDecl);
+
bool HasRootClassAttr = IDecl->hasAttr<ObjCRootClassAttr>();
- if (IDecl->getSuperClass() == NULL) {
+ if (IDecl->getSuperClass() == nullptr) {
// This class has no superclass, so check that it has been marked with
// __attribute((objc_root_class)).
if (!HasRootClassAttr) {
SourceLocation DeclLoc(IDecl->getLocation());
- SourceLocation SuperClassLoc(PP.getLocForEndOfToken(DeclLoc));
+ SourceLocation SuperClassLoc(getLocForEndOfToken(DeclLoc));
Diag(DeclLoc, diag::warn_objc_root_class_missing)
<< IDecl->getIdentifier();
// See if NSObject is in the current scope, and if it is, suggest
@@ -2729,72 +2752,14 @@ CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) {
return (Decl::ObjCDeclQualifier) (unsigned) PQTVal;
}
-static inline
-unsigned countAlignAttr(const AttrVec &A) {
- unsigned count=0;
- for (AttrVec::const_iterator i = A.begin(), e = A.end(); i != e; ++i)
- if ((*i)->getKind() == attr::Aligned)
- ++count;
- return count;
-}
-
-static inline
-bool containsInvalidMethodImplAttribute(ObjCMethodDecl *IMD,
- const AttrVec &A) {
- // If method is only declared in implementation (private method),
- // No need to issue any diagnostics on method definition with attributes.
- if (!IMD)
- return false;
-
- // method declared in interface has no attribute.
- // But implementation has attributes. This is invalid.
- // Except when implementation has 'Align' attribute which is
- // immaterial to method declared in interface.
- if (!IMD->hasAttrs())
- return (A.size() > countAlignAttr(A));
-
- const AttrVec &D = IMD->getAttrs();
-
- unsigned countAlignOnImpl = countAlignAttr(A);
- if (!countAlignOnImpl && (A.size() != D.size()))
- return true;
- else if (countAlignOnImpl) {
- unsigned countAlignOnDecl = countAlignAttr(D);
- if (countAlignOnDecl && (A.size() != D.size()))
- return true;
- else if (!countAlignOnDecl &&
- ((A.size()-countAlignOnImpl) != D.size()))
- return true;
- }
-
- // attributes on method declaration and definition must match exactly.
- // Note that we have at most a couple of attributes on methods, so this
- // n*n search is good enough.
- for (AttrVec::const_iterator i = A.begin(), e = A.end(); i != e; ++i) {
- if ((*i)->getKind() == attr::Aligned)
- continue;
- bool match = false;
- for (AttrVec::const_iterator i1 = D.begin(), e1 = D.end(); i1 != e1; ++i1) {
- if ((*i)->getKind() == (*i1)->getKind()) {
- match = true;
- break;
- }
- }
- if (!match)
- return true;
- }
-
- return false;
-}
-
/// \brief Check whether the declared result type of the given Objective-C
/// method declaration is compatible with the method's class.
///
static Sema::ResultTypeCompatibilityKind
CheckRelatedResultTypeCompatibility(Sema &S, ObjCMethodDecl *Method,
ObjCInterfaceDecl *CurrentClass) {
- QualType ResultType = Method->getResultType();
-
+ QualType ResultType = Method->getReturnType();
+
// If an Objective-C method inherits its related result type, then its
// declared result type must be compatible with its own class type. The
// declared result type is compatible if:
@@ -2928,12 +2893,8 @@ private:
return;
// - categories,
- for (ObjCInterfaceDecl::known_categories_iterator
- cat = iface->known_categories_begin(),
- catEnd = iface->known_categories_end();
- cat != catEnd; ++cat) {
- search(*cat);
- }
+ for (auto *Cat : iface->known_categories())
+ search(Cat);
// - the super class, and
if (ObjCInterfaceDecl *super = iface->getSuperClass())
@@ -3095,19 +3056,19 @@ Decl *Sema::ActOnMethodDeclaration(
// Make sure we can establish a context for the method.
if (!CurContext->isObjCContainer()) {
Diag(MethodLoc, diag::error_missing_method_context);
- return 0;
+ return nullptr;
}
ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
Decl *ClassDecl = cast<Decl>(OCD);
QualType resultDeclType;
bool HasRelatedResultType = false;
- TypeSourceInfo *ResultTInfo = 0;
+ TypeSourceInfo *ReturnTInfo = nullptr;
if (ReturnType) {
- resultDeclType = GetTypeFromParser(ReturnType, &ResultTInfo);
+ resultDeclType = GetTypeFromParser(ReturnType, &ReturnTInfo);
if (CheckFunctionReturnType(resultDeclType, MethodLoc))
- return 0;
+ return nullptr;
HasRelatedResultType = (resultDeclType == Context.getObjCInstanceType());
} else { // get the type for "id".
@@ -3116,18 +3077,14 @@ Decl *Sema::ActOnMethodDeclaration(
<< FixItHint::CreateInsertion(SelectorLocs.front(), "(id)");
}
- ObjCMethodDecl* ObjCMethod =
- ObjCMethodDecl::Create(Context, MethodLoc, EndLoc, Sel,
- resultDeclType,
- ResultTInfo,
- CurContext,
- MethodType == tok::minus, isVariadic,
- /*isPropertyAccessor=*/false,
- /*isImplicitlyDeclared=*/false, /*isDefined=*/false,
- MethodDeclKind == tok::objc_optional
- ? ObjCMethodDecl::Optional
- : ObjCMethodDecl::Required,
- HasRelatedResultType);
+ ObjCMethodDecl *ObjCMethod = ObjCMethodDecl::Create(
+ Context, MethodLoc, EndLoc, Sel, resultDeclType, ReturnTInfo, CurContext,
+ MethodType == tok::minus, isVariadic,
+ /*isPropertyAccessor=*/false,
+ /*isImplicitlyDeclared=*/false, /*isDefined=*/false,
+ MethodDeclKind == tok::objc_optional ? ObjCMethodDecl::Optional
+ : ObjCMethodDecl::Required,
+ HasRelatedResultType);
SmallVector<ParmVarDecl*, 16> Params;
@@ -3137,7 +3094,7 @@ Decl *Sema::ActOnMethodDeclaration(
if (!ArgInfo[i].Type) {
ArgType = Context.getObjCIdType();
- DI = 0;
+ DI = nullptr;
} else {
ArgType = GetTypeFromParser(ArgInfo[i].Type, &DI);
}
@@ -3204,7 +3161,7 @@ Decl *Sema::ActOnMethodDeclaration(
ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList);
// Add the method now.
- const ObjCMethodDecl *PrevMethod = 0;
+ const ObjCMethodDecl *PrevMethod = nullptr;
if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(ClassDecl)) {
if (MethodType == tok::minus) {
PrevMethod = ImpDecl->getInstanceMethod(Sel);
@@ -3214,24 +3171,22 @@ Decl *Sema::ActOnMethodDeclaration(
ImpDecl->addClassMethod(ObjCMethod);
}
- ObjCMethodDecl *IMD = 0;
+ ObjCMethodDecl *IMD = nullptr;
if (ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface())
IMD = IDecl->lookupMethod(ObjCMethod->getSelector(),
ObjCMethod->isInstanceMethod());
if (IMD && IMD->hasAttr<ObjCRequiresSuperAttr>() &&
!ObjCMethod->hasAttr<ObjCRequiresSuperAttr>()) {
// merge the attribute into implementation.
- ObjCMethod->addAttr(
- new (Context) ObjCRequiresSuperAttr(ObjCMethod->getLocation(), Context));
- }
- if (ObjCMethod->hasAttrs() &&
- containsInvalidMethodImplAttribute(IMD, ObjCMethod->getAttrs())) {
- SourceLocation MethodLoc = IMD->getLocation();
- if (!getSourceManager().isInSystemHeader(MethodLoc)) {
- Diag(EndLoc, diag::warn_attribute_method_def);
- Diag(MethodLoc, diag::note_method_declared_at)
+ ObjCMethod->addAttr(ObjCRequiresSuperAttr::CreateImplicit(Context,
+ ObjCMethod->getLocation()));
+ }
+ if (isa<ObjCCategoryImplDecl>(ImpDecl)) {
+ ObjCMethodFamily family =
+ ObjCMethod->getSelector().getMethodFamily();
+ if (family == OMF_dealloc && IMD && IMD->isOverriding())
+ Diag(ObjCMethod->getLocation(), diag::warn_dealloc_in_category)
<< ObjCMethod->getDeclName();
- }
}
} else {
cast<DeclContext>(ClassDecl)->addDecl(ObjCMethod);
@@ -3482,8 +3437,6 @@ void Sema::DiagnoseUseOfUnimplementedSelectors() {
ReferencedSelectors[Sels[I].first] = Sels[I].second;
}
- DiagnoseMismatchedMethodsInGlobalPool();
-
// Warning will be issued only when selector table is
// generated (which means there is at lease one implementation
// in the TU). This is to match gcc's behavior.
@@ -3503,39 +3456,93 @@ void Sema::DiagnoseUseOfUnimplementedSelectors() {
ObjCIvarDecl *
Sema::GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method,
const ObjCPropertyDecl *&PDecl) const {
-
+ if (Method->isClassMethod())
+ return nullptr;
const ObjCInterfaceDecl *IDecl = Method->getClassInterface();
if (!IDecl)
- return 0;
- Method = IDecl->lookupMethod(Method->getSelector(), true);
+ return nullptr;
+ Method = IDecl->lookupMethod(Method->getSelector(), /*isInstance=*/true,
+ /*shallowCategoryLookup=*/false,
+ /*followSuper=*/false);
if (!Method || !Method->isPropertyAccessor())
- return 0;
- if ((PDecl = Method->findPropertyDecl())) {
- if (!PDecl->getDeclContext())
- return 0;
- // Make sure property belongs to accessor's class and not to
- // one of its super classes.
- if (const ObjCInterfaceDecl *CID =
- dyn_cast<ObjCInterfaceDecl>(PDecl->getDeclContext()))
- if (CID != IDecl)
- return 0;
- return PDecl->getPropertyIvarDecl();
- }
- return 0;
-}
-
-void Sema::DiagnoseUnusedBackingIvarInAccessor(Scope *S) {
- if (S->hasUnrecoverableErrorOccurred() || !S->isInObjcMethodScope())
- return;
-
- const ObjCMethodDecl *CurMethod = getCurMethodDecl();
- if (!CurMethod)
+ return nullptr;
+ if ((PDecl = Method->findPropertyDecl()))
+ if (ObjCIvarDecl *IV = PDecl->getPropertyIvarDecl()) {
+ // property backing ivar must belong to property's class
+ // or be a private ivar in class's implementation.
+ // FIXME. fix the const-ness issue.
+ IV = const_cast<ObjCInterfaceDecl *>(IDecl)->lookupInstanceVariable(
+ IV->getIdentifier());
+ return IV;
+ }
+ return nullptr;
+}
+
+namespace {
+ /// Used by Sema::DiagnoseUnusedBackingIvarInAccessor to check if a property
+ /// accessor references the backing ivar.
+ class UnusedBackingIvarChecker :
+ public DataRecursiveASTVisitor<UnusedBackingIvarChecker> {
+ public:
+ Sema &S;
+ const ObjCMethodDecl *Method;
+ const ObjCIvarDecl *IvarD;
+ bool AccessedIvar;
+ bool InvokedSelfMethod;
+
+ UnusedBackingIvarChecker(Sema &S, const ObjCMethodDecl *Method,
+ const ObjCIvarDecl *IvarD)
+ : S(S), Method(Method), IvarD(IvarD),
+ AccessedIvar(false), InvokedSelfMethod(false) {
+ assert(IvarD);
+ }
+
+ bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
+ if (E->getDecl() == IvarD) {
+ AccessedIvar = true;
+ return false;
+ }
+ return true;
+ }
+
+ bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
+ if (E->getReceiverKind() == ObjCMessageExpr::Instance &&
+ S.isSelfExpr(E->getInstanceReceiver(), Method)) {
+ InvokedSelfMethod = true;
+ }
+ return true;
+ }
+ };
+}
+
+void Sema::DiagnoseUnusedBackingIvarInAccessor(Scope *S,
+ const ObjCImplementationDecl *ImplD) {
+ if (S->hasUnrecoverableErrorOccurred())
return;
- const ObjCPropertyDecl *PDecl;
- const ObjCIvarDecl *IV = GetIvarBackingPropertyAccessor(CurMethod, PDecl);
- if (IV && !IV->getBackingIvarReferencedInAccessor()) {
- Diag(getCurMethodDecl()->getLocation(), diag::warn_unused_property_backing_ivar)
- << IV->getDeclName();
- Diag(PDecl->getLocation(), diag::note_property_declare);
+
+ for (const auto *CurMethod : ImplD->instance_methods()) {
+ unsigned DIAG = diag::warn_unused_property_backing_ivar;
+ SourceLocation Loc = CurMethod->getLocation();
+ if (Diags.isIgnored(DIAG, Loc))
+ continue;
+
+ const ObjCPropertyDecl *PDecl;
+ const ObjCIvarDecl *IV = GetIvarBackingPropertyAccessor(CurMethod, PDecl);
+ if (!IV)
+ continue;
+
+ UnusedBackingIvarChecker Checker(*this, CurMethod, IV);
+ Checker.TraverseStmt(CurMethod->getBody());
+ if (Checker.AccessedIvar)
+ continue;
+
+ // Do not issue this warning if backing ivar is used somewhere and accessor
+ // implementation makes a self call. This is to prevent false positive in
+ // cases where the ivar is accessed by another method that the accessor
+ // delegates to.
+ if (!IV->isReferenced() || !Checker.InvokedSelfMethod) {
+ Diag(Loc, DIAG) << IV;
+ Diag(PDecl->getLocation(), diag::note_property_declare);
+ }
}
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
index 3e8f324..b92fcbd 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -12,13 +12,13 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
+#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
@@ -132,6 +132,25 @@ Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) {
return SourceDecl->getType()->castAs<FunctionProtoType>();
}
+void Sema::UpdateExceptionSpec(FunctionDecl *FD,
+ const FunctionProtoType::ExtProtoInfo &EPI) {
+ const FunctionProtoType *Proto = FD->getType()->castAs<FunctionProtoType>();
+
+ // Overwrite the exception spec and rebuild the function type.
+ FunctionProtoType::ExtProtoInfo NewEPI = Proto->getExtProtoInfo();
+ NewEPI.ExceptionSpecType = EPI.ExceptionSpecType;
+ NewEPI.NumExceptions = EPI.NumExceptions;
+ NewEPI.Exceptions = EPI.Exceptions;
+ NewEPI.NoexceptExpr = EPI.NoexceptExpr;
+ FD->setType(Context.getFunctionType(Proto->getReturnType(),
+ Proto->getParamTypes(), NewEPI));
+
+ // If we've fully resolved the exception specification, notify listeners.
+ if (!isUnresolvedExceptionSpec(EPI.ExceptionSpecType))
+ if (auto *Listener = getASTMutationListener())
+ Listener->ResolvedExceptionSpec(FD);
+}
+
/// Determine whether a function has an implicitly-generated exception
/// specification.
static bool hasImplicitExceptionSpec(FunctionDecl *Decl) {
@@ -140,10 +159,13 @@ static bool hasImplicitExceptionSpec(FunctionDecl *Decl) {
Decl->getDeclName().getCXXOverloadedOperator() != OO_Array_Delete)
return false;
- // If the user didn't declare the function, its exception specification must
- // be implicit.
+ // For a function that the user didn't declare:
+ // - if this is a destructor, its exception specification is implicit.
+ // - if this is 'operator delete' or 'operator delete[]', the exception
+ // specification is as-if an explicit exception specification was given
+ // (per [basic.stc.dynamic]p2).
if (!Decl->getTypeSourceInfo())
- return true;
+ return isa<CXXDestructorDecl>(Decl);
const FunctionProtoType *Ty =
Decl->getTypeSourceInfo()->getType()->getAs<FunctionProtoType>();
@@ -155,9 +177,13 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
bool IsOperatorNew = OO == OO_New || OO == OO_Array_New;
bool MissingExceptionSpecification = false;
bool MissingEmptyExceptionSpecification = false;
+
unsigned DiagID = diag::err_mismatched_exception_spec;
- if (getLangOpts().MicrosoftExt)
- DiagID = diag::warn_mismatched_exception_spec;
+ bool ReturnValueOnError = true;
+ if (getLangOpts().MicrosoftExt) {
+ DiagID = diag::ext_mismatched_exception_spec;
+ ReturnValueOnError = false;
+ }
// Check the types as written: they must match before any exception
// specification adjustment is applied.
@@ -182,9 +208,9 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
}
// The failure was something other than an missing exception
- // specification; return an error.
+ // specification; return an error, except in MS mode where this is a warning.
if (!MissingExceptionSpecification)
- return true;
+ return ReturnValueOnError;
const FunctionProtoType *NewProto =
New->getType()->castAs<FunctionProtoType>();
@@ -203,8 +229,8 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
Old->isExternC()) {
FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
EPI.ExceptionSpecType = EST_DynamicNone;
- QualType NewType = Context.getFunctionType(NewProto->getResultType(),
- NewProto->getArgTypes(), EPI);
+ QualType NewType = Context.getFunctionType(NewProto->getReturnType(),
+ NewProto->getParamTypes(), EPI);
New->setType(NewType);
return false;
}
@@ -224,8 +250,8 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
// Update the type of the function with the appropriate exception
// specification.
- QualType NewType = Context.getFunctionType(NewProto->getResultType(),
- NewProto->getArgTypes(), EPI);
+ QualType NewType = Context.getFunctionType(NewProto->getReturnType(),
+ NewProto->getParamTypes(), EPI);
New->setType(NewType);
// Warn about the lack of exception specification.
@@ -239,16 +265,13 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
case EST_Dynamic: {
OS << "throw(";
bool OnFirstException = true;
- for (FunctionProtoType::exception_iterator E = OldProto->exception_begin(),
- EEnd = OldProto->exception_end();
- E != EEnd;
- ++E) {
+ for (const auto &E : OldProto->exceptions()) {
if (OnFirstException)
OnFirstException = false;
else
OS << ", ";
- OS << E->getAsString(getPrintingPolicy());
+ OS << E.getAsString(getPrintingPolicy());
}
OS << ")";
break;
@@ -260,7 +283,8 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
case EST_ComputedNoexcept:
OS << "noexcept(";
- OldProto->getNoexceptExpr()->printPretty(OS, 0, getPrintingPolicy());
+ assert(OldProto->getNoexceptExpr() != nullptr && "Expected non-null Expr");
+ OldProto->getNoexceptExpr()->printPretty(OS, nullptr, getPrintingPolicy());
OS << ")";
break;
@@ -273,7 +297,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) {
TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens();
if (FunctionTypeLoc FTLoc = TL.getAs<FunctionTypeLoc>())
- FixItLoc = PP.getLocForEndOfToken(FTLoc.getLocalRangeEnd());
+ FixItLoc = getLocForEndOfToken(FTLoc.getLocalRangeEnd());
}
if (FixItLoc.isInvalid())
@@ -302,10 +326,14 @@ bool Sema::CheckEquivalentExceptionSpec(
const FunctionProtoType *New, SourceLocation NewLoc) {
unsigned DiagID = diag::err_mismatched_exception_spec;
if (getLangOpts().MicrosoftExt)
- DiagID = diag::warn_mismatched_exception_spec;
- return CheckEquivalentExceptionSpec(PDiag(DiagID),
- PDiag(diag::note_previous_declaration),
- Old, OldLoc, New, NewLoc);
+ DiagID = diag::ext_mismatched_exception_spec;
+ bool Result = CheckEquivalentExceptionSpec(PDiag(DiagID),
+ PDiag(diag::note_previous_declaration), Old, OldLoc, New, NewLoc);
+
+ // In Microsoft mode, mismatching exception specifications just cause a warning.
+ if (getLangOpts().MicrosoftExt)
+ return false;
+ return Result;
}
/// CheckEquivalentExceptionSpec - Check if the two types have compatible
@@ -428,7 +456,7 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
// throw(std::bad_alloc) as equivalent for operator new and operator new[].
// This is because the implicit declaration changed, but old code would break.
if (getLangOpts().CPlusPlus11 && IsOperatorNew) {
- const FunctionProtoType *WithExceptions = 0;
+ const FunctionProtoType *WithExceptions = nullptr;
if (OldEST == EST_None && NewEST == EST_Dynamic)
WithExceptions = New;
else if (OldEST == EST_Dynamic && NewEST == EST_None)
@@ -441,15 +469,8 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
IdentifierInfo* Name = ExRecord->getIdentifier();
if (Name && Name->getName() == "bad_alloc") {
// It's called bad_alloc, but is it in std?
- DeclContext* DC = ExRecord->getDeclContext();
- DC = DC->getEnclosingNamespaceContext();
- if (NamespaceDecl* NS = dyn_cast<NamespaceDecl>(DC)) {
- IdentifierInfo* NSName = NS->getIdentifier();
- DC = DC->getParent();
- if (NSName && NSName->getName() == "std" &&
- DC->getEnclosingNamespaceContext()->isTranslationUnit()) {
- return false;
- }
+ if (ExRecord->isInStdNamespace()) {
+ return false;
}
}
}
@@ -488,13 +509,11 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
// Both have a dynamic exception spec. Collect the first set, then compare
// to the second.
llvm::SmallPtrSet<CanQualType, 8> OldTypes, NewTypes;
- for (FunctionProtoType::exception_iterator I = Old->exception_begin(),
- E = Old->exception_end(); I != E; ++I)
- OldTypes.insert(Context.getCanonicalType(*I).getUnqualifiedType());
+ for (const auto &I : Old->exceptions())
+ OldTypes.insert(Context.getCanonicalType(I).getUnqualifiedType());
- for (FunctionProtoType::exception_iterator I = New->exception_begin(),
- E = New->exception_end(); I != E && Success; ++I) {
- CanQualType TypePtr = Context.getCanonicalType(*I).getUnqualifiedType();
+ for (const auto &I : New->exceptions()) {
+ CanQualType TypePtr = Context.getCanonicalType(I).getUnqualifiedType();
if(OldTypes.count(TypePtr))
NewTypes.insert(TypePtr);
else
@@ -602,10 +621,9 @@ bool Sema::CheckExceptionSpecSubset(
"Exception spec subset: non-dynamic case slipped through.");
// Neither contains everything or nothing. Do a proper comparison.
- for (FunctionProtoType::exception_iterator SubI = Subset->exception_begin(),
- SubE = Subset->exception_end(); SubI != SubE; ++SubI) {
+ for (const auto &SubI : Subset->exceptions()) {
// Take one type from the subset.
- QualType CanonicalSubT = Context.getCanonicalType(*SubI);
+ 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.
@@ -624,10 +642,8 @@ bool Sema::CheckExceptionSpecSubset(
bool Contained = false;
// Make sure it's in the superset.
- for (FunctionProtoType::exception_iterator SuperI =
- Superset->exception_begin(), SuperE = Superset->exception_end();
- SuperI != SuperE; ++SuperI) {
- QualType CanonicalSuperT = Context.getCanonicalType(*SuperI);
+ 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>())
@@ -711,23 +727,21 @@ bool Sema::CheckParamExceptionSpec(const PartialDiagnostic & NoteID,
const FunctionProtoType *Target, SourceLocation TargetLoc,
const FunctionProtoType *Source, SourceLocation SourceLoc)
{
- if (CheckSpecForTypesEquivalent(*this,
- PDiag(diag::err_deep_exception_specs_differ) << 0,
- PDiag(),
- Target->getResultType(), TargetLoc,
- Source->getResultType(), SourceLoc))
+ if (CheckSpecForTypesEquivalent(
+ *this, PDiag(diag::err_deep_exception_specs_differ) << 0, PDiag(),
+ Target->getReturnType(), TargetLoc, Source->getReturnType(),
+ SourceLoc))
return true;
// We shouldn't even be testing this unless the arguments are otherwise
// compatible.
- assert(Target->getNumArgs() == Source->getNumArgs() &&
+ assert(Target->getNumParams() == Source->getNumParams() &&
"Functions have different argument counts.");
- for (unsigned i = 0, E = Target->getNumArgs(); i != E; ++i) {
- if (CheckSpecForTypesEquivalent(*this,
- PDiag(diag::err_deep_exception_specs_differ) << 1,
- PDiag(),
- Target->getArgType(i), TargetLoc,
- Source->getArgType(i), SourceLoc))
+ for (unsigned i = 0, E = Target->getNumParams(); i != E; ++i) {
+ if (CheckSpecForTypesEquivalent(
+ *this, PDiag(diag::err_deep_exception_specs_differ) << 1, PDiag(),
+ Target->getParamType(i), TargetLoc, Source->getParamType(i),
+ SourceLoc))
return true;
}
return false;
@@ -773,7 +787,7 @@ bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
}
unsigned DiagID = diag::err_override_exception_spec;
if (getLangOpts().MicrosoftExt)
- DiagID = diag::warn_override_exception_spec;
+ DiagID = diag::ext_override_exception_spec;
return CheckExceptionSpecSubset(PDiag(DiagID),
PDiag(diag::note_overridden_virtual_function),
Old->getType()->getAs<FunctionProtoType>(),
@@ -1063,7 +1077,6 @@ CanThrowResult Sema::canThrow(const Expr *E) {
case Expr::AddrLabelExprClass:
case Expr::ArrayTypeTraitExprClass:
case Expr::AtomicExprClass:
- case Expr::BinaryTypeTraitExprClass:
case Expr::TypeTraitExprClass:
case Expr::CXXBoolLiteralExprClass:
case Expr::CXXNoexceptExprClass:
@@ -1086,7 +1099,6 @@ CanThrowResult Sema::canThrow(const Expr *E) {
case Expr::PredefinedExprClass:
case Expr::SizeOfPackExprClass:
case Expr::StringLiteralClass:
- case Expr::UnaryTypeTraitExprClass:
// These expressions can never throw.
return CT_Cannot;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
index e1f65f4..35dad82 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
@@ -59,8 +59,8 @@ bool Sema::CanUseDecl(NamedDecl *D) {
// If the function has a deduced return type, and we can't deduce it,
// then we can't use it either.
- if (getLangOpts().CPlusPlus1y && FD->getResultType()->isUndeducedType() &&
- DeduceReturnType(FD, SourceLocation(), /*Diagnose*/false))
+ if (getLangOpts().CPlusPlus1y && FD->getReturnType()->isUndeducedType() &&
+ DeduceReturnType(FD, SourceLocation(), /*Diagnose*/ false))
return false;
}
@@ -83,9 +83,16 @@ static void DiagnoseUnusedOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc) {
static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S,
NamedDecl *D, SourceLocation Loc,
- const ObjCInterfaceDecl *UnknownObjCClass) {
+ const ObjCInterfaceDecl *UnknownObjCClass,
+ bool ObjCPropertyAccess) {
// See if this declaration is unavailable or deprecated.
std::string Message;
+
+ // Forward class declarations get their attributes from their definition.
+ if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(D)) {
+ if (IDecl->getDefinition())
+ D = IDecl->getDefinition();
+ }
AvailabilityResult Result = D->getAvailability(&Message);
if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D))
if (Result == AR_Available) {
@@ -94,11 +101,11 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S,
Result = TheEnumDecl->getAvailability(&Message);
}
- const ObjCPropertyDecl *ObjCPDecl = 0;
+ const ObjCPropertyDecl *ObjCPDecl = nullptr;
if (Result == AR_Deprecated || Result == AR_Unavailable) {
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
if (const ObjCPropertyDecl *PD = MD->findPropertyDecl()) {
- AvailabilityResult PDeclResult = PD->getAvailability(0);
+ AvailabilityResult PDeclResult = PD->getAvailability(nullptr);
if (PDeclResult == Result)
ObjCPDecl = PD;
}
@@ -111,32 +118,19 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S,
break;
case AR_Deprecated:
- S.EmitDeprecationWarning(D, Message, Loc, UnknownObjCClass, ObjCPDecl);
+ if (S.getCurContextAvailability() != AR_Deprecated)
+ S.EmitAvailabilityWarning(Sema::AD_Deprecation,
+ D, Message, Loc, UnknownObjCClass, ObjCPDecl,
+ ObjCPropertyAccess);
break;
-
+
case AR_Unavailable:
- if (S.getCurContextAvailability() != AR_Unavailable) {
- if (Message.empty()) {
- if (!UnknownObjCClass) {
- S.Diag(Loc, diag::err_unavailable) << D->getDeclName();
- if (ObjCPDecl)
- S.Diag(ObjCPDecl->getLocation(), diag::note_property_attribute)
- << ObjCPDecl->getDeclName() << 1;
- }
- else
- S.Diag(Loc, diag::warn_unavailable_fwdclass_message)
- << D->getDeclName();
- }
- else
- S.Diag(Loc, diag::err_unavailable_message)
- << D->getDeclName() << Message;
- S.Diag(D->getLocation(), diag::note_unavailable_here)
- << isa<FunctionDecl>(D) << false;
- if (ObjCPDecl)
- S.Diag(ObjCPDecl->getLocation(), diag::note_property_attribute)
- << ObjCPDecl->getDeclName() << 1;
- }
+ if (S.getCurContextAvailability() != AR_Unavailable)
+ S.EmitAvailabilityWarning(Sema::AD_Unavailable,
+ D, Message, Loc, UnknownObjCClass, ObjCPDecl,
+ ObjCPropertyAccess);
break;
+
}
return Result;
}
@@ -176,16 +170,14 @@ void Sema::NoteDeletedFunction(FunctionDecl *Decl) {
}
}
- Diag(Decl->getLocation(), diag::note_unavailable_here)
- << 1 << true;
+ Diag(Decl->getLocation(), diag::note_availability_specified_here)
+ << Decl << true;
}
/// \brief Determine whether a FunctionDecl was ever declared with an
/// explicit storage class.
static bool hasAnyExplicitStorageClass(const FunctionDecl *D) {
- for (FunctionDecl::redecl_iterator I = D->redecls_begin(),
- E = D->redecls_end();
- I != E; ++I) {
+ for (auto I : D->redecls()) {
if (I->getStorageClass() != SC_None)
return true;
}
@@ -234,15 +226,14 @@ static void diagnoseUseOfInternalDeclInInlineFunction(Sema &S,
if (!DowngradeWarning && UsedFn)
DowngradeWarning = UsedFn->isInlined() || UsedFn->hasAttr<ConstAttr>();
- S.Diag(Loc, DowngradeWarning ? diag::ext_internal_in_extern_inline
- : diag::warn_internal_in_extern_inline)
+ S.Diag(Loc, DowngradeWarning ? diag::ext_internal_in_extern_inline_quiet
+ : diag::ext_internal_in_extern_inline)
<< /*IsVar=*/!UsedFn << D;
S.MaybeSuggestAddingStaticToDecl(Current);
- S.Diag(D->getCanonicalDecl()->getLocation(),
- diag::note_internal_decl_declared_here)
- << D;
+ S.Diag(D->getCanonicalDecl()->getLocation(), diag::note_entity_declared_at)
+ << D;
}
void Sema::MaybeSuggestAddingStaticToDecl(const FunctionDecl *Cur) {
@@ -269,7 +260,8 @@ void Sema::MaybeSuggestAddingStaticToDecl(const FunctionDecl *Cur) {
/// referenced), false otherwise.
///
bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
- const ObjCInterfaceDecl *UnknownObjCClass) {
+ const ObjCInterfaceDecl *UnknownObjCClass,
+ bool ObjCPropertyAccess) {
if (getLangOpts().CPlusPlus && isa<FunctionDecl>(D)) {
// If there were any diagnostics suppressed by template argument deduction,
// emit them now.
@@ -279,13 +271,18 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
SmallVectorImpl<PartialDiagnosticAt> &Suppressed = Pos->second;
for (unsigned I = 0, N = Suppressed.size(); I != N; ++I)
Diag(Suppressed[I].first, Suppressed[I].second);
-
+
// Clear out the list of suppressed diagnostics, so that we don't emit
// them again for this specialization. However, we don't obsolete this
// entry from the table, because we want to avoid ever emitting these
// diagnostics again.
Suppressed.clear();
}
+
+ // C++ [basic.start.main]p3:
+ // The function 'main' shall not be used within a program.
+ if (cast<FunctionDecl>(D)->isMain())
+ Diag(Loc, diag::ext_main_used);
}
// See if this is an auto-typed variable whose initializer we are parsing.
@@ -305,11 +302,11 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
// If the function has a deduced return type, and we can't deduce it,
// then we can't use it either.
- if (getLangOpts().CPlusPlus1y && FD->getResultType()->isUndeducedType() &&
+ if (getLangOpts().CPlusPlus1y && FD->getReturnType()->isUndeducedType() &&
DeduceReturnType(FD, Loc))
return true;
}
- DiagnoseAvailabilityOfDecl(*this, D, Loc, UnknownObjCClass);
+ DiagnoseAvailabilityOfDecl(*this, D, Loc, UnknownObjCClass, ObjCPropertyAccess);
DiagnoseUnusedOfDecl(*this, D, Loc);
@@ -354,7 +351,7 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
calleeType = CT_Function;
} else if (isa<VarDecl>(D)) {
QualType type = cast<ValueDecl>(D)->getType();
- const FunctionType *fn = 0;
+ const FunctionType *fn = nullptr;
if (const PointerType *ptr = type->getAs<PointerType>()) {
fn = ptr->getPointeeType()->getAs<FunctionType>();
if (!fn) return;
@@ -367,7 +364,7 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
}
if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(fn)) {
- numFormalParams = proto->getNumArgs();
+ numFormalParams = proto->getNumParams();
} else {
numFormalParams = 0;
}
@@ -438,16 +435,22 @@ ExprResult Sema::DefaultFunctionArrayConversion(Expr *E) {
if (E->getType()->isPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(E);
if (result.isInvalid()) return ExprError();
- E = result.take();
+ E = result.get();
}
QualType Ty = E->getType();
assert(!Ty.isNull() && "DefaultFunctionArrayConversion - missing type");
- if (Ty->isFunctionType())
+ if (Ty->isFunctionType()) {
+ // If we are here, we are not calling a function but taking
+ // its address (which is not allowed in OpenCL v1.0 s6.8.a.3).
+ if (getLangOpts().OpenCL) {
+ Diag(E->getExprLoc(), diag::err_opencl_taking_function_address);
+ return ExprError();
+ }
E = ImpCastExprToType(E, Context.getPointerType(Ty),
- CK_FunctionToPointerDecay).take();
- else if (Ty->isArrayType()) {
+ CK_FunctionToPointerDecay).get();
+ } else if (Ty->isArrayType()) {
// In C90 mode, arrays only promote to pointers if the array expression is
// an lvalue. The relevant legalese is C90 6.2.2.1p3: "an lvalue that has
// type 'array of type' is converted to an expression that has type 'pointer
@@ -461,9 +464,9 @@ ExprResult Sema::DefaultFunctionArrayConversion(Expr *E) {
//
if (getLangOpts().C99 || getLangOpts().CPlusPlus || E->isLValue())
E = ImpCastExprToType(E, Context.getArrayDecayedType(Ty),
- CK_ArrayToPointerDecay).take();
+ CK_ArrayToPointerDecay).get();
}
- return Owned(E);
+ return E;
}
static void CheckForNullPointerDereference(Sema &S, Expr *E) {
@@ -503,7 +506,7 @@ static void DiagnoseDirectIsaAccess(Sema &S, const ObjCIvarRefExpr *OIRE,
BaseType = BaseType->getPointeeType();
if (const ObjCObjectType *OTy = BaseType->getAs<ObjCObjectType>())
if (ObjCInterfaceDecl *IDecl = OTy->getInterface()) {
- ObjCInterfaceDecl *ClassDeclared = 0;
+ ObjCInterfaceDecl *ClassDeclared = nullptr;
ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared);
if (!ClassDeclared->getSuperClass()
&& (*ClassDeclared->ivar_begin()) == IV) {
@@ -546,13 +549,13 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
if (E->getType()->isPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(E);
if (result.isInvalid()) return ExprError();
- E = result.take();
+ E = result.get();
}
// C++ [conv.lval]p1:
// A glvalue of a non-function, non-array type T can be
// converted to a prvalue.
- if (!E->isGLValue()) return Owned(E);
+ if (!E->isGLValue()) return E;
QualType T = E->getType();
assert(!T.isNull() && "r-value conversion on typeless expression?");
@@ -563,7 +566,7 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
(E->getType() == Context.OverloadTy ||
T->isDependentType() ||
T->isRecordType()))
- return Owned(E);
+ return E;
// The C standard is actually really unclear on this point, and
// DR106 tells us what the result should be but not why. It's
@@ -571,7 +574,7 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
// lvalue-to-rvalue at all. Note that expressions of unqualified
// 'void' type are never l-values, but qualified void can be.
if (T->isVoidType())
- return Owned(E);
+ return E;
// OpenCL usually rejects direct accesses to values of 'half' type.
if (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp16 &&
@@ -596,8 +599,8 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
}
else if (const ObjCIvarRefExpr *OIRE =
dyn_cast<ObjCIvarRefExpr>(E->IgnoreParenCasts()))
- DiagnoseDirectIsaAccess(*this, OIRE, SourceLocation(), /* Expr*/0);
-
+ DiagnoseDirectIsaAccess(*this, OIRE, SourceLocation(), /* Expr*/nullptr);
+
// C++ [conv.lval]p1:
// [...] If T is a non-class type, the type of the prvalue is the
// cv-unqualified version of T. Otherwise, the type of the
@@ -618,16 +621,16 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
E->getType().getObjCLifetime() == Qualifiers::OCL_Weak)
ExprNeedsCleanups = true;
- ExprResult Res = Owned(ImplicitCastExpr::Create(Context, T, CK_LValueToRValue,
- E, 0, VK_RValue));
+ ExprResult Res = ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, E,
+ nullptr, VK_RValue);
// C11 6.3.2.1p2:
// ... if the lvalue has atomic type, the value has the non-atomic version
// of the type of the lvalue ...
if (const AtomicType *Atomic = T->getAs<AtomicType>()) {
T = Atomic->getValueType().getUnqualifiedType();
- Res = Owned(ImplicitCastExpr::Create(Context, T, CK_AtomicToNonAtomic,
- Res.get(), 0, VK_RValue));
+ Res = ImplicitCastExpr::Create(Context, T, CK_AtomicToNonAtomic, Res.get(),
+ nullptr, VK_RValue);
}
return Res;
@@ -637,12 +640,30 @@ ExprResult Sema::DefaultFunctionArrayLvalueConversion(Expr *E) {
ExprResult Res = DefaultFunctionArrayConversion(E);
if (Res.isInvalid())
return ExprError();
- Res = DefaultLvalueConversion(Res.take());
+ Res = DefaultLvalueConversion(Res.get());
if (Res.isInvalid())
return ExprError();
return Res;
}
+/// CallExprUnaryConversions - a special case of an unary conversion
+/// performed on a function designator of a call expression.
+ExprResult Sema::CallExprUnaryConversions(Expr *E) {
+ QualType Ty = E->getType();
+ ExprResult Res = E;
+ // Only do implicit cast for a function type, but not for a pointer
+ // to function type.
+ if (Ty->isFunctionType()) {
+ Res = ImpCastExprToType(E, Context.getPointerType(Ty),
+ CK_FunctionToPointerDecay).get();
+ if (Res.isInvalid())
+ return ExprError();
+ }
+ Res = DefaultLvalueConversion(Res.get());
+ if (Res.isInvalid())
+ return ExprError();
+ return Res.get();
+}
/// UsualUnaryConversions - Performs various conversions that are common to most
/// operators (C99 6.3). The conversions of array and function types are
@@ -654,14 +675,14 @@ ExprResult Sema::UsualUnaryConversions(Expr *E) {
ExprResult Res = DefaultFunctionArrayLvalueConversion(E);
if (Res.isInvalid())
return ExprError();
- E = Res.take();
+ E = Res.get();
QualType Ty = E->getType();
assert(!Ty.isNull() && "UsualUnaryConversions - missing type");
// Half FP have to be promoted to float unless it is natively supported
if (Ty->isHalfType() && !getLangOpts().NativeHalfType)
- return ImpCastExprToType(Res.take(), Context.FloatTy, CK_FloatingCast);
+ return ImpCastExprToType(Res.get(), Context.FloatTy, CK_FloatingCast);
// Try to perform integral promotions if the object has a theoretically
// promotable type.
@@ -682,16 +703,16 @@ ExprResult Sema::UsualUnaryConversions(Expr *E) {
QualType PTy = Context.isPromotableBitField(E);
if (!PTy.isNull()) {
- E = ImpCastExprToType(E, PTy, CK_IntegralCast).take();
- return Owned(E);
+ E = ImpCastExprToType(E, PTy, CK_IntegralCast).get();
+ return E;
}
if (Ty->isPromotableIntegerType()) {
QualType PT = Context.getPromotedIntegerType(Ty);
- E = ImpCastExprToType(E, PT, CK_IntegralCast).take();
- return Owned(E);
+ E = ImpCastExprToType(E, PT, CK_IntegralCast).get();
+ return E;
}
}
- return Owned(E);
+ return E;
}
/// DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that
@@ -705,14 +726,14 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) {
ExprResult Res = UsualUnaryConversions(E);
if (Res.isInvalid())
return ExprError();
- E = Res.take();
+ E = Res.get();
// If this is a 'float' or '__fp16' (CVR qualified or typedef) promote to
// double.
const BuiltinType *BTy = Ty->getAs<BuiltinType>();
if (BTy && (BTy->getKind() == BuiltinType::Half ||
BTy->getKind() == BuiltinType::Float))
- E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).take();
+ E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).get();
// C++ performs lvalue-to-rvalue conversion as a default argument
// promotion, even on class types, but note:
@@ -728,14 +749,13 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) {
if (getLangOpts().CPlusPlus && E->isGLValue() && !isUnevaluatedContext()) {
ExprResult Temp = PerformCopyInitialization(
InitializedEntity::InitializeTemporary(E->getType()),
- E->getExprLoc(),
- Owned(E));
+ E->getExprLoc(), E);
if (Temp.isInvalid())
return ExprError();
E = Temp.get();
}
- return Owned(E);
+ return E;
}
/// Determine the degree of POD-ness for an expression.
@@ -792,19 +812,25 @@ void Sema::checkVariadicArgument(const Expr *E, VariadicCallType CT) {
// Complain about passing non-POD types through varargs.
switch (VAK) {
- case VAK_Valid:
- break;
-
case VAK_ValidInCXX11:
DiagRuntimeBehavior(
- E->getLocStart(), 0,
+ E->getLocStart(), nullptr,
PDiag(diag::warn_cxx98_compat_pass_non_pod_arg_to_vararg)
- << E->getType() << CT);
+ << Ty << CT);
+ // Fall through.
+ case VAK_Valid:
+ if (Ty->isRecordType()) {
+ // This is unlikely to be what the user intended. If the class has a
+ // 'c_str' member function, the user probably meant to call that.
+ DiagRuntimeBehavior(E->getLocStart(), nullptr,
+ PDiag(diag::warn_pass_class_arg_to_vararg)
+ << Ty << CT << hasCStrMethod(E) << ".c_str()");
+ }
break;
case VAK_Undefined:
DiagRuntimeBehavior(
- E->getLocStart(), 0,
+ E->getLocStart(), nullptr,
PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
<< getLangOpts().CPlusPlus11 << Ty << CT);
break;
@@ -812,7 +838,7 @@ void Sema::checkVariadicArgument(const Expr *E, VariadicCallType CT) {
case VAK_Invalid:
if (Ty->isObjCObjectType())
DiagRuntimeBehavior(
- E->getLocStart(), 0,
+ E->getLocStart(), nullptr,
PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
<< Ty << CT);
else
@@ -838,14 +864,14 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,
ExprResult ExprRes = CheckPlaceholderExpr(E);
if (ExprRes.isInvalid())
return ExprError();
- E = ExprRes.take();
+ E = ExprRes.get();
}
}
ExprResult ExprRes = DefaultArgumentPromotion(E);
if (ExprRes.isInvalid())
return ExprError();
- E = ExprRes.take();
+ E = ExprRes.get();
// Diagnostics regarding non-POD argument types are
// emitted along with format string checking in Sema::CheckFunctionCall().
@@ -879,7 +905,7 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,
diag::err_call_incomplete_argument))
return ExprError();
- return Owned(E);
+ return E;
}
/// \brief Converts an integer to complex float type. Helper function of
@@ -896,12 +922,12 @@ static bool handleIntegerToComplexFloatConversion(Sema &S, ExprResult &IntExpr,
if (SkipCast) return false;
if (IntTy->isIntegerType()) {
QualType fpTy = cast<ComplexType>(ComplexTy)->getElementType();
- IntExpr = S.ImpCastExprToType(IntExpr.take(), fpTy, CK_IntegralToFloating);
- IntExpr = S.ImpCastExprToType(IntExpr.take(), ComplexTy,
+ IntExpr = S.ImpCastExprToType(IntExpr.get(), fpTy, CK_IntegralToFloating);
+ IntExpr = S.ImpCastExprToType(IntExpr.get(), ComplexTy,
CK_FloatingRealToComplex);
} else {
assert(IntTy->isComplexIntegerType());
- IntExpr = S.ImpCastExprToType(IntExpr.take(), ComplexTy,
+ IntExpr = S.ImpCastExprToType(IntExpr.get(), ComplexTy,
CK_IntegralComplexToFloatingComplex);
}
return false;
@@ -919,12 +945,12 @@ handleComplexFloatToComplexFloatConverstion(Sema &S, ExprResult &LHS,
if (order < 0) {
// _Complex float -> _Complex double
if (!IsCompAssign)
- LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_FloatingComplexCast);
+ LHS = S.ImpCastExprToType(LHS.get(), RHSType, CK_FloatingComplexCast);
return RHSType;
}
if (order > 0)
// _Complex float -> _Complex double
- RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_FloatingComplexCast);
+ RHS = S.ImpCastExprToType(RHS.get(), LHSType, CK_FloatingComplexCast);
return LHSType;
}
@@ -945,8 +971,8 @@ static QualType handleOtherComplexFloatConversion(Sema &S,
// float -> _Complex double
if (ConvertOtherExpr) {
QualType fp = cast<ComplexType>(ComplexTy)->getElementType();
- OtherExpr = S.ImpCastExprToType(OtherExpr.take(), fp, CK_FloatingCast);
- OtherExpr = S.ImpCastExprToType(OtherExpr.take(), ComplexTy,
+ OtherExpr = S.ImpCastExprToType(OtherExpr.get(), fp, CK_FloatingCast);
+ OtherExpr = S.ImpCastExprToType(OtherExpr.get(), ComplexTy,
CK_FloatingRealToComplex);
}
return ComplexTy;
@@ -958,12 +984,12 @@ static QualType handleOtherComplexFloatConversion(Sema &S,
// double -> _Complex double
if (ConvertOtherExpr)
- OtherExpr = S.ImpCastExprToType(OtherExpr.take(), result,
+ OtherExpr = S.ImpCastExprToType(OtherExpr.get(), result,
CK_FloatingRealToComplex);
// _Complex float -> _Complex double
if (ConvertComplexExpr && order < 0)
- ComplexExpr = S.ImpCastExprToType(ComplexExpr.take(), result,
+ ComplexExpr = S.ImpCastExprToType(ComplexExpr.get(), result,
CK_FloatingComplexCast);
return result;
@@ -1025,7 +1051,7 @@ static QualType handleIntToFloatConversion(Sema &S, ExprResult &FloatExpr,
if (IntTy->isIntegerType()) {
if (ConvertInt)
// Convert intExpr to the lhs floating point type.
- IntExpr = S.ImpCastExprToType(IntExpr.take(), FloatTy,
+ IntExpr = S.ImpCastExprToType(IntExpr.get(), FloatTy,
CK_IntegralToFloating);
return FloatTy;
}
@@ -1036,12 +1062,12 @@ static QualType handleIntToFloatConversion(Sema &S, ExprResult &FloatExpr,
// _Complex int -> _Complex float
if (ConvertInt)
- IntExpr = S.ImpCastExprToType(IntExpr.take(), result,
+ IntExpr = S.ImpCastExprToType(IntExpr.get(), result,
CK_IntegralComplexToFloatingComplex);
// float -> _Complex float
if (ConvertFloat)
- FloatExpr = S.ImpCastExprToType(FloatExpr.take(), result,
+ FloatExpr = S.ImpCastExprToType(FloatExpr.get(), result,
CK_FloatingRealToComplex);
return result;
@@ -1060,13 +1086,13 @@ static QualType handleFloatConversion(Sema &S, ExprResult &LHS,
if (LHSFloat && RHSFloat) {
int order = S.Context.getFloatingTypeOrder(LHSType, RHSType);
if (order > 0) {
- RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_FloatingCast);
+ RHS = S.ImpCastExprToType(RHS.get(), LHSType, CK_FloatingCast);
return LHSType;
}
assert(order < 0 && "illegal float comparison");
if (!IsCompAssign)
- LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_FloatingCast);
+ LHS = S.ImpCastExprToType(LHS.get(), RHSType, CK_FloatingCast);
return RHSType;
}
@@ -1108,29 +1134,29 @@ static QualType handleIntegerConversion(Sema &S, ExprResult &LHS,
if (LHSSigned == RHSSigned) {
// Same signedness; use the higher-ranked type
if (order >= 0) {
- RHS = (*doRHSCast)(S, RHS.take(), LHSType);
+ RHS = (*doRHSCast)(S, RHS.get(), LHSType);
return LHSType;
} else if (!IsCompAssign)
- LHS = (*doLHSCast)(S, LHS.take(), RHSType);
+ LHS = (*doLHSCast)(S, LHS.get(), RHSType);
return RHSType;
} else if (order != (LHSSigned ? 1 : -1)) {
// The unsigned type has greater than or equal rank to the
// signed type, so use the unsigned type
if (RHSSigned) {
- RHS = (*doRHSCast)(S, RHS.take(), LHSType);
+ RHS = (*doRHSCast)(S, RHS.get(), LHSType);
return LHSType;
} else if (!IsCompAssign)
- LHS = (*doLHSCast)(S, LHS.take(), RHSType);
+ LHS = (*doLHSCast)(S, LHS.get(), RHSType);
return RHSType;
} else if (S.Context.getIntWidth(LHSType) != S.Context.getIntWidth(RHSType)) {
// The two types are different widths; if we are here, that
// means the signed type is larger than the unsigned type, so
// use the signed type.
if (LHSSigned) {
- RHS = (*doRHSCast)(S, RHS.take(), LHSType);
+ RHS = (*doRHSCast)(S, RHS.get(), LHSType);
return LHSType;
} else if (!IsCompAssign)
- LHS = (*doLHSCast)(S, LHS.take(), RHSType);
+ LHS = (*doLHSCast)(S, LHS.get(), RHSType);
return RHSType;
} else {
// The signed type is higher-ranked than the unsigned type,
@@ -1139,9 +1165,9 @@ static QualType handleIntegerConversion(Sema &S, ExprResult &LHS,
// to the signed type.
QualType result =
S.Context.getCorrespondingUnsignedType(LHSSigned ? LHSType : RHSType);
- RHS = (*doRHSCast)(S, RHS.take(), result);
+ RHS = (*doRHSCast)(S, RHS.get(), result);
if (!IsCompAssign)
- LHS = (*doLHSCast)(S, LHS.take(), result);
+ LHS = (*doLHSCast)(S, LHS.get(), result);
return result;
}
}
@@ -1171,7 +1197,7 @@ static QualType handleComplexIntConversion(Sema &S, ExprResult &LHS,
handleIntegerConversion<doComplexIntegralCast, doIntegralCast>
(S, LHS, RHS, LHSEltType, RHSType, IsCompAssign);
QualType ComplexType = S.Context.getComplexType(ScalarType);
- RHS = S.ImpCastExprToType(RHS.take(), ComplexType,
+ RHS = S.ImpCastExprToType(RHS.get(), ComplexType,
CK_IntegralRealToComplex);
return ComplexType;
@@ -1186,7 +1212,7 @@ static QualType handleComplexIntConversion(Sema &S, ExprResult &LHS,
QualType ComplexType = S.Context.getComplexType(ScalarType);
if (!IsCompAssign)
- LHS = S.ImpCastExprToType(LHS.take(), ComplexType,
+ LHS = S.ImpCastExprToType(LHS.get(), ComplexType,
CK_IntegralRealToComplex);
return ComplexType;
}
@@ -1198,12 +1224,12 @@ static QualType handleComplexIntConversion(Sema &S, ExprResult &LHS,
QualType Sema::UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS,
bool IsCompAssign) {
if (!IsCompAssign) {
- LHS = UsualUnaryConversions(LHS.take());
+ LHS = UsualUnaryConversions(LHS.get());
if (LHS.isInvalid())
return QualType();
}
- RHS = UsualUnaryConversions(RHS.take());
+ RHS = UsualUnaryConversions(RHS.get());
if (RHS.isInvalid())
return QualType();
@@ -1235,7 +1261,7 @@ QualType Sema::UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS,
if (!LHSBitfieldPromoteTy.isNull())
LHSType = LHSBitfieldPromoteTy;
if (LHSType != LHSUnpromotedType && !IsCompAssign)
- LHS = ImpCastExprToType(LHS.take(), LHSType, CK_IntegralCast);
+ LHS = ImpCastExprToType(LHS.get(), LHSType, CK_IntegralCast);
// If both types are identical, no conversion is needed.
if (LHSType == RHSType)
@@ -1284,7 +1310,7 @@ Sema::ActOnGenericSelectionExpr(SourceLocation KeyLoc,
if (ArgTypes[i])
(void) GetTypeFromParser(ArgTypes[i], &Types[i]);
else
- Types[i] = 0;
+ Types[i] = nullptr;
}
ExprResult ER = CreateGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc,
@@ -1307,7 +1333,7 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc,
if (ControllingExpr->getType()->isPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(ControllingExpr);
if (result.isInvalid()) return ExprError();
- ControllingExpr = result.take();
+ ControllingExpr = result.get();
}
bool TypeErrorFound = false,
@@ -1369,10 +1395,9 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc,
// If we determined that the generic selection is result-dependent, don't
// try to compute the result expression.
if (IsResultDependent)
- return Owned(new (Context) GenericSelectionExpr(
- Context, KeyLoc, ControllingExpr,
- Types, Exprs,
- DefaultLoc, RParenLoc, ContainsUnexpandedParameterPack));
+ return new (Context) GenericSelectionExpr(
+ Context, KeyLoc, ControllingExpr, Types, Exprs, DefaultLoc, RParenLoc,
+ ContainsUnexpandedParameterPack);
SmallVector<unsigned, 1> CompatIndices;
unsigned DefaultIndex = -1U;
@@ -1424,11 +1449,9 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc,
unsigned ResultIndex =
CompatIndices.size() ? CompatIndices[0] : DefaultIndex;
- return Owned(new (Context) GenericSelectionExpr(
- Context, KeyLoc, ControllingExpr,
- Types, Exprs,
- DefaultLoc, RParenLoc, ContainsUnexpandedParameterPack,
- ResultIndex));
+ return new (Context) GenericSelectionExpr(
+ Context, KeyLoc, ControllingExpr, Types, Exprs, DefaultLoc, RParenLoc,
+ ContainsUnexpandedParameterPack, ResultIndex);
}
/// getUDSuffixLoc - Create a SourceLocation for a ud-suffix, given the
@@ -1476,16 +1499,15 @@ static ExprResult BuildCookedLiteralOperatorCall(Sema &S, Scope *Scope,
/// string.
///
ExprResult
-Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks,
- Scope *UDLScope) {
- assert(NumStringToks && "Must have at least one string!");
+Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) {
+ assert(!StringToks.empty() && "Must have at least one string!");
- StringLiteralParser Literal(StringToks, NumStringToks, PP);
+ StringLiteralParser Literal(StringToks, PP);
if (Literal.hadError)
return ExprError();
SmallVector<SourceLocation, 4> StringTokLocs;
- for (unsigned i = 0; i != NumStringToks; ++i)
+ for (unsigned i = 0; i != StringToks.size(); ++i)
StringTokLocs.push_back(StringToks[i].getLocation());
QualType CharTy = Context.CharTy;
@@ -1528,7 +1550,7 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks,
&StringTokLocs[0],
StringTokLocs.size());
if (Literal.getUDSuffix().empty())
- return Owned(Lit);
+ return Lit;
// We're building a user-defined literal.
IdentifierInfo *UDSuffix = &Context.Idents.get(Literal.getUDSuffix());
@@ -1643,7 +1665,7 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
NameInfo.getLoc(), Ty, VK, FoundD, TemplateArgs);
} else {
assert(!TemplateArgs && "No template arguments for non-variable"
- " template specialization referrences");
+ " template specialization references");
E = DeclRefExpr::Create(
Context,
SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc(),
@@ -1653,20 +1675,16 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
MarkDeclRefReferenced(E);
if (getLangOpts().ObjCARCWeak && isa<VarDecl>(D) &&
- Ty.getObjCLifetime() == Qualifiers::OCL_Weak) {
- DiagnosticsEngine::Level Level =
- Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
- E->getLocStart());
- if (Level != DiagnosticsEngine::Ignored)
+ Ty.getObjCLifetime() == Qualifiers::OCL_Weak &&
+ !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getLocStart()))
recordUseOfEvaluatedWeak(E);
- }
// Just in case we're building an illegal pointer-to-member.
FieldDecl *FD = dyn_cast<FieldDecl>(D);
if (FD && FD->isBitField())
E->setObjectKind(OK_BitField);
- return Owned(E);
+ return E;
}
/// Decomposes the given name into a DeclarationNameInfo, its location, and
@@ -1697,7 +1715,7 @@ Sema::DecomposeUnqualifiedId(const UnqualifiedId &Id,
TemplateArgs = &Buffer;
} else {
NameInfo = GetNameFromUnqualifiedId(Id);
- TemplateArgs = 0;
+ TemplateArgs = nullptr;
}
}
@@ -1724,7 +1742,7 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
// original lookup would not have found something because it was a
// dependent name.
DeclContext *DC = (SS.isEmpty() && !CallsUndergoingInstantiation.empty())
- ? CurContext : 0;
+ ? CurContext : nullptr;
while (DC) {
if (isa<CXXRecordDecl>(DC)) {
LookupQualifiedName(R, DC);
@@ -1748,8 +1766,8 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
// Give a code modification hint to insert 'this->'.
// TODO: fixit for inserting 'Base<T>::' in the other cases.
// Actually quite difficult!
- if (getLangOpts().MicrosoftMode)
- diagnostic = diag::warn_found_via_dependent_bases_lookup;
+ if (getLangOpts().MSVCCompat)
+ diagnostic = diag::ext_found_via_dependent_bases_lookup;
if (isInstance) {
Diag(R.getNameLoc(), diagnostic) << Name
<< FixItHint::CreateInsertion(R.getNameLoc(), "this->");
@@ -1782,9 +1800,9 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
CXXDependentScopeMemberExpr::Create(
Context, DepThis, DepThisType, true, SourceLocation(),
SS.getWithLocInContext(Context),
- ULE->getTemplateKeywordLoc(), 0,
+ ULE->getTemplateKeywordLoc(), nullptr,
R.getLookupNameInfo(),
- ULE->hasExplicitTemplateArgs() ? &TList : 0);
+ ULE->hasExplicitTemplateArgs() ? &TList : nullptr);
CallsUndergoingInstantiation.back()->setCallee(DepExpr);
} else {
Diag(R.getNameLoc(), diagnostic) << Name;
@@ -1814,7 +1832,7 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
// function definition declared at class scope then we must set
// DC to the lexical parent to be able to search into the parent
// class.
- if (getLangOpts().MicrosoftMode && isa<FunctionDecl>(DC) &&
+ if (getLangOpts().MSVCCompat && isa<FunctionDecl>(DC) &&
cast<FunctionDecl>(DC)->getFriendObjectKind() &&
DC->getLexicalParent()->isRecord())
DC = DC->getLexicalParent();
@@ -1825,7 +1843,7 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
// We didn't find anything, so try to correct for a typo.
TypoCorrection Corrected;
if (S && (Corrected = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(),
- S, &SS, CCC))) {
+ S, &SS, CCC, CTK_ErrorRecovery))) {
std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
bool DroppedSpecifier =
Corrected.WillReplaceSpecifier() && Name.getAsString() == CorrectedStr;
@@ -1836,7 +1854,8 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
NamedDecl *ND = Corrected.getCorrectionDecl();
if (ND) {
if (Corrected.isOverloaded()) {
- OverloadCandidateSet OCS(R.getNameLoc());
+ OverloadCandidateSet OCS(R.getNameLoc(),
+ OverloadCandidateSet::CSK_Normal);
OverloadCandidateSet::iterator Best;
for (TypoCorrection::decl_iterator CD = Corrected.begin(),
CDEnd = Corrected.end();
@@ -1863,6 +1882,17 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
}
}
R.addDecl(ND);
+ if (getLangOpts().CPlusPlus && ND->isCXXClassMember()) {
+ CXXRecordDecl *Record = nullptr;
+ if (Corrected.getCorrectionSpecifier()) {
+ const Type *Ty = Corrected.getCorrectionSpecifier()->getAsType();
+ Record = Ty->getAsCXXRecordDecl();
+ }
+ if (!Record)
+ Record = cast<CXXRecordDecl>(
+ ND->getDeclContext()->getRedeclContext());
+ R.setNamingClass(Record);
+ }
AcceptableWithRecovery =
isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND);
@@ -1913,6 +1943,53 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
return true;
}
+/// In Microsoft mode, if we are inside a template class whose parent class has
+/// dependent base classes, and we can't resolve an unqualified identifier, then
+/// assume the identifier is a member of a dependent base class. We can only
+/// recover successfully in static methods, instance methods, and other contexts
+/// where 'this' is available. This doesn't precisely match MSVC's
+/// instantiation model, but it's close enough.
+static Expr *
+recoverFromMSUnqualifiedLookup(Sema &S, ASTContext &Context,
+ DeclarationNameInfo &NameInfo,
+ SourceLocation TemplateKWLoc,
+ const TemplateArgumentListInfo *TemplateArgs) {
+ // Only try to recover from lookup into dependent bases in static methods or
+ // contexts where 'this' is available.
+ QualType ThisType = S.getCurrentThisType();
+ const CXXRecordDecl *RD = nullptr;
+ if (!ThisType.isNull())
+ RD = ThisType->getPointeeType()->getAsCXXRecordDecl();
+ else if (auto *MD = dyn_cast<CXXMethodDecl>(S.CurContext))
+ RD = MD->getParent();
+ if (!RD || !RD->hasAnyDependentBases())
+ return nullptr;
+
+ // Diagnose this as unqualified lookup into a dependent base class. If 'this'
+ // is available, suggest inserting 'this->' as a fixit.
+ SourceLocation Loc = NameInfo.getLoc();
+ auto DB = S.Diag(Loc, diag::ext_undeclared_unqual_id_with_dependent_base);
+ DB << NameInfo.getName() << RD;
+
+ if (!ThisType.isNull()) {
+ DB << FixItHint::CreateInsertion(Loc, "this->");
+ return CXXDependentScopeMemberExpr::Create(
+ Context, /*This=*/nullptr, ThisType, /*IsArrow=*/true,
+ /*Op=*/SourceLocation(), NestedNameSpecifierLoc(), TemplateKWLoc,
+ /*FirstQualifierInScope=*/nullptr, NameInfo, TemplateArgs);
+ }
+
+ // Synthesize a fake NNS that points to the derived class. This will
+ // perform name lookup during template instantiation.
+ CXXScopeSpec SS;
+ auto *NNS =
+ NestedNameSpecifier::Create(Context, nullptr, true, RD->getTypeForDecl());
+ SS.MakeTrivial(Context, NNS, SourceRange(Loc, Loc));
+ return DependentScopeDeclRefExpr::Create(
+ Context, SS.getWithLocInContext(Context), TemplateKWLoc, NameInfo,
+ TemplateArgs);
+}
+
ExprResult Sema::ActOnIdExpression(Scope *S,
CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
@@ -2000,77 +2077,59 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
if (E.isInvalid())
return ExprError();
- if (Expr *Ex = E.takeAs<Expr>())
- return Owned(Ex);
+ if (Expr *Ex = E.getAs<Expr>())
+ return Ex;
}
}
if (R.isAmbiguous())
return ExprError();
+ // This could be an implicitly declared function reference (legal in C90,
+ // extension in C99, forbidden in C++).
+ if (R.empty() && HasTrailingLParen && II && !getLangOpts().CPlusPlus) {
+ NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *II, S);
+ if (D) R.addDecl(D);
+ }
+
// Determine whether this name might be a candidate for
// argument-dependent lookup.
bool ADL = UseArgumentDependentLookup(SS, R, HasTrailingLParen);
if (R.empty() && !ADL) {
-
- // Otherwise, this could be an implicitly declared function reference (legal
- // in C90, extension in C99, forbidden in C++).
- if (HasTrailingLParen && II && !getLangOpts().CPlusPlus) {
- NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *II, S);
- if (D) R.addDecl(D);
+ if (SS.isEmpty() && getLangOpts().MSVCCompat) {
+ if (Expr *E = recoverFromMSUnqualifiedLookup(*this, Context, NameInfo,
+ TemplateKWLoc, TemplateArgs))
+ return E;
}
+ // Don't diagnose an empty lookup for inline assembly.
+ if (IsInlineAsmIdentifier)
+ return ExprError();
+
// If this name wasn't predeclared and if this is not a function
// call, diagnose the problem.
- if (R.empty()) {
- // In Microsoft mode, if we are inside a template class member function
- // whose parent class has dependent base classes, and we can't resolve
- // an identifier, then assume the identifier is a member of a dependent
- // base class. The goal is to postpone name lookup to instantiation time
- // to be able to search into the type dependent base classes.
- // FIXME: If we want 100% compatibility with MSVC, we will have delay all
- // unqualified name lookup. Any name lookup during template parsing means
- // clang might find something that MSVC doesn't. For now, we only handle
- // the common case of members of a dependent base class.
- if (getLangOpts().MicrosoftMode) {
- CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext);
- if (MD && MD->isInstance() && MD->getParent()->hasAnyDependentBases()) {
- assert(SS.isEmpty() && "qualifiers should be already handled");
- QualType ThisType = MD->getThisType(Context);
- // Since the 'this' expression is synthesized, we don't need to
- // perform the double-lookup check.
- NamedDecl *FirstQualifierInScope = 0;
- return Owned(CXXDependentScopeMemberExpr::Create(
- Context, /*This=*/0, ThisType, /*IsArrow=*/true,
- /*Op=*/SourceLocation(), SS.getWithLocInContext(Context),
- TemplateKWLoc, FirstQualifierInScope, NameInfo, TemplateArgs));
- }
- }
+ CorrectionCandidateCallback DefaultValidator;
+ DefaultValidator.IsAddressOfOperand = IsAddressOfOperand;
+ assert((!CCC || CCC->IsAddressOfOperand == IsAddressOfOperand) &&
+ "Typo correction callback misconfigured");
+ if (DiagnoseEmptyLookup(S, SS, R, CCC ? *CCC : DefaultValidator))
+ return ExprError();
- // Don't diagnose an empty lookup for inline assmebly.
- if (IsInlineAsmIdentifier)
- return ExprError();
+ assert(!R.empty() &&
+ "DiagnoseEmptyLookup returned false but added no results");
- CorrectionCandidateCallback DefaultValidator;
- if (DiagnoseEmptyLookup(S, SS, R, CCC ? *CCC : DefaultValidator))
+ // If we found an Objective-C instance variable, let
+ // LookupInObjCMethod build the appropriate expression to
+ // reference the ivar.
+ if (ObjCIvarDecl *Ivar = R.getAsSingle<ObjCIvarDecl>()) {
+ R.clear();
+ ExprResult E(LookupInObjCMethod(R, S, Ivar->getIdentifier()));
+ // In a hopelessly buggy code, Objective-C instance variable
+ // lookup fails and no expression will be built to reference it.
+ if (!E.isInvalid() && !E.get())
return ExprError();
-
- assert(!R.empty() &&
- "DiagnoseEmptyLookup returned false but added no results");
-
- // If we found an Objective-C instance variable, let
- // LookupInObjCMethod build the appropriate expression to
- // reference the ivar.
- if (ObjCIvarDecl *Ivar = R.getAsSingle<ObjCIvarDecl>()) {
- R.clear();
- ExprResult E(LookupInObjCMethod(R, S, Ivar->getIdentifier()));
- // In a hopelessly buggy code, Objective-C instance variable
- // lookup fails and no expression will be built to reference it.
- if (!E.isInvalid() && !E.get())
- return ExprError();
- return E;
- }
+ return E;
}
}
@@ -2145,11 +2204,12 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
ExprResult
Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
const DeclarationNameInfo &NameInfo,
- bool IsAddressOfOperand) {
+ bool IsAddressOfOperand,
+ TypeSourceInfo **RecoveryTSI) {
DeclContext *DC = computeDeclContext(SS, false);
if (!DC)
return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(),
- NameInfo, /*TemplateArgs=*/0);
+ NameInfo, /*TemplateArgs=*/nullptr);
if (RequireCompleteDeclContext(SS, DC))
return ExprError();
@@ -2162,7 +2222,7 @@ Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation)
return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(),
- NameInfo, /*TemplateArgs=*/0);
+ NameInfo, /*TemplateArgs=*/nullptr);
if (R.empty()) {
Diag(NameInfo.getLoc(), diag::err_no_member)
@@ -2170,6 +2230,41 @@ Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
return ExprError();
}
+ if (const TypeDecl *TD = R.getAsSingle<TypeDecl>()) {
+ // Diagnose a missing typename if this resolved unambiguously to a type in
+ // a dependent context. If we can recover with a type, downgrade this to
+ // a warning in Microsoft compatibility mode.
+ unsigned DiagID = diag::err_typename_missing;
+ if (RecoveryTSI && getLangOpts().MSVCCompat)
+ DiagID = diag::ext_typename_missing;
+ SourceLocation Loc = SS.getBeginLoc();
+ auto D = Diag(Loc, DiagID);
+ D << SS.getScopeRep() << NameInfo.getName().getAsString()
+ << SourceRange(Loc, NameInfo.getEndLoc());
+
+ // Don't recover if the caller isn't expecting us to or if we're in a SFINAE
+ // context.
+ if (!RecoveryTSI)
+ return ExprError();
+
+ // Only issue the fixit if we're prepared to recover.
+ D << FixItHint::CreateInsertion(Loc, "typename ");
+
+ // Recover by pretending this was an elaborated type.
+ QualType Ty = Context.getTypeDeclType(TD);
+ TypeLocBuilder TLB;
+ TLB.pushTypeSpec(Ty).setNameLoc(NameInfo.getLoc());
+
+ QualType ET = getElaboratedType(ETK_None, SS, Ty);
+ ElaboratedTypeLoc QTL = TLB.push<ElaboratedTypeLoc>(ET);
+ QTL.setElaboratedKeywordLoc(SourceLocation());
+ QTL.setQualifierLoc(SS.getWithLocInContext(Context));
+
+ *RecoveryTSI = TLB.getTypeSourceInfo(Context, ET);
+
+ return ExprEmpty();
+ }
+
// Defend against this resolving to an implicit member access. We usually
// won't get here if this might be a legitimate a class member (we end up in
// BuildMemberReferenceExpr instead), but this can be valid if we're forming
@@ -2177,7 +2272,7 @@ Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
if (!R.empty() && (*R.begin())->isCXXClassMember() && !IsAddressOfOperand)
return BuildPossibleImplicitMemberExpr(SS,
/*TemplateKWLoc=*/SourceLocation(),
- R, /*TemplateArgs=*/0);
+ R, /*TemplateArgs=*/nullptr);
return BuildDeclarationNameExpr(SS, R, /* ADL */ false);
}
@@ -2219,11 +2314,11 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
else
LookForIvars = (Lookup.isSingleResult() &&
Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod());
- ObjCInterfaceDecl *IFace = 0;
+ ObjCInterfaceDecl *IFace = nullptr;
if (LookForIvars) {
IFace = CurMethod->getClassInterface();
ObjCInterfaceDecl *ClassDeclared;
- ObjCIvarDecl *IV = 0;
+ ObjCIvarDecl *IV = nullptr;
if (IFace && (IV = IFace->lookupInstanceVariable(II, ClassDeclared))) {
// Diagnose using an ivar in a class method.
if (IsClassMethod)
@@ -2258,20 +2353,12 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
if (SelfExpr.isInvalid())
return ExprError();
- SelfExpr = DefaultLvalueConversion(SelfExpr.take());
+ SelfExpr = DefaultLvalueConversion(SelfExpr.get());
if (SelfExpr.isInvalid())
return ExprError();
MarkAnyDeclReferenced(Loc, IV, true);
- if (!IV->getBackingIvarReferencedInAccessor()) {
- // Mark this ivar 'referenced' in this method, if it is a backing ivar
- // of a property and current method is one of its property accessor.
- const ObjCPropertyDecl *PDecl;
- const ObjCIvarDecl *BIV = GetIvarBackingPropertyAccessor(CurMethod, PDecl);
- if (BIV && BIV == IV)
- IV->setBackingIvarReferencedInAccessor(true);
- }
-
+
ObjCMethodFamily MF = CurMethod->getMethodFamily();
if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize &&
!IvarBacksCurrentMethodAccessor(IFace, CurMethod, IV))
@@ -2279,14 +2366,12 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
ObjCIvarRefExpr *Result = new (Context) ObjCIvarRefExpr(IV, IV->getType(),
Loc, IV->getLocation(),
- SelfExpr.take(),
+ SelfExpr.get(),
true, true);
if (getLangOpts().ObjCAutoRefCount) {
if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
- DiagnosticsEngine::Level Level =
- Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, Loc);
- if (Level != DiagnosticsEngine::Ignored)
+ if (!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc))
recordUseOfEvaluatedWeak(Result);
}
if (CurContext->isClosure())
@@ -2294,7 +2379,7 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
<< FixItHint::CreateInsertion(Loc, "self->");
}
- return Owned(Result);
+ return Result;
}
} else if (CurMethod->isInstanceMethod()) {
// We should warn if a local variable hides an ivar.
@@ -2327,7 +2412,7 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
}
}
// Sentinel value saying that we didn't do anything special.
- return Owned((Expr*) 0);
+ return ExprResult((Expr *)nullptr);
}
/// \brief Cast a base object to a member's actual type.
@@ -2354,7 +2439,7 @@ Sema::PerformObjectMemberConversion(Expr *From,
NamedDecl *Member) {
CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Member->getDeclContext());
if (!RD)
- return Owned(From);
+ return From;
QualType DestRecordType;
QualType DestType;
@@ -2374,7 +2459,7 @@ Sema::PerformObjectMemberConversion(Expr *From,
}
} else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Member)) {
if (Method->isStatic())
- return Owned(From);
+ return From;
DestType = Method->getThisType(Context);
DestRecordType = DestType->getPointeeType();
@@ -2388,15 +2473,15 @@ Sema::PerformObjectMemberConversion(Expr *From,
}
} else {
// No conversion necessary.
- return Owned(From);
+ return From;
}
if (DestType->isDependentType() || FromType->isDependentType())
- return Owned(From);
+ return From;
// If the unqualified types are the same, no conversion is necessary.
if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType))
- return Owned(From);
+ return From;
SourceRange FromRange = From->getSourceRange();
SourceLocation FromLoc = FromRange.getBegin();
@@ -2439,7 +2524,7 @@ Sema::PerformObjectMemberConversion(Expr *From,
if (PointerConversions)
QType = Context.getPointerType(QType);
From = ImpCastExprToType(From, QType, CK_UncheckedDerivedToBase,
- VK, &BasePath).take();
+ VK, &BasePath).get();
FromType = QType;
FromRecordType = QRecordType;
@@ -2447,7 +2532,7 @@ Sema::PerformObjectMemberConversion(Expr *From,
// If the qualifier type was the same as the destination type,
// we're done.
if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType))
- return Owned(From);
+ return From;
}
}
@@ -2476,7 +2561,7 @@ Sema::PerformObjectMemberConversion(Expr *From,
if (PointerConversions)
UType = Context.getPointerType(UType);
From = ImpCastExprToType(From, UType, CK_UncheckedDerivedToBase,
- VK, &BasePath).take();
+ VK, &BasePath).get();
FromType = UType;
FromRecordType = URecordType;
}
@@ -2604,7 +2689,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
NeedsADL, R.isOverloadedResult(),
R.begin(), R.end());
- return Owned(ULE);
+ return ULE;
}
/// \brief Complete semantic analysis for a reference to the given declaration.
@@ -2755,7 +2840,7 @@ ExprResult Sema::BuildDeclarationNameExpr(
// If we're referring to a function with an __unknown_anytype
// result type, make the entire expression __unknown_anytype.
- if (fty->getResultType() == Context.UnknownAnyTy) {
+ if (fty->getReturnType() == Context.UnknownAnyTy) {
type = Context.UnknownAnyTy;
valueKind = VK_RValue;
break;
@@ -2774,7 +2859,7 @@ ExprResult Sema::BuildDeclarationNameExpr(
// type.
if (!cast<FunctionDecl>(VD)->hasPrototype() &&
isa<FunctionProtoType>(fty))
- type = Context.getFunctionNoProtoType(fty->getResultType(),
+ type = Context.getFunctionNoProtoType(fty->getReturnType(),
fty->getExtInfo());
// Functions are r-values in C.
@@ -2792,7 +2877,7 @@ ExprResult Sema::BuildDeclarationNameExpr(
// This should only be possible with a type written directly.
if (const FunctionProtoType *proto
= dyn_cast<FunctionProtoType>(VD->getType()))
- if (proto->getResultType() == Context.UnknownAnyTy) {
+ if (proto->getReturnType() == Context.UnknownAnyTy) {
type = Context.UnknownAnyTy;
valueKind = VK_RValue;
break;
@@ -2820,7 +2905,7 @@ ExprResult Sema::BuildDeclarationNameExpr(
ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
PredefinedExpr::IdentType IT) {
// Pick the current block, lambda, captured statement or function.
- Decl *currentDecl = 0;
+ Decl *currentDecl = nullptr;
if (const BlockScopeInfo *BSI = getCurBlock())
currentDecl = BSI->TheDecl;
else if (const LambdaScopeInfo *LSI = getCurLambda())
@@ -2851,7 +2936,7 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0);
}
- return Owned(new (Context) PredefinedExpr(Loc, ResTy, IT));
+ return new (Context) PredefinedExpr(Loc, ResTy, IT);
}
ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
@@ -2862,6 +2947,7 @@ ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
case tok::kw___func__: IT = PredefinedExpr::Func; break; // [C99 6.4.2.2]
case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break;
case tok::kw___FUNCDNAME__: IT = PredefinedExpr::FuncDName; break; // [MS]
+ case tok::kw___FUNCSIG__: IT = PredefinedExpr::FuncSig; break; // [MS]
case tok::kw_L__FUNCTION__: IT = PredefinedExpr::LFunction; break;
case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break;
}
@@ -2905,7 +2991,7 @@ ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) {
Tok.getLocation());
if (Literal.getUDSuffix().empty())
- return Owned(Lit);
+ return Lit;
// We're building a user-defined literal.
IdentifierInfo *UDSuffix = &Context.Idents.get(Literal.getUDSuffix());
@@ -2924,8 +3010,8 @@ ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) {
ExprResult Sema::ActOnIntegerConstant(SourceLocation Loc, uint64_t Val) {
unsigned IntSize = Context.getTargetInfo().getIntWidth();
- return Owned(IntegerLiteral::Create(Context, llvm::APInt(IntSize, Val),
- Context.IntTy, Loc));
+ return IntegerLiteral::Create(Context, llvm::APInt(IntSize, Val),
+ Context.IntTy, Loc);
}
static Expr *BuildFloatingLiteral(Sema &S, NumericLiteralParser &Literal,
@@ -3090,10 +3176,10 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
if (Ty == Context.DoubleTy) {
if (getLangOpts().SinglePrecisionConstants) {
- Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).take();
+ Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get();
} else if (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp64) {
Diag(Tok.getLocation(), diag::warn_double_const_requires_fp64);
- Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).take();
+ Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get();
}
}
} else if (!Literal.isIntegerLiteral()) {
@@ -3117,8 +3203,8 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
// may be wider than [u]intmax_t.
// FIXME: Actually, they don't. We seem to have accidentally invented the
// i128 suffix.
- if (Literal.isMicrosoftInteger && MaxWidth < 128 &&
- PP.getTargetInfo().hasInt128Type())
+ if (Literal.MicrosoftInteger == 128 && MaxWidth < 128 &&
+ Context.getTargetInfo().hasInt128Type())
MaxWidth = 128;
llvm::APInt ResultVal(MaxWidth, 0);
@@ -3138,7 +3224,22 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
// Check from smallest to largest, picking the smallest type we can.
unsigned Width = 0;
- if (!Literal.isLong && !Literal.isLongLong) {
+
+ // Microsoft specific integer suffixes are explicitly sized.
+ if (Literal.MicrosoftInteger) {
+ if (Literal.MicrosoftInteger > MaxWidth) {
+ // If this target doesn't support __int128, error and force to ull.
+ Diag(Tok.getLocation(), diag::err_int128_unsupported);
+ Width = MaxWidth;
+ Ty = Context.getIntMaxType();
+ } else {
+ Width = Literal.MicrosoftInteger;
+ Ty = Context.getIntTypeForBitwidth(Width,
+ /*Signed=*/!Literal.isUnsigned);
+ }
+ }
+
+ if (Ty.isNull() && !Literal.isLong && !Literal.isLongLong) {
// Are int/unsigned possibilities?
unsigned IntSize = Context.getTargetInfo().getIntWidth();
@@ -3185,22 +3286,11 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
Width = LongLongSize;
}
}
-
- // If it doesn't fit in unsigned long long, and we're using Microsoft
- // extensions, then its a 128-bit integer literal.
- if (Ty.isNull() && Literal.isMicrosoftInteger &&
- PP.getTargetInfo().hasInt128Type()) {
- if (Literal.isUnsigned)
- Ty = Context.UnsignedInt128Ty;
- else
- Ty = Context.Int128Ty;
- Width = 128;
- }
// If we still couldn't decide a type, we probably have something that
// does not fit in a signed long long, but has no U suffix.
if (Ty.isNull()) {
- Diag(Tok.getLocation(), diag::warn_integer_too_large_for_signed);
+ Diag(Tok.getLocation(), diag::ext_integer_too_large_for_signed);
Ty = Context.UnsignedLongLongTy;
Width = Context.getTargetInfo().getLongLongWidth();
}
@@ -3216,12 +3306,12 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
Res = new (Context) ImaginaryLiteral(Res,
Context.getComplexType(Res->getType()));
- return Owned(Res);
+ return Res;
}
ExprResult Sema::ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E) {
- assert((E != 0) && "ActOnParenExpr() missing expr");
- return Owned(new (Context) ParenExpr(L, R, E));
+ assert(E && "ActOnParenExpr() missing expr");
+ return new (Context) ParenExpr(L, R, E);
}
static bool CheckVecStepTraitOperandType(Sema &S, QualType T,
@@ -3259,9 +3349,12 @@ static bool CheckExtensionTraitOperandType(Sema &S, QualType T,
return false;
}
- // Allow sizeof(void)/alignof(void) as an extension.
+ // Allow sizeof(void)/alignof(void) as an extension, unless in OpenCL where
+ // this is an error (OpenCL v1.1 s6.3.k)
if (T->isVoidType()) {
- S.Diag(Loc, diag::ext_sizeof_alignof_void_type) << TraitKind << ArgRange;
+ unsigned DiagID = S.LangOpts.OpenCL ? diag::err_opencl_sizeof_alignof_type
+ : diag::ext_sizeof_alignof_void_type;
+ S.Diag(Loc, DiagID) << TraitKind << ArgRange;
return false;
}
@@ -3302,7 +3395,7 @@ static void warnOnSizeofOnArrayDecay(Sema &S, SourceLocation Loc, QualType T,
<< ICE->getSubExpr()->getType();
}
-/// \brief Check the constrains on expression operands to unary type expression
+/// \brief Check the constraints on expression operands to unary type expression
/// and type traits.
///
/// Completes any types necessary and validates the constraints on the operand
@@ -3323,10 +3416,21 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
E->getSourceRange(), ExprKind))
return false;
- if (RequireCompleteExprType(E,
- diag::err_sizeof_alignof_incomplete_type,
- ExprKind, E->getSourceRange()))
- return true;
+ // 'alignof' applied to an expression only requires the base element type of
+ // the expression to be complete. 'sizeof' requires the expression's type to
+ // be complete (and will attempt to complete it if it's an array of unknown
+ // bound).
+ if (ExprKind == UETT_AlignOf) {
+ if (RequireCompleteType(E->getExprLoc(),
+ Context.getBaseElementType(E->getType()),
+ diag::err_sizeof_alignof_incomplete_type, ExprKind,
+ E->getSourceRange()))
+ return true;
+ } else {
+ if (RequireCompleteExprType(E, diag::err_sizeof_alignof_incomplete_type,
+ ExprKind, E->getSourceRange()))
+ return true;
+ }
// Completing the expression's type may have changed it.
ExprTy = E->getType();
@@ -3391,13 +3495,21 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType,
if (ExprType->isDependentType())
return false;
- // C++ [expr.sizeof]p2: "When applied to a reference or a reference type,
- // the result is the size of the referenced type."
- // C++ [expr.alignof]p3: "When alignof is applied to a reference type, the
- // result shall be the alignment of the referenced type."
+ // C++ [expr.sizeof]p2:
+ // When applied to a reference or a reference type, the result
+ // is the size of the referenced type.
+ // C++11 [expr.alignof]p3:
+ // When alignof is applied to a reference type, the result
+ // shall be the alignment of the referenced type.
if (const ReferenceType *Ref = ExprType->getAs<ReferenceType>())
ExprType = Ref->getPointeeType();
+ // C11 6.5.3.4/3, C++11 [expr.alignof]p3:
+ // When alignof or _Alignof is applied to an array type, the result
+ // is the alignment of the element type.
+ if (ExprKind == UETT_AlignOf)
+ ExprType = Context.getBaseElementType(ExprType);
+
if (ExprKind == UETT_VecStep)
return CheckVecStepTraitOperandType(*this, ExprType, OpLoc, ExprRange);
@@ -3437,7 +3549,7 @@ static bool CheckAlignOfExpr(Sema &S, Expr *E) {
return true;
}
- ValueDecl *D = 0;
+ ValueDecl *D = nullptr;
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
D = DRE->getDecl();
} else if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
@@ -3447,21 +3559,10 @@ static bool CheckAlignOfExpr(Sema &S, Expr *E) {
// If it's a field, require the containing struct to have a
// complete definition so that we can compute the layout.
//
- // This requires a very particular set of circumstances. For a
- // field to be contained within an incomplete type, we must in the
- // process of parsing that type. To have an expression refer to a
- // field, it must be an id-expression or a member-expression, but
- // the latter are always ill-formed when the base type is
- // incomplete, including only being partially complete. An
- // id-expression can never refer to a field in C because fields
- // are not in the ordinary namespace. In C++, an id-expression
- // can implicitly be a member access, but only if there's an
- // implicit 'this' value, and all such contexts are subject to
- // delayed parsing --- except for trailing return types in C++11.
- // And if an id-expression referring to a field occurs in a
- // context that lacks a 'this' value, it's ill-formed --- except,
- // agian, in C++11, where such references are allowed in an
- // unevaluated context. So C++11 introduces some new complexity.
+ // This can happen in C++11 onwards, either by naming the member
+ // in a way that is not transformed into a member access expression
+ // (in an unevaluated operand, for instance), or by naming the member
+ // in a trailing-return-type.
//
// For the record, since __alignof__ on expressions is a GCC
// extension, GCC seems to permit this but always gives the
@@ -3518,9 +3619,8 @@ Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
return ExprError();
// C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
- return Owned(new (Context) UnaryExprOrTypeTraitExpr(ExprKind, TInfo,
- Context.getSizeType(),
- OpLoc, R.getEnd()));
+ return new (Context) UnaryExprOrTypeTraitExpr(
+ ExprKind, TInfo, Context.getSizeType(), OpLoc, R.getEnd());
}
/// \brief Build a sizeof or alignof expression given an expression
@@ -3555,13 +3655,12 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
if (ExprKind == UETT_SizeOf && E->getType()->isVariableArrayType()) {
PE = TransformToPotentiallyEvaluated(E);
if (PE.isInvalid()) return ExprError();
- E = PE.take();
+ E = PE.get();
}
// C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
- return Owned(new (Context) UnaryExprOrTypeTraitExpr(
- ExprKind, E, Context.getSizeType(), OpLoc,
- E->getSourceRange().getEnd()));
+ return new (Context) UnaryExprOrTypeTraitExpr(
+ ExprKind, E, Context.getSizeType(), OpLoc, E->getSourceRange().getEnd());
}
/// ActOnUnaryExprOrTypeTraitExpr - Handle @c sizeof(type) and @c sizeof @c
@@ -3572,7 +3671,7 @@ Sema::ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc,
UnaryExprOrTypeTrait ExprKind, bool IsType,
void *TyOrEx, const SourceRange &ArgRange) {
// If error parsing type, ignore.
- if (TyOrEx == 0) return ExprError();
+ if (!TyOrEx) return ExprError();
if (IsType) {
TypeSourceInfo *TInfo;
@@ -3592,7 +3691,7 @@ static QualType CheckRealImagOperand(Sema &S, ExprResult &V, SourceLocation Loc,
// _Real and _Imag are only l-values for normal l-values.
if (V.get()->getObjectKind() != OK_Ordinary) {
- V = S.DefaultLvalueConversion(V.take());
+ V = S.DefaultLvalueConversion(V.get());
if (V.isInvalid())
return QualType();
}
@@ -3634,7 +3733,7 @@ Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
// Since this might is a postfix expression, get rid of ParenListExprs.
ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Input);
if (Result.isInvalid()) return ExprError();
- Input = Result.take();
+ Input = Result.get();
return BuildUnaryOp(S, OpLoc, Opc, Input);
}
@@ -3663,7 +3762,7 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
if (isa<ParenListExpr>(base)) {
ExprResult result = MaybeConvertParenListExprToParenExpr(S, base);
if (result.isInvalid()) return ExprError();
- base = result.take();
+ base = result.get();
}
// Handle any non-overload placeholder types in the base and index
@@ -3674,21 +3773,19 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
if (base->getType()->isNonOverloadPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(base);
if (result.isInvalid()) return ExprError();
- base = result.take();
+ base = result.get();
}
if (idx->getType()->isNonOverloadPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(idx);
if (result.isInvalid()) return ExprError();
- idx = result.take();
+ idx = result.get();
}
// Build an unanalyzed expression if either operand is type-dependent.
if (getLangOpts().CPlusPlus &&
(base->isTypeDependent() || idx->isTypeDependent())) {
- return Owned(new (Context) ArraySubscriptExpr(base, idx,
- Context.DependentTy,
- VK_LValue, OK_Ordinary,
- rbLoc));
+ return new (Context) ArraySubscriptExpr(base, idx, Context.DependentTy,
+ VK_LValue, OK_Ordinary, rbLoc);
}
// Use C++ overloaded-operator rules if either operand has record
@@ -3720,12 +3817,12 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
ExprResult Result = DefaultFunctionArrayLvalueConversion(LHSExp);
if (Result.isInvalid())
return ExprError();
- LHSExp = Result.take();
+ LHSExp = Result.get();
}
ExprResult Result = DefaultFunctionArrayLvalueConversion(RHSExp);
if (Result.isInvalid())
return ExprError();
- RHSExp = Result.take();
+ RHSExp = Result.get();
QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType();
ExprValueKind VK = VK_LValue;
@@ -3753,7 +3850,8 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
// Use custom logic if this should be the pseudo-object subscript
// expression.
if (!LangOpts.isSubscriptPointerArithmetic())
- return BuildObjCSubscriptExpression(RLoc, BaseExpr, IndexExpr, 0, 0);
+ return BuildObjCSubscriptExpression(RLoc, BaseExpr, IndexExpr, nullptr,
+ nullptr);
ResultType = PTy->getPointeeType();
} else if (const PointerType *PTy = RHSTy->getAs<PointerType>()) {
@@ -3790,7 +3888,7 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
Diag(LHSExp->getLocStart(), diag::ext_subscript_non_lvalue) <<
LHSExp->getSourceRange();
LHSExp = ImpCastExprToType(LHSExp, Context.getArrayDecayedType(LHSTy),
- CK_ArrayToPointerDecay).take();
+ CK_ArrayToPointerDecay).get();
LHSTy = LHSExp->getType();
BaseExpr = LHSExp;
@@ -3801,7 +3899,7 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
Diag(RHSExp->getLocStart(), diag::ext_subscript_non_lvalue) <<
RHSExp->getSourceRange();
RHSExp = ImpCastExprToType(RHSExp, Context.getArrayDecayedType(RHSTy),
- CK_ArrayToPointerDecay).take();
+ CK_ArrayToPointerDecay).get();
RHSTy = RHSExp->getType();
BaseExpr = RHSExp;
@@ -3847,8 +3945,8 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
assert(VK == VK_RValue || LangOpts.CPlusPlus ||
!ResultType.isCForbiddenLValueType());
- return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp,
- ResultType, VK, OK, RLoc));
+ return new (Context)
+ ArraySubscriptExpr(LHSExp, RHSExp, ResultType, VK, OK, RLoc);
}
ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
@@ -3871,7 +3969,7 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
// Instantiate the expression.
MultiLevelTemplateArgumentList MutiLevelArgList
- = getTemplateInstantiationArgs(FD, 0, /*RelativeToPrimary=*/true);
+ = getTemplateInstantiationArgs(FD, nullptr, /*RelativeToPrimary=*/true);
InstantiatingTemplate Inst(*this, CallLoc, Param,
MutiLevelArgList.getInnermost());
@@ -3897,17 +3995,17 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
InitializationKind Kind
= InitializationKind::CreateCopy(Param->getLocation(),
/*FIXME:EqualLoc*/UninstExpr->getLocStart());
- Expr *ResultE = Result.takeAs<Expr>();
+ Expr *ResultE = Result.getAs<Expr>();
InitializationSequence InitSeq(*this, Entity, Kind, ResultE);
Result = InitSeq.Perform(*this, Entity, Kind, ResultE);
if (Result.isInvalid())
return ExprError();
- Expr *Arg = Result.takeAs<Expr>();
+ Expr *Arg = Result.getAs<Expr>();
CheckCompletedExpr(Arg, Param->getOuterLocStart());
// Build the default argument expression.
- return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param, Arg));
+ return CXXDefaultArgExpr::Create(Context, CallLoc, Param, Arg);
}
// If the default expression creates temporaries, we need to
@@ -3934,7 +4032,7 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
// as being "referenced".
MarkDeclarationsReferencedInExpr(Param->getDefaultArg(),
/*SkipLocalVariables=*/true);
- return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param));
+ return CXXDefaultArgExpr::Create(Context, CallLoc, Param);
}
@@ -3961,11 +4059,11 @@ namespace {
class FunctionCallCCC : public FunctionCallFilterCCC {
public:
FunctionCallCCC(Sema &SemaRef, const IdentifierInfo *FuncName,
- unsigned NumArgs, bool HasExplicitTemplateArgs)
- : FunctionCallFilterCCC(SemaRef, NumArgs, HasExplicitTemplateArgs),
+ unsigned NumArgs, MemberExpr *ME)
+ : FunctionCallFilterCCC(SemaRef, NumArgs, false, ME),
FunctionName(FuncName) {}
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
if (!candidate.getCorrectionSpecifier() ||
candidate.getCorrectionAsIdentifierInfo() != FunctionName) {
return false;
@@ -3979,17 +4077,21 @@ private:
};
}
-static TypoCorrection TryTypoCorrectionForCall(Sema &S,
- DeclarationNameInfo FuncName,
+static TypoCorrection TryTypoCorrectionForCall(Sema &S, Expr *Fn,
+ FunctionDecl *FDecl,
ArrayRef<Expr *> Args) {
- FunctionCallCCC CCC(S, FuncName.getName().getAsIdentifierInfo(),
- Args.size(), false);
- if (TypoCorrection Corrected =
- S.CorrectTypo(FuncName, Sema::LookupOrdinaryName,
- S.getScopeForContext(S.CurContext), NULL, CCC)) {
+ MemberExpr *ME = dyn_cast<MemberExpr>(Fn);
+ DeclarationName FuncName = FDecl->getDeclName();
+ SourceLocation NameLoc = ME ? ME->getMemberLoc() : Fn->getLocStart();
+ FunctionCallCCC CCC(S, FuncName.getAsIdentifierInfo(), Args.size(), ME);
+
+ if (TypoCorrection Corrected = S.CorrectTypo(
+ DeclarationNameInfo(FuncName, NameLoc), Sema::LookupOrdinaryName,
+ S.getScopeForContext(S.CurContext), nullptr, CCC,
+ Sema::CTK_ErrorRecovery)) {
if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
if (Corrected.isOverloaded()) {
- OverloadCandidateSet OCS(FuncName.getLoc());
+ OverloadCandidateSet OCS(NameLoc, OverloadCandidateSet::CSK_Normal);
OverloadCandidateSet::iterator Best;
for (TypoCorrection::decl_iterator CD = Corrected.begin(),
CDEnd = Corrected.end();
@@ -3998,7 +4100,7 @@ static TypoCorrection TryTypoCorrectionForCall(Sema &S,
S.AddOverloadCandidate(FD, DeclAccessPair::make(FD, AS_none), Args,
OCS);
}
- switch (OCS.BestViableFunction(S, FuncName.getLoc(), Best)) {
+ switch (OCS.BestViableFunction(S, NameLoc, Best)) {
case OR_Success:
ND = Best->Function;
Corrected.setCorrectionDecl(ND);
@@ -4037,9 +4139,9 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
// C99 6.5.2.2p7 - the arguments are implicitly converted, as if by
// assignment, to the types of the corresponding parameter, ...
- unsigned NumArgsInProto = Proto->getNumArgs();
+ unsigned NumParams = Proto->getNumParams();
bool Invalid = false;
- unsigned MinArgs = FDecl ? FDecl->getMinRequiredArguments() : NumArgsInProto;
+ unsigned MinArgs = FDecl ? FDecl->getMinRequiredArguments() : NumParams;
unsigned FnKind = Fn->getType()->isBlockPointerType()
? 1 /* block */
: (IsExecConfig ? 3 /* kernel function (exec config) */
@@ -4047,35 +4149,29 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
// If too few arguments are available (and we don't have default
// arguments for the remaining parameters), don't make the call.
- if (Args.size() < NumArgsInProto) {
+ if (Args.size() < NumParams) {
if (Args.size() < MinArgs) {
- MemberExpr *ME = dyn_cast<MemberExpr>(Fn);
TypoCorrection TC;
- if (FDecl && (TC = TryTypoCorrectionForCall(
- *this, DeclarationNameInfo(FDecl->getDeclName(),
- (ME ? ME->getMemberLoc()
- : Fn->getLocStart())),
- Args))) {
+ if (FDecl && (TC = TryTypoCorrectionForCall(*this, Fn, FDecl, Args))) {
unsigned diag_id =
- MinArgs == NumArgsInProto && !Proto->isVariadic()
+ MinArgs == NumParams && !Proto->isVariadic()
? diag::err_typecheck_call_too_few_args_suggest
: diag::err_typecheck_call_too_few_args_at_least_suggest;
diagnoseTypo(TC, PDiag(diag_id) << FnKind << MinArgs
<< static_cast<unsigned>(Args.size())
- << Fn->getSourceRange());
+ << TC.getCorrectionRange());
} else if (MinArgs == 1 && FDecl && FDecl->getParamDecl(0)->getDeclName())
- Diag(RParenLoc, MinArgs == NumArgsInProto && !Proto->isVariadic()
- ? diag::err_typecheck_call_too_few_args_one
- : diag::err_typecheck_call_too_few_args_at_least_one)
- << FnKind
- << FDecl->getParamDecl(0) << Fn->getSourceRange();
+ Diag(RParenLoc,
+ MinArgs == NumParams && !Proto->isVariadic()
+ ? diag::err_typecheck_call_too_few_args_one
+ : diag::err_typecheck_call_too_few_args_at_least_one)
+ << FnKind << FDecl->getParamDecl(0) << Fn->getSourceRange();
else
- Diag(RParenLoc, MinArgs == NumArgsInProto && !Proto->isVariadic()
- ? diag::err_typecheck_call_too_few_args
- : diag::err_typecheck_call_too_few_args_at_least)
- << FnKind
- << MinArgs << static_cast<unsigned>(Args.size())
- << Fn->getSourceRange();
+ Diag(RParenLoc, MinArgs == NumParams && !Proto->isVariadic()
+ ? diag::err_typecheck_call_too_few_args
+ : diag::err_typecheck_call_too_few_args_at_least)
+ << FnKind << MinArgs << static_cast<unsigned>(Args.size())
+ << Fn->getSourceRange();
// Emit the location of the prototype.
if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
@@ -4084,46 +4180,41 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
return true;
}
- Call->setNumArgs(Context, NumArgsInProto);
+ Call->setNumArgs(Context, NumParams);
}
// If too many are passed and not variadic, error on the extras and drop
// them.
- if (Args.size() > NumArgsInProto) {
+ if (Args.size() > NumParams) {
if (!Proto->isVariadic()) {
TypoCorrection TC;
- if (FDecl && (TC = TryTypoCorrectionForCall(
- *this, DeclarationNameInfo(FDecl->getDeclName(),
- Fn->getLocStart()),
- Args))) {
+ if (FDecl && (TC = TryTypoCorrectionForCall(*this, Fn, FDecl, Args))) {
unsigned diag_id =
- MinArgs == NumArgsInProto && !Proto->isVariadic()
+ MinArgs == NumParams && !Proto->isVariadic()
? diag::err_typecheck_call_too_many_args_suggest
: diag::err_typecheck_call_too_many_args_at_most_suggest;
- diagnoseTypo(TC, PDiag(diag_id) << FnKind << NumArgsInProto
+ diagnoseTypo(TC, PDiag(diag_id) << FnKind << NumParams
<< static_cast<unsigned>(Args.size())
- << Fn->getSourceRange());
- } else if (NumArgsInProto == 1 && FDecl &&
+ << TC.getCorrectionRange());
+ } else if (NumParams == 1 && FDecl &&
FDecl->getParamDecl(0)->getDeclName())
- Diag(Args[NumArgsInProto]->getLocStart(),
- MinArgs == NumArgsInProto
- ? diag::err_typecheck_call_too_many_args_one
- : diag::err_typecheck_call_too_many_args_at_most_one)
- << FnKind
- << FDecl->getParamDecl(0) << static_cast<unsigned>(Args.size())
- << Fn->getSourceRange()
- << SourceRange(Args[NumArgsInProto]->getLocStart(),
- Args.back()->getLocEnd());
+ Diag(Args[NumParams]->getLocStart(),
+ MinArgs == NumParams
+ ? diag::err_typecheck_call_too_many_args_one
+ : diag::err_typecheck_call_too_many_args_at_most_one)
+ << FnKind << FDecl->getParamDecl(0)
+ << static_cast<unsigned>(Args.size()) << Fn->getSourceRange()
+ << SourceRange(Args[NumParams]->getLocStart(),
+ Args.back()->getLocEnd());
else
- Diag(Args[NumArgsInProto]->getLocStart(),
- MinArgs == NumArgsInProto
- ? diag::err_typecheck_call_too_many_args
- : diag::err_typecheck_call_too_many_args_at_most)
- << FnKind
- << NumArgsInProto << static_cast<unsigned>(Args.size())
- << Fn->getSourceRange()
- << SourceRange(Args[NumArgsInProto]->getLocStart(),
- Args.back()->getLocEnd());
+ Diag(Args[NumParams]->getLocStart(),
+ MinArgs == NumParams
+ ? diag::err_typecheck_call_too_many_args
+ : diag::err_typecheck_call_too_many_args_at_most)
+ << FnKind << NumParams << static_cast<unsigned>(Args.size())
+ << Fn->getSourceRange()
+ << SourceRange(Args[NumParams]->getLocStart(),
+ Args.back()->getLocEnd());
// Emit the location of the prototype.
if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
@@ -4131,7 +4222,7 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
<< FDecl;
// This deletes the extra arguments.
- Call->setNumArgs(Context, NumArgsInProto);
+ Call->setNumArgs(Context, NumParams);
return true;
}
}
@@ -4149,28 +4240,21 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
return false;
}
-bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
- FunctionDecl *FDecl,
+bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl,
const FunctionProtoType *Proto,
- unsigned FirstProtoArg,
- ArrayRef<Expr *> Args,
+ unsigned FirstParam, ArrayRef<Expr *> Args,
SmallVectorImpl<Expr *> &AllArgs,
- VariadicCallType CallType,
- bool AllowExplicit,
+ VariadicCallType CallType, bool AllowExplicit,
bool IsListInitialization) {
- unsigned NumArgsInProto = Proto->getNumArgs();
- unsigned NumArgsToCheck = Args.size();
+ unsigned NumParams = Proto->getNumParams();
bool Invalid = false;
- if (Args.size() != NumArgsInProto)
- // Use default arguments for missing arguments
- NumArgsToCheck = NumArgsInProto;
unsigned ArgIx = 0;
// Continue to check argument types (even if we have too few/many args).
- for (unsigned i = FirstProtoArg; i != NumArgsToCheck; i++) {
- QualType ProtoArgType = Proto->getArgType(i);
+ for (unsigned i = FirstParam; i < NumParams; i++) {
+ QualType ProtoArgType = Proto->getParamType(i);
Expr *Arg;
- ParmVarDecl *Param;
+ ParmVarDecl *Param = FDecl ? FDecl->getParamDecl(i) : nullptr;
if (ArgIx < Args.size()) {
Arg = Args[ArgIx++];
@@ -4179,11 +4263,6 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
diag::err_call_incomplete_argument, Arg))
return true;
- // Pass the argument
- Param = 0;
- if (FDecl && i < FDecl->getNumParams())
- Param = FDecl->getParamDecl(i);
-
// Strip the unbridged-cast placeholder expression off, if applicable.
bool CFAudited = false;
if (Arg->getType() == Context.ARCUnbridgedCastTy &&
@@ -4195,34 +4274,31 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
(!Param || !Param->hasAttr<CFConsumedAttr>()))
CFAudited = true;
- InitializedEntity Entity = Param ?
- InitializedEntity::InitializeParameter(Context, Param, ProtoArgType)
- : InitializedEntity::InitializeParameter(Context, ProtoArgType,
- Proto->isArgConsumed(i));
-
+ InitializedEntity Entity =
+ Param ? InitializedEntity::InitializeParameter(Context, Param,
+ ProtoArgType)
+ : InitializedEntity::InitializeParameter(
+ Context, ProtoArgType, Proto->isParamConsumed(i));
+
// Remember that parameter belongs to a CF audited API.
if (CFAudited)
Entity.setParameterCFAudited();
-
- ExprResult ArgE = PerformCopyInitialization(Entity,
- SourceLocation(),
- Owned(Arg),
- IsListInitialization,
- AllowExplicit);
+
+ ExprResult ArgE = PerformCopyInitialization(
+ Entity, SourceLocation(), Arg, IsListInitialization, AllowExplicit);
if (ArgE.isInvalid())
return true;
- Arg = ArgE.takeAs<Expr>();
+ Arg = ArgE.getAs<Expr>();
} else {
- assert(FDecl && "can't use default arguments without a known callee");
- Param = FDecl->getParamDecl(i);
+ assert(Param && "can't use default arguments without a known callee");
ExprResult ArgExpr =
BuildCXXDefaultArgExpr(CallLoc, FDecl, Param);
if (ArgExpr.isInvalid())
return true;
- Arg = ArgExpr.takeAs<Expr>();
+ Arg = ArgExpr.getAs<Expr>();
}
// Check for array bounds violations for each argument to the call. This
@@ -4240,13 +4316,13 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
if (CallType != VariadicDoesNotApply) {
// Assume that extern "C" functions with variadic arguments that
// return __unknown_anytype aren't *really* variadic.
- if (Proto->getResultType() == Context.UnknownAnyTy &&
- FDecl && FDecl->isExternC()) {
+ if (Proto->getReturnType() == Context.UnknownAnyTy && FDecl &&
+ FDecl->isExternC()) {
for (unsigned i = ArgIx, e = Args.size(); i != e; ++i) {
QualType paramType; // ignored
ExprResult arg = checkUnknownAnyArg(CallLoc, Args[i], paramType);
Invalid |= arg.isInvalid();
- AllArgs.push_back(arg.take());
+ AllArgs.push_back(arg.get());
}
// Otherwise do argument promotion, (C99 6.5.2.2p7).
@@ -4255,7 +4331,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], CallType,
FDecl);
Invalid |= Arg.isInvalid();
- AllArgs.push_back(Arg.take());
+ AllArgs.push_back(Arg.get());
}
}
@@ -4377,7 +4453,7 @@ static bool checkArgsForPlaceholders(Sema &S, MultiExprArg args) {
if (isPlaceholderToRemoveAsArg(args[i]->getType())) {
ExprResult result = S.CheckPlaceholderExpr(args[i]);
if (result.isInvalid()) hasInvalid = true;
- else args[i] = result.take();
+ else args[i] = result.get();
}
}
return hasInvalid;
@@ -4393,7 +4469,7 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
// Since this might be a postfix expression, get rid of ParenListExprs.
ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Fn);
if (Result.isInvalid()) return ExprError();
- Fn = Result.take();
+ Fn = Result.get();
if (checkArgsForPlaceholders(*this, ArgExprs))
return ExprError();
@@ -4409,14 +4485,13 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
ArgExprs.back()->getLocEnd()));
}
- return Owned(new (Context) CallExpr(Context, Fn, None,
- Context.VoidTy, VK_RValue,
- RParenLoc));
+ return new (Context)
+ CallExpr(Context, Fn, None, Context.VoidTy, VK_RValue, RParenLoc);
}
if (Fn->getType() == Context.PseudoObjectTy) {
ExprResult result = CheckPlaceholderExpr(Fn);
if (result.isInvalid()) return ExprError();
- Fn = result.take();
+ Fn = result.get();
}
// Determine whether this is a dependent call inside a C++ template,
@@ -4431,25 +4506,24 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
if (Dependent) {
if (ExecConfig) {
- return Owned(new (Context) CUDAKernelCallExpr(
+ return new (Context) CUDAKernelCallExpr(
Context, Fn, cast<CallExpr>(ExecConfig), ArgExprs,
- Context.DependentTy, VK_RValue, RParenLoc));
+ Context.DependentTy, VK_RValue, RParenLoc);
} else {
- return Owned(new (Context) CallExpr(Context, Fn, ArgExprs,
- Context.DependentTy, VK_RValue,
- RParenLoc));
+ return new (Context) CallExpr(
+ Context, Fn, ArgExprs, Context.DependentTy, VK_RValue, RParenLoc);
}
}
// Determine whether this is a call to an object (C++ [over.call.object]).
if (Fn->getType()->isRecordType())
- return Owned(BuildCallToObjectOfClassType(S, Fn, LParenLoc,
- ArgExprs, RParenLoc));
+ return BuildCallToObjectOfClassType(S, Fn, LParenLoc, ArgExprs,
+ RParenLoc);
if (Fn->getType() == Context.UnknownAnyTy) {
ExprResult result = rebuildUnknownAnyFunction(*this, Fn);
if (result.isInvalid()) return ExprError();
- Fn = result.take();
+ Fn = result.get();
}
if (Fn->getType() == Context.BoundMemberTy) {
@@ -4479,12 +4553,12 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
if (Fn->getType() == Context.UnknownAnyTy) {
ExprResult result = rebuildUnknownAnyFunction(*this, Fn);
if (result.isInvalid()) return ExprError();
- Fn = result.take();
+ Fn = result.get();
}
Expr *NakedFn = Fn->IgnoreParens();
- NamedDecl *NDecl = 0;
+ NamedDecl *NDecl = nullptr;
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(NakedFn))
if (UnOp->getOpcode() == UO_AddrOf)
NakedFn = UnOp->getSubExpr()->IgnoreParens();
@@ -4494,6 +4568,21 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
else if (isa<MemberExpr>(NakedFn))
NDecl = cast<MemberExpr>(NakedFn)->getMemberDecl();
+ if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(NDecl)) {
+ if (FD->hasAttr<EnableIfAttr>()) {
+ if (const EnableIfAttr *Attr = CheckEnableIf(FD, ArgExprs, true)) {
+ Diag(Fn->getLocStart(),
+ isa<CXXMethodDecl>(FD) ?
+ diag::err_ovl_no_viable_member_function_in_call :
+ diag::err_ovl_no_viable_function_in_call)
+ << FD << FD->getSourceRange();
+ Diag(FD->getLocation(),
+ diag::note_ovl_candidate_disabled_by_enable_if_attr)
+ << Attr->getCond()->getSourceRange() << Attr->getMessage();
+ }
+ }
+ }
+
return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, ArgExprs, RParenLoc,
ExecConfig, IsExecConfig);
}
@@ -4511,7 +4600,7 @@ Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
ConfigDecl, false, ConfigQTy, VK_LValue, LLLLoc);
MarkFunctionReferenced(LLLLoc, ConfigDecl);
- return ActOnCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc, 0,
+ return ActOnCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc, nullptr,
/*IsExecConfig=*/true);
}
@@ -4532,8 +4621,7 @@ ExprResult Sema::ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy,
<< DstTy
<< SrcTy
<< E->getSourceRange());
- return Owned(new (Context) AsTypeExpr(E, DstTy, VK, OK, BuiltinLoc,
- RParenLoc));
+ return new (Context) AsTypeExpr(E, DstTy, VK, OK, BuiltinLoc, RParenLoc);
}
/// ActOnConvertVectorExpr - create a new convert-vector expression from the
@@ -4571,13 +4659,13 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
if (BuiltinID &&
Fn->getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn)) {
Result = ImpCastExprToType(Fn, Context.getPointerType(FDecl->getType()),
- CK_BuiltinFnToFnPtr).take();
+ CK_BuiltinFnToFnPtr).get();
} else {
- Result = UsualUnaryConversions(Fn);
+ Result = CallExprUnaryConversions(Fn);
}
if (Result.isInvalid())
return ExprError();
- Fn = Result.take();
+ Fn = Result.get();
// Make the call expr early, before semantic checks. This guarantees cleanup
// of arguments and function on error.
@@ -4601,7 +4689,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
// C99 6.5.2.2p1 - "The expression that denotes the called function shall
// have type pointer to function".
FuncT = PT->getPointeeType()->getAs<FunctionType>();
- if (FuncT == 0)
+ if (!FuncT)
return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
<< Fn->getType() << Fn->getSourceRange());
} else if (const BlockPointerType *BPT =
@@ -4612,7 +4700,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
if (Fn->getType() == Context.UnknownAnyTy) {
ExprResult rewrite = rebuildUnknownAnyFunction(*this, Fn);
if (rewrite.isInvalid()) return ExprError();
- Fn = rewrite.take();
+ Fn = rewrite.get();
TheCall->setCallee(Fn);
goto retry;
}
@@ -4629,7 +4717,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
<< FDecl->getName() << Fn->getSourceRange());
// CUDA: Kernel function must have 'void' return type
- if (!FuncT->getResultType()->isVoidType())
+ if (!FuncT->getReturnType()->isVoidType())
return ExprError(Diag(LParenLoc, diag::err_kern_type_not_void_return)
<< Fn->getType() << Fn->getSourceRange());
} else {
@@ -4641,14 +4729,13 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
}
// Check for a valid return type
- if (CheckCallReturnType(FuncT->getResultType(),
- Fn->getLocStart(), TheCall,
+ if (CheckCallReturnType(FuncT->getReturnType(), Fn->getLocStart(), TheCall,
FDecl))
return ExprError();
// We know the result type of the call, set it.
TheCall->setType(FuncT->getCallResultType(Context));
- TheCall->setValueKind(Expr::getValueKindForType(FuncT->getResultType()));
+ TheCall->setValueKind(Expr::getValueKindForType(FuncT->getReturnType()));
const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FuncT);
if (Proto) {
@@ -4661,7 +4748,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
if (FDecl) {
// Check if we have too few/too many template arguments, based
// on our knowledge of the function definition.
- const FunctionDecl *Def = 0;
+ const FunctionDecl *Def = nullptr;
if (FDecl->hasBody(Def) && Args.size() != Def->param_size()) {
Proto = Def->getType()->getAs<FunctionProtoType>();
if (!Proto || !(Proto->isVariadic() && Args.size() >= Def->param_size()))
@@ -4679,18 +4766,15 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
for (unsigned i = 0, e = Args.size(); i != e; i++) {
Expr *Arg = Args[i];
- if (Proto && i < Proto->getNumArgs()) {
- InitializedEntity Entity
- = InitializedEntity::InitializeParameter(Context,
- Proto->getArgType(i),
- Proto->isArgConsumed(i));
- ExprResult ArgE = PerformCopyInitialization(Entity,
- SourceLocation(),
- Owned(Arg));
+ if (Proto && i < Proto->getNumParams()) {
+ InitializedEntity Entity = InitializedEntity::InitializeParameter(
+ Context, Proto->getParamType(i), Proto->isParamConsumed(i));
+ ExprResult ArgE =
+ PerformCopyInitialization(Entity, SourceLocation(), Arg);
if (ArgE.isInvalid())
return true;
- Arg = ArgE.takeAs<Expr>();
+ Arg = ArgE.getAs<Expr>();
} else {
ExprResult ArgE = DefaultArgumentPromotion(Arg);
@@ -4698,7 +4782,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
if (ArgE.isInvalid())
return true;
- Arg = ArgE.takeAs<Expr>();
+ Arg = ArgE.getAs<Expr>();
}
if (RequireCompleteType(Arg->getLocStart(),
@@ -4785,7 +4869,7 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
return ExprError();
LiteralExpr = Result.get();
- bool isFileScope = getCurFunctionOrMethodDecl() == 0;
+ bool isFileScope = getCurFunctionOrMethodDecl() == nullptr;
if (isFileScope &&
!LiteralExpr->isTypeDependent() &&
!LiteralExpr->isValueDependent() &&
@@ -4815,7 +4899,7 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList,
// of one failure would be terrible for indexing/etc.
if (result.isInvalid()) continue;
- InitArgList[I] = result.take();
+ InitArgList[I] = result.get();
}
}
@@ -4825,7 +4909,7 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList,
InitListExpr *E = new (Context) InitListExpr(Context, LBraceLoc, InitArgList,
RBraceLoc);
E->setType(Context.VoidTy); // FIXME: just a place holder for now.
- return Owned(E);
+ return E;
}
/// Do an explicit extend of the given block pointer if we're in ARC.
@@ -4838,7 +4922,7 @@ static void maybeExtendBlockObject(Sema &S, ExprResult &E) {
E = ImplicitCastExpr::Create(S.Context, E.get()->getType(),
CK_ARCExtendBlockObject, E.get(),
- /*base path*/ 0, VK_RValue);
+ /*base path*/ nullptr, VK_RValue);
S.ExprNeedsCleanups = true;
}
@@ -4876,8 +4960,13 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
case Type::STK_BlockPointer:
case Type::STK_ObjCObjectPointer:
switch (DestTy->getScalarTypeKind()) {
- case Type::STK_CPointer:
+ case Type::STK_CPointer: {
+ unsigned SrcAS = SrcTy->getPointeeType().getAddressSpace();
+ unsigned DestAS = DestTy->getPointeeType().getAddressSpace();
+ if (SrcAS != DestAS)
+ return CK_AddressSpaceConversion;
return CK_BitCast;
+ }
case Type::STK_BlockPointer:
return (SrcKind == Type::STK_BlockPointer
? CK_BitCast : CK_AnyPointerToBlockPointerCast);
@@ -4917,12 +5006,12 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
case Type::STK_Floating:
return CK_IntegralToFloating;
case Type::STK_IntegralComplex:
- Src = ImpCastExprToType(Src.take(),
+ Src = ImpCastExprToType(Src.get(),
DestTy->castAs<ComplexType>()->getElementType(),
CK_IntegralCast);
return CK_IntegralRealToComplex;
case Type::STK_FloatingComplex:
- Src = ImpCastExprToType(Src.take(),
+ Src = ImpCastExprToType(Src.get(),
DestTy->castAs<ComplexType>()->getElementType(),
CK_IntegralToFloating);
return CK_FloatingRealToComplex;
@@ -4940,12 +5029,12 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
case Type::STK_Integral:
return CK_FloatingToIntegral;
case Type::STK_FloatingComplex:
- Src = ImpCastExprToType(Src.take(),
+ Src = ImpCastExprToType(Src.get(),
DestTy->castAs<ComplexType>()->getElementType(),
CK_FloatingCast);
return CK_FloatingRealToComplex;
case Type::STK_IntegralComplex:
- Src = ImpCastExprToType(Src.take(),
+ Src = ImpCastExprToType(Src.get(),
DestTy->castAs<ComplexType>()->getElementType(),
CK_FloatingToIntegral);
return CK_IntegralRealToComplex;
@@ -4968,13 +5057,13 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
QualType ET = SrcTy->castAs<ComplexType>()->getElementType();
if (Context.hasSameType(ET, DestTy))
return CK_FloatingComplexToReal;
- Src = ImpCastExprToType(Src.take(), ET, CK_FloatingComplexToReal);
+ Src = ImpCastExprToType(Src.get(), ET, CK_FloatingComplexToReal);
return CK_FloatingCast;
}
case Type::STK_Bool:
return CK_FloatingComplexToBoolean;
case Type::STK_Integral:
- Src = ImpCastExprToType(Src.take(),
+ Src = ImpCastExprToType(Src.get(),
SrcTy->castAs<ComplexType>()->getElementType(),
CK_FloatingComplexToReal);
return CK_FloatingToIntegral;
@@ -4997,13 +5086,13 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
QualType ET = SrcTy->castAs<ComplexType>()->getElementType();
if (Context.hasSameType(ET, DestTy))
return CK_IntegralComplexToReal;
- Src = ImpCastExprToType(Src.take(), ET, CK_IntegralComplexToReal);
+ Src = ImpCastExprToType(Src.get(), ET, CK_IntegralComplexToReal);
return CK_IntegralCast;
}
case Type::STK_Bool:
return CK_IntegralComplexToBoolean;
case Type::STK_Floating:
- Src = ImpCastExprToType(Src.take(),
+ Src = ImpCastExprToType(Src.get(),
SrcTy->castAs<ComplexType>()->getElementType(),
CK_IntegralComplexToReal);
return CK_IntegralToFloating;
@@ -5020,12 +5109,55 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
llvm_unreachable("Unhandled scalar cast");
}
+static bool breakDownVectorType(QualType type, uint64_t &len,
+ QualType &eltType) {
+ // Vectors are simple.
+ if (const VectorType *vecType = type->getAs<VectorType>()) {
+ len = vecType->getNumElements();
+ eltType = vecType->getElementType();
+ assert(eltType->isScalarType());
+ return true;
+ }
+
+ // We allow lax conversion to and from non-vector types, but only if
+ // they're real types (i.e. non-complex, non-pointer scalar types).
+ if (!type->isRealType()) return false;
+
+ len = 1;
+ eltType = type;
+ return true;
+}
+
+static bool VectorTypesMatch(Sema &S, QualType srcTy, QualType destTy) {
+ uint64_t srcLen, destLen;
+ QualType srcElt, destElt;
+ if (!breakDownVectorType(srcTy, srcLen, srcElt)) return false;
+ if (!breakDownVectorType(destTy, destLen, destElt)) return false;
+
+ // ASTContext::getTypeSize will return the size rounded up to a
+ // power of 2, so instead of using that, we need to use the raw
+ // element size multiplied by the element count.
+ uint64_t srcEltSize = S.Context.getTypeSize(srcElt);
+ uint64_t destEltSize = S.Context.getTypeSize(destElt);
+
+ return (srcLen * srcEltSize == destLen * destEltSize);
+}
+
+/// Is this a legal conversion between two known vector types?
+bool Sema::isLaxVectorConversion(QualType srcTy, QualType destTy) {
+ assert(destTy->isVectorType() || srcTy->isVectorType());
+
+ if (!Context.getLangOpts().LaxVectorConversions)
+ return false;
+ return VectorTypesMatch(*this, srcTy, destTy);
+}
+
bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
CastKind &Kind) {
assert(VectorTy->isVectorType() && "Not a vector type!");
if (Ty->isVectorType() || Ty->isIntegerType()) {
- if (Context.getTypeSize(VectorTy) != Context.getTypeSize(Ty))
+ if (!VectorTypesMatch(*this, Ty, VectorTy))
return Diag(R.getBegin(),
Ty->isVectorType() ?
diag::err_invalid_conversion_between_vectors :
@@ -5051,7 +5183,7 @@ ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy,
// In OpenCL, casts between vectors of different types are not allowed.
// (See OpenCL 6.2).
if (SrcTy->isVectorType()) {
- if (Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy)
+ if (!VectorTypesMatch(*this, SrcTy, DestTy)
|| (getLangOpts().OpenCL &&
(DestTy.getCanonicalType() != SrcTy.getCanonicalType()))) {
Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors)
@@ -5059,7 +5191,7 @@ ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy,
return ExprError();
}
Kind = CK_BitCast;
- return Owned(CastExpr);
+ return CastExpr;
}
// All non-pointer scalars can be cast to ExtVector type. The appropriate
@@ -5071,21 +5203,21 @@ ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy,
<< DestTy << SrcTy << R;
QualType DestElemTy = DestTy->getAs<ExtVectorType>()->getElementType();
- ExprResult CastExprRes = Owned(CastExpr);
+ ExprResult CastExprRes = CastExpr;
CastKind CK = PrepareScalarCast(CastExprRes, DestElemTy);
if (CastExprRes.isInvalid())
return ExprError();
- CastExpr = ImpCastExprToType(CastExprRes.take(), DestElemTy, CK).take();
+ CastExpr = ImpCastExprToType(CastExprRes.get(), DestElemTy, CK).get();
Kind = CK_VectorSplat;
- return Owned(CastExpr);
+ return CastExpr;
}
ExprResult
Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
Declarator &D, ParsedType &Ty,
SourceLocation RParenLoc, Expr *CastExpr) {
- assert(!D.isInvalidType() && (CastExpr != 0) &&
+ assert(!D.isInvalidType() && (CastExpr != nullptr) &&
"ActOnCastExpr(): missing type or expr");
TypeSourceInfo *castTInfo = GetTypeForDeclaratorCast(D, CastExpr->getType());
@@ -5134,9 +5266,17 @@ Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
if (isa<ParenListExpr>(CastExpr)) {
ExprResult Result = MaybeConvertParenListExprToParenExpr(S, CastExpr);
if (Result.isInvalid()) return ExprError();
- CastExpr = Result.take();
+ CastExpr = Result.get();
}
+ if (getLangOpts().CPlusPlus && !castType->isVoidType() &&
+ !getSourceManager().isInSystemMacro(LParenLoc))
+ Diag(LParenLoc, diag::warn_old_style_cast) << CastExpr->getSourceRange();
+
+ CheckTollFreeBridgeCast(castType, CastExpr);
+
+ CheckObjCBridgeRelatedCast(castType, CastExpr);
+
return BuildCStyleCastExpr(LParenLoc, castTInfo, RParenLoc, CastExpr);
}
@@ -5183,9 +5323,9 @@ ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc,
ExprResult Literal = DefaultLvalueConversion(exprs[0]);
if (Literal.isInvalid())
return ExprError();
- Literal = ImpCastExprToType(Literal.take(), ElemTy,
+ Literal = ImpCastExprToType(Literal.get(), ElemTy,
PrepareScalarCast(Literal, ElemTy));
- return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Literal.take());
+ return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Literal.get());
}
else if (numExprs < numElems) {
Diag(E->getExprLoc(),
@@ -5205,9 +5345,9 @@ ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc,
ExprResult Literal = DefaultLvalueConversion(exprs[0]);
if (Literal.isInvalid())
return ExprError();
- Literal = ImpCastExprToType(Literal.take(), ElemTy,
+ Literal = ImpCastExprToType(Literal.get(), ElemTy,
PrepareScalarCast(Literal, ElemTy));
- return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Literal.take());
+ return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Literal.get());
}
initExprs.append(exprs, exprs + numExprs);
@@ -5226,7 +5366,7 @@ ExprResult
Sema::MaybeConvertParenListExprToParenExpr(Scope *S, Expr *OrigExpr) {
ParenListExpr *E = dyn_cast<ParenListExpr>(OrigExpr);
if (!E)
- return Owned(OrigExpr);
+ return OrigExpr;
ExprResult Result(E->getExpr(0));
@@ -5243,7 +5383,7 @@ ExprResult Sema::ActOnParenListExpr(SourceLocation L,
SourceLocation R,
MultiExprArg Val) {
Expr *expr = new (Context) ParenListExpr(Context, L, Val, R);
- return Owned(expr);
+ return expr;
}
/// \brief Emit a specialized diagnostic when one expression is a null pointer
@@ -5324,8 +5464,8 @@ static bool checkConditionalConvertScalarsToVectors(Sema &S, ExprResult &LHS,
}
// Implicity convert these scalars to the type of the condition.
- LHS = S.ImpCastExprToType(LHS.take(), CondTy, CK_IntegralCast);
- RHS = S.ImpCastExprToType(RHS.take(), CondTy, CK_IntegralCast);
+ LHS = S.ImpCastExprToType(LHS.get(), CondTy, CK_IntegralCast);
+ RHS = S.ImpCastExprToType(RHS.get(), CondTy, CK_IntegralCast);
return false;
}
@@ -5341,8 +5481,8 @@ static QualType checkConditionalVoidType(Sema &S, ExprResult &LHS,
if (!RHSExpr->getType()->isVoidType())
S.Diag(LHSExpr->getLocStart(), diag::ext_typecheck_cond_one_void)
<< LHSExpr->getSourceRange();
- LHS = S.ImpCastExprToType(LHS.take(), S.Context.VoidTy, CK_ToVoid);
- RHS = S.ImpCastExprToType(RHS.take(), S.Context.VoidTy, CK_ToVoid);
+ LHS = S.ImpCastExprToType(LHS.get(), S.Context.VoidTy, CK_ToVoid);
+ RHS = S.ImpCastExprToType(RHS.get(), S.Context.VoidTy, CK_ToVoid);
return S.Context.VoidTy;
}
@@ -5355,7 +5495,7 @@ static bool checkConditionalNullPointer(Sema &S, ExprResult &NullExpr,
Expr::NPC_ValueDependentIsNull))
return true;
- NullExpr = S.ImpCastExprToType(NullExpr.take(), PointerTy, CK_NullToPointer);
+ NullExpr = S.ImpCastExprToType(NullExpr.get(), PointerTy, CK_NullToPointer);
return false;
}
@@ -5407,15 +5547,15 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS,
QualType CompositeTy = S.Context.mergeTypes(lhptee, rhptee);
if (CompositeTy.isNull()) {
- S.Diag(Loc, diag::warn_typecheck_cond_incompatible_pointers)
+ S.Diag(Loc, diag::ext_typecheck_cond_incompatible_pointers)
<< LHSTy << RHSTy << LHS.get()->getSourceRange()
<< RHS.get()->getSourceRange();
// In this situation, we assume void* type. No especially good
// reason, but this is what gcc does, and we do have to pick
// to get a consistent AST.
QualType incompatTy = S.Context.getPointerType(S.Context.VoidTy);
- LHS = S.ImpCastExprToType(LHS.take(), incompatTy, CK_BitCast);
- RHS = S.ImpCastExprToType(RHS.take(), incompatTy, CK_BitCast);
+ LHS = S.ImpCastExprToType(LHS.get(), incompatTy, CK_BitCast);
+ RHS = S.ImpCastExprToType(RHS.get(), incompatTy, CK_BitCast);
return incompatTy;
}
@@ -5426,11 +5566,41 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS,
else
ResultTy = S.Context.getPointerType(ResultTy);
- LHS = S.ImpCastExprToType(LHS.take(), ResultTy, CK_BitCast);
- RHS = S.ImpCastExprToType(RHS.take(), ResultTy, CK_BitCast);
+ LHS = S.ImpCastExprToType(LHS.get(), ResultTy, CK_BitCast);
+ RHS = S.ImpCastExprToType(RHS.get(), ResultTy, CK_BitCast);
return ResultTy;
}
+/// \brief Returns true if QT is quelified-id and implements 'NSObject' and/or
+/// 'NSCopying' protocols (and nothing else); or QT is an NSObject and optionally
+/// implements 'NSObject' and/or NSCopying' protocols (and nothing else).
+static bool isObjCPtrBlockCompatible(Sema &S, ASTContext &C, QualType QT) {
+ if (QT->isObjCIdType())
+ return true;
+
+ const ObjCObjectPointerType *OPT = QT->getAs<ObjCObjectPointerType>();
+ if (!OPT)
+ return false;
+
+ if (ObjCInterfaceDecl *ID = OPT->getInterfaceDecl())
+ if (ID->getIdentifier() != &C.Idents.get("NSObject"))
+ return false;
+
+ ObjCProtocolDecl* PNSCopying =
+ S.LookupProtocol(&C.Idents.get("NSCopying"), SourceLocation());
+ ObjCProtocolDecl* PNSObject =
+ S.LookupProtocol(&C.Idents.get("NSObject"), SourceLocation());
+
+ for (auto *Proto : OPT->quals()) {
+ if ((PNSCopying && declaresSameEntity(Proto, PNSCopying)) ||
+ (PNSObject && declaresSameEntity(Proto, PNSObject)))
+ ;
+ else
+ return false;
+ }
+ return true;
+}
+
/// \brief Return the resulting type when the operands are both block pointers.
static QualType checkConditionalBlockPointerCompatibility(Sema &S,
ExprResult &LHS,
@@ -5442,8 +5612,8 @@ static QualType checkConditionalBlockPointerCompatibility(Sema &S,
if (!LHSTy->isBlockPointerType() || !RHSTy->isBlockPointerType()) {
if (LHSTy->isVoidPointerType() || RHSTy->isVoidPointerType()) {
QualType destType = S.Context.getPointerType(S.Context.VoidTy);
- LHS = S.ImpCastExprToType(LHS.take(), destType, CK_BitCast);
- RHS = S.ImpCastExprToType(RHS.take(), destType, CK_BitCast);
+ LHS = S.ImpCastExprToType(LHS.get(), destType, CK_BitCast);
+ RHS = S.ImpCastExprToType(RHS.get(), destType, CK_BitCast);
return destType;
}
S.Diag(Loc, diag::err_typecheck_cond_incompatible_operands)
@@ -5476,9 +5646,9 @@ checkConditionalObjectPointersCompatibility(Sema &S, ExprResult &LHS,
= S.Context.getQualifiedType(lhptee, rhptee.getQualifiers());
QualType destType = S.Context.getPointerType(destPointee);
// Add qualifiers if necessary.
- LHS = S.ImpCastExprToType(LHS.take(), destType, CK_NoOp);
+ LHS = S.ImpCastExprToType(LHS.get(), destType, CK_NoOp);
// Promote to void*.
- RHS = S.ImpCastExprToType(RHS.take(), destType, CK_BitCast);
+ RHS = S.ImpCastExprToType(RHS.get(), destType, CK_BitCast);
return destType;
}
if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) {
@@ -5486,9 +5656,9 @@ checkConditionalObjectPointersCompatibility(Sema &S, ExprResult &LHS,
= S.Context.getQualifiedType(rhptee, lhptee.getQualifiers());
QualType destType = S.Context.getPointerType(destPointee);
// Add qualifiers if necessary.
- RHS = S.ImpCastExprToType(RHS.take(), destType, CK_NoOp);
+ RHS = S.ImpCastExprToType(RHS.get(), destType, CK_NoOp);
// Promote to void*.
- LHS = S.ImpCastExprToType(LHS.take(), destType, CK_BitCast);
+ LHS = S.ImpCastExprToType(LHS.get(), destType, CK_BitCast);
return destType;
}
@@ -5507,10 +5677,10 @@ static bool checkPointerIntegerMismatch(Sema &S, ExprResult &Int,
Expr *Expr1 = IsIntFirstExpr ? Int.get() : PointerExpr;
Expr *Expr2 = IsIntFirstExpr ? PointerExpr : Int.get();
- S.Diag(Loc, diag::warn_typecheck_cond_pointer_integer_mismatch)
+ S.Diag(Loc, diag::ext_typecheck_cond_pointer_integer_mismatch)
<< Expr1->getType() << Expr2->getType()
<< Expr1->getSourceRange() << Expr2->getSourceRange();
- Int = S.ImpCastExprToType(Int.take(), PointerExpr->getType(),
+ Int = S.ImpCastExprToType(Int.get(), PointerExpr->getType(),
CK_IntegralToPointer);
return true;
}
@@ -5539,7 +5709,7 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
OK = OK_Ordinary;
// First, check the condition.
- Cond = UsualUnaryConversions(Cond.take());
+ Cond = UsualUnaryConversions(Cond.get());
if (Cond.isInvalid())
return QualType();
if (checkCondition(*this, Cond.get()))
@@ -5645,34 +5815,34 @@ QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS,
// redefinition type if an attempt is made to access its fields.
if (LHSTy->isObjCClassType() &&
(Context.hasSameType(RHSTy, Context.getObjCClassRedefinitionType()))) {
- RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_CPointerToObjCPointerCast);
+ RHS = ImpCastExprToType(RHS.get(), LHSTy, CK_CPointerToObjCPointerCast);
return LHSTy;
}
if (RHSTy->isObjCClassType() &&
(Context.hasSameType(LHSTy, Context.getObjCClassRedefinitionType()))) {
- LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_CPointerToObjCPointerCast);
+ LHS = ImpCastExprToType(LHS.get(), RHSTy, CK_CPointerToObjCPointerCast);
return RHSTy;
}
// And the same for struct objc_object* / id
if (LHSTy->isObjCIdType() &&
(Context.hasSameType(RHSTy, Context.getObjCIdRedefinitionType()))) {
- RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_CPointerToObjCPointerCast);
+ RHS = ImpCastExprToType(RHS.get(), LHSTy, CK_CPointerToObjCPointerCast);
return LHSTy;
}
if (RHSTy->isObjCIdType() &&
(Context.hasSameType(LHSTy, Context.getObjCIdRedefinitionType()))) {
- LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_CPointerToObjCPointerCast);
+ LHS = ImpCastExprToType(LHS.get(), RHSTy, CK_CPointerToObjCPointerCast);
return RHSTy;
}
// And the same for struct objc_selector* / SEL
if (Context.isObjCSelType(LHSTy) &&
(Context.hasSameType(RHSTy, Context.getObjCSelRedefinitionType()))) {
- RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast);
+ RHS = ImpCastExprToType(RHS.get(), LHSTy, CK_BitCast);
return LHSTy;
}
if (Context.isObjCSelType(RHSTy) &&
(Context.hasSameType(LHSTy, Context.getObjCSelRedefinitionType()))) {
- LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_BitCast);
+ LHS = ImpCastExprToType(LHS.get(), RHSTy, CK_BitCast);
return RHSTy;
}
// Check constraints for Objective-C object pointers types.
@@ -5721,13 +5891,13 @@ QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS,
<< LHSTy << RHSTy
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
QualType incompatTy = Context.getObjCIdType();
- LHS = ImpCastExprToType(LHS.take(), incompatTy, CK_BitCast);
- RHS = ImpCastExprToType(RHS.take(), incompatTy, CK_BitCast);
+ LHS = ImpCastExprToType(LHS.get(), incompatTy, CK_BitCast);
+ RHS = ImpCastExprToType(RHS.get(), incompatTy, CK_BitCast);
return incompatTy;
}
// The object pointer types are compatible.
- LHS = ImpCastExprToType(LHS.take(), compositeType, CK_BitCast);
- RHS = ImpCastExprToType(RHS.take(), compositeType, CK_BitCast);
+ LHS = ImpCastExprToType(LHS.get(), compositeType, CK_BitCast);
+ RHS = ImpCastExprToType(RHS.get(), compositeType, CK_BitCast);
return compositeType;
}
// Check Objective-C object pointer types and 'void *'
@@ -5746,9 +5916,9 @@ QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS,
= Context.getQualifiedType(lhptee, rhptee.getQualifiers());
QualType destType = Context.getPointerType(destPointee);
// Add qualifiers if necessary.
- LHS = ImpCastExprToType(LHS.take(), destType, CK_NoOp);
+ LHS = ImpCastExprToType(LHS.get(), destType, CK_NoOp);
// Promote to void*.
- RHS = ImpCastExprToType(RHS.take(), destType, CK_BitCast);
+ RHS = ImpCastExprToType(RHS.get(), destType, CK_BitCast);
return destType;
}
if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) {
@@ -5766,9 +5936,9 @@ QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS,
= Context.getQualifiedType(rhptee, lhptee.getQualifiers());
QualType destType = Context.getPointerType(destPointee);
// Add qualifiers if necessary.
- RHS = ImpCastExprToType(RHS.take(), destType, CK_NoOp);
+ RHS = ImpCastExprToType(RHS.get(), destType, CK_NoOp);
// Promote to void*.
- LHS = ImpCastExprToType(LHS.take(), destType, CK_BitCast);
+ LHS = ImpCastExprToType(LHS.get(), destType, CK_BitCast);
return destType;
}
return QualType();
@@ -5900,9 +6070,9 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
Expr *RHSExpr) {
// If this is the gnu "x ?: y" extension, analyze the types as though the LHS
// was the condition.
- OpaqueValueExpr *opaqueValue = 0;
- Expr *commonExpr = 0;
- if (LHSExpr == 0) {
+ OpaqueValueExpr *opaqueValue = nullptr;
+ Expr *commonExpr = nullptr;
+ if (!LHSExpr) {
commonExpr = CondExpr;
// Lower out placeholder types first. This is important so that we don't
// try to capture a placeholder. This happens in few cases in C++; such
@@ -5910,7 +6080,7 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
if (commonExpr->hasPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(commonExpr);
if (!result.isUsable()) return ExprError();
- commonExpr = result.take();
+ commonExpr = result.get();
}
// We usually want to apply unary conversions *before* saving, except
// in the special case of a C++ l-value conditional.
@@ -5924,7 +6094,7 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
ExprResult commonRes = UsualUnaryConversions(commonExpr);
if (commonRes.isInvalid())
return ExprError();
- commonExpr = commonRes.take();
+ commonExpr = commonRes.get();
}
opaqueValue = new (Context) OpaqueValueExpr(commonExpr->getExprLoc(),
@@ -5937,7 +6107,7 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
ExprValueKind VK = VK_RValue;
ExprObjectKind OK = OK_Ordinary;
- ExprResult Cond = Owned(CondExpr), LHS = Owned(LHSExpr), RHS = Owned(RHSExpr);
+ ExprResult Cond = CondExpr, LHS = LHSExpr, RHS = RHSExpr;
QualType result = CheckConditionalOperands(Cond, LHS, RHS,
VK, OK, QuestionLoc);
if (result.isNull() || Cond.isInvalid() || LHS.isInvalid() ||
@@ -5948,14 +6118,13 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
RHS.get());
if (!commonExpr)
- return Owned(new (Context) ConditionalOperator(Cond.take(), QuestionLoc,
- LHS.take(), ColonLoc,
- RHS.take(), result, VK, OK));
+ return new (Context)
+ ConditionalOperator(Cond.get(), QuestionLoc, LHS.get(), ColonLoc,
+ RHS.get(), result, VK, OK);
- return Owned(new (Context)
- BinaryConditionalOperator(commonExpr, opaqueValue, Cond.take(), LHS.take(),
- RHS.take(), QuestionLoc, ColonLoc, result, VK,
- OK));
+ return new (Context) BinaryConditionalOperator(
+ commonExpr, opaqueValue, Cond.get(), LHS.get(), RHS.get(), QuestionLoc,
+ ColonLoc, result, VK, OK);
}
// checkPointerTypesForAssignment - This is a very tricky routine (despite
@@ -5971,15 +6140,16 @@ checkPointerTypesForAssignment(Sema &S, QualType LHSType, QualType RHSType) {
// get the "pointed to" type (ignoring qualifiers at the top level)
const Type *lhptee, *rhptee;
Qualifiers lhq, rhq;
- llvm::tie(lhptee, lhq) = cast<PointerType>(LHSType)->getPointeeType().split();
- llvm::tie(rhptee, rhq) = cast<PointerType>(RHSType)->getPointeeType().split();
+ std::tie(lhptee, lhq) =
+ cast<PointerType>(LHSType)->getPointeeType().split().asPair();
+ std::tie(rhptee, rhq) =
+ cast<PointerType>(RHSType)->getPointeeType().split().asPair();
Sema::AssignConvertType ConvTy = Sema::Compatible;
// C99 6.5.16.1p1: This following citation is common to constraints
// 3 & 4 (below). ...and the type *pointed to* by the left has all the
// qualifiers of the type *pointed to* by the right;
- Qualifiers lq;
// As a special case, 'non-__weak A *' -> 'non-__weak const *' is okay.
if (lhq.getObjCLifetime() != rhq.getObjCLifetime() &&
@@ -6206,7 +6376,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
if (result != Compatible)
return result;
if (Kind != CK_NoOp)
- RHS = ImpCastExprToType(RHS.take(), AtomicTy->getValueType(), Kind);
+ RHS = ImpCastExprToType(RHS.get(), AtomicTy->getValueType(), Kind);
Kind = CK_NonAtomicToAtomic;
return Compatible;
}
@@ -6237,7 +6407,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
QualType elType = cast<ExtVectorType>(LHSType)->getElementType();
if (elType != RHSType) {
Kind = PrepareScalarCast(RHS, elType);
- RHS = ImpCastExprToType(RHS.take(), elType, Kind);
+ RHS = ImpCastExprToType(RHS.get(), elType, Kind);
}
Kind = CK_VectorSplat;
return Compatible;
@@ -6257,8 +6427,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
// If we are allowing lax vector conversions, and LHS and RHS are both
// vectors, the total size only needs to be the same. This is a bitcast;
// no bits are changed but the result type is different.
- if (getLangOpts().LaxVectorConversions &&
- (Context.getTypeSize(LHSType) == Context.getTypeSize(RHSType))) {
+ if (isLaxVectorConversion(RHSType, LHSType)) {
Kind = CK_BitCast;
return IncompatibleVectors;
}
@@ -6389,8 +6558,9 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
return IncompatiblePointer;
}
- // T^ -> A*
- if (RHSType->isBlockPointerType()) {
+ // Only under strict condition T^ is compatible with an Objective-C pointer.
+ if (RHSType->isBlockPointerType() &&
+ isObjCPtrBlockCompatible(*this, Context, LHSType)) {
maybeExtendBlockObject(*this, RHS);
Kind = CK_BlockPointerToObjCPointerCast;
return Compatible;
@@ -6451,7 +6621,7 @@ static void ConstructTransparentUnion(Sema &S, ASTContext &C,
FieldDecl *Field) {
// Build an initializer list that designates the appropriate member
// of the transparent union.
- Expr *E = EResult.take();
+ Expr *E = EResult.get();
InitListExpr *Initializer = new (C) InitListExpr(C, SourceLocation(),
E, SourceLocation());
Initializer->setType(UnionType);
@@ -6460,9 +6630,8 @@ static void ConstructTransparentUnion(Sema &S, ASTContext &C,
// Build a compound literal constructing a value of the transparent
// union type from this initializer list.
TypeSourceInfo *unionTInfo = C.getTrivialTypeSourceInfo(UnionType);
- EResult = S.Owned(
- new (C) CompoundLiteralExpr(SourceLocation(), unionTInfo, UnionType,
- VK_RValue, Initializer, false));
+ EResult = new (C) CompoundLiteralExpr(SourceLocation(), unionTInfo, UnionType,
+ VK_RValue, Initializer, false);
}
Sema::AssignConvertType
@@ -6478,27 +6647,25 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType,
// The field to initialize within the transparent union.
RecordDecl *UD = UT->getDecl();
- FieldDecl *InitField = 0;
+ FieldDecl *InitField = nullptr;
// It's compatible if the expression matches any of the fields.
- for (RecordDecl::field_iterator it = UD->field_begin(),
- itend = UD->field_end();
- it != itend; ++it) {
+ for (auto *it : UD->fields()) {
if (it->getType()->isPointerType()) {
// If the transparent union contains a pointer type, we allow:
// 1) void pointer
// 2) null pointer constant
if (RHSType->isPointerType())
if (RHSType->castAs<PointerType>()->getPointeeType()->isVoidType()) {
- RHS = ImpCastExprToType(RHS.take(), it->getType(), CK_BitCast);
- InitField = *it;
+ RHS = ImpCastExprToType(RHS.get(), it->getType(), CK_BitCast);
+ InitField = it;
break;
}
if (RHS.get()->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull)) {
- RHS = ImpCastExprToType(RHS.take(), it->getType(),
+ RHS = ImpCastExprToType(RHS.get(), it->getType(),
CK_NullToPointer);
- InitField = *it;
+ InitField = it;
break;
}
}
@@ -6506,8 +6673,8 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType,
CastKind Kind = CK_Invalid;
if (CheckAssignmentConstraints(it->getType(), RHS, Kind)
== Compatible) {
- RHS = ImpCastExprToType(RHS.take(), it->getType(), Kind);
- InitField = *it;
+ RHS = ImpCastExprToType(RHS.get(), it->getType(), Kind);
+ InitField = it;
break;
}
}
@@ -6571,7 +6738,7 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
CastKind Kind;
CXXCastPath Path;
CheckPointerConversion(RHS.get(), LHSType, Kind, Path, false);
- RHS = ImpCastExprToType(RHS.take(), LHSType, Kind, VK_RValue, &Path);
+ RHS = ImpCastExprToType(RHS.get(), LHSType, Kind, VK_RValue, &Path);
return Compatible;
}
@@ -6582,7 +6749,7 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
//
// Suppress this for references: C++ 8.5.3p5.
if (!LHSType->isReferenceType()) {
- RHS = DefaultFunctionArrayLvalueConversion(RHS.take());
+ RHS = DefaultFunctionArrayLvalueConversion(RHS.get());
if (RHS.isInvalid())
return Incompatible;
}
@@ -6599,10 +6766,18 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
// does not have reference type.
if (result != Incompatible && RHS.get()->getType() != LHSType) {
QualType Ty = LHSType.getNonLValueExprType(Context);
- Expr *E = RHS.take();
+ Expr *E = RHS.get();
if (getLangOpts().ObjCAutoRefCount)
CheckObjCARCConversion(SourceRange(), Ty, E, CCK_ImplicitConversion,
DiagnoseCFAudited);
+ if (getLangOpts().ObjC1 &&
+ (CheckObjCBridgeRelatedConversions(E->getLocStart(),
+ LHSType, E->getType(), E) ||
+ ConversionToObjCStringLiteralCheck(LHSType, E))) {
+ RHS = E;
+ return Compatible;
+ }
+
RHS = ImpCastExprToType(E, Ty, Kind);
}
return result;
@@ -6616,97 +6791,128 @@ QualType Sema::InvalidOperands(SourceLocation Loc, ExprResult &LHS,
return QualType();
}
+/// Try to convert a value of non-vector type to a vector type by converting
+/// the type to the element type of the vector and then performing a splat.
+/// If the language is OpenCL, we only use conversions that promote scalar
+/// rank; for C, Obj-C, and C++ we allow any real scalar conversion except
+/// for float->int.
+///
+/// \param scalar - if non-null, actually perform the conversions
+/// \return true if the operation fails (but without diagnosing the failure)
+static bool tryVectorConvertAndSplat(Sema &S, ExprResult *scalar,
+ QualType scalarTy,
+ QualType vectorEltTy,
+ QualType vectorTy) {
+ // The conversion to apply to the scalar before splatting it,
+ // if necessary.
+ CastKind scalarCast = CK_Invalid;
+
+ if (vectorEltTy->isIntegralType(S.Context)) {
+ if (!scalarTy->isIntegralType(S.Context))
+ return true;
+ if (S.getLangOpts().OpenCL &&
+ S.Context.getIntegerTypeOrder(vectorEltTy, scalarTy) < 0)
+ return true;
+ scalarCast = CK_IntegralCast;
+ } else if (vectorEltTy->isRealFloatingType()) {
+ if (scalarTy->isRealFloatingType()) {
+ if (S.getLangOpts().OpenCL &&
+ S.Context.getFloatingTypeOrder(vectorEltTy, scalarTy) < 0)
+ return true;
+ scalarCast = CK_FloatingCast;
+ }
+ else if (scalarTy->isIntegralType(S.Context))
+ scalarCast = CK_IntegralToFloating;
+ else
+ return true;
+ } else {
+ return true;
+ }
+
+ // Adjust scalar if desired.
+ if (scalar) {
+ if (scalarCast != CK_Invalid)
+ *scalar = S.ImpCastExprToType(scalar->get(), vectorEltTy, scalarCast);
+ *scalar = S.ImpCastExprToType(scalar->get(), vectorTy, CK_VectorSplat);
+ }
+ return false;
+}
+
QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc, bool IsCompAssign) {
if (!IsCompAssign) {
- LHS = DefaultFunctionArrayLvalueConversion(LHS.take());
+ LHS = DefaultFunctionArrayLvalueConversion(LHS.get());
if (LHS.isInvalid())
return QualType();
}
- RHS = DefaultFunctionArrayLvalueConversion(RHS.take());
+ RHS = DefaultFunctionArrayLvalueConversion(RHS.get());
if (RHS.isInvalid())
return QualType();
// For conversion purposes, we ignore any qualifiers.
// For example, "const float" and "float" are equivalent.
- QualType LHSType =
- Context.getCanonicalType(LHS.get()->getType()).getUnqualifiedType();
- QualType RHSType =
- Context.getCanonicalType(RHS.get()->getType()).getUnqualifiedType();
+ QualType LHSType = LHS.get()->getType().getUnqualifiedType();
+ QualType RHSType = RHS.get()->getType().getUnqualifiedType();
// If the vector types are identical, return.
- if (LHSType == RHSType)
+ if (Context.hasSameType(LHSType, RHSType))
return LHSType;
- // Handle the case of equivalent AltiVec and GCC vector types
- if (LHSType->isVectorType() && RHSType->isVectorType() &&
+ const VectorType *LHSVecType = LHSType->getAs<VectorType>();
+ const VectorType *RHSVecType = RHSType->getAs<VectorType>();
+ assert(LHSVecType || RHSVecType);
+
+ // If we have compatible AltiVec and GCC vector types, use the AltiVec type.
+ if (LHSVecType && RHSVecType &&
Context.areCompatibleVectorTypes(LHSType, RHSType)) {
- if (LHSType->isExtVectorType()) {
- RHS = ImpCastExprToType(RHS.take(), LHSType, CK_BitCast);
+ if (isa<ExtVectorType>(LHSVecType)) {
+ RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BitCast);
return LHSType;
}
if (!IsCompAssign)
- LHS = ImpCastExprToType(LHS.take(), RHSType, CK_BitCast);
+ LHS = ImpCastExprToType(LHS.get(), RHSType, CK_BitCast);
return RHSType;
}
- if (getLangOpts().LaxVectorConversions &&
- Context.getTypeSize(LHSType) == Context.getTypeSize(RHSType)) {
- // If we are allowing lax vector conversions, and LHS and RHS are both
- // vectors, the total size only needs to be the same. This is a
- // bitcast; no bits are changed but the result type is different.
- // FIXME: Should we really be allowing this?
- RHS = ImpCastExprToType(RHS.take(), LHSType, CK_BitCast);
- return LHSType;
+ // If there's an ext-vector type and a scalar, try to convert the scalar to
+ // the vector element type and splat.
+ if (!RHSVecType && isa<ExtVectorType>(LHSVecType)) {
+ if (!tryVectorConvertAndSplat(*this, &RHS, RHSType,
+ LHSVecType->getElementType(), LHSType))
+ return LHSType;
+ }
+ if (!LHSVecType && isa<ExtVectorType>(RHSVecType)) {
+ if (!tryVectorConvertAndSplat(*this, (IsCompAssign ? nullptr : &LHS),
+ LHSType, RHSVecType->getElementType(),
+ RHSType))
+ return RHSType;
}
- // Canonicalize the ExtVector to the LHS, remember if we swapped so we can
- // swap back (so that we don't reverse the inputs to a subtract, for instance.
- bool swapped = false;
- if (RHSType->isExtVectorType() && !IsCompAssign) {
- swapped = true;
- std::swap(RHS, LHS);
- std::swap(RHSType, LHSType);
- }
-
- // Handle the case of an ext vector and scalar.
- if (const ExtVectorType *LV = LHSType->getAs<ExtVectorType>()) {
- QualType EltTy = LV->getElementType();
- if (EltTy->isIntegralType(Context) && RHSType->isIntegralType(Context)) {
- int order = Context.getIntegerTypeOrder(EltTy, RHSType);
- if (order > 0)
- RHS = ImpCastExprToType(RHS.take(), EltTy, CK_IntegralCast);
- if (order >= 0) {
- RHS = ImpCastExprToType(RHS.take(), LHSType, CK_VectorSplat);
- if (swapped) std::swap(RHS, LHS);
- return LHSType;
- }
- }
- if (EltTy->isRealFloatingType() && RHSType->isScalarType()) {
- if (RHSType->isRealFloatingType()) {
- int order = Context.getFloatingTypeOrder(EltTy, RHSType);
- if (order > 0)
- RHS = ImpCastExprToType(RHS.take(), EltTy, CK_FloatingCast);
- if (order >= 0) {
- RHS = ImpCastExprToType(RHS.take(), LHSType, CK_VectorSplat);
- if (swapped) std::swap(RHS, LHS);
- return LHSType;
- }
- }
- if (RHSType->isIntegralType(Context)) {
- RHS = ImpCastExprToType(RHS.take(), EltTy, CK_IntegralToFloating);
- RHS = ImpCastExprToType(RHS.take(), LHSType, CK_VectorSplat);
- if (swapped) std::swap(RHS, LHS);
- return LHSType;
- }
- }
+ // If we're allowing lax vector conversions, only the total (data) size
+ // needs to be the same.
+ // FIXME: Should we really be allowing this?
+ // FIXME: We really just pick the LHS type arbitrarily?
+ if (isLaxVectorConversion(RHSType, LHSType)) {
+ QualType resultType = LHSType;
+ RHS = ImpCastExprToType(RHS.get(), resultType, CK_BitCast);
+ return resultType;
}
- // Vectors of different size or scalar and non-ext-vector are errors.
- if (swapped) std::swap(RHS, LHS);
+ // Okay, the expression is invalid.
+
+ // If there's a non-vector, non-real operand, diagnose that.
+ if ((!RHSVecType && !RHSType->isRealType()) ||
+ (!LHSVecType && !LHSType->isRealType())) {
+ Diag(Loc, diag::err_typecheck_vector_not_convertable_non_scalar)
+ << LHSType << RHSType
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+ return QualType();
+ }
+
+ // Otherwise, use the generic diagnostic.
Diag(Loc, diag::err_typecheck_vector_not_convertable)
- << LHS.get()->getType() << RHS.get()->getType()
+ << LHSType << RHSType
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
return QualType();
}
@@ -7159,7 +7365,7 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
return QualType();
// Check array bounds for pointer arithemtic
- CheckArrayAccess(LHS.get(), RHS.get(), /*ArraySubscriptExpr*/0,
+ CheckArrayAccess(LHS.get(), RHS.get(), /*ArraySubscriptExpr*/nullptr,
/*AllowOnePastEnd*/true, /*IndexNegated*/true);
if (CompLHSTy) *CompLHSTy = LHS.get()->getType();
@@ -7302,14 +7508,14 @@ QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS,
// For the LHS, do usual unary conversions, but then reset them away
// if this is a compound assignment.
ExprResult OldLHS = LHS;
- LHS = UsualUnaryConversions(LHS.take());
+ LHS = UsualUnaryConversions(LHS.get());
if (LHS.isInvalid())
return QualType();
QualType LHSType = LHS.get()->getType();
if (IsCompAssign) LHS = OldLHS;
// The RHS is simpler.
- RHS = UsualUnaryConversions(RHS.take());
+ RHS = UsualUnaryConversions(RHS.get());
if (RHS.isInvalid())
return QualType();
QualType RHSType = RHS.get()->getType();
@@ -7409,7 +7615,7 @@ static bool convertPointersToCompositeType(Sema &S, SourceLocation Loc,
(LHSType->isMemberPointerType() && RHSType->isMemberPointerType()));
bool NonStandardCompositeType = false;
- bool *BoolPtr = S.isSFINAEContext() ? 0 : &NonStandardCompositeType;
+ bool *BoolPtr = S.isSFINAEContext() ? nullptr : &NonStandardCompositeType;
QualType T = S.FindCompositePointerType(Loc, LHS, RHS, BoolPtr);
if (T.isNull()) {
diagnoseDistinctPointerComparison(S, Loc, LHS, RHS, /*isError*/true);
@@ -7421,8 +7627,8 @@ static bool convertPointersToCompositeType(Sema &S, SourceLocation Loc,
<< LHSType << RHSType << T << LHS.get()->getSourceRange()
<< RHS.get()->getSourceRange();
- LHS = S.ImpCastExprToType(LHS.take(), T, CK_BitCast);
- RHS = S.ImpCastExprToType(RHS.take(), T, CK_BitCast);
+ LHS = S.ImpCastExprToType(LHS.get(), T, CK_BitCast);
+ RHS = S.ImpCastExprToType(RHS.get(), T, CK_BitCast);
return false;
}
@@ -7488,11 +7694,11 @@ static bool hasIsEqualMethod(Sema &S, const Expr *LHS, const Expr *RHS) {
if (!Method)
return false;
- QualType T = Method->param_begin()[0]->getType();
+ QualType T = Method->parameters()[0]->getType();
if (!T->isObjCObjectPointerType())
return false;
-
- QualType R = Method->getResultType();
+
+ QualType R = Method->getReturnType();
if (!R->isScalarType())
return false;
@@ -7646,7 +7852,7 @@ static ValueDecl *getCompareDecl(Expr *E) {
if (Mem->isImplicitAccess())
return Mem->getMemberDecl();
}
- return 0;
+ return nullptr;
}
// C99 6.5.8, C++ [expr.rel]
@@ -7689,7 +7895,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
ValueDecl *DL = getCompareDecl(LHSStripped);
ValueDecl *DR = getCompareDecl(RHSStripped);
if (DL && DR && DL == DR && !IsWithinTemplateSpecialization(DL)) {
- DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
+ DiagRuntimeBehavior(Loc, nullptr, PDiag(diag::warn_comparison_always)
<< 0 // self-
<< (Opc == BO_EQ
|| Opc == BO_LE
@@ -7711,7 +7917,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
always_evals_to = 2; // e.g. array1 <= array2
break;
}
- DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
+ DiagRuntimeBehavior(Loc, nullptr, PDiag(diag::warn_comparison_always)
<< 1 // array
<< always_evals_to);
}
@@ -7723,8 +7929,8 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
// Warn about comparisons against a string constant (unless the other
// operand is null), the user probably wants strcmp.
- Expr *literalString = 0;
- Expr *literalStringStripped = 0;
+ Expr *literalString = nullptr;
+ Expr *literalStringStripped = nullptr;
if ((isa<StringLiteral>(LHSStripped) || isa<ObjCEncodeExpr>(LHSStripped)) &&
!RHSStripped->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull)) {
@@ -7739,7 +7945,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
}
if (literalString) {
- DiagRuntimeBehavior(Loc, 0,
+ DiagRuntimeBehavior(Loc, nullptr,
PDiag(diag::warn_stringcompare)
<< isa<ObjCEncodeExpr>(literalStringStripped)
<< literalString->getSourceRange());
@@ -7769,10 +7975,22 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
return ResultTy;
}
- bool LHSIsNull = LHS.get()->isNullPointerConstant(Context,
- Expr::NPC_ValueDependentIsNull);
- bool RHSIsNull = RHS.get()->isNullPointerConstant(Context,
- Expr::NPC_ValueDependentIsNull);
+ const Expr::NullPointerConstantKind LHSNullKind =
+ LHS.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull);
+ const Expr::NullPointerConstantKind RHSNullKind =
+ RHS.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull);
+ bool LHSIsNull = LHSNullKind != Expr::NPCK_NotNull;
+ bool RHSIsNull = RHSNullKind != Expr::NPCK_NotNull;
+
+ if (!IsRelational && LHSIsNull != RHSIsNull) {
+ bool IsEquality = Opc == BO_EQ;
+ if (RHSIsNull)
+ DiagnoseAlwaysNonNullPointer(LHS.get(), RHSNullKind, IsEquality,
+ RHS.get()->getSourceRange());
+ else
+ DiagnoseAlwaysNonNullPointer(RHS.get(), LHSNullKind, IsEquality,
+ LHS.get()->getSourceRange());
+ }
// All of the following pointer-related warnings are GCC extensions, except
// when handling null pointer constants.
@@ -7799,7 +8017,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
if (isSFINAEContext())
return QualType();
- RHS = ImpCastExprToType(RHS.take(), LHSType, CK_BitCast);
+ RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BitCast);
return ResultTy;
}
}
@@ -7830,10 +8048,14 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
diagnoseDistinctPointerComparison(*this, Loc, LHS, RHS, /*isError*/false);
}
if (LCanPointeeTy != RCanPointeeTy) {
+ unsigned AddrSpaceL = LCanPointeeTy.getAddressSpace();
+ unsigned AddrSpaceR = RCanPointeeTy.getAddressSpace();
+ CastKind Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion
+ : CK_BitCast;
if (LHSIsNull && !RHSIsNull)
- LHS = ImpCastExprToType(LHS.take(), RHSType, CK_BitCast);
+ LHS = ImpCastExprToType(LHS.get(), RHSType, Kind);
else
- RHS = ImpCastExprToType(RHS.take(), LHSType, CK_BitCast);
+ RHS = ImpCastExprToType(RHS.get(), LHSType, Kind);
}
return ResultTy;
}
@@ -7849,7 +8071,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
((LHSType->isAnyPointerType() || LHSType->isNullPtrType()) ||
(!IsRelational &&
(LHSType->isMemberPointerType() || LHSType->isBlockPointerType())))) {
- RHS = ImpCastExprToType(RHS.take(), LHSType,
+ RHS = ImpCastExprToType(RHS.get(), LHSType,
LHSType->isMemberPointerType()
? CK_NullToMemberPointer
: CK_NullToPointer);
@@ -7859,7 +8081,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
((RHSType->isAnyPointerType() || RHSType->isNullPtrType()) ||
(!IsRelational &&
(RHSType->isMemberPointerType() || RHSType->isBlockPointerType())))) {
- LHS = ImpCastExprToType(LHS.take(), RHSType,
+ LHS = ImpCastExprToType(LHS.get(), RHSType,
RHSType->isMemberPointerType()
? CK_NullToMemberPointer
: CK_NullToPointer);
@@ -7895,7 +8117,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
<< LHSType << RHSType << LHS.get()->getSourceRange()
<< RHS.get()->getSourceRange();
}
- RHS = ImpCastExprToType(RHS.take(), LHSType, CK_BitCast);
+ RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BitCast);
return ResultTy;
}
@@ -7913,11 +8135,11 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
<< RHS.get()->getSourceRange();
}
if (LHSIsNull && !RHSIsNull)
- LHS = ImpCastExprToType(LHS.take(), RHSType,
+ LHS = ImpCastExprToType(LHS.get(), RHSType,
RHSType->isPointerType() ? CK_BitCast
: CK_AnyPointerToBlockPointerCast);
else
- RHS = ImpCastExprToType(RHS.take(), LHSType,
+ RHS = ImpCastExprToType(RHS.get(), LHSType,
LHSType->isPointerType() ? CK_BitCast
: CK_AnyPointerToBlockPointerCast);
return ResultTy;
@@ -7937,16 +8159,17 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
/*isError*/false);
}
if (LHSIsNull && !RHSIsNull) {
- Expr *E = LHS.take();
+ Expr *E = LHS.get();
if (getLangOpts().ObjCAutoRefCount)
CheckObjCARCConversion(SourceRange(), RHSType, E, CCK_ImplicitConversion);
LHS = ImpCastExprToType(E, RHSType,
RPT ? CK_BitCast :CK_CPointerToObjCPointerCast);
}
else {
- Expr *E = RHS.take();
+ Expr *E = RHS.get();
if (getLangOpts().ObjCAutoRefCount)
- CheckObjCARCConversion(SourceRange(), LHSType, E, CCK_ImplicitConversion);
+ CheckObjCARCConversion(SourceRange(), LHSType, E, CCK_ImplicitConversion, false,
+ Opc);
RHS = ImpCastExprToType(E, LHSType,
LPT ? CK_BitCast :CK_CPointerToObjCPointerCast);
}
@@ -7961,9 +8184,9 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
diagnoseObjCLiteralComparison(*this, Loc, LHS, RHS, Opc);
if (LHSIsNull && !RHSIsNull)
- LHS = ImpCastExprToType(LHS.take(), RHSType, CK_BitCast);
+ LHS = ImpCastExprToType(LHS.get(), RHSType, CK_BitCast);
else
- RHS = ImpCastExprToType(RHS.take(), LHSType, CK_BitCast);
+ RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BitCast);
return ResultTy;
}
}
@@ -7995,10 +8218,10 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
}
if (LHSType->isIntegerType())
- LHS = ImpCastExprToType(LHS.take(), RHSType,
+ LHS = ImpCastExprToType(LHS.get(), RHSType,
LHSIsNull ? CK_NullToPointer : CK_IntegralToPointer);
else
- RHS = ImpCastExprToType(RHS.take(), LHSType,
+ RHS = ImpCastExprToType(RHS.get(), LHSType,
RHSIsNull ? CK_NullToPointer : CK_IntegralToPointer);
return ResultTy;
}
@@ -8006,12 +8229,12 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
// Handle block pointers.
if (!IsRelational && RHSIsNull
&& LHSType->isBlockPointerType() && RHSType->isIntegerType()) {
- RHS = ImpCastExprToType(RHS.take(), LHSType, CK_NullToPointer);
+ RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
return ResultTy;
}
if (!IsRelational && LHSIsNull
&& LHSType->isIntegerType() && RHSType->isBlockPointerType()) {
- LHS = ImpCastExprToType(LHS.take(), RHSType, CK_NullToPointer);
+ LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer);
return ResultTy;
}
@@ -8068,7 +8291,7 @@ QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
if (DeclRefExpr* DRR
= dyn_cast<DeclRefExpr>(RHS.get()->IgnoreParenImpCasts()))
if (DRL->getDecl() == DRR->getDecl())
- DiagRuntimeBehavior(Loc, 0,
+ DiagRuntimeBehavior(Loc, nullptr,
PDiag(diag::warn_comparison_always)
<< 0 // self-
<< 2 // "a constant"
@@ -8112,13 +8335,13 @@ inline QualType Sema::CheckBitwiseOperands(
return InvalidOperands(Loc, LHS, RHS);
}
- ExprResult LHSResult = Owned(LHS), RHSResult = Owned(RHS);
+ ExprResult LHSResult = LHS, RHSResult = RHS;
QualType compType = UsualArithmeticConversions(LHSResult, RHSResult,
IsCompAssign);
if (LHSResult.isInvalid() || RHSResult.isInvalid())
return QualType();
- LHS = LHSResult.take();
- RHS = RHSResult.take();
+ LHS = LHSResult.get();
+ RHS = RHSResult.get();
if (!compType.isNull() && compType->isIntegralOrUnscopedEnumerationType())
return compType;
@@ -8146,7 +8369,8 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
// Parens on the RHS are ignored.
llvm::APSInt Result;
if (RHS.get()->EvaluateAsInt(Result, Context))
- if ((getLangOpts().Bool && !RHS.get()->getType()->isBooleanType()) ||
+ if ((getLangOpts().Bool && !RHS.get()->getType()->isBooleanType() &&
+ !RHS.get()->getExprLoc().isMacroID()) ||
(Result != 0 && Result != 1)) {
Diag(Loc, diag::warn_logical_instead_of_bitwise)
<< RHS.get()->getSourceRange()
@@ -8180,11 +8404,11 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
return InvalidOperands(Loc, LHS, RHS);
}
- LHS = UsualUnaryConversions(LHS.take());
+ LHS = UsualUnaryConversions(LHS.get());
if (LHS.isInvalid())
return QualType();
- RHS = UsualUnaryConversions(RHS.take());
+ RHS = UsualUnaryConversions(RHS.get());
if (RHS.isInvalid())
return QualType();
@@ -8224,7 +8448,7 @@ static bool IsReadonlyMessage(Expr *E, Sema &S) {
ObjCMessageExpr *Base =
dyn_cast<ObjCMessageExpr>(ME->getBase()->IgnoreParenImpCasts());
if (!Base) return false;
- return Base->getMethodDecl() != 0;
+ return Base->getMethodDecl() != nullptr;
}
/// Is the given expression (which must be 'const') a reference to a
@@ -8247,7 +8471,7 @@ static NonConstCaptureKind isReferenceToNonConstCapture(Sema &S, Expr *E) {
assert(var->hasLocalStorage() && "capture added 'const' to non-local?");
// Decide whether the first capture was for a block or a lambda.
- DeclContext *DC = S.CurContext, *Prev = 0;
+ DeclContext *DC = S.CurContext, *Prev = nullptr;
while (DC != var->getDeclContext()) {
Prev = DC;
DC = DC->getParent();
@@ -8464,10 +8688,8 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
// 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.
- DiagnosticsEngine::Level Level =
- Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
- RHS.get()->getLocStart());
- if (Level != DiagnosticsEngine::Ignored)
+ if (!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak,
+ RHS.get()->getLocStart()))
getCurFunction()->markSafeWeakUse(RHS.get());
} else if (getLangOpts().ObjCAutoRefCount) {
@@ -8499,8 +8721,8 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
// C99 6.5.17
static QualType CheckCommaOperands(Sema &S, ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc) {
- LHS = S.CheckPlaceholderExpr(LHS.take());
- RHS = S.CheckPlaceholderExpr(RHS.take());
+ LHS = S.CheckPlaceholderExpr(LHS.get());
+ RHS = S.CheckPlaceholderExpr(RHS.get());
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
@@ -8510,14 +8732,14 @@ static QualType CheckCommaOperands(Sema &S, ExprResult &LHS, ExprResult &RHS,
// So we treat the LHS as a ignored value, and in C++ we allow the
// containing site to determine what should be done with the RHS.
- LHS = S.IgnoredValueConversions(LHS.take());
+ LHS = S.IgnoredValueConversions(LHS.get());
if (LHS.isInvalid())
return QualType();
S.DiagnoseUnusedExprResult(LHS.get());
if (!S.getLangOpts().CPlusPlus) {
- RHS = S.DefaultFunctionArrayLvalueConversion(RHS.take());
+ RHS = S.DefaultFunctionArrayLvalueConversion(RHS.get());
if (RHS.isInvalid())
return QualType();
if (!RHS.get()->getType()->isVoidType())
@@ -8577,7 +8799,7 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
} else if (ResType->isPlaceholderType()) {
ExprResult PR = S.CheckPlaceholderExpr(Op);
if (PR.isInvalid()) return QualType();
- return CheckIncrementDecrementOperand(S, PR.take(), VK, OpLoc,
+ return CheckIncrementDecrementOperand(S, PR.get(), VK, OpLoc,
IsInc, IsPrefix);
} else if (S.getLangOpts().AltiVec && ResType->isVectorType()) {
// OK! ( C/C++ Language Extensions for CBEA(Version 2.6) 10.3 )
@@ -8627,7 +8849,7 @@ static ValueDecl *getPrimaryDecl(Expr *E) {
// the base's value, so the object the base refers to is
// irrelevant.
if (cast<MemberExpr>(E)->isArrow())
- return 0;
+ return nullptr;
// Otherwise, the expression refers to a part of the base
return getPrimaryDecl(cast<MemberExpr>(E)->getBase());
case Stmt::ArraySubscriptExprClass: {
@@ -8638,7 +8860,7 @@ static ValueDecl *getPrimaryDecl(Expr *E) {
if (ICE->getSubExpr()->getType()->isArrayType())
return getPrimaryDecl(ICE->getSubExpr());
}
- return 0;
+ return nullptr;
}
case Stmt::UnaryOperatorClass: {
UnaryOperator *UO = cast<UnaryOperator>(E);
@@ -8649,7 +8871,7 @@ static ValueDecl *getPrimaryDecl(Expr *E) {
case UO_Extension:
return getPrimaryDecl(UO->getSubExpr());
default:
- return 0;
+ return nullptr;
}
}
case Stmt::ParenExprClass:
@@ -8659,7 +8881,7 @@ static ValueDecl *getPrimaryDecl(Expr *E) {
// the sub-expression; otherwise, the result here doesn't matter.
return getPrimaryDecl(cast<ImplicitCastExpr>(E)->getSubExpr());
default:
- return 0;
+ return nullptr;
}
}
@@ -8718,7 +8940,7 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
return QualType();
}
- OrigOp = CheckPlaceholderExpr(OrigOp.take());
+ OrigOp = CheckPlaceholderExpr(OrigOp.get());
if (OrigOp.isInvalid()) return QualType();
}
@@ -8730,6 +8952,12 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
// Make sure to ignore parentheses in subsequent checks
Expr *op = OrigOp.get()->IgnoreParens();
+ // OpenCL v1.0 s6.8.a.3: Pointers to functions are not allowed.
+ if (LangOpts.OpenCL && op->getType()->isFunctionType()) {
+ Diag(op->getExprLoc(), diag::err_opencl_taking_function_address);
+ return QualType();
+ }
+
if (getLangOpts().C99) {
// Implement C99-only parts of addressof rules.
if (UnaryOperator* uOp = dyn_cast<UnaryOperator>(op)) {
@@ -8754,7 +8982,7 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
return QualType();
// Materialize the temporary as an lvalue so that we can take its address.
OrigOp = op = new (Context)
- MaterializeTemporaryExpr(op->getType(), OrigOp.take(), true, 0);
+ MaterializeTemporaryExpr(op->getType(), OrigOp.get(), true);
} else if (isa<ObjCSelectorExpr>(op)) {
return Context.getPointerType(op->getType());
} else if (lval == Expr::LV_MemberFunction) {
@@ -8793,8 +9021,11 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
if (isa<CXXDestructorDecl>(MD))
Diag(OpLoc, diag::err_typecheck_addrof_dtor) << op->getSourceRange();
- return Context.getMemberPointerType(op->getType(),
- Context.getTypeDeclType(MD->getParent()).getTypePtr());
+ QualType MPTy = Context.getMemberPointerType(
+ op->getType(), Context.getTypeDeclType(MD->getParent()).getTypePtr());
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft())
+ RequireCompleteType(OpLoc, MPTy, 0);
+ return MPTy;
} else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) {
// C99 6.5.3.2p1
// The operand must be either an l-value or a function designator
@@ -8842,8 +9073,13 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
while (cast<RecordDecl>(Ctx)->isAnonymousStructOrUnion())
Ctx = Ctx->getParent();
- return Context.getMemberPointerType(op->getType(),
- Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
+
+ QualType MPTy = Context.getMemberPointerType(
+ op->getType(),
+ Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft())
+ RequireCompleteType(OpLoc, MPTy, 0);
+ return MPTy;
}
}
} else if (!isa<FunctionDecl>(dcl) && !isa<NonTypeTemplateParmDecl>(dcl))
@@ -8877,7 +9113,7 @@ static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK,
ExprResult ConvResult = S.UsualUnaryConversions(Op);
if (ConvResult.isInvalid())
return QualType();
- Op = ConvResult.take();
+ Op = ConvResult.get();
QualType OpTy = Op->getType();
QualType Result;
@@ -8887,10 +9123,6 @@ static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK,
Op->getSourceRange());
}
- // Note that per both C89 and C99, indirection is always legal, even if OpTy
- // is an incomplete type or void. It would be possible to warn about
- // dereferencing a void pointer, but it's completely well-defined, and such a
- // warning is unlikely to catch any mistakes.
if (const PointerType *PT = OpTy->getAs<PointerType>())
Result = PT->getPointeeType();
else if (const ObjCObjectPointerType *OPT =
@@ -8899,8 +9131,8 @@ static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK,
else {
ExprResult PR = S.CheckPlaceholderExpr(Op);
if (PR.isInvalid()) return QualType();
- if (PR.take() != Op)
- return CheckIndirectionOperand(S, PR.take(), VK, OpLoc);
+ if (PR.get() != Op)
+ return CheckIndirectionOperand(S, PR.get(), VK, OpLoc);
}
if (Result.isNull()) {
@@ -8909,6 +9141,19 @@ static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK,
return QualType();
}
+ // Note that per both C89 and C99, indirection is always legal, even if Result
+ // is an incomplete type or void. It would be possible to warn about
+ // dereferencing a void pointer, but it's completely well-defined, and such a
+ // warning is unlikely to catch any mistakes. In C++, indirection is not valid
+ // for pointers to 'void' but is fine for any other pointer type:
+ //
+ // C++ [expr.unary.op]p1:
+ // [...] the expression to which [the unary * operator] is applied shall
+ // be a pointer to an object type, or a pointer to a function type
+ if (S.getLangOpts().CPlusPlus && Result->isVoidType())
+ S.Diag(OpLoc, diag::ext_typecheck_indirection_through_void_pointer)
+ << OpTy << Op->getSourceRange();
+
// Dereferences are usually l-values...
VK = VK_LValue;
@@ -9021,7 +9266,7 @@ static void checkObjCPointerIntrospection(Sema &S, ExprResult &L, ExprResult &R,
if (!S.getLangOpts().ObjC1)
return;
- const Expr *ObjCPointerExpr = 0, *OtherExpr = 0;
+ const Expr *ObjCPointerExpr = nullptr, *OtherExpr = nullptr;
const Expr *LHS = L.get();
const Expr *RHS = R.get();
@@ -9078,10 +9323,10 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
ExprResult Init = InitSeq.Perform(*this, Entity, Kind, RHSExpr);
if (Init.isInvalid())
return Init;
- RHSExpr = Init.take();
+ RHSExpr = Init.get();
}
- ExprResult LHS = Owned(LHSExpr), RHS = Owned(RHSExpr);
+ ExprResult LHS = LHSExpr, RHS = RHSExpr;
QualType ResultTy; // Result type of the binary operator.
// The following two variables are used for compound assignment operators
QualType CompLHSTy; // Type of LHS after promotions for computation
@@ -9175,8 +9420,9 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy);
break;
case BO_AndAssign:
+ case BO_OrAssign: // fallthrough
+ DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc);
case BO_XorAssign:
- case BO_OrAssign:
CompResultTy = CheckBitwiseOperands(LHS, RHS, OpLoc, true);
CompLHSTy = CompResultTy;
if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid())
@@ -9216,18 +9462,16 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
DiagnoseDirectIsaAccess(*this, OIRE, OpLoc, RHS.get());
if (CompResultTy.isNull())
- return Owned(new (Context) BinaryOperator(LHS.take(), RHS.take(), Opc,
- ResultTy, VK, OK, OpLoc,
- FPFeatures.fp_contract));
+ return new (Context) BinaryOperator(LHS.get(), RHS.get(), Opc, ResultTy, VK,
+ OK, OpLoc, FPFeatures.fp_contract);
if (getLangOpts().CPlusPlus && LHS.get()->getObjectKind() !=
OK_ObjCProperty) {
VK = VK_LValue;
OK = LHS.get()->getObjectKind();
}
- return Owned(new (Context) CompoundAssignOperator(LHS.take(), RHS.take(), Opc,
- ResultTy, VK, OK, CompLHSTy,
- CompResultTy, OpLoc,
- FPFeatures.fp_contract));
+ return new (Context) CompoundAssignOperator(
+ LHS.get(), RHS.get(), Opc, ResultTy, VK, OK, CompLHSTy, CompResultTy,
+ OpLoc, FPFeatures.fp_contract);
}
/// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison
@@ -9445,8 +9689,8 @@ ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
tok::TokenKind Kind,
Expr *LHSExpr, Expr *RHSExpr) {
BinaryOperatorKind Opc = ConvertTokenKindToBinaryOpcode(Kind);
- assert((LHSExpr != 0) && "ActOnBinOp(): missing left expression");
- assert((RHSExpr != 0) && "ActOnBinOp(): missing right expression");
+ assert(LHSExpr && "ActOnBinOp(): missing left expression");
+ assert(RHSExpr && "ActOnBinOp(): missing right expression");
// Emit warnings for tricky precedence issues, e.g. "bitfield & 0x4 == 0"
DiagnoseBinOpPrecedence(*this, Opc, TokLoc, LHSExpr, RHSExpr);
@@ -9499,7 +9743,7 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
// instantiates to having an overloadable type.
ExprResult resolvedRHS = CheckPlaceholderExpr(RHSExpr);
if (resolvedRHS.isInvalid()) return ExprError();
- RHSExpr = resolvedRHS.take();
+ RHSExpr = resolvedRHS.get();
if (RHSExpr->isTypeDependent() ||
RHSExpr->getType()->isOverloadableType())
@@ -9508,7 +9752,7 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
ExprResult LHS = CheckPlaceholderExpr(LHSExpr);
if (LHS.isInvalid()) return ExprError();
- LHSExpr = LHS.take();
+ LHSExpr = LHS.get();
}
// Handle pseudo-objects in the RHS.
@@ -9532,7 +9776,7 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
ExprResult resolvedRHS = CheckPlaceholderExpr(RHSExpr);
if (!resolvedRHS.isUsable()) return ExprError();
- RHSExpr = resolvedRHS.take();
+ RHSExpr = resolvedRHS.get();
}
if (getLangOpts().CPlusPlus) {
@@ -9555,7 +9799,7 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
UnaryOperatorKind Opc,
Expr *InputExpr) {
- ExprResult Input = Owned(InputExpr);
+ ExprResult Input = InputExpr;
ExprValueKind VK = VK_RValue;
ExprObjectKind OK = OK_Ordinary;
QualType resultType;
@@ -9574,14 +9818,14 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
resultType = CheckAddressOfOperand(Input, OpLoc);
break;
case UO_Deref: {
- Input = DefaultFunctionArrayLvalueConversion(Input.take());
+ Input = DefaultFunctionArrayLvalueConversion(Input.get());
if (Input.isInvalid()) return ExprError();
resultType = CheckIndirectionOperand(*this, Input.get(), VK, OpLoc);
break;
}
case UO_Plus:
case UO_Minus:
- Input = UsualUnaryConversions(Input.take());
+ Input = UsualUnaryConversions(Input.get());
if (Input.isInvalid()) return ExprError();
resultType = Input.get()->getType();
if (resultType->isDependentType())
@@ -9598,7 +9842,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
<< resultType << Input.get()->getSourceRange());
case UO_Not: // bitwise complement
- Input = UsualUnaryConversions(Input.take());
+ Input = UsualUnaryConversions(Input.get());
if (Input.isInvalid())
return ExprError();
resultType = Input.get()->getType();
@@ -9629,24 +9873,24 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
case UO_LNot: // logical negation
// Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5).
- Input = DefaultFunctionArrayLvalueConversion(Input.take());
+ Input = DefaultFunctionArrayLvalueConversion(Input.get());
if (Input.isInvalid()) return ExprError();
resultType = Input.get()->getType();
// Though we still have to promote half FP to float...
if (resultType->isHalfType() && !Context.getLangOpts().NativeHalfType) {
- Input = ImpCastExprToType(Input.take(), Context.FloatTy, CK_FloatingCast).take();
+ Input = ImpCastExprToType(Input.get(), Context.FloatTy, CK_FloatingCast).get();
resultType = Context.FloatTy;
}
if (resultType->isDependentType())
break;
- if (resultType->isScalarType()) {
+ if (resultType->isScalarType() && !isScopedEnumerationType(resultType)) {
// C99 6.5.3.3p1: ok, fallthrough;
if (Context.getLangOpts().CPlusPlus) {
// C++03 [expr.unary.op]p8, C++0x [expr.unary.op]p9:
// operand contextually converted to bool.
- Input = ImpCastExprToType(Input.take(), Context.BoolTy,
+ Input = ImpCastExprToType(Input.get(), Context.BoolTy,
ScalarTypeToBooleanCastKind(resultType));
} else if (Context.getLangOpts().OpenCL &&
Context.getLangOpts().OpenCLVersion < 120) {
@@ -9690,7 +9934,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
VK = Input.get()->getValueKind();
} else if (!getLangOpts().CPlusPlus) {
// In C, a volatile scalar is read by __imag. In C++, it is not.
- Input = DefaultLvalueConversion(Input.take());
+ Input = DefaultLvalueConversion(Input.get());
}
break;
case UO_Extension:
@@ -9709,8 +9953,8 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
if (Opc != UO_AddrOf && Opc != UO_Deref)
CheckArrayAccess(Input.get());
- return Owned(new (Context) UnaryOperator(Input.take(), Opc, resultType,
- VK, OK, OpLoc));
+ return new (Context)
+ UnaryOperator(Input.get(), Opc, resultType, VK, OK, OpLoc);
}
/// \brief Determine whether the given expression is a qualified member
@@ -9780,7 +10024,7 @@ ExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc,
// Anything else needs to be handled now.
ExprResult Result = CheckPlaceholderExpr(Input);
if (Result.isInvalid()) return ExprError();
- Input = Result.take();
+ Input = Result.get();
}
if (getLangOpts().CPlusPlus && Input->getType()->isOverloadableType() &&
@@ -9813,8 +10057,8 @@ ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
LabelDecl *TheDecl) {
TheDecl->markUsed(Context);
// Create the AST node. The address of a label always has type 'void*'.
- return Owned(new (Context) AddrLabelExpr(OpLoc, LabLoc, TheDecl,
- Context.getPointerType(Context.VoidTy)));
+ return new (Context) AddrLabelExpr(OpLoc, LabLoc, TheDecl,
+ Context.getPointerType(Context.VoidTy));
}
/// Given the last statement in a statement-expression, check whether
@@ -9825,11 +10069,11 @@ ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
static Expr *maybeRebuildARCConsumingStmt(Stmt *Statement) {
// Should always be wrapped with one of these.
ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(Statement);
- if (!cleanups) return 0;
+ if (!cleanups) return nullptr;
ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(cleanups->getSubExpr());
if (!cast || cast->getCastKind() != CK_ARCConsumeObject)
- return 0;
+ return nullptr;
// Splice out the cast. This shouldn't modify any interesting
// features of the statement.
@@ -9864,7 +10108,7 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
PopExpressionEvaluationContext();
bool isFileScope
- = (getCurFunctionOrMethodDecl() == 0) && (getCurBlock() == 0);
+ = (getCurFunctionOrMethodDecl() == nullptr) && (getCurBlock() == nullptr);
if (isFileScope)
return ExprError(Diag(LPLoc, diag::err_stmtexpr_file_scope));
@@ -9872,13 +10116,13 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
// example, it is not possible to goto into a stmt expression apparently.
// More semantic analysis is needed.
- // If there are sub stmts in the compound stmt, take the type of the last one
+ // If there are sub-stmts in the compound stmt, take the type of the last one
// as the type of the stmtexpr.
QualType Ty = Context.VoidTy;
bool StmtExprMayBindToTemp = false;
if (!Compound->body_empty()) {
Stmt *LastStmt = Compound->body_back();
- LabelStmt *LastLabelStmt = 0;
+ LabelStmt *LastLabelStmt = nullptr;
// If LastStmt is a label, skip down through into the body.
while (LabelStmt *Label = dyn_cast<LabelStmt>(LastStmt)) {
LastLabelStmt = Label;
@@ -9914,11 +10158,11 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
if (LastExpr.isInvalid())
return ExprError();
- if (LastExpr.get() != 0) {
+ if (LastExpr.get() != nullptr) {
if (!LastLabelStmt)
- Compound->setLastStmt(LastExpr.take());
+ Compound->setLastStmt(LastExpr.get());
else
- LastLabelStmt->setSubStmt(LastExpr.take());
+ LastLabelStmt->setSubStmt(LastExpr.get());
StmtExprMayBindToTemp = true;
}
}
@@ -9930,7 +10174,7 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
Expr *ResStmtExpr = new (Context) StmtExpr(Compound, Ty, LPLoc, RPLoc);
if (StmtExprMayBindToTemp)
return MaybeBindToTemporary(ResStmtExpr);
- return Owned(ResStmtExpr);
+ return ResStmtExpr;
}
ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
@@ -9985,7 +10229,7 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
ExprResult IdxRval = DefaultLvalueConversion(static_cast<Expr*>(OC.U.E));
if (IdxRval.isInvalid())
return ExprError();
- Expr *Idx = IdxRval.take();
+ Expr *Idx = IdxRval.get();
// The expression must be an integral expression.
// FIXME: An integral constant expression?
@@ -10032,11 +10276,11 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
bool IsSafe = LangOpts.CPlusPlus11? CRD->isStandardLayout() : CRD->isPOD();
unsigned DiagID =
- LangOpts.CPlusPlus11? diag::warn_offsetof_non_standardlayout_type
- : diag::warn_offsetof_non_pod_type;
+ LangOpts.CPlusPlus11? diag::ext_offsetof_non_standardlayout_type
+ : diag::ext_offsetof_non_pod_type;
if (!IsSafe && !DidWarnAboutNonPOD &&
- DiagRuntimeBehavior(BuiltinLoc, 0,
+ DiagRuntimeBehavior(BuiltinLoc, nullptr,
PDiag(DiagID)
<< SourceRange(CompPtr[0].LocStart, OC.LocEnd)
<< CurrentType))
@@ -10047,7 +10291,7 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
LookupResult R(*this, OC.U.IdentInfo, OC.LocStart, LookupMemberName);
LookupQualifiedName(R, RD);
FieldDecl *MemberDecl = R.getAsSingle<FieldDecl>();
- IndirectFieldDecl *IndirectMemberDecl = 0;
+ IndirectFieldDecl *IndirectMemberDecl = nullptr;
if (!MemberDecl) {
if ((IndirectMemberDecl = R.getAsSingle<IndirectFieldDecl>()))
MemberDecl = IndirectMemberDecl->getAnonField();
@@ -10092,12 +10336,10 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
}
if (IndirectMemberDecl) {
- for (IndirectFieldDecl::chain_iterator FI =
- IndirectMemberDecl->chain_begin(),
- FEnd = IndirectMemberDecl->chain_end(); FI != FEnd; FI++) {
- assert(isa<FieldDecl>(*FI));
+ for (auto *FI : IndirectMemberDecl->chain()) {
+ assert(isa<FieldDecl>(FI));
Comps.push_back(OffsetOfNode(OC.LocStart,
- cast<FieldDecl>(*FI), OC.LocEnd));
+ cast<FieldDecl>(FI), OC.LocEnd));
}
} else
Comps.push_back(OffsetOfNode(OC.LocStart, MemberDecl, OC.LocEnd));
@@ -10105,8 +10347,8 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
CurrentType = MemberDecl->getType().getNonReferenceType();
}
- return Owned(OffsetOfExpr::Create(Context, Context.getSizeType(), BuiltinLoc,
- TInfo, Comps, Exprs, RParenLoc));
+ return OffsetOfExpr::Create(Context, Context.getSizeType(), BuiltinLoc, TInfo,
+ Comps, Exprs, RParenLoc);
}
ExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
@@ -10152,7 +10394,7 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
diag::err_typecheck_choose_expr_requires_constant, false);
if (CondICE.isInvalid())
return ExprError();
- CondExpr = CondICE.take();
+ CondExpr = CondICE.get();
CondIsTrue = condEval.getZExtValue();
// If the condition is > zero, then the AST type is the same as the LSHExpr.
@@ -10164,10 +10406,9 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
OK = ActiveExpr->getObjectKind();
}
- return Owned(new (Context) ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr,
- resType, VK, OK, RPLoc, CondIsTrue,
- resType->isDependentType(),
- ValueDependent));
+ return new (Context)
+ ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr, resType, VK, OK, RPLoc,
+ CondIsTrue, resType->isDependentType(), ValueDependent);
}
//===----------------------------------------------------------------------===//
@@ -10204,7 +10445,8 @@ void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) {
void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
Scope *CurScope) {
- assert(ParamInfo.getIdentifier()==0 && "block-id should have no identifier!");
+ assert(ParamInfo.getIdentifier() == nullptr &&
+ "block-id should have no identifier!");
assert(ParamInfo.getContext() == Declarator::BlockLiteralContext);
BlockScopeInfo *CurBlock = getCurBlock();
@@ -10241,7 +10483,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
ExplicitSignature.getLocalRangeEnd()) {
// This would be much cheaper if we stored TypeLocs instead of
// TypeSourceInfos.
- TypeLoc Result = ExplicitSignature.getResultLoc();
+ TypeLoc Result = ExplicitSignature.getReturnLoc();
unsigned Size = Result.getFullDataSize();
Sig = Context.CreateTypeSourceInfo(Result.getType(), Size);
Sig->getTypeLoc().initializeFullCopy(Result, Size);
@@ -10254,7 +10496,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
CurBlock->FunctionType = T;
const FunctionType *Fn = T->getAs<FunctionType>();
- QualType RetTy = Fn->getResultType();
+ QualType RetTy = Fn->getReturnType();
bool isVariadic =
(isa<FunctionProtoType>(Fn) && cast<FunctionProtoType>(Fn)->isVariadic());
@@ -10273,9 +10515,9 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
// Push block parameters from the declarator if we had them.
SmallVector<ParmVarDecl*, 8> Params;
if (ExplicitSignature) {
- for (unsigned I = 0, E = ExplicitSignature.getNumArgs(); I != E; ++I) {
- ParmVarDecl *Param = ExplicitSignature.getArg(I);
- if (Param->getIdentifier() == 0 &&
+ for (unsigned I = 0, E = ExplicitSignature.getNumParams(); I != E; ++I) {
+ ParmVarDecl *Param = ExplicitSignature.getParam(I);
+ if (Param->getIdentifier() == nullptr &&
!Param->isImplicit() &&
!Param->isInvalidDecl() &&
!getLangOpts().CPlusPlus)
@@ -10286,12 +10528,9 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
// Fake up parameter variables if we have a typedef, like
// ^ fntype { ... }
} else if (const FunctionProtoType *Fn = T->getAs<FunctionProtoType>()) {
- for (FunctionProtoType::arg_type_iterator
- I = Fn->arg_type_begin(), E = Fn->arg_type_end(); I != E; ++I) {
- ParmVarDecl *Param =
- BuildParmVarDeclForTypedef(CurBlock->TheDecl,
- ParamInfo.getLocStart(),
- *I);
+ for (const auto &I : Fn->param_types()) {
+ ParmVarDecl *Param = BuildParmVarDeclForTypedef(
+ CurBlock->TheDecl, ParamInfo.getLocStart(), I);
Params.push_back(Param);
}
}
@@ -10308,15 +10547,14 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
// Put the parameter variables in scope.
- for (BlockDecl::param_iterator AI = CurBlock->TheDecl->param_begin(),
- E = CurBlock->TheDecl->param_end(); AI != E; ++AI) {
- (*AI)->setOwningFunction(CurBlock->TheDecl);
+ for (auto AI : CurBlock->TheDecl->params()) {
+ AI->setOwningFunction(CurBlock->TheDecl);
// If this has an identifier, add it to the scope stack.
- if ((*AI)->getIdentifier()) {
- CheckShadow(CurBlock->TheScope, *AI);
+ if (AI->getIdentifier()) {
+ CheckShadow(CurBlock->TheScope, AI);
- PushOnScopeChains(*AI, CurBlock->TheScope);
+ PushOnScopeChains(AI, CurBlock->TheScope);
}
}
}
@@ -10358,7 +10596,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
if (!BSI->ReturnType.isNull())
RetTy = BSI->ReturnType;
- bool NoReturn = BSI->TheDecl->getAttr<NoReturnAttr>();
+ bool NoReturn = BSI->TheDecl->hasAttr<NoReturnAttr>();
QualType BlockTy;
// Set the captured variables on the block.
@@ -10390,7 +10628,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
// Otherwise, if we don't need to change anything about the function type,
// preserve its sugar structure.
- } else if (FTy->getResultType() == RetTy &&
+ } else if (FTy->getReturnType() == RetTy &&
(!NoReturn || FTy->getNoReturnAttr())) {
BlockTy = BSI->FunctionType;
@@ -10400,7 +10638,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.TypeQuals = 0; // FIXME: silently?
EPI.ExtInfo = Ext;
- BlockTy = Context.getFunctionType(RetTy, FPT->getArgTypes(), EPI);
+ BlockTy = Context.getFunctionType(RetTy, FPT->getParamTypes(), EPI);
}
// If we don't have a function type, just build one from nothing.
@@ -10416,7 +10654,6 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
// If needed, diagnose invalid gotos and switches in the block.
if (getCurFunction()->NeedsScopeChecking() &&
- !hasAnyUnrecoverableErrorsInThisFunction() &&
!PP.isCodeCompletionEnabled())
DiagnoseInvalidJumps(cast<CompoundStmt>(Body));
@@ -10427,7 +10664,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
// to deduce an implicit return type.
if (getLangOpts().CPlusPlus && RetTy->isRecordType() &&
!BSI->TheDecl->isDependentContext())
- computeNRVO(Body, getCurBlock());
+ computeNRVO(Body, BSI);
BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy);
AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
@@ -10442,10 +10679,8 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
// It also gets a branch-protected scope if any of the captured
// variables needs destruction.
- for (BlockDecl::capture_const_iterator
- ci = Result->getBlockDecl()->capture_begin(),
- ce = Result->getBlockDecl()->capture_end(); ci != ce; ++ci) {
- const VarDecl *var = ci->getVariable();
+ for (const auto &CI : Result->getBlockDecl()->captures()) {
+ const VarDecl *var = CI.getVariable();
if (var->getType().isDestructedType() != QualType::DK_none) {
getCurFunction()->setHasBranchProtectedScope();
break;
@@ -10453,7 +10688,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
}
}
- return Owned(Result);
+ return Result;
}
ExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc,
@@ -10480,7 +10715,7 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc,
ExprResult Result = UsualUnaryConversions(E);
if (Result.isInvalid())
return ExprError();
- E = Result.take();
+ E = Result.get();
} else if (VaListType->isRecordType() && getLangOpts().CPlusPlus) {
// If va_list is a record type and we are compiling in C++ mode,
// check the argument using reference binding.
@@ -10490,7 +10725,7 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc,
ExprResult Init = PerformCopyInitialization(Entity, SourceLocation(), E);
if (Init.isInvalid())
return ExprError();
- E = Init.takeAs<Expr>();
+ E = Init.getAs<Expr>();
} else {
// Otherwise, the va_list argument must be an l-value because
// it is modified by va_arg.
@@ -10546,7 +10781,7 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc,
}
QualType T = TInfo->getType().getNonLValueExprType(Context);
- return Owned(new (Context) VAArgExpr(BuiltinLoc, E, TInfo, RPLoc, T));
+ return new (Context) VAArgExpr(BuiltinLoc, E, TInfo, RPLoc, T);
}
ExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) {
@@ -10564,41 +10799,40 @@ ExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) {
llvm_unreachable("I don't know size of pointer!");
}
- return Owned(new (Context) GNUNullExpr(Ty, TokenLoc));
+ return new (Context) GNUNullExpr(Ty, TokenLoc);
}
-static void MakeObjCStringLiteralFixItHint(Sema& SemaRef, QualType DstType,
- Expr *SrcExpr, FixItHint &Hint,
- bool &IsNSString) {
- if (!SemaRef.getLangOpts().ObjC1)
- return;
+bool
+Sema::ConversionToObjCStringLiteralCheck(QualType DstType, Expr *&Exp) {
+ if (!getLangOpts().ObjC1)
+ return false;
const ObjCObjectPointerType *PT = DstType->getAs<ObjCObjectPointerType>();
if (!PT)
- return;
+ return false;
- // Check if the destination is of type 'id'.
if (!PT->isObjCIdType()) {
// Check if the destination is the 'NSString' interface.
const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
if (!ID || !ID->getIdentifier()->isStr("NSString"))
- return;
- IsNSString = true;
+ return false;
}
-
+
// Ignore any parens, implicit casts (should only be
// array-to-pointer decays), and not-so-opaque values. The last is
// important for making this trigger for property assignments.
- SrcExpr = SrcExpr->IgnoreParenImpCasts();
+ Expr *SrcExpr = Exp->IgnoreParenImpCasts();
if (OpaqueValueExpr *OV = dyn_cast<OpaqueValueExpr>(SrcExpr))
if (OV->getSourceExpr())
SrcExpr = OV->getSourceExpr()->IgnoreParenImpCasts();
StringLiteral *SL = dyn_cast<StringLiteral>(SrcExpr);
if (!SL || !SL->isAscii())
- return;
-
- Hint = FixItHint::CreateInsertion(SL->getLocStart(), "@");
+ return false;
+ Diag(SL->getLocStart(), diag::err_missing_atsign_prefix)
+ << FixItHint::CreateInsertion(SL->getLocStart(), "@");
+ Exp = BuildObjCStringLiteral(SL->getLocStart(), SL).get();
+ return true;
}
bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
@@ -10617,7 +10851,8 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
ConversionFixItGenerator ConvHints;
bool MayHaveConvFixit = false;
bool MayHaveFunctionDiff = false;
- bool IsNSString = false;
+ const ObjCInterfaceDecl *IFace = nullptr;
+ const ObjCProtocolDecl *PDecl = nullptr;
switch (ConvTy) {
case Compatible:
@@ -10635,7 +10870,6 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
MayHaveConvFixit = true;
break;
case IncompatiblePointer:
- MakeObjCStringLiteralFixItHint(*this, DstType, SrcExpr, Hint, IsNSString);
DiagKind =
(Action == AA_Passing_CFAudited ?
diag::err_arc_typecheck_convert_incompatible_pointer :
@@ -10649,8 +10883,6 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
SrcType = SrcType.getUnqualifiedType();
DstType = DstType.getUnqualifiedType();
}
- else if (IsNSString && !Hint.isNull())
- DiagKind = diag::warn_missing_atsign_prefix;
MayHaveConvFixit = true;
break;
case IncompatiblePointerSign:
@@ -10702,11 +10934,32 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
case IncompatibleBlockPointer:
DiagKind = diag::err_typecheck_convert_incompatible_block_pointer;
break;
- case IncompatibleObjCQualifiedId:
- // FIXME: Diagnose the problem in ObjCQualifiedIdTypesAreCompatible, since
- // it can give a more specific diagnostic.
+ case IncompatibleObjCQualifiedId: {
+ if (SrcType->isObjCQualifiedIdType()) {
+ const ObjCObjectPointerType *srcOPT =
+ SrcType->getAs<ObjCObjectPointerType>();
+ for (auto *srcProto : srcOPT->quals()) {
+ PDecl = srcProto;
+ break;
+ }
+ if (const ObjCInterfaceType *IFaceT =
+ DstType->getAs<ObjCObjectPointerType>()->getInterfaceType())
+ IFace = IFaceT->getDecl();
+ }
+ else if (DstType->isObjCQualifiedIdType()) {
+ const ObjCObjectPointerType *dstOPT =
+ DstType->getAs<ObjCObjectPointerType>();
+ for (auto *dstProto : dstOPT->quals()) {
+ PDecl = dstProto;
+ break;
+ }
+ if (const ObjCInterfaceType *IFaceT =
+ SrcType->getAs<ObjCObjectPointerType>()->getInterfaceType())
+ IFace = IFaceT->getDecl();
+ }
DiagKind = diag::warn_incompatible_qualified_id;
break;
+ }
case IncompatibleVectors:
DiagKind = diag::warn_incompatible_vectors;
break;
@@ -10764,7 +11017,11 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
HandleFunctionTypeMismatch(FDiag, SecondType, FirstType);
Diag(Loc, FDiag);
-
+ if (DiagKind == diag::warn_incompatible_qualified_id &&
+ PDecl && IFace && !IFace->hasDefinition())
+ Diag(IFace->getLocation(), diag::not_incomplete_class_and_qualified_id)
+ << IFace->getName() << PDecl->getName();
+
if (SecondType == Context.OverloadTy)
NoteAllOverloadCandidates(OverloadExpr::find(SrcExpr).Expression,
FirstType);
@@ -10784,7 +11041,7 @@ ExprResult Sema::VerifyIntegerConstantExpression(Expr *E,
llvm::APSInt *Result) {
class SimpleICEDiagnoser : public VerifyICEDiagnoser {
public:
- virtual void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) {
+ void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) override {
S.Diag(Loc, diag::err_expr_not_ice) << S.LangOpts.CPlusPlus << SR;
}
} Diagnoser;
@@ -10803,7 +11060,7 @@ ExprResult Sema::VerifyIntegerConstantExpression(Expr *E,
IDDiagnoser(unsigned DiagID)
: VerifyICEDiagnoser(DiagID == 0), DiagID(DiagID) { }
- virtual void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) {
+ void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) override {
S.Diag(Loc, DiagID) << SR;
}
} Diagnoser(DiagID);
@@ -10835,40 +11092,40 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
: ICEConvertDiagnoser(/*AllowScopedEnumerations*/false,
Silent, true) {}
- virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
- QualType T) {
+ SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
+ QualType T) override {
return S.Diag(Loc, diag::err_ice_not_integral) << T;
}
- virtual SemaDiagnosticBuilder diagnoseIncomplete(
- Sema &S, SourceLocation Loc, QualType T) {
+ SemaDiagnosticBuilder diagnoseIncomplete(
+ Sema &S, SourceLocation Loc, QualType T) override {
return S.Diag(Loc, diag::err_ice_incomplete_type) << T;
}
- virtual SemaDiagnosticBuilder diagnoseExplicitConv(
- Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
+ SemaDiagnosticBuilder diagnoseExplicitConv(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override {
return S.Diag(Loc, diag::err_ice_explicit_conversion) << T << ConvTy;
}
- virtual SemaDiagnosticBuilder noteExplicitConv(
- Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
+ SemaDiagnosticBuilder noteExplicitConv(
+ Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here)
<< ConvTy->isEnumeralType() << ConvTy;
}
- virtual SemaDiagnosticBuilder diagnoseAmbiguous(
- Sema &S, SourceLocation Loc, QualType T) {
+ SemaDiagnosticBuilder diagnoseAmbiguous(
+ Sema &S, SourceLocation Loc, QualType T) override {
return S.Diag(Loc, diag::err_ice_ambiguous_conversion) << T;
}
- virtual SemaDiagnosticBuilder noteAmbiguous(
- Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
+ SemaDiagnosticBuilder noteAmbiguous(
+ Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here)
<< ConvTy->isEnumeralType() << ConvTy;
}
- virtual SemaDiagnosticBuilder diagnoseConversion(
- Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
+ SemaDiagnosticBuilder diagnoseConversion(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override {
llvm_unreachable("conversion functions are permitted");
}
} ConvertDiagnoser(Diagnoser.Suppress);
@@ -10877,7 +11134,7 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
ConvertDiagnoser);
if (Converted.isInvalid())
return Converted;
- E = Converted.take();
+ E = Converted.get();
if (!E->getType()->isIntegralOrUnscopedEnumerationType())
return ExprError();
} else if (!E->getType()->isIntegralOrUnscopedEnumerationType()) {
@@ -10892,7 +11149,7 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
if (!getLangOpts().CPlusPlus11 && E->isIntegerConstantExpr(Context)) {
if (Result)
*Result = E->EvaluateKnownConstInt(Context);
- return Owned(E);
+ return E;
}
Expr::EvalResult EvalResult;
@@ -10910,7 +11167,7 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
if (Folded && getLangOpts().CPlusPlus11 && Notes.empty()) {
if (Result)
*Result = EvalResult.Val.getInt();
- return Owned(E);
+ return E;
}
// If our only note is the usual "invalid subexpression" note, just point
@@ -10938,7 +11195,7 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
if (Result)
*Result = EvalResult.Val.getInt();
- return Owned(E);
+ return E;
}
namespace {
@@ -10957,7 +11214,7 @@ namespace {
// FIXME: This does the right thing, but maybe we need a more general
// fix to TreeTransform?
StmtResult TransformLabelStmt(LabelStmt *S) {
- S->getDecl()->setStmt(0);
+ S->getDecl()->setStmt(nullptr);
return BaseTransform::TransformLabelStmt(S);
}
@@ -11174,37 +11431,32 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) {
// Note that this declaration has been used.
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Func)) {
+ Constructor = cast<CXXConstructorDecl>(Constructor->getFirstDecl());
if (Constructor->isDefaulted() && !Constructor->isDeleted()) {
if (Constructor->isDefaultConstructor()) {
- if (Constructor->isTrivial())
+ if (Constructor->isTrivial() && !Constructor->hasAttr<DLLExportAttr>())
return;
- if (!Constructor->isUsed(false))
- DefineImplicitDefaultConstructor(Loc, Constructor);
+ DefineImplicitDefaultConstructor(Loc, Constructor);
} else if (Constructor->isCopyConstructor()) {
- if (!Constructor->isUsed(false))
- DefineImplicitCopyConstructor(Loc, Constructor);
+ DefineImplicitCopyConstructor(Loc, Constructor);
} else if (Constructor->isMoveConstructor()) {
- if (!Constructor->isUsed(false))
- DefineImplicitMoveConstructor(Loc, Constructor);
+ DefineImplicitMoveConstructor(Loc, Constructor);
}
} else if (Constructor->getInheritedConstructor()) {
- if (!Constructor->isUsed(false))
- DefineInheritingConstructor(Loc, Constructor);
+ DefineInheritingConstructor(Loc, Constructor);
}
-
- MarkVTableUsed(Loc, Constructor->getParent());
} else if (CXXDestructorDecl *Destructor =
dyn_cast<CXXDestructorDecl>(Func)) {
- if (Destructor->isDefaulted() && !Destructor->isDeleted() &&
- !Destructor->isUsed(false))
+ Destructor = cast<CXXDestructorDecl>(Destructor->getFirstDecl());
+ if (Destructor->isDefaulted() && !Destructor->isDeleted())
DefineImplicitDestructor(Loc, Destructor);
if (Destructor->isVirtual())
MarkVTableUsed(Loc, Destructor->getParent());
} else if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(Func)) {
- if (MethodDecl->isDefaulted() && !MethodDecl->isDeleted() &&
- MethodDecl->isOverloadedOperator() &&
+ if (MethodDecl->isOverloadedOperator() &&
MethodDecl->getOverloadedOperator() == OO_Equal) {
- if (!MethodDecl->isUsed(false)) {
+ MethodDecl = cast<CXXMethodDecl>(MethodDecl->getFirstDecl());
+ if (MethodDecl->isDefaulted() && !MethodDecl->isDeleted()) {
if (MethodDecl->isCopyAssignmentOperator())
DefineImplicitCopyAssignment(Loc, MethodDecl);
else
@@ -11212,7 +11464,8 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) {
}
} else if (isa<CXXConversionDecl>(MethodDecl) &&
MethodDecl->getParent()->isLambda()) {
- CXXConversionDecl *Conversion = cast<CXXConversionDecl>(MethodDecl);
+ CXXConversionDecl *Conversion =
+ cast<CXXConversionDecl>(MethodDecl->getFirstDecl());
if (Conversion->isLambdaToBlockPointerConversion())
DefineImplicitLambdaToBlockPointerConversion(Loc, Conversion);
else
@@ -11276,10 +11529,9 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) {
}
} else {
// Walk redefinitions, as some of them may be instantiable.
- for (FunctionDecl::redecl_iterator i(Func->redecls_begin()),
- e(Func->redecls_end()); i != e; ++i) {
+ for (auto i : Func->redecls()) {
if (!i->isUsed(false) && i->isImplicitlyInstantiable())
- MarkFunctionReferenced(Loc, *i);
+ MarkFunctionReferenced(Loc, i);
}
}
@@ -11345,8 +11597,8 @@ diagnoseUncapturableValueReference(Sema &S, SourceLocation loc,
<< var->getIdentifier();
}
- S.Diag(var->getLocation(), diag::note_local_variable_declared_here)
- << var->getIdentifier();
+ S.Diag(var->getLocation(), diag::note_entity_declared_at)
+ << var->getIdentifier();
// FIXME: Add additional diagnostic info about class etc. which prevents
// capture.
@@ -11388,7 +11640,7 @@ static DeclContext *getParentOfCapturingContextOrNull(DeclContext *DC, VarDecl *
if (Diagnose)
diagnoseUncapturableValueReference(S, Loc, Var, DC);
}
- return 0;
+ return nullptr;
}
// Certain capturing entities (lambdas, blocks etc.) are not allowed to capture
@@ -11414,7 +11666,7 @@ static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var,
}
// Prohibit variably-modified types; they're difficult to deal with.
- if (Var->getType()->isVariablyModifiedType()) {
+ if (Var->getType()->isVariablyModifiedType() && (IsBlock || IsLambda)) {
if (Diagnose) {
if (IsBlock)
S.Diag(Loc, diag::err_ref_vm_type);
@@ -11465,7 +11717,7 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
QualType &DeclRefType,
const bool Nested,
Sema &S) {
- Expr *CopyExpr = 0;
+ Expr *CopyExpr = nullptr;
bool ByRef = false;
// Blocks are not allowed to capture arrays.
@@ -11523,7 +11775,7 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
= S.PerformCopyInitialization(
InitializedEntity::InitializeBlock(Var->getLocation(),
CaptureType, false),
- Loc, S.Owned(DeclRef));
+ Loc, DeclRef);
// Build a full-expression copy expression if initialization
// succeeded and used a non-trivial constructor. Recover from
@@ -11532,7 +11784,7 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
!cast<CXXConstructExpr>(Result.get())->getConstructor()
->isTrivial()) {
Result = S.MaybeCreateExprWithCleanups(Result);
- CopyExpr = Result.take();
+ CopyExpr = Result.get();
}
}
}
@@ -11562,18 +11814,17 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
bool ByRef = true;
// Using an LValue reference type is consistent with Lambdas (see below).
CaptureType = S.Context.getLValueReferenceType(DeclRefType);
- Expr *CopyExpr = 0;
+ Expr *CopyExpr = nullptr;
if (BuildAndDiagnose) {
// The current implementation assumes that all variables are captured
- // by references. Since there is no capture by copy, no expression evaluation
- // will be needed.
- //
+ // by references. Since there is no capture by copy, no expression
+ // evaluation will be needed.
RecordDecl *RD = RSI->TheRecordDecl;
FieldDecl *Field
- = FieldDecl::Create(S.Context, RD, Loc, Loc, 0, CaptureType,
+ = FieldDecl::Create(S.Context, RD, Loc, Loc, nullptr, CaptureType,
S.Context.getTrivialTypeSourceInfo(CaptureType, Loc),
- 0, false, ICIS_NoInit);
+ nullptr, false, ICIS_NoInit);
Field->setImplicit(true);
Field->setAccess(AS_private);
RD->addDecl(Field);
@@ -11605,9 +11856,9 @@ static ExprResult addAsFieldToClosureType(Sema &S,
// Build the non-static data member.
FieldDecl *Field
- = FieldDecl::Create(S.Context, Lambda, Loc, Loc, 0, FieldType,
+ = FieldDecl::Create(S.Context, Lambda, Loc, Loc, nullptr, FieldType,
S.Context.getTrivialTypeSourceInfo(FieldType, Loc),
- 0, false, ICIS_NoInit);
+ nullptr, false, ICIS_NoInit);
Field->setImplicit(true);
Field->setAccess(AS_private);
Lambda->addDecl(Field);
@@ -11645,7 +11896,7 @@ static ExprResult addAsFieldToClosureType(Sema &S,
while (const ConstantArrayType *Array
= S.Context.getAsConstantArrayType(BaseType)) {
// Create the iteration variable for this array index.
- IdentifierInfo *IterationVarName = 0;
+ IdentifierInfo *IterationVarName = nullptr;
{
SmallString<8> Str;
llvm::raw_svector_ostream OS(Str);
@@ -11665,20 +11916,20 @@ static ExprResult addAsFieldToClosureType(Sema &S,
= S.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc);
assert(!IterationVarRef.isInvalid() &&
"Reference to invented variable cannot fail!");
- IterationVarRef = S.DefaultLvalueConversion(IterationVarRef.take());
+ IterationVarRef = S.DefaultLvalueConversion(IterationVarRef.get());
assert(!IterationVarRef.isInvalid() &&
"Conversion of invented variable cannot fail!");
// Subscript the array with this iteration variable.
ExprResult Subscript = S.CreateBuiltinArraySubscriptExpr(
- Ref, Loc, IterationVarRef.take(), Loc);
+ Ref, Loc, IterationVarRef.get(), Loc);
if (Subscript.isInvalid()) {
S.CleanupVarDeclMarking();
S.DiscardCleanupsInEvaluationContext();
return ExprError();
}
- Ref = Subscript.take();
+ Ref = Subscript.get();
BaseType = Array->getElementType();
}
@@ -11778,19 +12029,28 @@ static bool captureInLambda(LambdaScopeInfo *LSI,
return false;
}
- if (S.RequireNonAbstractType(Loc, CaptureType,
- diag::err_capture_of_abstract_type))
- return false;
+ // Make sure that by-copy captures are of a complete and non-abstract type.
+ if (BuildAndDiagnose) {
+ if (!CaptureType->isDependentType() &&
+ S.RequireCompleteType(Loc, CaptureType,
+ diag::err_capture_of_incomplete_type,
+ Var->getDeclName()))
+ return false;
+
+ if (S.RequireNonAbstractType(Loc, CaptureType,
+ diag::err_capture_of_abstract_type))
+ return false;
+ }
}
// Capture this variable in the lambda.
- Expr *CopyExpr = 0;
+ Expr *CopyExpr = nullptr;
if (BuildAndDiagnose) {
ExprResult Result = addAsFieldToClosureType(S, LSI, Var,
CaptureType, DeclRefType, Loc,
RefersToEnclosingLocal);
if (!Result.isInvalid())
- CopyExpr = Result.take();
+ CopyExpr = Result.get();
}
// Compute the type of a reference to this captured variable.
@@ -11893,8 +12153,107 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc,
// certain types of variables (unnamed, variably modified types etc.)
// so check for eligibility.
if (!isVariableCapturable(CSI, Var, ExprLoc, BuildAndDiagnose, *this))
- return true;
-
+ return true;
+
+ // Try to capture variable-length arrays types.
+ if (Var->getType()->isVariablyModifiedType()) {
+ // We're going to walk down into the type and look for VLA
+ // expressions.
+ QualType QTy = Var->getType();
+ if (ParmVarDecl *PVD = dyn_cast_or_null<ParmVarDecl>(Var))
+ QTy = PVD->getOriginalType();
+ do {
+ const Type *Ty = QTy.getTypePtr();
+ switch (Ty->getTypeClass()) {
+#define TYPE(Class, Base)
+#define ABSTRACT_TYPE(Class, Base)
+#define NON_CANONICAL_TYPE(Class, Base)
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base)
+#include "clang/AST/TypeNodes.def"
+ QTy = QualType();
+ break;
+ // These types are never variably-modified.
+ case Type::Builtin:
+ case Type::Complex:
+ case Type::Vector:
+ case Type::ExtVector:
+ case Type::Record:
+ case Type::Enum:
+ case Type::Elaborated:
+ case Type::TemplateSpecialization:
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ case Type::ObjCObjectPointer:
+ llvm_unreachable("type class is never variably-modified!");
+ case Type::Adjusted:
+ QTy = cast<AdjustedType>(Ty)->getOriginalType();
+ break;
+ case Type::Decayed:
+ QTy = cast<DecayedType>(Ty)->getPointeeType();
+ break;
+ case Type::Pointer:
+ QTy = cast<PointerType>(Ty)->getPointeeType();
+ break;
+ case Type::BlockPointer:
+ QTy = cast<BlockPointerType>(Ty)->getPointeeType();
+ break;
+ case Type::LValueReference:
+ case Type::RValueReference:
+ QTy = cast<ReferenceType>(Ty)->getPointeeType();
+ break;
+ case Type::MemberPointer:
+ QTy = cast<MemberPointerType>(Ty)->getPointeeType();
+ break;
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ // Losing element qualification here is fine.
+ QTy = cast<ArrayType>(Ty)->getElementType();
+ break;
+ case Type::VariableArray: {
+ // Losing element qualification here is fine.
+ const VariableArrayType *Vat = cast<VariableArrayType>(Ty);
+
+ // Unknown size indication requires no size computation.
+ // Otherwise, evaluate and record it.
+ if (Expr *Size = Vat->getSizeExpr()) {
+ MarkDeclarationsReferencedInExpr(Size);
+ }
+ QTy = Vat->getElementType();
+ break;
+ }
+ case Type::FunctionProto:
+ case Type::FunctionNoProto:
+ QTy = cast<FunctionType>(Ty)->getReturnType();
+ break;
+ case Type::Paren:
+ case Type::TypeOf:
+ case Type::UnaryTransform:
+ case Type::Attributed:
+ case Type::SubstTemplateTypeParm:
+ case Type::PackExpansion:
+ // Keep walking after single level desugaring.
+ QTy = QTy.getSingleStepDesugaredType(getASTContext());
+ break;
+ case Type::Typedef:
+ QTy = cast<TypedefType>(Ty)->desugar();
+ break;
+ case Type::Decltype:
+ QTy = cast<DecltypeType>(Ty)->desugar();
+ break;
+ case Type::Auto:
+ QTy = cast<AutoType>(Ty)->getDeducedType();
+ break;
+ case Type::TypeOfExpr:
+ QTy = cast<TypeOfExprType>(Ty)->getUnderlyingExpr()->getType();
+ break;
+ case Type::Atomic:
+ QTy = cast<AtomicType>(Ty)->getValueType();
+ break;
+ }
+ } while (!QTy.isNull() && QTy->isVariablyModifiedType());
+ }
+
if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None && !Explicit) {
// No capture-default, and this is not an explicit capture
// so cannot capture this variable.
@@ -11964,7 +12323,7 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc,
QualType DeclRefType;
return tryCaptureVariable(Var, Loc, Kind, EllipsisLoc,
/*BuildAndDiagnose=*/true, CaptureType,
- DeclRefType, 0);
+ DeclRefType, nullptr);
}
QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) {
@@ -11974,7 +12333,7 @@ QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) {
// Determine whether we can capture this variable.
if (tryCaptureVariable(Var, Loc, TryCapture_Implicit, SourceLocation(),
/*BuildAndDiagnose=*/false, CaptureType,
- DeclRefType, 0))
+ DeclRefType, nullptr))
return QualType();
return DeclRefType;
@@ -11991,7 +12350,7 @@ static inline bool IsVariableNonDependentAndAConstantExpression(VarDecl *Var,
if (Var->getType()->isDependentType())
return false;
- const VarDecl *DefVD = 0;
+ const VarDecl *DefVD = nullptr;
Var->getAnyInitializer(DefVD);
if (!DefVD)
return false;
@@ -12017,7 +12376,7 @@ void Sema::UpdateMarkingForLValueToRValue(Expr *E) {
// variable.
if (LambdaScopeInfo *LSI = getCurLambda()) {
Expr *SansParensExpr = E->IgnoreParens();
- VarDecl *Var = 0;
+ VarDecl *Var = nullptr;
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SansParensExpr))
Var = dyn_cast<VarDecl>(DRE->getFoundDecl());
else if (MemberExpr *ME = dyn_cast<MemberExpr>(SansParensExpr))
@@ -12056,7 +12415,8 @@ void Sema::CleanupVarDeclMarking() {
llvm_unreachable("Unexpcted expression");
}
- MarkVarDeclODRUsed(Var, Loc, *this, /*MaxFunctionScopeIndex Pointer*/ 0);
+ MarkVarDeclODRUsed(Var, Loc, *this,
+ /*MaxFunctionScopeIndex Pointer*/ nullptr);
}
MaybeODRUseExprs.clear();
@@ -12069,42 +12429,39 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
"Invalid Expr argument to DoMarkVarDeclReferenced");
Var->setReferenced();
- // If the context is not PotentiallyEvaluated and not Unevaluated
- // (i.e PotentiallyEvaluatedIfUsed) do not bother to consider variables
- // in this context for odr-use unless we are within a lambda.
- // If we don't know whether the context is potentially evaluated or not
- // (for e.g., if we're in a generic lambda), we want to add a potential
- // capture and eventually analyze for odr-use.
- // We should also be able to analyze certain constructs in a non-generic
- // lambda setting for potential odr-use and capture violation:
- // template<class T> void foo(T t) {
- // auto L = [](int i) { return t; };
- // }
- //
+ // If the context is not potentially evaluated, this is not an odr-use and
+ // does not trigger instantiation.
if (!IsPotentiallyEvaluatedContext(SemaRef)) {
+ if (SemaRef.isUnevaluatedContext())
+ return;
- if (SemaRef.isUnevaluatedContext()) return;
+ // If we don't yet know whether this context is going to end up being an
+ // evaluated context, and we're referencing a variable from an enclosing
+ // scope, add a potential capture.
+ //
+ // FIXME: Is this necessary? These contexts are only used for default
+ // arguments, where local variables can't be used.
+ const bool RefersToEnclosingScope =
+ (SemaRef.CurContext != Var->getDeclContext() &&
+ Var->getDeclContext()->isFunctionOrMethod() &&
+ Var->hasLocalStorage());
+ if (!RefersToEnclosingScope)
+ return;
- const bool refersToEnclosingScope =
- (SemaRef.CurContext != Var->getDeclContext() &&
- Var->getDeclContext()->isFunctionOrMethod());
- if (!refersToEnclosingScope) return;
-
if (LambdaScopeInfo *const LSI = SemaRef.getCurLambda()) {
// If a variable could potentially be odr-used, defer marking it so
- // until we finish analyzing the full expression for any lvalue-to-rvalue
+ // until we finish analyzing the full expression for any lvalue-to-rvalue
// or discarded value conversions that would obviate odr-use.
// Add it to the list of potential captures that will be analyzed
// later (ActOnFinishFullExpr) for eventual capture and odr-use marking
// unless the variable is a reference that was initialized by a constant
// expression (this will never need to be captured or odr-used).
- const bool IsConstantExpr = IsVariableNonDependentAndAConstantExpression(
- Var, SemaRef.Context);
assert(E && "Capture variable should be used in an expression.");
- if (!IsConstantExpr || !Var->getType()->isReferenceType())
- LSI->addPotentialCapture(E->IgnoreParens());
- }
- return;
+ if (!Var->getType()->isReferenceType() ||
+ !IsVariableNonDependentAndAConstantExpression(Var, SemaRef.Context))
+ LSI->addPotentialCapture(E->IgnoreParens());
+ }
+ return;
}
VarTemplateSpecializationDecl *VarSpec =
@@ -12112,10 +12469,10 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
assert(!isa<VarTemplatePartialSpecializationDecl>(Var) &&
"Can't instantiate a partial template specialization.");
- // Implicit instantiation of static data members, static data member
- // templates of class templates, and variable template specializations.
- // Delay instantiations of variable templates, except for those
- // that could be used in a constant expression.
+ // Perform implicit instantiation of static data members, static data member
+ // templates of class templates, and variable template specializations. Delay
+ // instantiations of variable templates, except for those that could be used
+ // in a constant expression.
TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind();
if (isTemplateInstantiation(TSK)) {
bool TryInstantiating = TSK == TSK_ImplicitInstantiation;
@@ -12155,6 +12512,7 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
}
}
}
+
// Per C++11 [basic.def.odr], a variable is odr-used "unless it satisfies
// the requirements for appearing in a constant expression (5.19) and, if
// it is an object, the lvalue-to-rvalue conversion (4.1)
@@ -12164,22 +12522,20 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
// C++03 depends on whether we get the C++03 version correct. The second
// part does not apply to references, since they are not objects.
if (E && IsVariableAConstantExpression(Var, SemaRef.Context)) {
- // A reference initialized by a constant expression can never be
+ // A reference initialized by a constant expression can never be
// odr-used, so simply ignore it.
- // But a non-reference might get odr-used if it doesn't undergo
- // an lvalue-to-rvalue or is discarded, so track it.
if (!Var->getType()->isReferenceType())
SemaRef.MaybeODRUseExprs.insert(E);
- }
- else
- MarkVarDeclODRUsed(Var, Loc, SemaRef, /*MaxFunctionScopeIndex ptr*/0);
+ } else
+ MarkVarDeclODRUsed(Var, Loc, SemaRef,
+ /*MaxFunctionScopeIndex ptr*/ nullptr);
}
/// \brief 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) {
- DoMarkVarDeclReferenced(*this, Loc, Var, 0);
+ DoMarkVarDeclReferenced(*this, Loc, Var, nullptr);
}
static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc,
@@ -12241,9 +12597,9 @@ void Sema::MarkMemberReferenced(MemberExpr *E) {
}
/// \brief 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 an normal
-/// expression which refers to a variable.
+/// 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.
void Sema::MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, bool OdrUse) {
if (OdrUse) {
if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
@@ -12277,7 +12633,7 @@ namespace {
}
bool MarkReferencedDecls::TraverseTemplateArgument(
- const TemplateArgument &Arg) {
+ const TemplateArgument &Arg) {
if (Arg.getKind() == TemplateArgument::Declaration) {
if (Decl *D = Arg.getAsDecl())
S.MarkAnyDeclReferenced(Loc, D, true);
@@ -12324,7 +12680,7 @@ namespace {
S.MarkDeclRefReferenced(E);
}
-
+
void VisitMemberExpr(MemberExpr *E) {
S.MarkMemberReferenced(E);
Inherited::VisitMemberExpr(E);
@@ -12447,8 +12803,8 @@ bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc,
public:
CallReturnIncompleteDiagnoser(FunctionDecl *FD, CallExpr *CE)
: FD(FD), CE(CE) { }
-
- virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
+
+ void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
if (!FD) {
S.Diag(Loc, diag::err_call_incomplete_return)
<< T << CE->getSourceRange();
@@ -12457,9 +12813,8 @@ bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc,
S.Diag(Loc, diag::err_call_function_incomplete_return)
<< CE->getSourceRange() << FD->getDeclName() << T;
- S.Diag(FD->getLocation(),
- diag::note_function_with_incomplete_return_type_declared_here)
- << FD->getDeclName();
+ S.Diag(FD->getLocation(), diag::note_entity_declared_at)
+ << FD->getDeclName();
}
} Diagnoser(FD, CE);
@@ -12563,7 +12918,7 @@ ExprResult Sema::CheckBooleanCondition(Expr *E, SourceLocation Loc) {
ExprResult result = CheckPlaceholderExpr(E);
if (result.isInvalid()) return ExprError();
- E = result.take();
+ E = result.get();
if (!E->isTypeDependent()) {
if (getLangOpts().CPlusPlus)
@@ -12572,7 +12927,7 @@ ExprResult Sema::CheckBooleanCondition(Expr *E, SourceLocation Loc) {
ExprResult ERes = DefaultFunctionArrayLvalueConversion(E);
if (ERes.isInvalid())
return ExprError();
- E = ERes.take();
+ E = ERes.get();
QualType T = E->getType();
if (!T->isScalarType()) { // C99 6.8.4.1p1
@@ -12582,7 +12937,7 @@ ExprResult Sema::CheckBooleanCondition(Expr *E, SourceLocation Loc) {
}
}
- return Owned(E);
+ return E;
}
ExprResult Sema::ActOnBooleanCondition(Scope *S, SourceLocation Loc,
@@ -12619,7 +12974,7 @@ namespace {
ExprResult SubResult = Visit(E->getSubExpr());
if (SubResult.isInvalid()) return ExprError();
- Expr *SubExpr = SubResult.take();
+ Expr *SubExpr = SubResult.get();
E->setSubExpr(SubExpr);
E->setType(SubExpr->getType());
E->setValueKind(SubExpr->getValueKind());
@@ -12639,7 +12994,7 @@ namespace {
ExprResult SubResult = Visit(E->getSubExpr());
if (SubResult.isInvalid()) return ExprError();
- Expr *SubExpr = SubResult.take();
+ Expr *SubExpr = SubResult.get();
E->setSubExpr(SubExpr);
E->setType(S.Context.getPointerType(SubExpr->getType()));
assert(E->getValueKind() == VK_RValue);
@@ -12676,7 +13031,7 @@ namespace {
static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *FunctionExpr) {
ExprResult Result = RebuildUnknownAnyFunction(S).Visit(FunctionExpr);
if (Result.isInvalid()) return ExprError();
- return S.DefaultFunctionArrayConversion(Result.take());
+ return S.DefaultFunctionArrayConversion(Result.get());
}
namespace {
@@ -12713,7 +13068,7 @@ namespace {
template <class T> ExprResult rebuildSugarExpr(T *E) {
ExprResult SubResult = Visit(E->getSubExpr());
if (SubResult.isInvalid()) return ExprError();
- Expr *SubExpr = SubResult.take();
+ Expr *SubExpr = SubResult.get();
E->setSubExpr(SubExpr);
E->setType(SubExpr->getType());
E->setValueKind(SubExpr->getValueKind());
@@ -12744,7 +13099,7 @@ namespace {
DestType = Ptr->getPointeeType();
ExprResult SubResult = Visit(E->getSubExpr());
if (SubResult.isInvalid()) return ExprError();
- E->setSubExpr(SubResult.take());
+ E->setSubExpr(SubResult.get());
return E;
}
@@ -12825,7 +13180,7 @@ ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *E) {
// This is a hack, but it is far superior to moving the
// corresponding target-specific code from IR-gen to Sema/AST.
- ArrayRef<QualType> ParamTypes = Proto->getArgTypes();
+ ArrayRef<QualType> ParamTypes = Proto->getParamTypes();
SmallVector<QualType, 8> ArgTypes;
if (ParamTypes.empty() && Proto->isVariadic()) { // the special case
ArgTypes.reserve(E->getNumArgs());
@@ -12866,7 +13221,7 @@ ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *E) {
// Finally, we can recurse.
ExprResult CalleeResult = Visit(CalleeExpr);
if (!CalleeResult.isUsable()) return ExprError();
- E->setCallee(CalleeResult.take());
+ E->setCallee(CalleeResult.get());
// Bind a temporary if necessary.
return S.MaybeBindToTemporary(E);
@@ -12882,8 +13237,8 @@ ExprResult RebuildUnknownAnyExpr::VisitObjCMessageExpr(ObjCMessageExpr *E) {
// Rewrite the method result type if available.
if (ObjCMethodDecl *Method = E->getMethodDecl()) {
- assert(Method->getResultType() == S.Context.UnknownAnyTy);
- Method->setResultType(DestType);
+ assert(Method->getReturnType() == S.Context.UnknownAnyTy);
+ Method->setReturnType(DestType);
}
// Change the type of the message.
@@ -12907,8 +13262,8 @@ ExprResult RebuildUnknownAnyExpr::VisitImplicitCastExpr(ImplicitCastExpr *E) {
ExprResult Result = Visit(E->getSubExpr());
if (!Result.isUsable()) return ExprError();
- E->setSubExpr(Result.take());
- return S.Owned(E);
+ E->setSubExpr(Result.get());
+ return E;
} else if (E->getCastKind() == CK_LValueToRValue) {
assert(E->getValueKind() == VK_RValue);
assert(E->getObjectKind() == OK_Ordinary);
@@ -12923,8 +13278,8 @@ ExprResult RebuildUnknownAnyExpr::VisitImplicitCastExpr(ImplicitCastExpr *E) {
ExprResult Result = Visit(E->getSubExpr());
if (!Result.isUsable()) return ExprError();
- E->setSubExpr(Result.take());
- return S.Owned(E);
+ E->setSubExpr(Result.get());
+ return E;
} else {
llvm_unreachable("Unhandled cast type!");
}
@@ -12942,7 +13297,7 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) {
DestType = Ptr->getPointeeType();
ExprResult Result = resolveDecl(E, VD);
if (Result.isInvalid()) return ExprError();
- return S.ImpCastExprToType(Result.take(), Type,
+ return S.ImpCastExprToType(Result.get(), Type,
CK_FunctionToPointerDecay, VK_RValue);
}
@@ -12984,7 +13339,7 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) {
VD->setType(DestType);
E->setType(Type);
E->setValueKind(ValueKind);
- return S.Owned(E);
+ return E;
}
/// Check a cast of an unknown-any type. We intentionally only
@@ -12996,7 +13351,7 @@ ExprResult Sema::checkUnknownAnyCast(SourceRange TypeRange, QualType CastType,
ExprResult result = RebuildUnknownAnyExpr(*this, CastType).Visit(CastExpr);
if (!result.isUsable()) return ExprError();
- CastExpr = result.take();
+ CastExpr = result.get();
VK = CastExpr->getValueKind();
CastKind = CK_NoOp;
@@ -13027,7 +13382,7 @@ ExprResult Sema::checkUnknownAnyArg(SourceLocation callLoc,
InitializedEntity entity =
InitializedEntity::InitializeParameter(Context, paramType,
/*consumed*/ false);
- return PerformCopyInitialization(entity, callLoc, Owned(arg));
+ return PerformCopyInitialization(entity, callLoc, arg);
}
static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *E) {
@@ -13077,7 +13432,7 @@ static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *E) {
/// Returns true if there was an error and no recovery was possible.
ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
const BuiltinType *placeholderType = E->getType()->getAsPlaceholderType();
- if (!placeholderType) return Owned(E);
+ if (!placeholderType) return E;
switch (placeholderType->getKind()) {
@@ -13085,7 +13440,7 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
case BuiltinType::Overload: {
// Try to resolve a single function template specialization.
// This is obligatory.
- ExprResult result = Owned(E);
+ ExprResult result = E;
if (ResolveAndFixSingleFunctionTemplateSpecialization(result, false)) {
return result;
@@ -13099,7 +13454,7 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
// Bound member functions.
case BuiltinType::BoundMember: {
- ExprResult result = Owned(E);
+ ExprResult result = E;
tryToRecoverWithCall(result, PDiag(diag::err_bound_member_function),
/*complain*/ true);
return result;
@@ -13109,7 +13464,7 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
case BuiltinType::ARCUnbridgedCast: {
Expr *realCast = stripARCUnbridgedCast(E);
diagnoseARCUnbridgedCast(realCast);
- return Owned(realCast);
+ return realCast;
}
// Expressions of unknown type.
@@ -13120,9 +13475,22 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
case BuiltinType::PseudoObject:
return checkPseudoObjectRValue(E);
- case BuiltinType::BuiltinFn:
+ case BuiltinType::BuiltinFn: {
+ // Accept __noop without parens by implicitly converting it to a call expr.
+ auto *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts());
+ if (DRE) {
+ auto *FD = cast<FunctionDecl>(DRE->getDecl());
+ if (FD->getBuiltinID() == Builtin::BI__noop) {
+ E = ImpCastExprToType(E, Context.getPointerType(FD->getType()),
+ CK_BuiltinFnToFnPtr).get();
+ return new (Context) CallExpr(Context, E, None, Context.IntTy,
+ VK_RValue, SourceLocation());
+ }
+ }
+
Diag(E->getLocStart(), diag::err_builtin_fn_use);
return ExprError();
+ }
// Everything else should be impossible.
#define BUILTIN_TYPE(Id, SingletonId) \
@@ -13160,6 +13528,6 @@ Sema::ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) {
}
if (Context.getBOOLDecl())
BoolT = Context.getBOOLType();
- return Owned(new (Context) ObjCBoolLiteralExpr(Kind == tok::kw___objc_yes,
- BoolT, OpLoc));
+ return new (Context)
+ ObjCBoolLiteralExpr(Kind == tok::kw___objc_yes, BoolT, OpLoc);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
index 20118b5..0dabdca 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
@@ -15,6 +15,7 @@
#include "clang/Sema/SemaInternal.h"
#include "TypeLocBuilder.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTLambda.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclObjC.h"
@@ -106,7 +107,7 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
// For this reason, we're currently only doing the C++03 version of this
// code; the C++0x version has to wait until we get a proper spec.
QualType SearchType;
- DeclContext *LookupCtx = 0;
+ DeclContext *LookupCtx = nullptr;
bool isDependent = false;
bool LookInScope = false;
@@ -117,38 +118,33 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
SearchType = GetTypeFromParser(ObjectTypePtr);
if (SS.isSet()) {
- NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
+ NestedNameSpecifier *NNS = SS.getScopeRep();
bool AlreadySearched = false;
bool LookAtPrefix = true;
- // C++ [basic.lookup.qual]p6:
+ // C++11 [basic.lookup.qual]p6:
// If a pseudo-destructor-name (5.2.4) contains a nested-name-specifier,
// the type-names are looked up as types in the scope designated by the
- // nested-name-specifier. In a qualified-id of the form:
+ // nested-name-specifier. Similarly, in a qualified-id of the form:
//
- // ::[opt] nested-name-specifier ~ class-name
+ // nested-name-specifier[opt] class-name :: ~ class-name
//
- // where the nested-name-specifier designates a namespace scope, and in
- // a qualified-id of the form:
+ // the second class-name is looked up in the same scope as the first.
//
- // ::opt nested-name-specifier class-name :: ~ class-name
- //
- // the class-names are looked up as types in the scope designated by
- // the nested-name-specifier.
- //
- // Here, we check the first case (completely) and determine whether the
- // code below is permitted to look at the prefix of the
- // nested-name-specifier.
+ // Here, we determine whether the code below is permitted to look at the
+ // prefix of the nested-name-specifier.
DeclContext *DC = computeDeclContext(SS, EnteringContext);
if (DC && DC->isFileContext()) {
AlreadySearched = true;
LookupCtx = DC;
isDependent = false;
- } else if (DC && isa<CXXRecordDecl>(DC))
+ } else if (DC && isa<CXXRecordDecl>(DC)) {
LookAtPrefix = false;
+ LookInScope = true;
+ }
// The second case from the C++03 rules quoted further above.
- NestedNameSpecifier *Prefix = 0;
+ NestedNameSpecifier *Prefix = nullptr;
if (AlreadySearched) {
// Nothing left to do.
} else if (LookAtPrefix && (Prefix = NNS->getPrefix())) {
@@ -163,8 +159,6 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
LookupCtx = computeDeclContext(SS, EnteringContext);
isDependent = LookupCtx && LookupCtx->isDependentContext();
}
-
- LookInScope = false;
} else if (ObjectTypePtr) {
// C++ [basic.lookup.classref]p3:
// If the unqualified-id is ~type-name, the type-name is looked up
@@ -184,7 +178,7 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
LookInScope = true;
}
- TypeDecl *NonMatchingTypeDecl = 0;
+ TypeDecl *NonMatchingTypeDecl = nullptr;
LookupResult Found(*this, &II, NameLoc, LookupOrdinaryName);
for (unsigned Step = 0; Step != 2; ++Step) {
// Look for the name first in the computed lookup context (if we
@@ -209,7 +203,8 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
Context.hasSameUnqualifiedType(T, SearchType)) {
// We found our type!
- return ParsedType::make(T);
+ return CreateParsedType(T,
+ Context.getTrivialTypeSourceInfo(T, NameLoc));
}
if (!SearchType.isNull())
@@ -245,7 +240,9 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
= dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
if (Spec->getSpecializedTemplate()->getCanonicalDecl() ==
Template->getCanonicalDecl())
- return ParsedType::make(MemberOfType);
+ return CreateParsedType(
+ MemberOfType,
+ Context.getTrivialTypeSourceInfo(MemberOfType, NameLoc));
}
continue;
@@ -264,7 +261,9 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
// specialized.
if (TemplateDecl *SpecTemplate = SpecName.getAsTemplateDecl()) {
if (SpecTemplate->getCanonicalDecl() == Template->getCanonicalDecl())
- return ParsedType::make(MemberOfType);
+ return CreateParsedType(
+ MemberOfType,
+ Context.getTrivialTypeSourceInfo(MemberOfType, NameLoc));
continue;
}
@@ -275,7 +274,9 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
= SpecName.getAsDependentTemplateName()) {
if (DepTemplate->isIdentifier() &&
DepTemplate->getIdentifier() == Template->getIdentifier())
- return ParsedType::make(MemberOfType);
+ return CreateParsedType(
+ MemberOfType,
+ Context.getTrivialTypeSourceInfo(MemberOfType, NameLoc));
continue;
}
@@ -333,6 +334,34 @@ ParsedType Sema::getDestructorType(const DeclSpec& DS, ParsedType ObjectType) {
return ParsedType();
}
+bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS,
+ const UnqualifiedId &Name) {
+ assert(Name.getKind() == UnqualifiedId::IK_LiteralOperatorId);
+
+ if (!SS.isValid())
+ return false;
+
+ switch (SS.getScopeRep()->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ // Per C++11 [over.literal]p2, literal operators can only be declared at
+ // namespace scope. Therefore, this unqualified-id cannot name anything.
+ // Reject it early, because we have no AST representation for this in the
+ // case where the scope is dependent.
+ Diag(Name.getLocStart(), diag::err_literal_operator_id_outside_namespace)
+ << SS.getScopeRep();
+ return true;
+
+ case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
+ return false;
+ }
+
+ llvm_unreachable("unknown nested name specifier kind");
+}
+
/// \brief Build a C++ typeid expression with a type operand.
ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
SourceLocation TypeidLoc,
@@ -351,9 +380,8 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
RequireCompleteType(TypeidLoc, T, diag::err_incomplete_typeid))
return ExprError();
- return Owned(new (Context) CXXTypeidExpr(TypeInfoType.withConst(),
- Operand,
- SourceRange(TypeidLoc, RParenLoc)));
+ return new (Context) CXXTypeidExpr(TypeInfoType.withConst(), Operand,
+ SourceRange(TypeidLoc, RParenLoc));
}
/// \brief Build a C++ typeid expression with an expression operand.
@@ -365,7 +393,7 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
if (E->getType()->isPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(E);
if (result.isInvalid()) return ExprError();
- E = result.take();
+ E = result.get();
}
QualType T = E->getType();
@@ -386,7 +414,7 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
// and recheck the subexpression.
ExprResult Result = TransformToPotentiallyEvaluated(E);
if (Result.isInvalid()) return ExprError();
- E = Result.take();
+ E = Result.get();
// We require a vtable to query the type at run time.
MarkVTableUsed(TypeidLoc, RecordD);
@@ -402,13 +430,12 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
QualType UnqualT = Context.getUnqualifiedArrayType(T, Quals);
if (!Context.hasSameType(T, UnqualT)) {
T = UnqualT;
- E = ImpCastExprToType(E, UnqualT, CK_NoOp, E->getValueKind()).take();
+ E = ImpCastExprToType(E, UnqualT, CK_NoOp, E->getValueKind()).get();
}
}
- return Owned(new (Context) CXXTypeidExpr(TypeInfoType.withConst(),
- E,
- SourceRange(TypeidLoc, RParenLoc)));
+ return new (Context) CXXTypeidExpr(TypeInfoType.withConst(), E,
+ SourceRange(TypeidLoc, RParenLoc));
}
/// ActOnCXXTypeidOfType - Parse typeid( type-id ) or typeid (expression);
@@ -426,7 +453,7 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
CXXTypeInfoDecl = R.getAsSingle<RecordDecl>();
// Microsoft's typeinfo doesn't have type_info in std but in the global
// namespace if _HAS_EXCEPTIONS is defined to 0. See PR13153.
- if (!CXXTypeInfoDecl && LangOpts.MicrosoftMode) {
+ if (!CXXTypeInfoDecl && LangOpts.MSVCCompat) {
LookupQualifiedName(R, Context.getTranslationUnitDecl());
CXXTypeInfoDecl = R.getAsSingle<RecordDecl>();
}
@@ -442,7 +469,7 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
if (isType) {
// The operand is a type; handle it as such.
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
QualType T = GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrExpr),
&TInfo);
if (T.isNull())
@@ -474,9 +501,8 @@ ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType,
}
}
- return Owned(new (Context) CXXUuidofExpr(TypeInfoType.withConst(),
- Operand,
- SourceRange(TypeidLoc, RParenLoc)));
+ return new (Context) CXXUuidofExpr(TypeInfoType.withConst(), Operand,
+ SourceRange(TypeidLoc, RParenLoc));
}
/// \brief Build a Microsoft __uuidof expression with an expression operand.
@@ -495,9 +521,8 @@ ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType,
}
}
- return Owned(new (Context) CXXUuidofExpr(TypeInfoType.withConst(),
- E,
- SourceRange(TypeidLoc, RParenLoc)));
+ return new (Context) CXXUuidofExpr(TypeInfoType.withConst(), E,
+ SourceRange(TypeidLoc, RParenLoc));
}
/// ActOnCXXUuidof - Parse __uuidof( type-id ) or __uuidof (expression);
@@ -518,7 +543,7 @@ Sema::ActOnCXXUuidof(SourceLocation OpLoc, SourceLocation LParenLoc,
if (isType) {
// The operand is a type; handle it as such.
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
QualType T = GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrExpr),
&TInfo);
if (T.isNull())
@@ -539,14 +564,14 @@ ExprResult
Sema::ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) {
assert((Kind == tok::kw_true || Kind == tok::kw_false) &&
"Unknown C++ Boolean value!");
- return Owned(new (Context) CXXBoolLiteralExpr(Kind == tok::kw_true,
- Context.BoolTy, OpLoc));
+ return new (Context)
+ CXXBoolLiteralExpr(Kind == tok::kw_true, Context.BoolTy, OpLoc);
}
/// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
ExprResult
Sema::ActOnCXXNullPtrLiteral(SourceLocation Loc) {
- return Owned(new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc));
+ return new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc);
}
/// ActOnCXXThrow - Parse throw expressions.
@@ -593,16 +618,19 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex,
if (!getLangOpts().CXXExceptions &&
!getSourceManager().isInSystemHeader(OpLoc))
Diag(OpLoc, diag::err_exceptions_disabled) << "throw";
-
+
+ if (getCurScope() && getCurScope()->isOpenMPSimdDirectiveScope())
+ Diag(OpLoc, diag::err_omp_simd_region_cannot_use_stmt) << "throw";
+
if (Ex && !Ex->isTypeDependent()) {
ExprResult ExRes = CheckCXXThrowOperand(OpLoc, Ex, IsThrownVarInScope);
if (ExRes.isInvalid())
return ExprError();
- Ex = ExRes.take();
+ Ex = ExRes.get();
}
- return Owned(new (Context) CXXThrowExpr(Ex, Context.VoidTy, OpLoc,
- IsThrownVarInScope));
+ return new (Context)
+ CXXThrowExpr(Ex, Context.VoidTy, OpLoc, IsThrownVarInScope);
}
/// CheckCXXThrowOperand - Validate the operand of a throw.
@@ -616,12 +644,12 @@ ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E,
// or "pointer to function returning T", [...]
if (E->getType().hasQualifiers())
E = ImpCastExprToType(E, E->getType().getUnqualifiedType(), CK_NoOp,
- E->getValueKind()).take();
+ E->getValueKind()).get();
ExprResult Res = DefaultFunctionArrayConversion(E);
if (Res.isInvalid())
return ExprError();
- E = Res.take();
+ E = Res.get();
// If the type of the exception would be an incomplete type or a pointer
// to an incomplete type other than (cv) void the program is ill-formed.
@@ -657,24 +685,24 @@ ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E,
// operation from the operand to the exception object (15.1) can be
// omitted by constructing the automatic object directly into the
// exception object
- const VarDecl *NRVOVariable = 0;
+ const VarDecl *NRVOVariable = nullptr;
if (IsThrownVarInScope)
NRVOVariable = getCopyElisionCandidate(QualType(), E, false);
-
+
InitializedEntity Entity =
InitializedEntity::InitializeException(ThrowLoc, E->getType(),
- /*NRVO=*/NRVOVariable != 0);
+ /*NRVO=*/NRVOVariable != nullptr);
Res = PerformMoveOrCopyInitialization(Entity, NRVOVariable,
QualType(), E,
IsThrownVarInScope);
if (Res.isInvalid())
return ExprError();
- E = Res.take();
+ E = Res.get();
// If the exception has class type, we need additional handling.
const RecordType *RecordTy = Ty->getAs<RecordType>();
if (!RecordTy)
- return Owned(E);
+ return E;
CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
// If we are throwing a polymorphic class type or pointer thereof,
@@ -683,22 +711,22 @@ ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E,
// If a pointer is thrown, the referenced object will not be destroyed.
if (isPointer)
- return Owned(E);
+ return E;
// If the class has a destructor, we must be able to call it.
if (RD->hasIrrelevantDestructor())
- return Owned(E);
+ return E;
CXXDestructorDecl *Destructor = LookupDestructor(RD);
if (!Destructor)
- return Owned(E);
+ return E;
MarkFunctionReferenced(E->getExprLoc(), Destructor);
CheckDestructorAccess(E->getExprLoc(), Destructor,
PDiag(diag::err_access_dtor_exception) << Ty);
if (DiagnoseUseOfDecl(Destructor, E->getExprLoc()))
return ExprError();
- return Owned(E);
+ return E;
}
QualType Sema::getCurrentThisType() {
@@ -708,7 +736,20 @@ QualType Sema::getCurrentThisType() {
if (method && method->isInstance())
ThisTy = method->getThisType(Context);
}
-
+ if (ThisTy.isNull()) {
+ if (isGenericLambdaCallOperatorSpecialization(CurContext) &&
+ CurContext->getParent()->getParent()->isRecord()) {
+ // This is a generic lambda call operator that is being instantiated
+ // within a default initializer - so use the enclosing class as 'this'.
+ // There is no enclosing member function to retrieve the 'this' pointer
+ // from.
+ QualType ClassTy = Context.getTypeDeclType(
+ cast<CXXRecordDecl>(CurContext->getParent()->getParent()));
+ // There are no cv-qualifiers for 'this' within default initializers,
+ // per [expr.prim.general]p4.
+ return Context.getPointerType(ClassTy);
+ }
+ }
return ThisTy;
}
@@ -720,8 +761,8 @@ Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S,
{
if (!Enabled || !ContextDecl)
return;
-
- CXXRecordDecl *Record = 0;
+
+ CXXRecordDecl *Record = nullptr;
if (ClassTemplateDecl *Template = dyn_cast<ClassTemplateDecl>(ContextDecl))
Record = Template->getTemplatedDecl();
else
@@ -744,9 +785,9 @@ Sema::CXXThisScopeRAII::~CXXThisScopeRAII() {
static Expr *captureThis(ASTContext &Context, RecordDecl *RD,
QualType ThisTy, SourceLocation Loc) {
FieldDecl *Field
- = FieldDecl::Create(Context, RD, Loc, Loc, 0, ThisTy,
+ = FieldDecl::Create(Context, RD, Loc, Loc, nullptr, ThisTy,
Context.getTrivialTypeSourceInfo(ThisTy, Loc),
- 0, false, ICIS_NoInit);
+ nullptr, false, ICIS_NoInit);
Field->setImplicit(true);
Field->setAccess(AS_private);
RD->addDecl(Field);
@@ -801,7 +842,7 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, bool Explicit,
for (unsigned idx = MaxFunctionScopesIndex; NumClosures;
--idx, --NumClosures) {
CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[idx]);
- Expr *ThisExpr = 0;
+ Expr *ThisExpr = nullptr;
QualType ThisTy = getCurrentThisType();
if (LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(CSI))
// For lambda expressions, build a field and an initializing expression.
@@ -825,7 +866,7 @@ ExprResult Sema::ActOnCXXThis(SourceLocation Loc) {
if (ThisTy.isNull()) return Diag(Loc, diag::err_invalid_this_use);
CheckCXXThisCapture(Loc);
- return Owned(new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit=*/false));
+ return new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit=*/false);
}
bool Sema::isThisOutsideMemberFunctionBody(QualType BaseType) {
@@ -869,10 +910,8 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
SourceLocation TyBeginLoc = TInfo->getTypeLoc().getBeginLoc();
if (Ty->isDependentType() || CallExpr::hasAnyTypeDependentArguments(Exprs)) {
- return Owned(CXXUnresolvedConstructExpr::Create(Context, TInfo,
- LParenLoc,
- Exprs,
- RParenLoc));
+ return CXXUnresolvedConstructExpr::Create(Context, TInfo, LParenLoc, Exprs,
+ RParenLoc);
}
bool ListInitialization = LParenLoc.isInvalid();
@@ -928,9 +967,9 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
// want, since it will be treated as an initializer list in further
// processing. Explicitly insert a cast here.
QualType ResultType = Result.get()->getType();
- Result = Owned(CXXFunctionalCastExpr::Create(
+ Result = CXXFunctionalCastExpr::Create(
Context, ResultType, Expr::getValueKindForType(TInfo->getType()), TInfo,
- CK_NoOp, Result.take(), /*Path=*/ 0, LParenLoc, RParenLoc));
+ CK_NoOp, Result.get(), /*Path=*/nullptr, LParenLoc, RParenLoc);
}
// FIXME: Improve AST representation?
@@ -1016,7 +1055,7 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
Declarator &D, Expr *Initializer) {
bool TypeContainsAuto = D.getDeclSpec().containsPlaceholderType();
- Expr *ArraySize = 0;
+ Expr *ArraySize = nullptr;
// If the specified type is an array, unwrap it and save the expression.
if (D.getNumTypeObjects() > 0 &&
D.getTypeObject(0).Kind == DeclaratorChunk::Array) {
@@ -1054,12 +1093,12 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
Array.NumElts
= CheckConvertedConstantExpression(NumElts, Context.getSizeType(), Value,
CCEK_NewExpr)
- .take();
+ .get();
} else {
Array.NumElts
- = VerifyIntegerConstantExpression(NumElts, 0,
+ = VerifyIntegerConstantExpression(NumElts, nullptr,
diag::err_new_array_nonconst)
- .take();
+ .get();
}
if (!Array.NumElts)
return ExprError();
@@ -1068,7 +1107,7 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
}
}
- TypeSourceInfo *TInfo = GetTypeForDeclarator(D, /*Scope=*/0);
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, /*Scope=*/nullptr);
QualType AllocType = TInfo->getType();
if (D.isInvalidType())
return ExprError();
@@ -1145,22 +1184,15 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
NumInits = List->getNumExprs();
}
- // Determine whether we've already built the initializer.
- bool HaveCompleteInit = false;
- if (Initializer && isa<CXXConstructExpr>(Initializer) &&
- !isa<CXXTemporaryObjectExpr>(Initializer))
- HaveCompleteInit = true;
- else if (Initializer && isa<ImplicitValueInitExpr>(Initializer))
- HaveCompleteInit = true;
-
- // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
+ // C++11 [dcl.spec.auto]p6. Deduce the type which 'auto' stands in for.
if (TypeMayContainAuto && AllocType->isUndeducedType()) {
if (initStyle == CXXNewExpr::NoInit || NumInits == 0)
return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg)
<< AllocType << TypeRange);
- if (initStyle == CXXNewExpr::ListInit)
+ if (initStyle == CXXNewExpr::ListInit ||
+ (NumInits == 1 && isa<InitListExpr>(Inits[0])))
return ExprError(Diag(Inits[0]->getLocStart(),
- diag::err_auto_new_requires_parens)
+ diag::err_auto_new_list_init)
<< AllocType << TypeRange);
if (NumInits > 1) {
Expr *FirstBad = Inits[1];
@@ -1194,7 +1226,8 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
if (CheckAllocatedType(AllocType, TypeRange.getBegin(), TypeRange))
return ExprError();
- if (initStyle == CXXNewExpr::ListInit && isStdInitializerList(AllocType, 0)) {
+ 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();
@@ -1213,7 +1246,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
if (ArraySize && ArraySize->getType()->isNonOverloadPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(ArraySize);
if (result.isInvalid()) return ExprError();
- ArraySize = result.take();
+ ArraySize = result.get();
}
// C++98 5.3.4p6: "The expression in a direct-new-declarator shall have
// integral or enumeration type with a non-negative value."
@@ -1225,9 +1258,8 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
if (ArraySize && !ArraySize->isTypeDependent()) {
ExprResult ConvertedSize;
if (getLangOpts().CPlusPlus1y) {
- unsigned IntWidth = Context.getTargetInfo().getIntWidth();
- assert(IntWidth && "Builtin type of size 0?");
- llvm::APSInt Value(IntWidth);
+ assert(Context.getTargetInfo().getIntWidth() && "Builtin type of size 0?");
+
ConvertedSize = PerformImplicitConversion(ArraySize, Context.getSizeType(),
AA_Converting);
@@ -1245,43 +1277,43 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
SizeConvertDiagnoser(Expr *ArraySize)
: ICEConvertDiagnoser(/*AllowScopedEnumerations*/false, false, false),
ArraySize(ArraySize) {}
-
- virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
- QualType T) {
+
+ SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
+ QualType T) override {
return S.Diag(Loc, diag::err_array_size_not_integral)
<< S.getLangOpts().CPlusPlus11 << T;
}
-
- virtual SemaDiagnosticBuilder diagnoseIncomplete(
- Sema &S, SourceLocation Loc, QualType T) {
+
+ SemaDiagnosticBuilder diagnoseIncomplete(
+ Sema &S, SourceLocation Loc, QualType T) override {
return S.Diag(Loc, diag::err_array_size_incomplete_type)
<< T << ArraySize->getSourceRange();
}
-
- virtual SemaDiagnosticBuilder diagnoseExplicitConv(
- Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
+
+ SemaDiagnosticBuilder diagnoseExplicitConv(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override {
return S.Diag(Loc, diag::err_array_size_explicit_conversion) << T << ConvTy;
}
-
- virtual SemaDiagnosticBuilder noteExplicitConv(
- Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
+
+ SemaDiagnosticBuilder noteExplicitConv(
+ Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
return S.Diag(Conv->getLocation(), diag::note_array_size_conversion)
<< ConvTy->isEnumeralType() << ConvTy;
}
-
- virtual SemaDiagnosticBuilder diagnoseAmbiguous(
- Sema &S, SourceLocation Loc, QualType T) {
+
+ SemaDiagnosticBuilder diagnoseAmbiguous(
+ Sema &S, SourceLocation Loc, QualType T) override {
return S.Diag(Loc, diag::err_array_size_ambiguous_conversion) << T;
}
-
- virtual SemaDiagnosticBuilder noteAmbiguous(
- Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
+
+ SemaDiagnosticBuilder noteAmbiguous(
+ Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
return S.Diag(Conv->getLocation(), diag::note_array_size_conversion)
<< ConvTy->isEnumeralType() << ConvTy;
}
virtual SemaDiagnosticBuilder diagnoseConversion(
- Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override {
return S.Diag(Loc,
S.getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_array_size_conversion
@@ -1296,7 +1328,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
if (ConvertedSize.isInvalid())
return ExprError();
- ArraySize = ConvertedSize.take();
+ ArraySize = ConvertedSize.get();
QualType SizeType = ArraySize->getType();
if (!SizeType->isIntegralOrUnscopedEnumerationType())
@@ -1359,8 +1391,8 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
// be signed, larger than size_t, whatever.
}
- FunctionDecl *OperatorNew = 0;
- FunctionDecl *OperatorDelete = 0;
+ FunctionDecl *OperatorNew = nullptr;
+ FunctionDecl *OperatorDelete = nullptr;
if (!AllocType->isDependentType() &&
!Expr::hasAnyTypeDependentArguments(PlacementArgs) &&
@@ -1379,12 +1411,14 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
SmallVector<Expr *, 8> AllPlaceArgs;
if (OperatorNew) {
- // Add default arguments, if any.
const FunctionProtoType *Proto =
- OperatorNew->getType()->getAs<FunctionProtoType>();
- VariadicCallType CallType =
- Proto->isVariadic() ? VariadicFunction : VariadicDoesNotApply;
+ OperatorNew->getType()->getAs<FunctionProtoType>();
+ VariadicCallType CallType = Proto->isVariadic() ? VariadicFunction
+ : VariadicDoesNotApply;
+ // We've already converted the placement args, just fill in any default
+ // arguments. Skip the first parameter because we don't have a corresponding
+ // argument.
if (GatherArgumentsForCall(PlacementLParen, OperatorNew, Proto, 1,
PlacementArgs, AllPlaceArgs, CallType))
return ExprError();
@@ -1392,6 +1426,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
if (!AllPlaceArgs.empty())
PlacementArgs = AllPlaceArgs;
+ // FIXME: This is wrong: PlacementArgs misses out the first (size) argument.
DiagnoseSentinelCalls(OperatorNew, PlacementLParen, PlacementArgs);
// FIXME: Missing call to CheckFunctionCall or equivalent
@@ -1438,8 +1473,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
// do it now.
if (!AllocType->isDependentType() &&
!Expr::hasAnyTypeDependentArguments(
- llvm::makeArrayRef(Inits, NumInits)) &&
- !HaveCompleteInit) {
+ llvm::makeArrayRef(Inits, NumInits))) {
// C++11 [expr.new]p15:
// A new-expression that creates an object of type T initializes that
// object as follows:
@@ -1469,9 +1503,9 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
// we don't want the initialized object to be destructed.
if (CXXBindTemporaryExpr *Binder =
dyn_cast_or_null<CXXBindTemporaryExpr>(FullInit.get()))
- FullInit = Owned(Binder->getSubExpr());
+ FullInit = Binder->getSubExpr();
- Initializer = FullInit.take();
+ Initializer = FullInit.get();
}
// Mark the new and delete operators as referenced.
@@ -1504,13 +1538,11 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
}
}
- return Owned(new (Context) CXXNewExpr(Context, UseGlobal, OperatorNew,
- OperatorDelete,
- UsualArrayDeleteWantsSize,
- PlacementArgs, TypeIdParens,
- ArraySize, initStyle, Initializer,
- ResultType, AllocTypeInfo,
- Range, DirectInitRange));
+ return new (Context)
+ CXXNewExpr(Context, UseGlobal, OperatorNew, OperatorDelete,
+ UsualArrayDeleteWantsSize, PlacementArgs, TypeIdParens,
+ ArraySize, initStyle, Initializer, ResultType, AllocTypeInfo,
+ Range, DirectInitRange);
}
/// \brief Checks that a type is suitable as the allocated type
@@ -1623,7 +1655,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
// Didn't find a member overload. Look for a global one.
DeclareGlobalNewDelete();
DeclContext *TUDecl = Context.getTranslationUnitDecl();
- bool FallbackEnabled = IsArray && Context.getLangOpts().MicrosoftMode;
+ bool FallbackEnabled = IsArray && Context.getLangOpts().MSVCCompat;
if (FindAllocationOverload(StartLoc, Range, NewName, AllocArgs, TUDecl,
/*AllowMissing=*/FallbackEnabled, OperatorNew,
/*Diagnose=*/!FallbackEnabled)) {
@@ -1645,15 +1677,10 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
// We don't need an operator delete if we're running under
// -fno-exceptions.
if (!getLangOpts().Exceptions) {
- OperatorDelete = 0;
+ OperatorDelete = nullptr;
return false;
}
- // FindAllocationOverload can change the passed in arguments, so we need to
- // copy them back.
- if (!PlaceArgs.empty())
- std::copy(AllocArgs.begin() + 1, AllocArgs.end(), PlaceArgs.data());
-
// C++ [expr.new]p19:
//
// If the new-expression begins with a unary :: operator, the
@@ -1708,8 +1735,8 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
SmallVector<QualType, 4> ArgTypes;
ArgTypes.push_back(Context.VoidPtrTy);
- for (unsigned I = 1, N = Proto->getNumArgs(); I < N; ++I)
- ArgTypes.push_back(Proto->getArgType(I));
+ for (unsigned I = 1, N = Proto->getNumParams(); I < N; ++I)
+ ArgTypes.push_back(Proto->getParamType(I));
FunctionProtoType::ExtProtoInfo EPI;
EPI.Variadic = Proto->isVariadic();
@@ -1721,13 +1748,14 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
for (LookupResult::iterator D = FoundDelete.begin(),
DEnd = FoundDelete.end();
D != DEnd; ++D) {
- FunctionDecl *Fn = 0;
+ FunctionDecl *Fn = nullptr;
if (FunctionTemplateDecl *FnTmpl
= dyn_cast<FunctionTemplateDecl>((*D)->getUnderlyingDecl())) {
// Perform template argument deduction to try to match the
// expected function type.
TemplateDeductionInfo Info(StartLoc);
- if (DeduceTemplateArguments(FnTmpl, 0, ExpectedFunctionType, Fn, Info))
+ if (DeduceTemplateArguments(FnTmpl, nullptr, ExpectedFunctionType, Fn,
+ Info))
continue;
} else
Fn = cast<FunctionDecl>((*D)->getUnderlyingDecl());
@@ -1763,7 +1791,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
else
Matches.erase(Matches.begin() + 1);
assert(Matches[0].second->getNumParams() == 2 &&
- "found an unexpected uusal deallocation function");
+ "found an unexpected usual deallocation function");
}
}
@@ -1797,8 +1825,22 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
return false;
}
-/// FindAllocationOverload - Find an fitting overload for the allocation
-/// function in the specified scope.
+/// \brief Find an fitting overload for the allocation function
+/// in the specified scope.
+///
+/// \param StartLoc The location of the 'new' token.
+/// \param Range The range of the placement arguments.
+/// \param Name The name of the function ('operator new' or 'operator new[]').
+/// \param Args The placement arguments specified.
+/// \param Ctx The scope in which we should search; either a class scope or the
+/// translation unit.
+/// \param AllowMissing If \c true, report an error if we can't find any
+/// allocation functions. Otherwise, succeed but don't fill in \p
+/// Operator.
+/// \param Operator Filled in with the found allocation function. Unchanged if
+/// no allocation function was found.
+/// \param Diagnose If \c true, issue errors if the allocation function is not
+/// usable.
bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
DeclarationName Name, MultiExprArg Args,
DeclContext *Ctx,
@@ -1818,7 +1860,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
R.suppressDiagnostics();
- OverloadCandidateSet Candidates(StartLoc);
+ OverloadCandidateSet Candidates(StartLoc, OverloadCandidateSet::CSK_Normal);
for (LookupResult::iterator Alloc = R.begin(), AllocEnd = R.end();
Alloc != AllocEnd; ++Alloc) {
// Even member operator new/delete are implicitly treated as
@@ -1827,7 +1869,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
if (FunctionTemplateDecl *FnTemplate = dyn_cast<FunctionTemplateDecl>(D)) {
AddTemplateOverloadCandidate(FnTemplate, Alloc.getPair(),
- /*ExplicitTemplateArgs=*/0,
+ /*ExplicitTemplateArgs=*/nullptr,
Args, Candidates,
/*SuppressUserConversions=*/false);
continue;
@@ -1844,33 +1886,11 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
case OR_Success: {
// Got one!
FunctionDecl *FnDecl = Best->Function;
- MarkFunctionReferenced(StartLoc, FnDecl);
- // The first argument is size_t, and the first parameter must be size_t,
- // too. This is checked on declaration and can be assumed. (It can't be
- // asserted on, though, since invalid decls are left in there.)
- // Watch out for variadic allocator function.
- unsigned NumArgsInFnDecl = FnDecl->getNumParams();
- for (unsigned i = 0; (i < Args.size() && i < NumArgsInFnDecl); ++i) {
- InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
- FnDecl->getParamDecl(i));
-
- if (!Diagnose && !CanPerformCopyInitialization(Entity, Owned(Args[i])))
- return true;
-
- ExprResult Result
- = PerformCopyInitialization(Entity, SourceLocation(), Owned(Args[i]));
- if (Result.isInvalid())
- return true;
-
- Args[i] = Result.takeAs<Expr>();
- }
-
- Operator = FnDecl;
-
if (CheckAllocationAccess(StartLoc, Range, R.getNamingClass(),
Best->FoundDecl, Diagnose) == AR_inaccessible)
return true;
+ Operator = FnDecl;
return false;
}
@@ -1970,7 +1990,7 @@ void Sema::DeclareGlobalNewDelete() {
getOrCreateStdNamespace(),
SourceLocation(), SourceLocation(),
&PP.getIdentifierTable().get("bad_alloc"),
- 0);
+ nullptr);
getStdBadAlloc()->setImplicit(true);
}
@@ -2031,8 +2051,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
if (InitialParam1Type == Param1 &&
(NumParams == 1 || InitialParam2Type == Param2)) {
if (AddMallocAttr && !Func->hasAttr<MallocAttr>())
- Func->addAttr(::new (Context) MallocAttr(SourceLocation(),
- Context));
+ Func->addAttr(MallocAttr::CreateImplicit(Context));
// Make the function visible to name lookup, even if we found it in
// an unimported module. It either is an implicitly-declared global
// allocation function, or is suppressing that function.
@@ -2043,18 +2062,16 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
}
}
+ FunctionProtoType::ExtProtoInfo EPI;
+
QualType BadAllocType;
bool HasBadAllocExceptionSpec
= (Name.getCXXOverloadedOperator() == OO_New ||
Name.getCXXOverloadedOperator() == OO_Array_New);
- if (HasBadAllocExceptionSpec && !getLangOpts().CPlusPlus11) {
- assert(StdBadAlloc && "Must have std::bad_alloc declared");
- BadAllocType = Context.getTypeDeclType(getStdBadAlloc());
- }
-
- FunctionProtoType::ExtProtoInfo EPI;
if (HasBadAllocExceptionSpec) {
if (!getLangOpts().CPlusPlus11) {
+ BadAllocType = Context.getTypeDeclType(getStdBadAlloc());
+ assert(StdBadAlloc && "Must have std::bad_alloc declared");
EPI.ExceptionSpecType = EST_Dynamic;
EPI.NumExceptions = 1;
EPI.Exceptions = &BadAllocType;
@@ -2071,24 +2088,24 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
FunctionDecl *Alloc =
FunctionDecl::Create(Context, GlobalCtx, SourceLocation(),
SourceLocation(), Name,
- FnType, /*TInfo=*/0, SC_None, false, true);
+ FnType, /*TInfo=*/nullptr, SC_None, false, true);
Alloc->setImplicit();
if (AddMallocAttr)
- Alloc->addAttr(::new (Context) MallocAttr(SourceLocation(), Context));
+ Alloc->addAttr(MallocAttr::CreateImplicit(Context));
ParmVarDecl *ParamDecls[2];
- for (unsigned I = 0; I != NumParams; ++I)
+ for (unsigned I = 0; I != NumParams; ++I) {
ParamDecls[I] = ParmVarDecl::Create(Context, Alloc, SourceLocation(),
- SourceLocation(), 0,
- Params[I], /*TInfo=*/0,
- SC_None, 0);
+ SourceLocation(), nullptr,
+ Params[I], /*TInfo=*/nullptr,
+ SC_None, nullptr);
+ ParamDecls[I]->setImplicit();
+ }
Alloc->setParams(ArrayRef<ParmVarDecl*>(ParamDecls, NumParams));
- // FIXME: Also add this declaration to the IdentifierResolver, but
- // make sure it is at the end of the chain to coincide with the
- // global scope.
Context.getTranslationUnitDecl()->addDecl(Alloc);
+ IdResolver.tryAddTopLevelDecl(Alloc, Name);
}
FunctionDecl *Sema::FindUsualDeallocationFunction(SourceLocation StartLoc,
@@ -2125,7 +2142,7 @@ FunctionDecl *Sema::FindUsualDeallocationFunction(SourceLocation StartLoc,
else
Matches.erase(Matches.begin() + 1);
assert(Matches[0]->getNumParams() == NumArgs &&
- "found an unexpected uusal deallocation function");
+ "found an unexpected usual deallocation function");
}
assert(Matches.size() == 1 &&
@@ -2206,7 +2223,7 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
return true;
}
- Operator = 0;
+ Operator = nullptr;
return false;
}
@@ -2224,14 +2241,14 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
//
// DR599 amends "pointer type" to "pointer to object type" in both cases.
- ExprResult Ex = Owned(ExE);
- FunctionDecl *OperatorDelete = 0;
+ ExprResult Ex = ExE;
+ FunctionDecl *OperatorDelete = nullptr;
bool ArrayFormAsWritten = ArrayForm;
bool UsualArrayDeleteWantsSize = false;
if (!Ex.get()->isTypeDependent()) {
// Perform lvalue-to-rvalue cast, if needed.
- Ex = DefaultLvalueConversion(Ex.take());
+ Ex = DefaultLvalueConversion(Ex.get());
if (Ex.isInvalid())
return ExprError();
@@ -2241,7 +2258,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
public:
DeleteConverter() : ContextualImplicitConverter(false, true) {}
- bool match(QualType ConvType) {
+ bool match(QualType ConvType) override {
// FIXME: If we have an operator T* and an operator void*, we must pick
// the operator T*.
if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
@@ -2251,44 +2268,46 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
}
SemaDiagnosticBuilder diagnoseNoMatch(Sema &S, SourceLocation Loc,
- QualType T) {
+ QualType T) override {
return S.Diag(Loc, diag::err_delete_operand) << T;
}
SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
- QualType T) {
+ QualType T) override {
return S.Diag(Loc, diag::err_delete_incomplete_class_type) << T;
}
SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
- QualType T, QualType ConvTy) {
+ QualType T,
+ QualType ConvTy) override {
return S.Diag(Loc, diag::err_delete_explicit_conversion) << T << ConvTy;
}
SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
- QualType ConvTy) {
+ QualType ConvTy) override {
return S.Diag(Conv->getLocation(), diag::note_delete_conversion)
<< ConvTy;
}
SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
- QualType T) {
+ QualType T) override {
return S.Diag(Loc, diag::err_ambiguous_delete_operand) << T;
}
SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
- QualType ConvTy) {
+ QualType ConvTy) override {
return S.Diag(Conv->getLocation(), diag::note_delete_conversion)
<< ConvTy;
}
SemaDiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc,
- QualType T, QualType ConvTy) {
+ QualType T,
+ QualType ConvTy) override {
llvm_unreachable("conversion functions are permitted");
}
} Converter;
- Ex = PerformContextualImplicitConversion(StartLoc, Ex.take(), Converter);
+ Ex = PerformContextualImplicitConversion(StartLoc, Ex.get(), Converter);
if (Ex.isInvalid())
return ExprError();
Type = Ex.get()->getType();
@@ -2305,7 +2324,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
diag::err_address_space_qualified_delete)
<< Pointee.getUnqualifiedType() << AddressSpace;
- CXXRecordDecl *PointeeRD = 0;
+ CXXRecordDecl *PointeeRD = nullptr;
if (Pointee->isVoidType() && !isSFINAEContext()) {
// The C++ standard bans deleting a pointer to a non-object type, which
// effectively bans deletion of "void*". However, most compilers support
@@ -2413,10 +2432,9 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
}
}
- return Owned(new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm,
- ArrayFormAsWritten,
- UsualArrayDeleteWantsSize,
- OperatorDelete, Ex.take(), StartLoc));
+ return new (Context) CXXDeleteExpr(
+ Context.VoidTy, UseGlobal, ArrayForm, ArrayFormAsWritten,
+ UsualArrayDeleteWantsSize, OperatorDelete, Ex.get(), StartLoc);
}
/// \brief Check the use of the given variable as a C++ condition in an if,
@@ -2440,19 +2458,15 @@ ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar,
diag::err_invalid_use_of_array_type)
<< ConditionVar->getSourceRange());
- ExprResult Condition =
- Owned(DeclRefExpr::Create(Context, NestedNameSpecifierLoc(),
- SourceLocation(),
- ConditionVar,
- /*enclosing*/ false,
- ConditionVar->getLocation(),
- ConditionVar->getType().getNonReferenceType(),
- VK_LValue));
+ ExprResult Condition = DeclRefExpr::Create(
+ Context, NestedNameSpecifierLoc(), SourceLocation(), ConditionVar,
+ /*enclosing*/ false, ConditionVar->getLocation(),
+ ConditionVar->getType().getNonReferenceType(), VK_LValue);
MarkDeclRefReferenced(cast<DeclRefExpr>(Condition.get()));
if (ConvertToBoolean) {
- Condition = CheckBooleanCondition(Condition.take(), StmtLoc);
+ Condition = CheckBooleanCondition(Condition.get(), StmtLoc);
if (Condition.isInvalid())
return ExprError();
}
@@ -2537,15 +2551,15 @@ static ExprResult BuildCXXCastArgument(Sema &S,
InitializedEntity::InitializeTemporary(Ty),
Constructor->getAccess());
- ExprResult Result
- = S.BuildCXXConstructExpr(CastLoc, Ty, cast<CXXConstructorDecl>(Method),
- ConstructorArgs, HadMultipleCandidates,
- /*ListInit*/ false, /*ZeroInit*/ false,
- CXXConstructExpr::CK_Complete, SourceRange());
+ ExprResult Result = S.BuildCXXConstructExpr(
+ CastLoc, Ty, cast<CXXConstructorDecl>(Method),
+ ConstructorArgs, HadMultipleCandidates,
+ /*ListInit*/ false, /*StdInitListInit*/ false, /*ZeroInit*/ false,
+ CXXConstructExpr::CK_Complete, SourceRange());
if (Result.isInvalid())
return ExprError();
- return S.MaybeBindToTemporary(Result.takeAs<Expr>());
+ return S.MaybeBindToTemporary(Result.getAs<Expr>());
}
case CK_UserDefinedConversion: {
@@ -2558,13 +2572,11 @@ static ExprResult BuildCXXCastArgument(Sema &S,
if (Result.isInvalid())
return ExprError();
// Record usage of conversion in an implicit cast.
- Result = S.Owned(ImplicitCastExpr::Create(S.Context,
- Result.get()->getType(),
- CK_UserDefinedConversion,
- Result.get(), 0,
- Result.get()->getValueKind()));
+ Result = ImplicitCastExpr::Create(S.Context, Result.get()->getType(),
+ CK_UserDefinedConversion, Result.get(),
+ nullptr, Result.get()->getValueKind());
- S.CheckMemberOperatorAccess(CastLoc, From, /*arg*/ 0, FoundDecl);
+ S.CheckMemberOperatorAccess(CastLoc, From, /*arg*/ nullptr, FoundDecl);
return S.MaybeBindToTemporary(Result.get());
}
@@ -2587,7 +2599,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
Action, CCK);
if (Res.isInvalid())
return ExprError();
- From = Res.take();
+ From = Res.get();
break;
}
@@ -2623,7 +2635,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
CCK);
if (Res.isInvalid())
return ExprError();
- From = Res.take();
+ From = Res.get();
}
ExprResult CastArg
@@ -2638,7 +2650,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
if (CastArg.isInvalid())
return ExprError();
- From = CastArg.take();
+ From = CastArg.get();
return PerformImplicitConversion(From, ToType, ICS.UserDefined.After,
AA_Converting, CCK);
@@ -2658,7 +2670,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
}
// Everything went well.
- return Owned(From);
+ return From;
}
/// PerformImplicitConversion - Perform an implicit conversion of the
@@ -2688,20 +2700,17 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
From, /*FIXME:ConstructLoc*/SourceLocation(),
ConstructorArgs))
return ExprError();
- return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(),
- ToType, SCS.CopyConstructor,
- ConstructorArgs,
- /*HadMultipleCandidates*/ false,
- /*ListInit*/ false, /*ZeroInit*/ false,
- CXXConstructExpr::CK_Complete,
- SourceRange());
+ return BuildCXXConstructExpr(
+ /*FIXME:ConstructLoc*/ SourceLocation(), ToType, SCS.CopyConstructor,
+ ConstructorArgs, /*HadMultipleCandidates*/ false,
+ /*ListInit*/ false, /*StdInitListInit*/ false, /*ZeroInit*/ false,
+ CXXConstructExpr::CK_Complete, SourceRange());
}
- return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(),
- ToType, SCS.CopyConstructor,
- From, /*HadMultipleCandidates*/ false,
- /*ListInit*/ false, /*ZeroInit*/ false,
- CXXConstructExpr::CK_Complete,
- SourceRange());
+ return BuildCXXConstructExpr(
+ /*FIXME:ConstructLoc*/ SourceLocation(), ToType, SCS.CopyConstructor,
+ From, /*HadMultipleCandidates*/ false,
+ /*ListInit*/ false, /*StdInitListInit*/ false, /*ZeroInit*/ false,
+ CXXConstructExpr::CK_Complete, SourceRange());
}
// Resolve overloaded function references.
@@ -2738,20 +2747,20 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
FromType = FromType.getUnqualifiedType();
ExprResult FromRes = DefaultLvalueConversion(From);
assert(!FromRes.isInvalid() && "Can't perform deduced conversion?!");
- From = FromRes.take();
+ From = FromRes.get();
break;
}
case ICK_Array_To_Pointer:
FromType = Context.getArrayDecayedType(FromType);
From = ImpCastExprToType(From, FromType, CK_ArrayToPointerDecay,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).get();
break;
case ICK_Function_To_Pointer:
FromType = Context.getPointerType(FromType);
From = ImpCastExprToType(From, FromType, CK_FunctionToPointerDecay,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).get();
break;
default:
@@ -2775,7 +2784,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
return ExprError();
From = ImpCastExprToType(From, ToType, CK_NoOp,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).get();
break;
case ICK_Integral_Promotion:
@@ -2785,17 +2794,17 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
SCS.Second == ICK_Integral_Promotion &&
"only enums with fixed underlying type can promote to bool");
From = ImpCastExprToType(From, ToType, CK_IntegralToBoolean,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).get();
} else {
From = ImpCastExprToType(From, ToType, CK_IntegralCast,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).get();
}
break;
case ICK_Floating_Promotion:
case ICK_Floating_Conversion:
From = ImpCastExprToType(From, ToType, CK_FloatingCast,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).get();
break;
case ICK_Complex_Promotion:
@@ -2814,22 +2823,22 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
CK = CK_IntegralComplexCast;
}
From = ImpCastExprToType(From, ToType, CK,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).get();
break;
}
case ICK_Floating_Integral:
if (ToType->isRealFloatingType())
From = ImpCastExprToType(From, ToType, CK_IntegralToFloating,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).get();
else
From = ImpCastExprToType(From, ToType, CK_FloatingToIntegral,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).get();
break;
case ICK_Compatible_Conversion:
From = ImpCastExprToType(From, ToType, CK_NoOp,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).get();
break;
case ICK_Writeback_Conversion:
@@ -2874,12 +2883,12 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
if (Kind == CK_BlockPointerToObjCPointerCast) {
ExprResult E = From;
(void) PrepareCastToObjCObjectPointer(E);
- From = E.take();
+ From = E.get();
}
if (getLangOpts().ObjCAutoRefCount)
CheckObjCARCConversion(SourceRange(), ToType, From, CCK);
From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath, CCK)
- .take();
+ .get();
break;
}
@@ -2891,20 +2900,20 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
if (CheckExceptionSpecCompatibility(From, ToType))
return ExprError();
From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath, CCK)
- .take();
+ .get();
break;
}
case ICK_Boolean_Conversion:
// Perform half-to-boolean conversion via float.
if (From->getType()->isHalfType()) {
- From = ImpCastExprToType(From, Context.FloatTy, CK_FloatingCast).take();
+ From = ImpCastExprToType(From, Context.FloatTy, CK_FloatingCast).get();
FromType = Context.FloatTy;
}
From = ImpCastExprToType(From, Context.BoolTy,
ScalarTypeToBooleanCastKind(FromType),
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).get();
break;
case ICK_Derived_To_Base: {
@@ -2919,18 +2928,18 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
From = ImpCastExprToType(From, ToType.getNonReferenceType(),
CK_DerivedToBase, From->getValueKind(),
- &BasePath, CCK).take();
+ &BasePath, CCK).get();
break;
}
case ICK_Vector_Conversion:
From = ImpCastExprToType(From, ToType, CK_BitCast,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).get();
break;
case ICK_Vector_Splat:
From = ImpCastExprToType(From, ToType, CK_VectorSplat,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).get();
break;
case ICK_Complex_Real:
@@ -2944,16 +2953,16 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
// do nothing
} else if (From->getType()->isRealFloatingType()) {
From = ImpCastExprToType(From, ElType,
- isFloatingComplex ? CK_FloatingCast : CK_FloatingToIntegral).take();
+ isFloatingComplex ? CK_FloatingCast : CK_FloatingToIntegral).get();
} else {
assert(From->getType()->isIntegerType());
From = ImpCastExprToType(From, ElType,
- isFloatingComplex ? CK_IntegralToFloating : CK_IntegralCast).take();
+ isFloatingComplex ? CK_IntegralToFloating : CK_IntegralCast).get();
}
// y -> _Complex y
From = ImpCastExprToType(From, ToType,
isFloatingComplex ? CK_FloatingRealToComplex
- : CK_IntegralRealToComplex).take();
+ : CK_IntegralRealToComplex).get();
// Case 2. _Complex x -> y
} else {
@@ -2967,7 +2976,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
From = ImpCastExprToType(From, ElType,
isFloatingComplex ? CK_FloatingComplexToReal
: CK_IntegralComplexToReal,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).get();
// x -> y
if (Context.hasSameUnqualifiedType(ElType, ToType)) {
@@ -2975,29 +2984,29 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
} else if (ToType->isRealFloatingType()) {
From = ImpCastExprToType(From, ToType,
isFloatingComplex ? CK_FloatingCast : CK_IntegralToFloating,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).get();
} else {
assert(ToType->isIntegerType());
From = ImpCastExprToType(From, ToType,
isFloatingComplex ? CK_FloatingToIntegral : CK_IntegralCast,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).get();
}
}
break;
case ICK_Block_Pointer_Conversion: {
From = ImpCastExprToType(From, ToType.getUnqualifiedType(), CK_BitCast,
- VK_RValue, /*BasePath=*/0, CCK).take();
+ VK_RValue, /*BasePath=*/nullptr, CCK).get();
break;
}
case ICK_TransparentUnionConversion: {
- ExprResult FromRes = Owned(From);
+ ExprResult FromRes = From;
Sema::AssignConvertType ConvTy =
CheckTransparentUnionArgumentConstraints(ToType, FromRes);
if (FromRes.isInvalid())
return ExprError();
- From = FromRes.take();
+ From = FromRes.get();
assert ((ConvTy == Sema::Compatible) &&
"Improper transparent union conversion");
(void)ConvTy;
@@ -3007,7 +3016,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
case ICK_Zero_Event_Conversion:
From = ImpCastExprToType(From, ToType,
CK_ZeroToOCLEvent,
- From->getValueKind()).take();
+ From->getValueKind()).get();
break;
case ICK_Lvalue_To_Rvalue:
@@ -3029,12 +3038,15 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
ExprValueKind VK = ToType->isReferenceType() ?
From->getValueKind() : VK_RValue;
From = ImpCastExprToType(From, ToType.getNonLValueExprType(Context),
- CK_NoOp, VK, /*BasePath=*/0, CCK).take();
+ CK_NoOp, VK, /*BasePath=*/nullptr, CCK).get();
if (SCS.DeprecatedStringLiteralToCharPtr &&
- !getLangOpts().WritableStrings)
- Diag(From->getLocStart(), diag::warn_deprecated_string_literal_conversion)
+ !getLangOpts().WritableStrings) {
+ Diag(From->getLocStart(), getLangOpts().CPlusPlus11
+ ? diag::ext_deprecated_string_literal_conversion
+ : diag::warn_deprecated_string_literal_conversion)
<< ToType.getNonReferenceType();
+ }
break;
}
@@ -3049,22 +3061,10 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
assert(Context.hasSameType(
ToAtomicType->castAs<AtomicType>()->getValueType(), From->getType()));
From = ImpCastExprToType(From, ToAtomicType, CK_NonAtomicToAtomic,
- VK_RValue, 0, CCK).take();
+ VK_RValue, nullptr, CCK).get();
}
- return Owned(From);
-}
-
-ExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait UTT,
- SourceLocation KWLoc,
- ParsedType Ty,
- SourceLocation RParen) {
- TypeSourceInfo *TSInfo;
- QualType T = GetTypeFromParser(Ty, &TSInfo);
-
- if (!TSInfo)
- TSInfo = Context.getTrivialTypeSourceInfo(T);
- return BuildUnaryTypeTrait(UTT, KWLoc, TSInfo, RParen);
+ return From;
}
/// \brief Check the completeness of a type in a unary type trait.
@@ -3073,8 +3073,7 @@ ExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait UTT,
/// it. If completing the type fails, a diagnostic is emitted and false
/// returned. If completing the type succeeds or no completion was required,
/// returns true.
-static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S,
- UnaryTypeTrait UTT,
+static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
SourceLocation Loc,
QualType ArgTy) {
// C++0x [meta.unary.prop]p3:
@@ -3087,6 +3086,7 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S,
// these class templates. We also try to follow any GCC documented behavior
// in these expressions to ensure portability of standard libraries.
switch (UTT) {
+ default: llvm_unreachable("not a UTT");
// is_complete_type somewhat obviously cannot require a complete type.
case UTT_IsCompleteType:
// Fall-through
@@ -3139,6 +3139,8 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S,
case UTT_IsPolymorphic:
case UTT_IsAbstract:
case UTT_IsInterfaceClass:
+ case UTT_IsDestructible:
+ case UTT_IsNothrowDestructible:
// Fall-through
// These traits require a complete type.
@@ -3173,7 +3175,6 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S,
return !S.RequireCompleteType(
Loc, ElTy, diag::err_incomplete_type_used_in_type_trait_expr);
}
- llvm_unreachable("Type trait not handled by switch");
}
static bool HasNoThrowOperator(const RecordType *RT, OverloadedOperatorKind Op,
@@ -3203,7 +3204,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(Self.Context))
+ if (!CPT || !CPT->isNothrow(C))
return false;
}
}
@@ -3212,12 +3213,13 @@ static bool HasNoThrowOperator(const RecordType *RT, OverloadedOperatorKind Op,
return false;
}
-static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
+static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
SourceLocation KeyLoc, QualType T) {
assert(!T->isDependentType() && "Cannot evaluate traits of dependent type");
ASTContext &C = Self.Context;
switch(UTT) {
+ default: llvm_unreachable("not a UTT");
// Type trait expressions corresponding to the primary type category
// predicates in C++0x [meta.unary.cat].
case UTT_IsVoid:
@@ -3404,8 +3406,12 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
return RD->hasTrivialCopyAssignment() &&
!RD->hasNonTrivialCopyAssignment();
return false;
+ case UTT_IsDestructible:
+ case UTT_IsNothrowDestructible:
+ // FIXME: Implement UTT_IsDestructible and UTT_IsNothrowDestructible.
+ // For now, let's fall through.
case UTT_HasTrivialDestructor:
- // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+ // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html
// If __is_pod (type) is true or type is a reference type
// then the trait is true, else if type is a cv class or union
// type (or array thereof) with a trivial destructor
@@ -3488,9 +3494,9 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
if (!CPT)
return false;
- // FIXME: check whether evaluating default arguments can throw.
+ // TODO: check whether evaluating default arguments can throw.
// For now, we'll be conservative and assume that they can throw.
- if (!CPT->isNothrow(Self.Context) || CPT->getNumArgs() > 1)
+ if (!CPT->isNothrow(Self.Context) || CPT->getNumParams() > 1)
return false;
}
}
@@ -3499,7 +3505,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
}
return false;
case UTT_HasNothrowConstructor:
- // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+ // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html
// If __has_trivial_constructor (type) is true then the trait is
// true, else if type is a cv class or union type (or array
// thereof) with a default constructor that is known not to
@@ -3511,6 +3517,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
!RD->hasNonTrivialDefaultConstructor())
return true;
+ bool FoundConstructor = false;
DeclContext::lookup_const_result R = Self.LookupConstructors(RD);
for (DeclContext::lookup_const_iterator Con = R.begin(),
ConEnd = R.end(); Con != ConEnd; ++Con) {
@@ -3519,16 +3526,19 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
continue;
CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
if (Constructor->isDefaultConstructor()) {
+ FoundConstructor = true;
const FunctionProtoType *CPT
= Constructor->getType()->getAs<FunctionProtoType>();
CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
if (!CPT)
return false;
- // TODO: check whether evaluating default arguments can throw.
+ // FIXME: check whether evaluating default arguments can throw.
// For now, we'll be conservative and assume that they can throw.
- return CPT->isNothrow(Self.Context) && CPT->getNumArgs() == 0;
+ if (!CPT->isNothrow(Self.Context) || CPT->getNumParams() > 0)
+ return false;
}
}
+ return FoundConstructor;
}
return false;
case UTT_HasVirtualDestructor:
@@ -3549,41 +3559,6 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
// function call.
return !T->isIncompleteType();
}
- llvm_unreachable("Type trait not covered by switch");
-}
-
-ExprResult Sema::BuildUnaryTypeTrait(UnaryTypeTrait UTT,
- SourceLocation KWLoc,
- TypeSourceInfo *TSInfo,
- SourceLocation RParen) {
- QualType T = TSInfo->getType();
- if (!CheckUnaryTypeTraitTypeCompleteness(*this, UTT, KWLoc, T))
- return ExprError();
-
- bool Value = false;
- if (!T->isDependentType())
- Value = EvaluateUnaryTypeTrait(*this, UTT, KWLoc, T);
-
- return Owned(new (Context) UnaryTypeTraitExpr(KWLoc, UTT, TSInfo, Value,
- RParen, Context.BoolTy));
-}
-
-ExprResult Sema::ActOnBinaryTypeTrait(BinaryTypeTrait BTT,
- SourceLocation KWLoc,
- ParsedType LhsTy,
- ParsedType RhsTy,
- SourceLocation RParen) {
- TypeSourceInfo *LhsTSInfo;
- QualType LhsT = GetTypeFromParser(LhsTy, &LhsTSInfo);
- if (!LhsTSInfo)
- LhsTSInfo = Context.getTrivialTypeSourceInfo(LhsT);
-
- TypeSourceInfo *RhsTSInfo;
- QualType RhsT = GetTypeFromParser(RhsTy, &RhsTSInfo);
- if (!RhsTSInfo)
- RhsTSInfo = Context.getTrivialTypeSourceInfo(RhsT);
-
- return BuildBinaryTypeTrait(BTT, KWLoc, LhsTSInfo, RhsTSInfo, RParen);
}
/// \brief Determine whether T has a non-trivial Objective-C lifetime in
@@ -3605,10 +3580,22 @@ static bool hasNontrivialObjCLifetime(QualType T) {
llvm_unreachable("Unknown ObjC lifetime qualifier");
}
+static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
+ QualType RhsT, SourceLocation KeyLoc);
+
static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
ArrayRef<TypeSourceInfo *> Args,
SourceLocation RParenLoc) {
+ if (Kind <= UTT_Last)
+ return EvaluateUnaryTypeTrait(S, Kind, KWLoc, Args[0]->getType());
+
+ if (Kind <= BTT_Last)
+ return EvaluateBinaryTypeTrait(S, Kind, Args[0]->getType(),
+ Args[1]->getType(), RParenLoc);
+
switch (Kind) {
+ case clang::TT_IsConstructible:
+ case clang::TT_IsNothrowConstructible:
case clang::TT_IsTriviallyConstructible: {
// C++11 [meta.unary.prop]:
// is_trivially_constructible is defined as:
@@ -3623,11 +3610,7 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
// variable t:
//
// T t(create<Args>()...);
- if (Args.empty()) {
- S.Diag(KWLoc, diag::err_type_trait_arity)
- << 1 << 1 << 1 << (int)Args.size();
- return false;
- }
+ assert(!Args.empty());
// Precondition: T and all types in the parameter pack Args shall be
// complete types, (possibly cv-qualified) void, or arrays of
@@ -3646,6 +3629,11 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
if (Args[0]->getType()->isIncompleteType())
return false;
+ // Make sure the first argument is not an abstract type.
+ CXXRecordDecl *RD = Args[0]->getType()->getAsCXXRecordDecl();
+ if (RD && RD->isAbstract())
+ return false;
+
SmallVector<OpaqueValueExpr, 2> OpaqueArgExprs;
SmallVector<Expr *, 2> ArgExprs;
ArgExprs.reserve(Args.size() - 1);
@@ -3671,21 +3659,33 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
InitializationSequence Init(S, To, InitKind, ArgExprs);
if (Init.Failed())
return false;
-
+
ExprResult Result = Init.Perform(S, To, InitKind, ArgExprs);
if (Result.isInvalid() || SFINAE.hasErrorOccurred())
return false;
- // Under Objective-C ARC, if the destination has non-trivial Objective-C
- // lifetime, this is a non-trivial construction.
- if (S.getLangOpts().ObjCAutoRefCount &&
- hasNontrivialObjCLifetime(Args[0]->getType().getNonReferenceType()))
- return false;
+ if (Kind == clang::TT_IsConstructible)
+ return true;
+
+ if (Kind == clang::TT_IsNothrowConstructible)
+ return S.canThrow(Result.get()) == CT_Cannot;
- // The initialization succeeded; now make sure there are no non-trivial
- // calls.
- return !Result.get()->hasNonTrivialCall(S.Context);
+ if (Kind == clang::TT_IsTriviallyConstructible) {
+ // Under Objective-C ARC, if the destination has non-trivial Objective-C
+ // lifetime, this is a non-trivial construction.
+ if (S.getLangOpts().ObjCAutoRefCount &&
+ hasNontrivialObjCLifetime(Args[0]->getType().getNonReferenceType()))
+ return false;
+
+ // The initialization succeeded; now make sure there are no non-trivial
+ // calls.
+ return !Result.get()->hasNonTrivialCall(S.Context);
+ }
+
+ llvm_unreachable("unhandled type trait");
+ return false;
}
+ default: llvm_unreachable("not a TT");
}
return false;
@@ -3694,6 +3694,12 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
ArrayRef<TypeSourceInfo *> Args,
SourceLocation RParenLoc) {
+ QualType ResultType = Context.getLogicalOperationType();
+
+ if (Kind <= UTT_Last && !CheckUnaryTypeTraitTypeCompleteness(
+ *this, Kind, KWLoc, Args[0]->getType()))
+ return ExprError();
+
bool Dependent = false;
for (unsigned I = 0, N = Args.size(); I != N; ++I) {
if (Args[I]->getType()->isDependentType()) {
@@ -3701,17 +3707,17 @@ ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
break;
}
}
-
- bool Value = false;
+
+ bool Result = false;
if (!Dependent)
- Value = evaluateTypeTrait(*this, Kind, KWLoc, Args, RParenLoc);
-
- return TypeTraitExpr::Create(Context, Context.BoolTy, KWLoc, Kind,
- Args, RParenLoc, Value);
+ Result = evaluateTypeTrait(*this, Kind, KWLoc, Args, RParenLoc);
+
+ return TypeTraitExpr::Create(Context, ResultType, KWLoc, Kind, Args,
+ RParenLoc, Result);
}
-ExprResult Sema::ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
- ArrayRef<ParsedType> Args,
+ExprResult Sema::ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
+ ArrayRef<ParsedType> Args,
SourceLocation RParenLoc) {
SmallVector<TypeSourceInfo *, 4> ConvertedArgs;
ConvertedArgs.reserve(Args.size());
@@ -3724,13 +3730,12 @@ ExprResult Sema::ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
ConvertedArgs.push_back(TInfo);
}
-
+
return BuildTypeTrait(Kind, KWLoc, ConvertedArgs, RParenLoc);
}
-static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT,
- QualType LhsT, QualType RhsT,
- SourceLocation KeyLoc) {
+static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
+ QualType RhsT, SourceLocation KeyLoc) {
assert(!LhsT->isDependentType() && !RhsT->isDependentType() &&
"Cannot evaluate traits of dependent types");
@@ -3833,7 +3838,8 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT,
ExprResult Result = Init.Perform(Self, To, Kind, FromPtr);
return !Result.isInvalid() && !SFINAE.hasErrorOccurred();
}
-
+
+ case BTT_IsNothrowAssignable:
case BTT_IsTriviallyAssignable: {
// C++11 [meta.unary.prop]p3:
// is_trivially_assignable is defined as:
@@ -3875,56 +3881,30 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT,
EnterExpressionEvaluationContext Unevaluated(Self, Sema::Unevaluated);
Sema::SFINAETrap SFINAE(Self, /*AccessCheckingSFINAE=*/true);
Sema::ContextRAII TUContext(Self, Self.Context.getTranslationUnitDecl());
- ExprResult Result = Self.BuildBinOp(/*S=*/0, KeyLoc, BO_Assign, &Lhs, &Rhs);
+ ExprResult Result = Self.BuildBinOp(/*S=*/nullptr, KeyLoc, BO_Assign, &Lhs,
+ &Rhs);
if (Result.isInvalid() || SFINAE.hasErrorOccurred())
return false;
- // Under Objective-C ARC, if the destination has non-trivial Objective-C
- // lifetime, this is a non-trivial assignment.
- if (Self.getLangOpts().ObjCAutoRefCount &&
- hasNontrivialObjCLifetime(LhsT.getNonReferenceType()))
- return false;
-
- return !Result.get()->hasNonTrivialCall(Self.Context);
- }
- }
- llvm_unreachable("Unknown type trait or not implemented");
-}
+ if (BTT == BTT_IsNothrowAssignable)
+ return Self.canThrow(Result.get()) == CT_Cannot;
-ExprResult Sema::BuildBinaryTypeTrait(BinaryTypeTrait BTT,
- SourceLocation KWLoc,
- TypeSourceInfo *LhsTSInfo,
- TypeSourceInfo *RhsTSInfo,
- SourceLocation RParen) {
- QualType LhsT = LhsTSInfo->getType();
- QualType RhsT = RhsTSInfo->getType();
+ if (BTT == BTT_IsTriviallyAssignable) {
+ // Under Objective-C ARC, if the destination has non-trivial Objective-C
+ // lifetime, this is a non-trivial assignment.
+ if (Self.getLangOpts().ObjCAutoRefCount &&
+ hasNontrivialObjCLifetime(LhsT.getNonReferenceType()))
+ return false;
- if (BTT == BTT_TypeCompatible) {
- if (getLangOpts().CPlusPlus) {
- Diag(KWLoc, diag::err_types_compatible_p_in_cplusplus)
- << SourceRange(KWLoc, RParen);
- return ExprError();
+ return !Result.get()->hasNonTrivialCall(Self.Context);
}
- }
-
- bool Value = false;
- if (!LhsT->isDependentType() && !RhsT->isDependentType())
- Value = EvaluateBinaryTypeTrait(*this, BTT, LhsT, RhsT, KWLoc);
- // Select trait result type.
- QualType ResultType;
- switch (BTT) {
- case BTT_IsBaseOf: ResultType = Context.BoolTy; break;
- case BTT_IsConvertible: ResultType = Context.BoolTy; break;
- case BTT_IsSame: ResultType = Context.BoolTy; break;
- case BTT_TypeCompatible: ResultType = Context.IntTy; break;
- case BTT_IsConvertibleTo: ResultType = Context.BoolTy; break;
- case BTT_IsTriviallyAssignable: ResultType = Context.BoolTy;
+ llvm_unreachable("unhandled type trait");
+ return false;
}
-
- return Owned(new (Context) BinaryTypeTraitExpr(KWLoc, BTT, LhsTSInfo,
- RhsTSInfo, Value, RParen,
- ResultType));
+ default: llvm_unreachable("not a BTT");
+ }
+ llvm_unreachable("Unknown type trait or not implemented");
}
ExprResult Sema::ActOnArrayTypeTrait(ArrayTypeTrait ATT,
@@ -4012,9 +3992,8 @@ ExprResult Sema::BuildArrayTypeTrait(ArrayTypeTrait ATT,
// returns 'size_t'. On Windows, the primary platform for the Embarcadero
// compiler, there is no difference. On several other platforms this is an
// important distinction.
- return Owned(new (Context) ArrayTypeTraitExpr(KWLoc, ATT, TSInfo, Value,
- DimExpr, RParen,
- Context.getSizeType()));
+ return new (Context) ArrayTypeTraitExpr(KWLoc, ATT, TSInfo, Value, DimExpr,
+ RParen, Context.getSizeType());
}
ExprResult Sema::ActOnExpressionTrait(ExpressionTrait ET,
@@ -4047,13 +4026,13 @@ ExprResult Sema::BuildExpressionTrait(ExpressionTrait ET,
} else if (Queried->getType()->isPlaceholderType()) {
ExprResult PE = CheckPlaceholderExpr(Queried);
if (PE.isInvalid()) return ExprError();
- return BuildExpressionTrait(ET, KWLoc, PE.take(), RParen);
+ return BuildExpressionTrait(ET, KWLoc, PE.get(), RParen);
}
bool Value = EvaluateExpressionTrait(ET, Queried);
- return Owned(new (Context) ExpressionTraitExpr(KWLoc, ET, Queried, Value,
- RParen, Context.BoolTy));
+ return new (Context)
+ ExpressionTraitExpr(KWLoc, ET, Queried, Value, RParen, Context.BoolTy);
}
QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS,
@@ -4066,12 +4045,12 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS,
// The LHS undergoes lvalue conversions if this is ->*.
if (isIndirect) {
- LHS = DefaultLvalueConversion(LHS.take());
+ LHS = DefaultLvalueConversion(LHS.get());
if (LHS.isInvalid()) return QualType();
}
// The RHS always undergoes lvalue conversions.
- RHS = DefaultLvalueConversion(RHS.take());
+ RHS = DefaultLvalueConversion(RHS.get());
if (RHS.isInvalid()) return QualType();
const char *OpSpelling = isIndirect ? "->*" : ".*";
@@ -4117,23 +4096,24 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS,
OpSpelling, (int)isIndirect)) {
return QualType();
}
- CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
- /*DetectVirtual=*/false);
- // FIXME: Would it be useful to print full ambiguity paths, or is that
- // overkill?
- if (!IsDerivedFrom(LHSType, Class, Paths) ||
- Paths.isAmbiguous(Context.getCanonicalType(Class))) {
+
+ if (!IsDerivedFrom(LHSType, Class)) {
Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling
<< (int)isIndirect << LHS.get()->getType();
return QualType();
}
+
+ CXXCastPath BasePath;
+ if (CheckDerivedToBaseConversion(LHSType, Class, Loc,
+ SourceRange(LHS.get()->getLocStart(),
+ RHS.get()->getLocEnd()),
+ &BasePath))
+ return QualType();
+
// Cast LHS to type of use.
QualType UseType = isIndirect ? Context.getPointerType(Class) : Class;
ExprValueKind VK = isIndirect ? VK_RValue : LHS.get()->getValueKind();
-
- CXXCastPath BasePath;
- BuildBasePathArray(Paths, BasePath);
- LHS = ImpCastExprToType(LHS.take(), UseType, CK_DerivedToBase, VK,
+ LHS = ImpCastExprToType(LHS.get(), UseType, CK_DerivedToBase, VK,
&BasePath);
}
@@ -4296,7 +4276,8 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To,
static bool FindConditionalOverload(Sema &Self, ExprResult &LHS, ExprResult &RHS,
SourceLocation QuestionLoc) {
Expr *Args[2] = { LHS.get(), RHS.get() };
- OverloadCandidateSet CandidateSet(QuestionLoc);
+ OverloadCandidateSet CandidateSet(QuestionLoc,
+ OverloadCandidateSet::CSK_Operator);
Self.AddBuiltinOperatorCandidates(OO_Conditional, QuestionLoc, Args,
CandidateSet);
@@ -4355,7 +4336,7 @@ static bool ConvertForConditional(Sema &Self, ExprResult &E, QualType T) {
InitializedEntity Entity = InitializedEntity::InitializeTemporary(T);
InitializationKind Kind = InitializationKind::CreateCopy(E.get()->getLocStart(),
SourceLocation());
- Expr *Arg = E.take();
+ Expr *Arg = E.get();
InitializationSequence InitSeq(Self, Entity, Kind, Arg);
ExprResult Result = InitSeq.Perform(Self, Entity, Kind, Arg);
if (Result.isInvalid())
@@ -4379,7 +4360,7 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
// C++11 [expr.cond]p1
// The first expression is contextually converted to bool.
if (!Cond.get()->isTypeDependent()) {
- ExprResult CondRes = CheckCXXBooleanCondition(Cond.take());
+ ExprResult CondRes = CheckCXXBooleanCondition(Cond.get());
if (CondRes.isInvalid())
return QualType();
Cond = CondRes;
@@ -4400,42 +4381,21 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
bool LVoid = LTy->isVoidType();
bool RVoid = RTy->isVoidType();
if (LVoid || RVoid) {
- // ... then the [l2r] conversions are performed on the second and third
- // operands ...
- LHS = DefaultFunctionArrayLvalueConversion(LHS.take());
- RHS = DefaultFunctionArrayLvalueConversion(RHS.take());
- if (LHS.isInvalid() || RHS.isInvalid())
- return QualType();
-
- // Finish off the lvalue-to-rvalue conversion by copy-initializing a
- // temporary if necessary. DefaultFunctionArrayLvalueConversion doesn't
- // do this part for us.
- ExprResult &NonVoid = LVoid ? RHS : LHS;
- if (NonVoid.get()->getType()->isRecordType() &&
- NonVoid.get()->isGLValue()) {
- if (RequireNonAbstractType(QuestionLoc, NonVoid.get()->getType(),
- diag::err_allocation_of_abstract_type))
- return QualType();
- InitializedEntity Entity =
- InitializedEntity::InitializeTemporary(NonVoid.get()->getType());
- NonVoid = PerformCopyInitialization(Entity, SourceLocation(), NonVoid);
- if (NonVoid.isInvalid())
- return QualType();
+ // ... one of the following shall hold:
+ // -- The second or the third operand (but not both) is a (possibly
+ // parenthesized) throw-expression; the result is of the type
+ // and value category of the other.
+ bool LThrow = isa<CXXThrowExpr>(LHS.get()->IgnoreParenImpCasts());
+ bool RThrow = isa<CXXThrowExpr>(RHS.get()->IgnoreParenImpCasts());
+ if (LThrow != RThrow) {
+ Expr *NonThrow = LThrow ? RHS.get() : LHS.get();
+ VK = NonThrow->getValueKind();
+ // DR (no number yet): the result is a bit-field if the
+ // non-throw-expression operand is a bit-field.
+ OK = NonThrow->getObjectKind();
+ return NonThrow->getType();
}
- LTy = LHS.get()->getType();
- RTy = RHS.get()->getType();
-
- // ... and one of the following shall hold:
- // -- The second or the third operand (but not both) is a throw-
- // expression; the result is of the type of the other and is a prvalue.
- bool LThrow = isa<CXXThrowExpr>(LHS.get()->IgnoreParenCasts());
- bool RThrow = isa<CXXThrowExpr>(RHS.get()->IgnoreParenCasts());
- if (LThrow && !RThrow)
- return RTy;
- if (RThrow && !LThrow)
- return LTy;
-
// -- Both the second and third operands have type void; the result is of
// type void and is a prvalue.
if (LVoid && RVoid)
@@ -4456,7 +4416,6 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
// those operands to the type of the other.
if (!Context.hasSameType(LTy, RTy) &&
(LTy->isRecordType() || RTy->isRecordType())) {
- ImplicitConversionSequence ICSLeftToRight, ICSRightToLeft;
// These return true if a single direction is already ambiguous.
QualType L2RType, R2LType;
bool HaveL2R, HaveR2L;
@@ -4501,11 +4460,11 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
Qualifiers LCVR = Qualifiers::fromCVRMask(LTy.getCVRQualifiers());
Qualifiers RCVR = Qualifiers::fromCVRMask(RTy.getCVRQualifiers());
if (RCVR.isStrictSupersetOf(LCVR)) {
- LHS = ImpCastExprToType(LHS.take(), RTy, CK_NoOp, LVK);
+ LHS = ImpCastExprToType(LHS.get(), RTy, CK_NoOp, LVK);
LTy = LHS.get()->getType();
}
else if (LCVR.isStrictSupersetOf(RCVR)) {
- RHS = ImpCastExprToType(RHS.take(), LTy, CK_NoOp, RVK);
+ RHS = ImpCastExprToType(RHS.get(), LTy, CK_NoOp, RVK);
RTy = RHS.get()->getType();
}
}
@@ -4542,8 +4501,8 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
// C++11 [expr.cond]p6
// Lvalue-to-rvalue, array-to-pointer, and function-to-pointer standard
// conversions are performed on the second and third operands.
- LHS = DefaultFunctionArrayLvalueConversion(LHS.take());
- RHS = DefaultFunctionArrayLvalueConversion(RHS.take());
+ LHS = DefaultFunctionArrayLvalueConversion(LHS.get());
+ RHS = DefaultFunctionArrayLvalueConversion(RHS.get());
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
LTy = LHS.get()->getType();
@@ -4610,7 +4569,8 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
// operand. The result is of the common type.
bool NonStandardCompositeType = false;
QualType Composite = FindCompositePointerType(QuestionLoc, LHS, RHS,
- isSFINAEContext()? 0 : &NonStandardCompositeType);
+ isSFINAEContext() ? nullptr
+ : &NonStandardCompositeType);
if (!Composite.isNull()) {
if (NonStandardCompositeType)
Diag(QuestionLoc,
@@ -4669,12 +4629,12 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc,
!T2->isAnyPointerType() && !T2->isMemberPointerType()) {
if (T1->isNullPtrType() &&
E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
- E2 = ImpCastExprToType(E2, T1, CK_NullToPointer).take();
+ E2 = ImpCastExprToType(E2, T1, CK_NullToPointer).get();
return T1;
}
if (T2->isNullPtrType() &&
E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
- E1 = ImpCastExprToType(E1, T2, CK_NullToPointer).take();
+ E1 = ImpCastExprToType(E1, T2, CK_NullToPointer).get();
return T2;
}
return QualType();
@@ -4682,16 +4642,16 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc,
if (E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
if (T2->isMemberPointerType())
- E1 = ImpCastExprToType(E1, T2, CK_NullToMemberPointer).take();
+ E1 = ImpCastExprToType(E1, T2, CK_NullToMemberPointer).get();
else
- E1 = ImpCastExprToType(E1, T2, CK_NullToPointer).take();
+ E1 = ImpCastExprToType(E1, T2, CK_NullToPointer).get();
return T2;
}
if (E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
if (T1->isMemberPointerType())
- E2 = ImpCastExprToType(E2, T1, CK_NullToMemberPointer).take();
+ E2 = ImpCastExprToType(E2, T1, CK_NullToMemberPointer).get();
else
- E2 = ImpCastExprToType(E2, T1, CK_NullToPointer).take();
+ E2 = ImpCastExprToType(E2, T1, CK_NullToPointer).get();
return T1;
}
@@ -4734,7 +4694,7 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc,
QualifierUnion.push_back(
Composite1.getCVRQualifiers() | Composite2.getCVRQualifiers());
- MemberOfClass.push_back(std::make_pair((const Type *)0, (const Type *)0));
+ MemberOfClass.push_back(std::make_pair(nullptr, nullptr));
continue;
}
@@ -4829,14 +4789,14 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc,
= E1ToC1.Perform(*this, Entity1, Kind, E1);
if (E1Result.isInvalid())
return QualType();
- E1 = E1Result.takeAs<Expr>();
+ E1 = E1Result.getAs<Expr>();
// Convert E2 to Composite1
ExprResult E2Result
= E2ToC1.Perform(*this, Entity1, Kind, E2);
if (E2Result.isInvalid())
return QualType();
- E2 = E2Result.takeAs<Expr>();
+ E2 = E2Result.getAs<Expr>();
return Composite1;
}
@@ -4854,14 +4814,14 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc,
= E1ToC2.Perform(*this, Entity2, Kind, E1);
if (E1Result.isInvalid())
return QualType();
- E1 = E1Result.takeAs<Expr>();
+ E1 = E1Result.getAs<Expr>();
// Convert E2 to Composite2
ExprResult E2Result
= E2ToC2.Perform(*this, Entity2, Kind, E2);
if (E2Result.isInvalid())
return QualType();
- E2 = E2Result.takeAs<Expr>();
+ E2 = E2Result.getAs<Expr>();
return Composite2;
}
@@ -4874,7 +4834,7 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) {
// If the result is a glvalue, we shouldn't bind it.
if (!E->isRValue())
- return Owned(E);
+ return E;
// In ARC, calls that return a retainable type can return retained,
// in which case we have to insert a consuming cast.
@@ -4917,13 +4877,13 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) {
// we don't want any extra casts here.
} else if (isa<CastExpr>(E) &&
isa<BlockExpr>(cast<CastExpr>(E)->getSubExpr())) {
- return Owned(E);
+ return E;
// For message sends and property references, we try to find an
// actual method. FIXME: we should infer retention by selector in
// cases where we don't have an actual method.
} else {
- ObjCMethodDecl *D = 0;
+ ObjCMethodDecl *D = nullptr;
if (ObjCMessageExpr *Send = dyn_cast<ObjCMessageExpr>(E)) {
D = Send->getMethodDecl();
} else if (ObjCBoxedExpr *BoxedExpr = dyn_cast<ObjCBoxedExpr>(E)) {
@@ -4942,28 +4902,28 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) {
// return an object.
if (!ReturnsRetained &&
D && D->getMethodFamily() == OMF_performSelector)
- return Owned(E);
+ return E;
}
// Don't reclaim an object of Class type.
if (!ReturnsRetained && E->getType()->isObjCARCImplicitlyUnretainedType())
- return Owned(E);
+ return E;
ExprNeedsCleanups = true;
CastKind ck = (ReturnsRetained ? CK_ARCConsumeObject
: CK_ARCReclaimReturnedObject);
- return Owned(ImplicitCastExpr::Create(Context, E->getType(), ck, E, 0,
- VK_RValue));
+ return ImplicitCastExpr::Create(Context, E->getType(), ck, E, nullptr,
+ VK_RValue);
}
if (!getLangOpts().CPlusPlus)
- return Owned(E);
+ return E;
// Search for the base element type (cf. ASTContext::getBaseElementType) with
// a fast path for the common case that the type is directly a RecordType.
const Type *T = Context.getCanonicalType(E->getType().getTypePtr());
- const RecordType *RT = 0;
+ const RecordType *RT = nullptr;
while (!RT) {
switch (T->getTypeClass()) {
case Type::Record:
@@ -4976,7 +4936,7 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) {
T = cast<ArrayType>(T)->getElementType().getTypePtr();
break;
default:
- return Owned(E);
+ return E;
}
}
@@ -4984,10 +4944,10 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) {
// not processing a decltype expression.
CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
if (RD->isInvalidDecl() || RD->isDependentContext())
- return Owned(E);
+ return E;
bool IsDecltype = ExprEvalContexts.back().IsDecltype;
- CXXDestructorDecl *Destructor = IsDecltype ? 0 : LookupDestructor(RD);
+ CXXDestructorDecl *Destructor = IsDecltype ? nullptr : LookupDestructor(RD);
if (Destructor) {
MarkFunctionReferenced(E->getExprLoc(), Destructor);
@@ -4999,7 +4959,7 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) {
// If destructor is trivial, we can avoid the extra copy.
if (Destructor->isTrivial())
- return Owned(E);
+ return E;
// We need a cleanup, but we don't need to remember the temporary.
ExprNeedsCleanups = true;
@@ -5011,7 +4971,7 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) {
if (IsDecltype)
ExprEvalContexts.back().DelayedDecltypeBinds.push_back(Bind);
- return Owned(Bind);
+ return Bind;
}
ExprResult
@@ -5019,11 +4979,11 @@ Sema::MaybeCreateExprWithCleanups(ExprResult SubExpr) {
if (SubExpr.isInvalid())
return ExprError();
- return Owned(MaybeCreateExprWithCleanups(SubExpr.take()));
+ return MaybeCreateExprWithCleanups(SubExpr.get());
}
Expr *Sema::MaybeCreateExprWithCleanups(Expr *SubExpr) {
- assert(SubExpr && "sub expression can't be null!");
+ assert(SubExpr && "subexpression can't be null!");
CleanupVarDeclMarking();
@@ -5044,7 +5004,7 @@ Expr *Sema::MaybeCreateExprWithCleanups(Expr *SubExpr) {
}
Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) {
- assert(SubStmt && "sub statement can't be null!");
+ assert(SubStmt && "sub-statement can't be null!");
CleanupVarDeclMarking();
@@ -5085,8 +5045,8 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
if (SubExpr.isInvalid())
return ExprError();
if (SubExpr.get() == PE->getSubExpr())
- return Owned(E);
- return ActOnParenExpr(PE->getLParen(), PE->getRParen(), SubExpr.take());
+ return E;
+ return ActOnParenExpr(PE->getLParen(), PE->getRParen(), SubExpr.get());
}
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
if (BO->getOpcode() == BO_Comma) {
@@ -5094,30 +5054,30 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
if (RHS.isInvalid())
return ExprError();
if (RHS.get() == BO->getRHS())
- return Owned(E);
- return Owned(new (Context) BinaryOperator(BO->getLHS(), RHS.take(),
- BO_Comma, BO->getType(),
- BO->getValueKind(),
- BO->getObjectKind(),
- BO->getOperatorLoc(),
- BO->isFPContractable()));
+ return E;
+ return new (Context) BinaryOperator(
+ BO->getLHS(), RHS.get(), BO_Comma, BO->getType(), BO->getValueKind(),
+ BO->getObjectKind(), BO->getOperatorLoc(), BO->isFPContractable());
}
}
CXXBindTemporaryExpr *TopBind = dyn_cast<CXXBindTemporaryExpr>(E);
- if (TopBind)
- E = TopBind->getSubExpr();
+ CallExpr *TopCall = TopBind ? dyn_cast<CallExpr>(TopBind->getSubExpr())
+ : nullptr;
+ if (TopCall)
+ E = TopCall;
+ else
+ TopBind = nullptr;
// Disable the special decltype handling now.
ExprEvalContexts.back().IsDecltype = false;
// In MS mode, don't perform any extra checking of call return types within a
// decltype expression.
- if (getLangOpts().MicrosoftMode)
- return Owned(E);
+ if (getLangOpts().MSVCCompat)
+ return E;
// Perform the semantic checks we delayed until this point.
- CallExpr *TopCall = dyn_cast<CallExpr>(E);
for (unsigned I = 0, N = ExprEvalContexts.back().DelayedDecltypeCalls.size();
I != N; ++I) {
CallExpr *Call = ExprEvalContexts.back().DelayedDecltypeCalls[I];
@@ -5158,12 +5118,12 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
}
// Possibly strip off the top CXXBindTemporaryExpr.
- return Owned(E);
+ return E;
}
/// Note a set of 'operator->' functions that were used for a member access.
static void noteOperatorArrows(Sema &S,
- llvm::ArrayRef<FunctionDecl *> OperatorArrows) {
+ ArrayRef<FunctionDecl *> OperatorArrows) {
unsigned SkipStart = OperatorArrows.size(), SkipCount = 0;
// FIXME: Make this configurable?
unsigned Limit = 9;
@@ -5198,7 +5158,7 @@ Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc,
Result = CheckPlaceholderExpr(Base);
if (Result.isInvalid()) return ExprError();
- Base = Result.take();
+ Base = Result.get();
QualType BaseType = Base->getType();
MayBePseudoDestructor = false;
@@ -5212,7 +5172,7 @@ Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc,
ObjectType = ParsedType::make(BaseType);
MayBePseudoDestructor = true;
- return Owned(Base);
+ return Base;
}
// C++ [over.match.oper]p8:
@@ -5245,7 +5205,7 @@ Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc,
// separate note) instead of having the error reported back to here
// and giving a diagnostic with a fixit attached to the error itself.
(FirstIteration && CurFD && CurFD->isFunctionTemplateSpecialization())
- ? 0
+ ? nullptr
: &NoArrowOperatorFound);
if (Result.isInvalid()) {
if (NoArrowOperatorFound) {
@@ -5259,7 +5219,7 @@ Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc,
Diag(OpLoc, diag::err_typecheck_member_reference_arrow)
<< BaseType << Base->getSourceRange();
CallExpr *CE = dyn_cast<CallExpr>(Base);
- if (Decl *CD = (CE ? CE->getCalleeDecl() : 0)) {
+ if (Decl *CD = (CE ? CE->getCalleeDecl() : nullptr)) {
Diag(CD->getLocStart(),
diag::note_member_reference_arrow_from_operator_arrow);
}
@@ -5302,7 +5262,7 @@ Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc,
} else if (!BaseType->isRecordType()) {
ObjectType = ParsedType();
MayBePseudoDestructor = true;
- return Owned(Base);
+ return Base;
}
// The object type must be complete (or dependent), or
@@ -5331,7 +5291,7 @@ ExprResult Sema::DiagnoseDtorReference(SourceLocation NameLoc,
<< isa<CXXPseudoDestructorExpr>(MemExpr)
<< FixItHint::CreateInsertion(ExpectedLParenLoc, "()");
- return ActOnCallExpr(/*Scope*/ 0,
+ return ActOnCallExpr(/*Scope*/ nullptr,
MemExpr,
/*LPLoc*/ ExpectedLParenLoc,
None,
@@ -5343,7 +5303,7 @@ static bool CheckArrow(Sema& S, QualType& ObjectType, Expr *&Base,
if (Base->hasPlaceholderType()) {
ExprResult result = S.CheckPlaceholderExpr(Base);
if (result.isInvalid()) return true;
- Base = result.take();
+ Base = result.get();
}
ObjectType = Base->getType();
@@ -5388,12 +5348,13 @@ ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base,
if (!ObjectType->isDependentType() && !ObjectType->isScalarType() &&
!ObjectType->isVectorType()) {
- if (getLangOpts().MicrosoftMode && ObjectType->isVoidType())
+ if (getLangOpts().MSVCCompat && ObjectType->isVoidType())
Diag(OpLoc, diag::ext_pseudo_dtor_on_void) << Base->getSourceRange();
- else
+ else {
Diag(OpLoc, diag::err_pseudo_dtor_base_not_scalar)
<< ObjectType << Base->getSourceRange();
- return ExprError();
+ return ExprError();
+ }
}
// C++ [expr.pseudo]p2:
@@ -5453,7 +5414,7 @@ ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base,
<< ScopeTypeInfo->getTypeLoc().getLocalSourceRange();
ScopeType = QualType();
- ScopeTypeInfo = 0;
+ ScopeTypeInfo = nullptr;
}
}
@@ -5467,7 +5428,7 @@ ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base,
Destructed);
if (HasTrailingLParen)
- return Owned(Result);
+ return Result;
return DiagnoseDtorReference(Destructed.getLocation(), Result);
}
@@ -5505,7 +5466,7 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
// Convert the name of the type being destructed (following the ~) into a
// type (with source-location information).
QualType DestructedType;
- TypeSourceInfo *DestructedTypeInfo = 0;
+ TypeSourceInfo *DestructedTypeInfo = nullptr;
PseudoDestructorTypeStorage Destructed;
if (SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) {
ParsedType T = getTypeName(*SecondTypeName.Identifier,
@@ -5560,7 +5521,7 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
}
// Convert the name of the scope type (the type prior to '::') into a type.
- TypeSourceInfo *ScopeTypeInfo = 0;
+ TypeSourceInfo *ScopeTypeInfo = nullptr;
QualType ScopeType;
if (FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
FirstTypeName.Identifier) {
@@ -5629,7 +5590,7 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
PseudoDestructorTypeStorage Destructed(DestructedTypeInfo);
return BuildPseudoDestructorExpr(Base, OpLoc, OpKind, CXXScopeSpec(),
- 0, SourceLocation(), TildeLoc,
+ nullptr, SourceLocation(), TildeLoc,
Destructed, HasTrailingLParen);
}
@@ -5662,22 +5623,21 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,
return Exp;
}
}
-
- ExprResult Exp = PerformObjectArgumentInitialization(E, /*Qualifier=*/0,
+ ExprResult Exp = PerformObjectArgumentInitialization(E, /*Qualifier=*/nullptr,
FoundDecl, Method);
if (Exp.isInvalid())
return true;
MemberExpr *ME =
- new (Context) MemberExpr(Exp.take(), /*IsArrow=*/false, Method,
+ new (Context) MemberExpr(Exp.get(), /*IsArrow=*/false, Method,
SourceLocation(), Context.BoundMemberTy,
VK_RValue, OK_Ordinary);
if (HadMultipleCandidates)
ME->setHadMultipleCandidates(true);
MarkMemberReferenced(ME);
- QualType ResultType = Method->getResultType();
+ QualType ResultType = Method->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultType);
ResultType = ResultType.getNonLValueExprType(Context);
@@ -5690,8 +5650,8 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,
ExprResult Sema::BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand,
SourceLocation RParen) {
CanThrowResult CanThrow = canThrow(Operand);
- return Owned(new (Context) CXXNoexceptExpr(Context.BoolTy, Operand,
- CanThrow, KeyLoc, RParen));
+ return new (Context)
+ CXXNoexceptExpr(Context.BoolTy, Operand, CanThrow, KeyLoc, RParen);
}
ExprResult Sema::ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation,
@@ -5759,8 +5719,8 @@ static bool IsSpecialDiscardedValue(Expr *E) {
ExprResult Sema::IgnoredValueConversions(Expr *E) {
if (E->hasPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(E);
- if (result.isInvalid()) return Owned(E);
- E = result.take();
+ if (result.isInvalid()) return E;
+ E = result.get();
}
// C99 6.3.2.1:
@@ -5775,7 +5735,7 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) {
if (!getLangOpts().CPlusPlus && E->getType()->isFunctionType())
return DefaultFunctionArrayConversion(E);
- return Owned(E);
+ return E;
}
if (getLangOpts().CPlusPlus) {
@@ -5788,30 +5748,30 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) {
IsSpecialDiscardedValue(E)) {
ExprResult Res = DefaultLvalueConversion(E);
if (Res.isInvalid())
- return Owned(E);
- E = Res.take();
+ return E;
+ E = Res.get();
}
- return Owned(E);
+ return E;
}
// GCC seems to also exclude expressions of incomplete enum type.
if (const EnumType *T = E->getType()->getAs<EnumType>()) {
if (!T->getDecl()->isComplete()) {
// FIXME: stupid workaround for a codegen bug!
- E = ImpCastExprToType(E, Context.VoidTy, CK_ToVoid).take();
- return Owned(E);
+ E = ImpCastExprToType(E, Context.VoidTy, CK_ToVoid).get();
+ return E;
}
}
ExprResult Res = DefaultFunctionArrayLvalueConversion(E);
if (Res.isInvalid())
- return Owned(E);
- E = Res.take();
+ return E;
+ E = Res.get();
if (!E->getType()->isVoidType())
RequireCompleteType(E->getExprLoc(), E->getType(),
diag::err_incomplete_type);
- return Owned(E);
+ return E;
}
// If we can unambiguously determine whether Var can never be used
@@ -5829,7 +5789,7 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) {
static inline bool VariableCanNeverBeAConstantExpression(VarDecl *Var,
ASTContext &Context) {
if (isa<ParmVarDecl>(Var)) return true;
- const VarDecl *DefVD = 0;
+ const VarDecl *DefVD = nullptr;
// If there is no initializer - this can not be a constant expression.
if (!Var->getAnyInitializer(DefVD)) return true;
@@ -5849,42 +5809,58 @@ static inline bool VariableCanNeverBeAConstantExpression(VarDecl *Var,
return !IsVariableAConstantExpression(Var, Context);
}
-/// \brief Check if the current lambda scope has any potential captures, and
-/// whether they can be captured by any of the 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
-/// variables are uncaptureable or do not involve an odr-use so do not
-/// need to be captured.
+/// \brief 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
+/// variables are uncaptureable or do not involve an odr-use so do not
+/// need to be captured.
+
+static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(
+ Expr *const FE, LambdaScopeInfo *const CurrentLSI, Sema &S) {
-static void CheckLambdaCaptures(Expr *const FE,
- LambdaScopeInfo *const CurrentLSI, Sema &S) {
-
assert(!S.isUnevaluatedContext());
assert(S.CurContext->isDependentContext());
- const bool IsFullExprInstantiationDependent =
- FE->isInstantiationDependent();
- // All the potentially captureable variables in the current nested
+ assert(CurrentLSI->CallOperator == S.CurContext &&
+ "The current call operator must be synchronized with Sema's CurContext");
+
+ 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.
-
- for (size_t I = 0, N = CurrentLSI->getNumPotentialVariableCaptures();
- I != N; ++I) {
- Expr *VarExpr = 0;
- VarDecl *Var = 0;
+ const unsigned NumPotentialCaptures =
+ CurrentLSI->getNumPotentialVariableCaptures();
+ for (unsigned I = 0; I != NumPotentialCaptures; ++I) {
+ Expr *VarExpr = nullptr;
+ VarDecl *Var = nullptr;
CurrentLSI->getPotentialVariableCapture(I, Var, VarExpr);
- //
- if (CurrentLSI->isVariableExprMarkedAsNonODRUsed(VarExpr) &&
+ // If the variable is clearly identified as non-odr-used and the full
+ // expression is not instantiation dependent, only then do we not
+ // need to check enclosing lambda's for speculative captures.
+ // For e.g.:
+ // Even though 'x' is not odr-used, it should be captured.
+ // int test() {
+ // const int x = 10;
+ // auto L = [=](auto a) {
+ // (void) +x + a;
+ // };
+ // }
+ if (CurrentLSI->isVariableExprMarkedAsNonODRUsed(VarExpr) &&
!IsFullExprInstantiationDependent)
- continue;
- // Climb up until we find a lambda that can capture:
- // - a generic-or-non-generic lambda call operator that is enclosed
- // within a non-dependent context.
- unsigned FunctionScopeIndexOfCapturableLambda = 0;
- if (GetInnermostEnclosingCapturableLambda(
- S.FunctionScopes, FunctionScopeIndexOfCapturableLambda,
- S.CurContext, Var, S)) {
- MarkVarDeclODRUsed(Var, VarExpr->getExprLoc(),
- S, &FunctionScopeIndexOfCapturableLambda);
+ continue;
+
+ // If we have a capture-capable lambda for the variable, go ahead and
+ // capture the variable in that lambda (and all its enclosing lambdas).
+ if (const Optional<unsigned> Index =
+ getStackIndexOfNearestEnclosingCaptureCapableLambda(
+ FunctionScopesArrayRef, Var, S)) {
+ const unsigned FunctionScopeIndexOfCapturableLambda = Index.getValue();
+ MarkVarDeclODRUsed(Var, VarExpr->getExprLoc(), S,
+ &FunctionScopeIndexOfCapturableLambda);
}
const bool IsVarNeverAConstantExpression =
VariableCanNeverBeAConstantExpression(Var, S.Context);
@@ -5900,27 +5876,32 @@ static void CheckLambdaCaptures(Expr *const FE,
if (S.tryCaptureVariable(Var, ExprLoc, S.TryCapture_Implicit,
/*EllipsisLoc*/ SourceLocation(),
/*BuildAndDiagnose*/false, CaptureType,
- DeclRefType, 0)) {
+ DeclRefType, nullptr)) {
// We will never be able to capture this variable, and we need
// to be able to in any and all instantiations, so diagnose it.
S.tryCaptureVariable(Var, ExprLoc, S.TryCapture_Implicit,
/*EllipsisLoc*/ SourceLocation(),
/*BuildAndDiagnose*/true, CaptureType,
- DeclRefType, 0);
+ DeclRefType, nullptr);
}
}
}
+ // Check if 'this' needs to be captured.
if (CurrentLSI->hasPotentialThisCapture()) {
- unsigned FunctionScopeIndexOfCapturableLambda = 0;
- if (GetInnermostEnclosingCapturableLambda(
- S.FunctionScopes, FunctionScopeIndexOfCapturableLambda,
- S.CurContext, /*0 is 'this'*/ 0, S)) {
- S.CheckCXXThisCapture(CurrentLSI->PotentialThisCaptureLocation,
- /*Explicit*/false, /*BuildAndDiagnose*/true,
- &FunctionScopeIndexOfCapturableLambda);
+ // If we have a capture-capable lambda for 'this', go ahead and capture
+ // 'this' in that lambda (and all its enclosing lambdas).
+ if (const Optional<unsigned> Index =
+ getStackIndexOfNearestEnclosingCaptureCapableLambda(
+ FunctionScopesArrayRef, /*0 is 'this'*/ nullptr, S)) {
+ const unsigned FunctionScopeIndexOfCapturableLambda = Index.getValue();
+ S.CheckCXXThisCapture(CurrentLSI->PotentialThisCaptureLocation,
+ /*Explicit*/ false, /*BuildAndDiagnose*/ true,
+ &FunctionScopeIndexOfCapturableLambda);
}
}
+
+ // Reset all the potential captures at the end of each full-expression.
CurrentLSI->clearPotentialCaptures();
}
@@ -5929,7 +5910,7 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,
bool DiscardedValue,
bool IsConstexpr,
bool IsLambdaInitCaptureInitializer) {
- ExprResult FullExpr = Owned(FE);
+ ExprResult FullExpr = FE;
if (!FullExpr.get())
return ExprError();
@@ -5956,17 +5937,17 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,
// Top-level expressions default to 'id' when we're in a debugger.
if (DiscardedValue && getLangOpts().DebuggerCastResultToId &&
FullExpr.get()->getType() == Context.UnknownAnyTy) {
- FullExpr = forceUnknownAnyToType(FullExpr.take(), Context.getObjCIdType());
+ FullExpr = forceUnknownAnyToType(FullExpr.get(), Context.getObjCIdType());
if (FullExpr.isInvalid())
return ExprError();
}
if (DiscardedValue) {
- FullExpr = CheckPlaceholderExpr(FullExpr.take());
+ FullExpr = CheckPlaceholderExpr(FullExpr.get());
if (FullExpr.isInvalid())
return ExprError();
- FullExpr = IgnoredValueConversions(FullExpr.take());
+ FullExpr = IgnoredValueConversions(FullExpr.get());
if (FullExpr.isInvalid())
return ExprError();
}
@@ -6017,11 +5998,12 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,
// FunctionScopes.size() in InstantiatingTemplate's
// constructor/destructor.
// - Teach the handful of places that iterate over FunctionScopes to
- // stop at the outermost enclosing lexical scope."
- const bool IsInLambdaDeclContext = isLambdaCallOperator(CurContext);
- if (IsInLambdaDeclContext && CurrentLSI &&
+ // stop at the outermost enclosing lexical scope."
+ const bool IsInLambdaDeclContext = isLambdaCallOperator(CurContext);
+ if (IsInLambdaDeclContext && CurrentLSI &&
CurrentLSI->hasPotentialCaptures() && !FullExpr.isInvalid())
- CheckLambdaCaptures(FE, CurrentLSI, *this);
+ CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(FE, CurrentLSI,
+ *this);
return MaybeCreateExprWithCleanups(FullExpr);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp
index f6accb1..ef78982 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp
@@ -206,7 +206,7 @@ static void diagnoseInstanceReference(Sema &SemaRef,
DeclContext *FunctionLevelDC = SemaRef.getFunctionLevelDeclContext();
CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FunctionLevelDC);
- CXXRecordDecl *ContextClass = Method ? Method->getParent() : 0;
+ CXXRecordDecl *ContextClass = Method ? Method->getParent() : nullptr;
CXXRecordDecl *RepClass = dyn_cast<CXXRecordDecl>(Rep->getDeclContext());
bool InStaticMethod = Method && Method->isStatic();
@@ -292,7 +292,7 @@ CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK,
// This flag determines whether or not CompName has an 's' char prefix,
// indicating that it is a string of hex values to be used as vector indices.
- bool HexSwizzle = *compStr == 's' || *compStr == 'S';
+ bool HexSwizzle = (*compStr == 's' || *compStr == 'S') && compStr[1];
bool HasRepeated = false;
bool HasIndex[16] = {};
@@ -384,13 +384,12 @@ static Decl *FindGetterSetterNameDeclFromProtocolList(const ObjCProtocolDecl*PDe
if (ObjCMethodDecl *OMD = PDecl->getInstanceMethod(Sel))
return OMD;
- for (ObjCProtocolDecl::protocol_iterator I = PDecl->protocol_begin(),
- E = PDecl->protocol_end(); I != E; ++I) {
- if (Decl *D = FindGetterSetterNameDeclFromProtocolList(*I, Member, Sel,
+ for (const auto *I : PDecl->protocols()) {
+ if (Decl *D = FindGetterSetterNameDeclFromProtocolList(I, Member, Sel,
Context))
return D;
}
- return 0;
+ return nullptr;
}
static Decl *FindGetterSetterNameDecl(const ObjCObjectPointerType *QIdTy,
@@ -398,26 +397,23 @@ static Decl *FindGetterSetterNameDecl(const ObjCObjectPointerType *QIdTy,
const Selector &Sel,
ASTContext &Context) {
// Check protocols on qualified interfaces.
- Decl *GDecl = 0;
- for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
- E = QIdTy->qual_end(); I != E; ++I) {
+ Decl *GDecl = nullptr;
+ for (const auto *I : QIdTy->quals()) {
if (Member)
- if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) {
+ if (ObjCPropertyDecl *PD = I->FindPropertyDeclaration(Member)) {
GDecl = PD;
break;
}
// Also must look for a getter or setter name which uses property syntax.
- if (ObjCMethodDecl *OMD = (*I)->getInstanceMethod(Sel)) {
+ if (ObjCMethodDecl *OMD = I->getInstanceMethod(Sel)) {
GDecl = OMD;
break;
}
}
if (!GDecl) {
- for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
- E = QIdTy->qual_end(); I != E; ++I) {
+ for (const auto *I : QIdTy->quals()) {
// Search in the protocol-qualifier list of current protocol.
- GDecl = FindGetterSetterNameDeclFromProtocolList(*I, Member, Sel,
- Context);
+ GDecl = FindGetterSetterNameDeclFromProtocolList(I, Member, Sel, Context);
if (GDecl)
return GDecl;
}
@@ -459,12 +455,10 @@ Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType,
// Get the type being accessed in BaseType. If this is an arrow, the BaseExpr
// must have pointer type, and the accessed type is the pointee.
- return Owned(CXXDependentScopeMemberExpr::Create(Context, BaseExpr, BaseType,
- IsArrow, OpLoc,
- SS.getWithLocInContext(Context),
- TemplateKWLoc,
- FirstQualifierInScope,
- NameInfo, TemplateArgs));
+ return CXXDependentScopeMemberExpr::Create(
+ Context, BaseExpr, BaseType, IsArrow, OpLoc,
+ SS.getWithLocInContext(Context), TemplateKWLoc, FirstQualifierInScope,
+ NameInfo, TemplateArgs);
}
/// We know that the given qualified member reference points only to
@@ -546,7 +540,7 @@ class RecordMemberExprValidatorCCC : public CorrectionCandidateCallback {
explicit RecordMemberExprValidatorCCC(const RecordType *RTy)
: Record(RTy->getDecl()) {}
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
NamedDecl *ND = candidate.getCorrectionDecl();
// Don't accept candidates that cannot be member functions, constants,
// variables, or templates.
@@ -559,11 +553,9 @@ class RecordMemberExprValidatorCCC : public CorrectionCandidateCallback {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Record)) {
// Accept candidates that occur in any of the current class' base classes.
- for (CXXRecordDecl::base_class_const_iterator BS = RD->bases_begin(),
- BSEnd = RD->bases_end();
- BS != BSEnd; ++BS) {
+ for (const auto &BS : RD->bases()) {
if (const RecordType *BSTy = dyn_cast_or_null<RecordType>(
- BS->getType().getTypePtrOrNull())) {
+ BS.getType().getTypePtrOrNull())) {
if (BSTy->getDecl()->containsDecl(ND))
return true;
}
@@ -596,7 +588,7 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
QualType ObjectType = SS.isSet() ? QualType() : QualType(RTy, 0);
bool MOUS;
- SemaRef.LookupTemplateName(R, 0, SS, ObjectType, false, MOUS);
+ SemaRef.LookupTemplateName(R, nullptr, SS, ObjectType, false, MOUS);
return false;
}
@@ -632,8 +624,9 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
DeclarationName Name = R.getLookupName();
RecordMemberExprValidatorCCC Validator(RTy);
TypoCorrection Corrected = SemaRef.CorrectTypo(R.getLookupNameInfo(),
- R.getLookupKind(), NULL,
- &SS, Validator, DC);
+ R.getLookupKind(), nullptr,
+ &SS, Validator,
+ Sema::CTK_ErrorRecovery, DC);
R.clear();
if (Corrected.isResolved() && !Corrected.isKeyword()) {
R.setLookupName(Corrected.getCorrection());
@@ -648,7 +641,7 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
// information to do overload resolution, so we don't know which previous
// declaration to point to.
if (Corrected.isOverloaded())
- Corrected.setCorrectionDecl(0);
+ Corrected.setCorrectionDecl(nullptr);
bool DroppedSpecifier =
Corrected.WillReplaceSpecifier() &&
Name.getAsString() == Corrected.getAsString(SemaRef.getLangOpts());
@@ -660,6 +653,11 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
return false;
}
+static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
+ ExprResult &BaseExpr, bool &IsArrow,
+ SourceLocation OpLoc, CXXScopeSpec &SS,
+ Decl *ObjCImpDecl, bool HasTemplateArgs);
+
ExprResult
Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
SourceLocation OpLoc, bool IsArrow,
@@ -667,7 +665,8 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
SourceLocation TemplateKWLoc,
NamedDecl *FirstQualifierInScope,
const DeclarationNameInfo &NameInfo,
- const TemplateArgumentListInfo *TemplateArgs) {
+ const TemplateArgumentListInfo *TemplateArgs,
+ ActOnMemberAccessExtraArgs *ExtraArgs) {
if (BaseType->isDependentType() ||
(SS.isSet() && isDependentScopeSpecifier(SS)))
return ActOnDependentMemberExpr(Base, BaseType,
@@ -683,24 +682,23 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
if (IsArrow) RecordTy = RecordTy->getAs<PointerType>()->getPointeeType();
if (LookupMemberExprInRecord(*this, R, SourceRange(),
RecordTy->getAs<RecordType>(),
- OpLoc, SS, TemplateArgs != 0))
+ OpLoc, SS, TemplateArgs != nullptr))
return ExprError();
// Explicit member accesses.
} else {
- ExprResult BaseResult = Owned(Base);
- ExprResult Result =
- LookupMemberExpr(R, BaseResult, IsArrow, OpLoc,
- SS, /*ObjCImpDecl*/ 0, TemplateArgs != 0);
+ ExprResult BaseResult = Base;
+ ExprResult Result = LookupMemberExpr(
+ *this, R, BaseResult, IsArrow, OpLoc, SS,
+ ExtraArgs ? ExtraArgs->ObjCImpDecl : nullptr,
+ TemplateArgs != nullptr);
if (BaseResult.isInvalid())
return ExprError();
- Base = BaseResult.take();
+ Base = BaseResult.get();
- if (Result.isInvalid()) {
- Owned(Base);
+ if (Result.isInvalid())
return ExprError();
- }
if (Result.get())
return Result;
@@ -711,7 +709,8 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
return BuildMemberReferenceExpr(Base, BaseType,
OpLoc, IsArrow, SS, TemplateKWLoc,
- FirstQualifierInScope, R, TemplateArgs);
+ FirstQualifierInScope, R, TemplateArgs,
+ false, ExtraArgs);
}
static ExprResult
@@ -751,7 +750,7 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
= BuildDeclarationNameExpr(EmptySS, baseNameInfo, baseVariable);
if (result.isInvalid()) return ExprError();
- baseObjectExpr = result.take();
+ baseObjectExpr = result.get();
baseObjectIsPointer = false;
baseQuals = baseObjectExpr->getType().getQualifiers();
@@ -807,12 +806,10 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
result = BuildFieldReferenceExpr(*this, result, baseObjectIsPointer,
EmptySS, field, foundDecl,
- memberNameInfo).take();
+ memberNameInfo).get();
if (!result)
return ExprError();
- baseObjectIsPointer = false;
-
// FIXME: check qualified member access
}
@@ -829,10 +826,10 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
result = BuildFieldReferenceExpr(*this, result, /*isarrow*/ false,
(FI == FEnd? SS : EmptySS), field,
- fakeFoundDecl, memberNameInfo).take();
+ fakeFoundDecl, memberNameInfo).get();
}
- return Owned(result);
+ return result;
}
static ExprResult
@@ -849,16 +846,13 @@ BuildMSPropertyRefExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
}
/// \brief Build a MemberExpr AST node.
-static MemberExpr *BuildMemberExpr(Sema &SemaRef,
- ASTContext &C, Expr *Base, bool isArrow,
- const CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- ValueDecl *Member,
- DeclAccessPair FoundDecl,
- const DeclarationNameInfo &MemberNameInfo,
- QualType Ty,
- ExprValueKind VK, ExprObjectKind OK,
- const TemplateArgumentListInfo *TemplateArgs = 0) {
+static MemberExpr *
+BuildMemberExpr(Sema &SemaRef, ASTContext &C, Expr *Base, bool isArrow,
+ const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+ ValueDecl *Member, DeclAccessPair FoundDecl,
+ const DeclarationNameInfo &MemberNameInfo, QualType Ty,
+ ExprValueKind VK, ExprObjectKind OK,
+ const TemplateArgumentListInfo *TemplateArgs = nullptr) {
assert((!isArrow || Base->isRValue()) && "-> base must be a pointer rvalue");
MemberExpr *E =
MemberExpr::Create(C, Base, isArrow, SS.getWithLocInContext(C),
@@ -1006,7 +1000,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
TemplateKWLoc, MemberNameInfo,
TemplateArgs, R.begin(), R.end());
- return Owned(MemExpr);
+ return MemExpr;
}
assert(R.isSingleResult());
@@ -1043,10 +1037,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
}
// Check the use of this member.
- if (ShouldCheckUse && DiagnoseUseOfDecl(MemberDecl, MemberLoc)) {
- Owned(BaseExpr);
+ if (ShouldCheckUse && DiagnoseUseOfDecl(MemberDecl, MemberLoc))
return ExprError();
- }
if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl))
return BuildFieldReferenceExpr(*this, BaseExpr, IsArrow,
@@ -1064,10 +1056,10 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
OpLoc);
if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
- return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS,
- TemplateKWLoc, Var, FoundDecl, MemberNameInfo,
- Var->getType().getNonReferenceType(),
- VK_LValue, OK_Ordinary));
+ return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, TemplateKWLoc,
+ Var, FoundDecl, MemberNameInfo,
+ Var->getType().getNonReferenceType(), VK_LValue,
+ OK_Ordinary);
}
if (CXXMethodDecl *MemberFn = dyn_cast<CXXMethodDecl>(MemberDecl)) {
@@ -1081,21 +1073,18 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
type = MemberFn->getType();
}
- return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS,
- TemplateKWLoc, MemberFn, FoundDecl,
- MemberNameInfo, type, valueKind,
- OK_Ordinary));
+ return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, TemplateKWLoc,
+ MemberFn, FoundDecl, MemberNameInfo, type, valueKind,
+ OK_Ordinary);
}
assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?");
if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
- return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS,
- TemplateKWLoc, Enum, FoundDecl, MemberNameInfo,
- Enum->getType(), VK_RValue, OK_Ordinary));
+ return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, TemplateKWLoc,
+ Enum, FoundDecl, MemberNameInfo, Enum->getType(),
+ VK_RValue, OK_Ordinary);
}
- Owned(BaseExpr);
-
// We found something that we didn't expect. Complain.
if (isa<TypeDecl>(MemberDecl))
Diag(MemberLoc, diag::err_typecheck_member_reference_type)
@@ -1138,7 +1127,7 @@ static bool ShouldTryAgainWithRedefinitionType(Sema &S, ExprResult &base) {
if (opty && !opty->getObjectType()->getInterface())
return false;
- base = S.ImpCastExprToType(base.take(), redef, CK_BitCast);
+ base = S.ImpCastExprToType(base.get(), redef, CK_BitCast);
return true;
}
@@ -1170,15 +1159,14 @@ Sema::PerformMemberExprBaseConversion(Expr *Base, bool IsArrow) {
///
/// The ObjCImpDecl bit is a gross hack that will need to be properly
/// fixed for ObjC++.
-ExprResult
-Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
- bool &IsArrow, SourceLocation OpLoc,
- CXXScopeSpec &SS,
- Decl *ObjCImpDecl, bool HasTemplateArgs) {
+static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
+ ExprResult &BaseExpr, bool &IsArrow,
+ SourceLocation OpLoc, CXXScopeSpec &SS,
+ Decl *ObjCImpDecl, bool HasTemplateArgs) {
assert(BaseExpr.get() && "no base expression");
// Perform default conversions.
- BaseExpr = PerformMemberExprBaseConversion(BaseExpr.take(), IsArrow);
+ BaseExpr = S.PerformMemberExprBaseConversion(BaseExpr.get(), IsArrow);
if (BaseExpr.isInvalid())
return ExprError();
@@ -1206,8 +1194,8 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
// overloaded operator->, but that should have been dealt with
// by now--or a diagnostic message already issued if a problem
// was encountered while looking for the overloaded operator->.
- if (!getLangOpts().CPlusPlus) {
- Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
+ if (!S.getLangOpts().CPlusPlus) {
+ S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
<< BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
<< FixItHint::CreateReplacement(OpLoc, ".");
}
@@ -1215,7 +1203,7 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
} else if (BaseType->isFunctionType()) {
goto fail;
} else {
- Diag(MemberLoc, diag::err_typecheck_member_reference_arrow)
+ S.Diag(MemberLoc, diag::err_typecheck_member_reference_arrow)
<< BaseType << BaseExpr.get()->getSourceRange();
return ExprError();
}
@@ -1223,24 +1211,24 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
// Handle field access to simple records.
if (const RecordType *RTy = BaseType->getAs<RecordType>()) {
- if (LookupMemberExprInRecord(*this, R, BaseExpr.get()->getSourceRange(),
+ if (LookupMemberExprInRecord(S, R, BaseExpr.get()->getSourceRange(),
RTy, OpLoc, SS, HasTemplateArgs))
return ExprError();
// Returning valid-but-null is how we indicate to the caller that
// the lookup result was filled in.
- return Owned((Expr*) 0);
+ return ExprResult((Expr *)nullptr);
}
// Handle ivar access to Objective-C objects.
if (const ObjCObjectType *OTy = BaseType->getAs<ObjCObjectType>()) {
if (!SS.isEmpty() && !SS.isInvalid()) {
- Diag(SS.getRange().getBegin(), diag::err_qualified_objc_access)
+ S.Diag(SS.getRange().getBegin(), diag::err_qualified_objc_access)
<< 1 << SS.getScopeRep()
<< FixItHint::CreateRemoval(SS.getRange());
SS.clear();
}
-
+
IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
// There are three cases for the base type:
@@ -1249,40 +1237,41 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
// - an interface
ObjCInterfaceDecl *IDecl = OTy->getInterface();
if (!IDecl) {
- if (getLangOpts().ObjCAutoRefCount &&
+ if (S.getLangOpts().ObjCAutoRefCount &&
(OTy->isObjCId() || OTy->isObjCClass()))
goto fail;
// There's an implicit 'isa' ivar on all objects.
// But we only actually find it this way on objects of type 'id',
// apparently.
if (OTy->isObjCId() && Member->isStr("isa"))
- return Owned(new (Context) ObjCIsaExpr(BaseExpr.take(), IsArrow, MemberLoc,
- OpLoc,
- Context.getObjCClassType()));
- if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr))
- return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
+ return new (S.Context) ObjCIsaExpr(BaseExpr.get(), IsArrow, MemberLoc,
+ OpLoc, S.Context.getObjCClassType());
+ if (ShouldTryAgainWithRedefinitionType(S, BaseExpr))
+ return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
ObjCImpDecl, HasTemplateArgs);
goto fail;
}
-
- if (RequireCompleteType(OpLoc, BaseType, diag::err_typecheck_incomplete_tag,
- BaseExpr.get()))
+
+ if (S.RequireCompleteType(OpLoc, BaseType,
+ diag::err_typecheck_incomplete_tag,
+ BaseExpr.get()))
return ExprError();
-
- ObjCInterfaceDecl *ClassDeclared = 0;
+
+ ObjCInterfaceDecl *ClassDeclared = nullptr;
ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared);
if (!IV) {
// Attempt to correct for typos in ivar names.
DeclFilterCCC<ObjCIvarDecl> Validator;
Validator.IsObjCIvarLookup = IsArrow;
- if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(),
- LookupMemberName, NULL, NULL,
- Validator, IDecl)) {
+ if (TypoCorrection Corrected = S.CorrectTypo(
+ R.getLookupNameInfo(), Sema::LookupMemberName, nullptr, nullptr,
+ Validator, Sema::CTK_ErrorRecovery, IDecl)) {
IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>();
- diagnoseTypo(Corrected,
- PDiag(diag::err_typecheck_member_reference_ivar_suggest)
- << IDecl->getDeclName() << MemberName);
+ S.diagnoseTypo(
+ Corrected,
+ S.PDiag(diag::err_typecheck_member_reference_ivar_suggest)
+ << IDecl->getDeclName() << MemberName);
// Figure out the class that declares the ivar.
assert(!ClassDeclared);
@@ -1292,20 +1281,19 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
ClassDeclared = cast<ObjCInterfaceDecl>(D);
} else {
if (IsArrow && IDecl->FindPropertyDeclaration(Member)) {
- Diag(MemberLoc,
- diag::err_property_found_suggest)
- << Member << BaseExpr.get()->getType()
- << FixItHint::CreateReplacement(OpLoc, ".");
+ S.Diag(MemberLoc, diag::err_property_found_suggest)
+ << Member << BaseExpr.get()->getType()
+ << FixItHint::CreateReplacement(OpLoc, ".");
return ExprError();
}
- Diag(MemberLoc, diag::err_typecheck_member_reference_ivar)
- << IDecl->getDeclName() << MemberName
- << BaseExpr.get()->getSourceRange();
+ S.Diag(MemberLoc, diag::err_typecheck_member_reference_ivar)
+ << IDecl->getDeclName() << MemberName
+ << BaseExpr.get()->getSourceRange();
return ExprError();
}
}
-
+
assert(ClassDeclared);
// If the decl being referenced had an error, return an error for this
@@ -1315,14 +1303,14 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
return ExprError();
// Check whether we can reference this field.
- if (DiagnoseUseOfDecl(IV, MemberLoc))
+ if (S.DiagnoseUseOfDecl(IV, MemberLoc))
return ExprError();
if (IV->getAccessControl() != ObjCIvarDecl::Public &&
IV->getAccessControl() != ObjCIvarDecl::Package) {
- ObjCInterfaceDecl *ClassOfMethodDecl = 0;
- if (ObjCMethodDecl *MD = getCurMethodDecl())
+ ObjCInterfaceDecl *ClassOfMethodDecl = nullptr;
+ if (ObjCMethodDecl *MD = S.getCurMethodDecl())
ClassOfMethodDecl = MD->getClassInterface();
- else if (ObjCImpDecl && getCurFunctionDecl()) {
+ else if (ObjCImpDecl && S.getCurFunctionDecl()) {
// Case of a c-function declared inside an objc implementation.
// FIXME: For a c-style function nested inside an objc implementation
// class, there is no implementation context available, so we pass
@@ -1336,20 +1324,20 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
dyn_cast<ObjCCategoryImplDecl>(ObjCImpDecl))
ClassOfMethodDecl = CatImplClass->getClassInterface();
}
- if (!getLangOpts().DebuggerSupport) {
+ if (!S.getLangOpts().DebuggerSupport) {
if (IV->getAccessControl() == ObjCIvarDecl::Private) {
if (!declaresSameEntity(ClassDeclared, IDecl) ||
!declaresSameEntity(ClassOfMethodDecl, ClassDeclared))
- Diag(MemberLoc, diag::error_private_ivar_access)
+ S.Diag(MemberLoc, diag::error_private_ivar_access)
<< IV->getDeclName();
} else if (!IDecl->isSuperClassOf(ClassOfMethodDecl))
// @protected
- Diag(MemberLoc, diag::error_protected_ivar_access)
- << IV->getDeclName();
+ S.Diag(MemberLoc, diag::error_protected_ivar_access)
+ << IV->getDeclName();
}
}
bool warn = true;
- if (getLangOpts().ObjCAutoRefCount) {
+ if (S.getLangOpts().ObjCAutoRefCount) {
Expr *BaseExp = BaseExpr.get()->IgnoreParenImpCasts();
if (UnaryOperator *UO = dyn_cast<UnaryOperator>(BaseExp))
if (UO->getOpcode() == UO_Deref)
@@ -1357,55 +1345,50 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
if (DeclRefExpr *DE = dyn_cast<DeclRefExpr>(BaseExp))
if (DE->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
- Diag(DE->getLocation(), diag::error_arc_weak_ivar_access);
+ S.Diag(DE->getLocation(), diag::error_arc_weak_ivar_access);
warn = false;
}
}
if (warn) {
- if (ObjCMethodDecl *MD = getCurMethodDecl()) {
+ if (ObjCMethodDecl *MD = S.getCurMethodDecl()) {
ObjCMethodFamily MF = MD->getMethodFamily();
warn = (MF != OMF_init && MF != OMF_dealloc &&
MF != OMF_finalize &&
- !IvarBacksCurrentMethodAccessor(IDecl, MD, IV));
+ !S.IvarBacksCurrentMethodAccessor(IDecl, MD, IV));
}
if (warn)
- Diag(MemberLoc, diag::warn_direct_ivar_access) << IV->getDeclName();
+ S.Diag(MemberLoc, diag::warn_direct_ivar_access) << IV->getDeclName();
}
- ObjCIvarRefExpr *Result = new (Context) ObjCIvarRefExpr(IV, IV->getType(),
- MemberLoc, OpLoc,
- BaseExpr.take(),
- IsArrow);
+ ObjCIvarRefExpr *Result = new (S.Context) ObjCIvarRefExpr(
+ IV, IV->getType(), MemberLoc, OpLoc, BaseExpr.get(), IsArrow);
- if (getLangOpts().ObjCAutoRefCount) {
+ if (S.getLangOpts().ObjCAutoRefCount) {
if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
- DiagnosticsEngine::Level Level =
- Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
- MemberLoc);
- if (Level != DiagnosticsEngine::Ignored)
- recordUseOfEvaluatedWeak(Result);
+ if (!S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, MemberLoc))
+ S.recordUseOfEvaluatedWeak(Result);
}
}
- return Owned(Result);
+ return Result;
}
// Objective-C property access.
const ObjCObjectPointerType *OPT;
if (!IsArrow && (OPT = BaseType->getAs<ObjCObjectPointerType>())) {
if (!SS.isEmpty() && !SS.isInvalid()) {
- Diag(SS.getRange().getBegin(), diag::err_qualified_objc_access)
- << 0 << SS.getScopeRep()
- << FixItHint::CreateRemoval(SS.getRange());
+ S.Diag(SS.getRange().getBegin(), diag::err_qualified_objc_access)
+ << 0 << SS.getScopeRep() << FixItHint::CreateRemoval(SS.getRange());
SS.clear();
}
// This actually uses the base as an r-value.
- BaseExpr = DefaultLvalueConversion(BaseExpr.take());
+ BaseExpr = S.DefaultLvalueConversion(BaseExpr.get());
if (BaseExpr.isInvalid())
return ExprError();
- assert(Context.hasSameUnqualifiedType(BaseType, BaseExpr.get()->getType()));
+ assert(S.Context.hasSameUnqualifiedType(BaseType,
+ BaseExpr.get()->getType()));
IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
@@ -1414,77 +1397,75 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
// id, with and without qualifiers.
if (OT->isObjCId()) {
// Check protocols on qualified interfaces.
- Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
- if (Decl *PMDecl = FindGetterSetterNameDecl(OPT, Member, Sel, Context)) {
+ Selector Sel = S.PP.getSelectorTable().getNullarySelector(Member);
+ if (Decl *PMDecl =
+ FindGetterSetterNameDecl(OPT, Member, Sel, S.Context)) {
if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(PMDecl)) {
// Check the use of this declaration
- if (DiagnoseUseOfDecl(PD, MemberLoc))
+ if (S.DiagnoseUseOfDecl(PD, MemberLoc))
return ExprError();
- return Owned(new (Context) ObjCPropertyRefExpr(PD,
- Context.PseudoObjectTy,
- VK_LValue,
- OK_ObjCProperty,
- MemberLoc,
- BaseExpr.take()));
+ return new (S.Context)
+ ObjCPropertyRefExpr(PD, S.Context.PseudoObjectTy, VK_LValue,
+ OK_ObjCProperty, MemberLoc, BaseExpr.get());
}
if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(PMDecl)) {
// Check the use of this method.
- if (DiagnoseUseOfDecl(OMD, MemberLoc))
+ if (S.DiagnoseUseOfDecl(OMD, MemberLoc))
return ExprError();
Selector SetterSel =
- SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
- PP.getSelectorTable(),
+ SelectorTable::constructSetterSelector(S.PP.getIdentifierTable(),
+ S.PP.getSelectorTable(),
Member);
- ObjCMethodDecl *SMD = 0;
- if (Decl *SDecl = FindGetterSetterNameDecl(OPT, /*Property id*/0,
- SetterSel, Context))
+ ObjCMethodDecl *SMD = nullptr;
+ if (Decl *SDecl = FindGetterSetterNameDecl(OPT,
+ /*Property id*/ nullptr,
+ SetterSel, S.Context))
SMD = dyn_cast<ObjCMethodDecl>(SDecl);
-
- return Owned(new (Context) ObjCPropertyRefExpr(OMD, SMD,
- Context.PseudoObjectTy,
- VK_LValue, OK_ObjCProperty,
- MemberLoc, BaseExpr.take()));
+
+ return new (S.Context)
+ ObjCPropertyRefExpr(OMD, SMD, S.Context.PseudoObjectTy, VK_LValue,
+ OK_ObjCProperty, MemberLoc, BaseExpr.get());
}
}
// Use of id.member can only be for a property reference. Do not
// use the 'id' redefinition in this case.
- if (IsArrow && ShouldTryAgainWithRedefinitionType(*this, BaseExpr))
- return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
+ if (IsArrow && ShouldTryAgainWithRedefinitionType(S, BaseExpr))
+ return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
ObjCImpDecl, HasTemplateArgs);
- return ExprError(Diag(MemberLoc, diag::err_property_not_found)
+ return ExprError(S.Diag(MemberLoc, diag::err_property_not_found)
<< MemberName << BaseType);
}
// 'Class', unqualified only.
if (OT->isObjCClass()) {
// Only works in a method declaration (??!).
- ObjCMethodDecl *MD = getCurMethodDecl();
+ ObjCMethodDecl *MD = S.getCurMethodDecl();
if (!MD) {
- if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr))
- return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
+ if (ShouldTryAgainWithRedefinitionType(S, BaseExpr))
+ return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
ObjCImpDecl, HasTemplateArgs);
goto fail;
}
// Also must look for a getter name which uses property syntax.
- Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
+ Selector Sel = S.PP.getSelectorTable().getNullarySelector(Member);
ObjCInterfaceDecl *IFace = MD->getClassInterface();
ObjCMethodDecl *Getter;
if ((Getter = IFace->lookupClassMethod(Sel))) {
// Check the use of this method.
- if (DiagnoseUseOfDecl(Getter, MemberLoc))
+ if (S.DiagnoseUseOfDecl(Getter, MemberLoc))
return ExprError();
} else
Getter = IFace->lookupPrivateMethod(Sel, false);
// If we found a getter then this may be a valid dot-reference, we
// will look for the matching setter, in case it is needed.
Selector SetterSel =
- SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
- PP.getSelectorTable(),
+ SelectorTable::constructSetterSelector(S.PP.getIdentifierTable(),
+ S.PP.getSelectorTable(),
Member);
ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);
if (!Setter) {
@@ -1493,28 +1474,27 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
Setter = IFace->lookupPrivateMethod(SetterSel, false);
}
- if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc))
+ if (Setter && S.DiagnoseUseOfDecl(Setter, MemberLoc))
return ExprError();
if (Getter || Setter) {
- return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
- Context.PseudoObjectTy,
- VK_LValue, OK_ObjCProperty,
- MemberLoc, BaseExpr.take()));
+ return new (S.Context) ObjCPropertyRefExpr(
+ Getter, Setter, S.Context.PseudoObjectTy, VK_LValue,
+ OK_ObjCProperty, MemberLoc, BaseExpr.get());
}
- if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr))
- return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
+ if (ShouldTryAgainWithRedefinitionType(S, BaseExpr))
+ return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
ObjCImpDecl, HasTemplateArgs);
- return ExprError(Diag(MemberLoc, diag::err_property_not_found)
+ return ExprError(S.Diag(MemberLoc, diag::err_property_not_found)
<< MemberName << BaseType);
}
// Normal property access.
- return HandleExprPropertyRefExpr(OPT, BaseExpr.get(), OpLoc,
- MemberName, MemberLoc,
- SourceLocation(), QualType(), false);
+ return S.HandleExprPropertyRefExpr(OPT, BaseExpr.get(), OpLoc, MemberName,
+ MemberLoc, SourceLocation(), QualType(),
+ false);
}
// Handle 'field access' to vectors, such as 'V.xx'.
@@ -1522,24 +1502,22 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
// FIXME: this expr should store IsArrow.
IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
ExprValueKind VK = (IsArrow ? VK_LValue : BaseExpr.get()->getValueKind());
- QualType ret = CheckExtVectorComponent(*this, BaseType, VK, OpLoc,
+ QualType ret = CheckExtVectorComponent(S, BaseType, VK, OpLoc,
Member, MemberLoc);
if (ret.isNull())
return ExprError();
- return Owned(new (Context) ExtVectorElementExpr(ret, VK, BaseExpr.take(),
- *Member, MemberLoc));
+ return new (S.Context)
+ ExtVectorElementExpr(ret, VK, BaseExpr.get(), *Member, MemberLoc);
}
// Adjust builtin-sel to the appropriate redefinition type if that's
// not just a pointer to builtin-sel again.
- if (IsArrow &&
- BaseType->isSpecificBuiltinType(BuiltinType::ObjCSel) &&
- !Context.getObjCSelRedefinitionType()->isObjCSelType()) {
- BaseExpr = ImpCastExprToType(BaseExpr.take(),
- Context.getObjCSelRedefinitionType(),
- CK_BitCast);
- return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
+ if (IsArrow && BaseType->isSpecificBuiltinType(BuiltinType::ObjCSel) &&
+ !S.Context.getObjCSelRedefinitionType()->isObjCSelType()) {
+ BaseExpr = S.ImpCastExprToType(
+ BaseExpr.get(), S.Context.getObjCSelRedefinitionType(), CK_BitCast);
+ return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
ObjCImpDecl, HasTemplateArgs);
}
@@ -1556,31 +1534,31 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
if (!IsArrow && Ptr->getPointeeType()->isRecordType() &&
MemberName.getNameKind() != DeclarationName::CXXDestructorName) {
- Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
- << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
+ S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
+ << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
<< FixItHint::CreateReplacement(OpLoc, "->");
// Recurse as an -> access.
IsArrow = true;
- return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
+ return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
ObjCImpDecl, HasTemplateArgs);
}
}
// If the user is trying to apply -> or . to a function name, it's probably
// because they forgot parentheses to call that function.
- if (tryToRecoverWithCall(BaseExpr,
- PDiag(diag::err_member_reference_needs_call),
- /*complain*/ false,
- IsArrow ? &isPointerToRecordType : &isRecordType)) {
+ if (S.tryToRecoverWithCall(
+ BaseExpr, S.PDiag(diag::err_member_reference_needs_call),
+ /*complain*/ false,
+ IsArrow ? &isPointerToRecordType : &isRecordType)) {
if (BaseExpr.isInvalid())
return ExprError();
- BaseExpr = DefaultFunctionArrayConversion(BaseExpr.take());
- return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
+ BaseExpr = S.DefaultFunctionArrayConversion(BaseExpr.get());
+ return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
ObjCImpDecl, HasTemplateArgs);
}
- Diag(OpLoc, diag::err_typecheck_member_reference_struct_union)
+ S.Diag(OpLoc, diag::err_typecheck_member_reference_struct_union)
<< BaseType << BaseExpr.get()->getSourceRange() << MemberLoc;
return ExprError();
@@ -1610,6 +1588,19 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
if (SS.isSet() && SS.isInvalid())
return ExprError();
+ // The only way a reference to a destructor can be used is to
+ // immediately call it. If the next token is not a '(', produce
+ // a diagnostic and build the call now.
+ if (!HasTrailingLParen &&
+ Id.getKind() == UnqualifiedId::IK_DestructorName) {
+ ExprResult DtorAccess =
+ ActOnMemberAccessExpr(S, Base, OpLoc, OpKind, SS, TemplateKWLoc, Id,
+ ObjCImpDecl, /*HasTrailingLParen*/true);
+ if (DtorAccess.isInvalid())
+ return DtorAccess;
+ return DiagnoseDtorReference(Id.getLocStart(), DtorAccess.get());
+ }
+
// Warn about the explicit constructor calls Microsoft extension.
if (getLangOpts().MicrosoftExt &&
Id.getKind() == UnqualifiedId::IK_ConstructorName)
@@ -1628,54 +1619,25 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
bool IsArrow = (OpKind == tok::arrow);
NamedDecl *FirstQualifierInScope
- = (!SS.isSet() ? 0 : FindFirstQualifierInScope(S,
- static_cast<NestedNameSpecifier*>(SS.getScopeRep())));
+ = (!SS.isSet() ? nullptr : FindFirstQualifierInScope(S, SS.getScopeRep()));
// This is a postfix expression, so get rid of ParenListExprs.
ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base);
if (Result.isInvalid()) return ExprError();
- Base = Result.take();
+ Base = Result.get();
if (Base->getType()->isDependentType() || Name.isDependentName() ||
isDependentScopeSpecifier(SS)) {
- Result = ActOnDependentMemberExpr(Base, Base->getType(),
- IsArrow, OpLoc,
- SS, TemplateKWLoc, FirstQualifierInScope,
- NameInfo, TemplateArgs);
- } else {
- LookupResult R(*this, NameInfo, LookupMemberName);
- ExprResult BaseResult = Owned(Base);
- Result = LookupMemberExpr(R, BaseResult, IsArrow, OpLoc,
- SS, ObjCImpDecl, TemplateArgs != 0);
- if (BaseResult.isInvalid())
- return ExprError();
- Base = BaseResult.take();
-
- if (Result.isInvalid()) {
- Owned(Base);
- return ExprError();
- }
-
- if (Result.get()) {
- // The only way a reference to a destructor can be used is to
- // immediately call it, which falls into this case. If the
- // next token is not a '(', produce a diagnostic and build the
- // call now.
- if (!HasTrailingLParen &&
- Id.getKind() == UnqualifiedId::IK_DestructorName)
- return DiagnoseDtorReference(NameInfo.getLoc(), Result.get());
-
- return Result;
- }
-
- ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl, HasTrailingLParen};
- Result = BuildMemberReferenceExpr(Base, Base->getType(),
- OpLoc, IsArrow, SS, TemplateKWLoc,
- FirstQualifierInScope, R, TemplateArgs,
- false, &ExtraArgs);
+ return ActOnDependentMemberExpr(Base, Base->getType(), IsArrow, OpLoc, SS,
+ TemplateKWLoc, FirstQualifierInScope,
+ NameInfo, TemplateArgs);
}
- return Result;
+ ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl,
+ HasTrailingLParen};
+ return BuildMemberReferenceExpr(Base, Base->getType(), OpLoc, IsArrow, SS,
+ TemplateKWLoc, FirstQualifierInScope,
+ NameInfo, TemplateArgs, &ExtraArgs);
}
static ExprResult
@@ -1734,10 +1696,9 @@ BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
FoundDecl, Field);
if (Base.isInvalid())
return ExprError();
- return S.Owned(BuildMemberExpr(S, S.Context, Base.take(), IsArrow, SS,
- /*TemplateKWLoc=*/SourceLocation(),
- Field, FoundDecl, MemberNameInfo,
- MemberType, VK, OK));
+ return BuildMemberExpr(S, S.Context, Base.get(), IsArrow, SS,
+ /*TemplateKWLoc=*/SourceLocation(), Field, FoundDecl,
+ MemberNameInfo, MemberType, VK, OK);
}
/// Builds an implicit member access expression. The current context
@@ -1753,21 +1714,14 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
assert(!R.empty() && !R.isAmbiguous());
SourceLocation loc = R.getNameLoc();
-
- // We may have found a field within an anonymous union or struct
- // (C++ [class.union]).
- // FIXME: template-ids inside anonymous structs?
- if (IndirectFieldDecl *FD = R.getAsSingle<IndirectFieldDecl>())
- return BuildAnonymousStructUnionMemberReference(SS, R.getNameLoc(), FD,
- R.begin().getPair());
-
+
// If this is known to be an instance access, go ahead and build an
// implicit 'this' expression now.
// 'this' expression now.
QualType ThisTy = getCurrentThisType();
assert(!ThisTy.isNull() && "didn't correctly pre-flight capture of 'this'");
-
- Expr *baseExpr = 0; // null signifies implicit access
+
+ Expr *baseExpr = nullptr; // null signifies implicit access
if (IsKnownInstance) {
SourceLocation Loc = R.getNameLoc();
if (SS.getRange().isValid())
@@ -1775,11 +1729,11 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
CheckCXXThisCapture(Loc);
baseExpr = new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/true);
}
-
+
return BuildMemberReferenceExpr(baseExpr, ThisTy,
/*OpLoc*/ SourceLocation(),
/*IsArrow*/ true,
SS, TemplateKWLoc,
- /*FirstQualifierInScope*/ 0,
+ /*FirstQualifierInScope*/ nullptr,
R, TemplateArgs);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
index cc8eace..5002332 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
@@ -67,10 +67,14 @@ ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
// Create the aggregate string with the appropriate content and location
// information.
- S = StringLiteral::Create(Context, StrBuf,
- StringLiteral::Ascii, /*Pascal=*/false,
- Context.getPointerType(Context.CharTy),
- &StrLocs[0], StrLocs.size());
+ const ConstantArrayType *CAT = Context.getAsConstantArrayType(S->getType());
+ assert(CAT && "String literal not of constant array type!");
+ QualType StrTy = Context.getConstantArrayType(
+ CAT->getElementType(), llvm::APInt(32, StrBuf.size() + 1),
+ CAT->getSizeModifier(), CAT->getIndexTypeCVRQualifiers());
+ S = StringLiteral::Create(Context, StrBuf, StringLiteral::Ascii,
+ /*Pascal=*/false, StrTy, &StrLocs[0],
+ StrLocs.size());
}
return BuildObjCStringLiteral(AtLocs[0], S);
@@ -89,7 +93,7 @@ ExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){
if (!Ty.isNull()) {
Ty = Context.getObjCObjectPointerType(Ty);
} else if (getLangOpts().NoConstantCFStrings) {
- IdentifierInfo *NSIdent=0;
+ IdentifierInfo *NSIdent=nullptr;
std::string StringClass(getLangOpts().ObjCConstantStringClass);
if (StringClass.empty())
@@ -129,7 +133,7 @@ ExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){
ObjCInterfaceDecl::Create (Context,
Context.getTranslationUnitDecl(),
SourceLocation(), NSIdent,
- 0, SourceLocation());
+ nullptr, SourceLocation());
Ty = Context.getObjCInterfaceType(NSStringIDecl);
Context.setObjCNSStringType(Ty);
}
@@ -152,7 +156,7 @@ static bool validateBoxingMethod(Sema &S, SourceLocation Loc,
}
// Make sure the return type is reasonable.
- QualType ReturnType = Method->getResultType();
+ QualType ReturnType = Method->getReturnType();
if (!ReturnType->isObjCObjectPointerType()) {
S.Diag(Loc, diag::err_objc_literal_method_sig)
<< Sel;
@@ -178,7 +182,7 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
S.Diag(Loc, diag::err_invalid_nsnumber_type)
<< NumberType << R;
}
- return 0;
+ return nullptr;
}
// If we already looked up this method, we're done.
@@ -204,15 +208,15 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
S.NSNumberDecl = ObjCInterfaceDecl::Create(CX,
CX.getTranslationUnitDecl(),
SourceLocation(), NSNumberId,
- 0, SourceLocation());
+ nullptr, SourceLocation());
} else {
// Otherwise, require a declaration of NSNumber.
S.Diag(Loc, diag::err_undeclared_nsnumber);
- return 0;
+ return nullptr;
}
} else if (!S.NSNumberDecl->hasDefinition()) {
S.Diag(Loc, diag::err_undeclared_nsnumber);
- return 0;
+ return nullptr;
}
// generate the pointer to NSNumber type.
@@ -224,26 +228,25 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
ObjCMethodDecl *Method = S.NSNumberDecl->lookupClassMethod(Sel);
if (!Method && S.getLangOpts().DebuggerObjCLiteral) {
// create a stub definition this NSNumber factory method.
- TypeSourceInfo *ResultTInfo = 0;
- Method = ObjCMethodDecl::Create(CX, SourceLocation(), SourceLocation(), Sel,
- S.NSNumberPointer, ResultTInfo,
- S.NSNumberDecl,
- /*isInstance=*/false, /*isVariadic=*/false,
- /*isPropertyAccessor=*/false,
- /*isImplicitlyDeclared=*/true,
- /*isDefined=*/false,
- ObjCMethodDecl::Required,
- /*HasRelatedResultType=*/false);
+ TypeSourceInfo *ReturnTInfo = nullptr;
+ Method =
+ ObjCMethodDecl::Create(CX, SourceLocation(), SourceLocation(), Sel,
+ S.NSNumberPointer, ReturnTInfo, S.NSNumberDecl,
+ /*isInstance=*/false, /*isVariadic=*/false,
+ /*isPropertyAccessor=*/false,
+ /*isImplicitlyDeclared=*/true,
+ /*isDefined=*/false, ObjCMethodDecl::Required,
+ /*HasRelatedResultType=*/false);
ParmVarDecl *value = ParmVarDecl::Create(S.Context, Method,
SourceLocation(), SourceLocation(),
&CX.Idents.get("value"),
- NumberType, /*TInfo=*/0, SC_None,
- 0);
+ NumberType, /*TInfo=*/nullptr,
+ SC_None, nullptr);
Method->setMethodParams(S.Context, value, None);
}
if (!validateBoxingMethod(S, Loc, S.NSNumberDecl, Sel, Method))
- return 0;
+ return nullptr;
// Note: if the parameter type is out-of-line, we'll catch it later in the
// implicit conversion.
@@ -288,12 +291,12 @@ ExprResult Sema::BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number) {
return ExprError();
// Convert the number to the type that the parameter expects.
- ParmVarDecl *ParamDecl = Method->param_begin()[0];
+ ParmVarDecl *ParamDecl = Method->parameters()[0];
InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
ParamDecl);
ExprResult ConvertedNumber = PerformCopyInitialization(Entity,
SourceLocation(),
- Owned(Number));
+ Number);
if (ConvertedNumber.isInvalid())
return ExprError();
Number = ConvertedNumber.get();
@@ -441,10 +444,10 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,
ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
if (ValueExpr->isTypeDependent()) {
ObjCBoxedExpr *BoxedExpr =
- new (Context) ObjCBoxedExpr(ValueExpr, Context.DependentTy, NULL, SR);
- return Owned(BoxedExpr);
+ new (Context) ObjCBoxedExpr(ValueExpr, Context.DependentTy, nullptr, SR);
+ return BoxedExpr;
}
- ObjCMethodDecl *BoxingMethod = NULL;
+ ObjCMethodDecl *BoxingMethod = nullptr;
QualType BoxedType;
// Convert the expression to an RValue, so we can check for pointer types...
ExprResult RValue = DefaultFunctionArrayLvalueConversion(ValueExpr);
@@ -470,7 +473,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
NSStringDecl = ObjCInterfaceDecl::Create(Context, TU,
SourceLocation(),
NSStringId,
- 0, SourceLocation());
+ nullptr, SourceLocation());
} else {
Diag(SR.getBegin(), diag::err_undeclared_nsstring);
return ExprError();
@@ -492,25 +495,23 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
BoxingMethod = NSStringDecl->lookupClassMethod(stringWithUTF8String);
if (!BoxingMethod && getLangOpts().DebuggerObjCLiteral) {
// Debugger needs to work even if NSString hasn't been defined.
- TypeSourceInfo *ResultTInfo = 0;
- ObjCMethodDecl *M =
- ObjCMethodDecl::Create(Context, SourceLocation(), SourceLocation(),
- stringWithUTF8String, NSStringPointer,
- ResultTInfo, NSStringDecl,
- /*isInstance=*/false, /*isVariadic=*/false,
- /*isPropertyAccessor=*/false,
- /*isImplicitlyDeclared=*/true,
- /*isDefined=*/false,
- ObjCMethodDecl::Required,
- /*HasRelatedResultType=*/false);
+ TypeSourceInfo *ReturnTInfo = nullptr;
+ ObjCMethodDecl *M = ObjCMethodDecl::Create(
+ Context, SourceLocation(), SourceLocation(), stringWithUTF8String,
+ NSStringPointer, ReturnTInfo, NSStringDecl,
+ /*isInstance=*/false, /*isVariadic=*/false,
+ /*isPropertyAccessor=*/false,
+ /*isImplicitlyDeclared=*/true,
+ /*isDefined=*/false, ObjCMethodDecl::Required,
+ /*HasRelatedResultType=*/false);
QualType ConstCharType = Context.CharTy.withConst();
ParmVarDecl *value =
ParmVarDecl::Create(Context, M,
SourceLocation(), SourceLocation(),
&Context.Idents.get("value"),
Context.getPointerType(ConstCharType),
- /*TInfo=*/0,
- SC_None, 0);
+ /*TInfo=*/nullptr,
+ SC_None, nullptr);
M->setMethodParams(Context, value, None);
BoxingMethod = M;
}
@@ -554,7 +555,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
break;
}
}
-
+ CheckForIntOverflow(ValueExpr);
// FIXME: Do I need to do anything special with BoolTy expressions?
// Look for the appropriate method within NSNumber.
@@ -580,12 +581,12 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
}
// Convert the expression to the type that the parameter requires.
- ParmVarDecl *ParamDecl = BoxingMethod->param_begin()[0];
+ ParmVarDecl *ParamDecl = BoxingMethod->parameters()[0];
InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
ParamDecl);
ExprResult ConvertedValueExpr = PerformCopyInitialization(Entity,
SourceLocation(),
- Owned(ValueExpr));
+ ValueExpr);
if (ConvertedValueExpr.isInvalid())
return ExprError();
ValueExpr = ConvertedValueExpr.get();
@@ -623,13 +624,9 @@ ExprResult Sema::BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr,
BaseExpr = Result.get();
// Build the pseudo-object expression.
- return Owned(ObjCSubscriptRefExpr::Create(Context,
- BaseExpr,
- IndexExpr,
- Context.PseudoObjectTy,
- getterMethod,
- setterMethod, RB));
-
+ return ObjCSubscriptRefExpr::Create(Context, BaseExpr, IndexExpr,
+ Context.PseudoObjectTy, getterMethod,
+ setterMethod, RB);
}
ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
@@ -645,7 +642,7 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
Context.getTranslationUnitDecl(),
SourceLocation(),
NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray),
- 0, SourceLocation());
+ nullptr, SourceLocation());
if (!NSArrayDecl) {
Diag(SR.getBegin(), diag::err_undeclared_nsarray);
@@ -660,31 +657,30 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
Sel = NSAPIObj->getNSArraySelector(NSAPI::NSArr_arrayWithObjectsCount);
ObjCMethodDecl *Method = NSArrayDecl->lookupClassMethod(Sel);
if (!Method && getLangOpts().DebuggerObjCLiteral) {
- TypeSourceInfo *ResultTInfo = 0;
- Method = ObjCMethodDecl::Create(Context,
- SourceLocation(), SourceLocation(), Sel,
- IdT,
- ResultTInfo,
- Context.getTranslationUnitDecl(),
- false /*Instance*/, false/*isVariadic*/,
- /*isPropertyAccessor=*/false,
- /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
- ObjCMethodDecl::Required,
- false);
+ TypeSourceInfo *ReturnTInfo = nullptr;
+ Method = ObjCMethodDecl::Create(
+ Context, SourceLocation(), SourceLocation(), Sel, IdT, ReturnTInfo,
+ Context.getTranslationUnitDecl(), false /*Instance*/,
+ false /*isVariadic*/,
+ /*isPropertyAccessor=*/false,
+ /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
+ ObjCMethodDecl::Required, false);
SmallVector<ParmVarDecl *, 2> Params;
ParmVarDecl *objects = ParmVarDecl::Create(Context, Method,
SourceLocation(),
SourceLocation(),
&Context.Idents.get("objects"),
Context.getPointerType(IdT),
- /*TInfo=*/0, SC_None, 0);
+ /*TInfo=*/nullptr,
+ SC_None, nullptr);
Params.push_back(objects);
ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method,
SourceLocation(),
SourceLocation(),
&Context.Idents.get("cnt"),
Context.UnsignedLongTy,
- /*TInfo=*/0, SC_None, 0);
+ /*TInfo=*/nullptr, SC_None,
+ nullptr);
Params.push_back(cnt);
Method->setMethodParams(Context, Params, None);
}
@@ -693,13 +689,13 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
return ExprError();
// Dig out the type that all elements should be converted to.
- QualType T = Method->param_begin()[0]->getType();
+ QualType T = Method->parameters()[0]->getType();
const PointerType *PtrT = T->getAs<PointerType>();
if (!PtrT ||
!Context.hasSameUnqualifiedType(PtrT->getPointeeType(), IdT)) {
Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
<< Sel;
- Diag(Method->param_begin()[0]->getLocation(),
+ Diag(Method->parameters()[0]->getLocation(),
diag::note_objc_literal_method_param)
<< 0 << T
<< Context.getPointerType(IdT.withConst());
@@ -707,13 +703,13 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
}
// Check that the 'count' parameter is integral.
- if (!Method->param_begin()[1]->getType()->isIntegerType()) {
+ if (!Method->parameters()[1]->getType()->isIntegerType()) {
Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
<< Sel;
- Diag(Method->param_begin()[1]->getLocation(),
+ Diag(Method->parameters()[1]->getLocation(),
diag::note_objc_literal_method_param)
<< 1
- << Method->param_begin()[1]->getType()
+ << Method->parameters()[1]->getType()
<< "integral";
return ExprError();
}
@@ -722,7 +718,7 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
ArrayWithObjectsMethod = Method;
}
- QualType ObjectsType = ArrayWithObjectsMethod->param_begin()[0]->getType();
+ QualType ObjectsType = ArrayWithObjectsMethod->parameters()[0]->getType();
QualType RequiredType = ObjectsType->castAs<PointerType>()->getPointeeType();
// Check that each of the elements provided is valid in a collection literal,
@@ -761,7 +757,7 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
Context.getTranslationUnitDecl(),
SourceLocation(),
NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary),
- 0, SourceLocation());
+ nullptr, SourceLocation());
if (!NSDictionaryDecl) {
Diag(SR.getBegin(), diag::err_undeclared_nsdictionary);
@@ -780,7 +776,7 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
Method = ObjCMethodDecl::Create(Context,
SourceLocation(), SourceLocation(), Sel,
IdT,
- 0 /*TypeSourceInfo */,
+ nullptr /*TypeSourceInfo */,
Context.getTranslationUnitDecl(),
false /*Instance*/, false/*isVariadic*/,
/*isPropertyAccessor=*/false,
@@ -793,21 +789,24 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
SourceLocation(),
&Context.Idents.get("objects"),
Context.getPointerType(IdT),
- /*TInfo=*/0, SC_None, 0);
+ /*TInfo=*/nullptr, SC_None,
+ nullptr);
Params.push_back(objects);
ParmVarDecl *keys = ParmVarDecl::Create(Context, Method,
SourceLocation(),
SourceLocation(),
&Context.Idents.get("keys"),
Context.getPointerType(IdT),
- /*TInfo=*/0, SC_None, 0);
+ /*TInfo=*/nullptr, SC_None,
+ nullptr);
Params.push_back(keys);
ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method,
SourceLocation(),
SourceLocation(),
&Context.Idents.get("cnt"),
Context.UnsignedLongTy,
- /*TInfo=*/0, SC_None, 0);
+ /*TInfo=*/nullptr, SC_None,
+ nullptr);
Params.push_back(cnt);
Method->setMethodParams(Context, Params, None);
}
@@ -817,13 +816,13 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
return ExprError();
// Dig out the type that all values should be converted to.
- QualType ValueT = Method->param_begin()[0]->getType();
+ QualType ValueT = Method->parameters()[0]->getType();
const PointerType *PtrValue = ValueT->getAs<PointerType>();
if (!PtrValue ||
!Context.hasSameUnqualifiedType(PtrValue->getPointeeType(), IdT)) {
Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
<< Sel;
- Diag(Method->param_begin()[0]->getLocation(),
+ Diag(Method->parameters()[0]->getLocation(),
diag::note_objc_literal_method_param)
<< 0 << ValueT
<< Context.getPointerType(IdT.withConst());
@@ -831,7 +830,7 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
}
// Dig out the type that all keys should be converted to.
- QualType KeyT = Method->param_begin()[1]->getType();
+ QualType KeyT = Method->parameters()[1]->getType();
const PointerType *PtrKey = KeyT->getAs<PointerType>();
if (!PtrKey ||
!Context.hasSameUnqualifiedType(PtrKey->getPointeeType(),
@@ -857,7 +856,7 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
if (err) {
Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
<< Sel;
- Diag(Method->param_begin()[1]->getLocation(),
+ Diag(Method->parameters()[1]->getLocation(),
diag::note_objc_literal_method_param)
<< 1 << KeyT
<< Context.getPointerType(IdT.withConst());
@@ -866,11 +865,11 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
}
// Check that the 'count' parameter is integral.
- QualType CountType = Method->param_begin()[2]->getType();
+ QualType CountType = Method->parameters()[2]->getType();
if (!CountType->isIntegerType()) {
Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
<< Sel;
- Diag(Method->param_begin()[2]->getLocation(),
+ Diag(Method->parameters()[2]->getLocation(),
diag::note_objc_literal_method_param)
<< 2 << CountType
<< "integral";
@@ -881,9 +880,9 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
DictionaryWithObjectsMethod = Method;
}
- QualType ValuesT = DictionaryWithObjectsMethod->param_begin()[0]->getType();
+ QualType ValuesT = DictionaryWithObjectsMethod->parameters()[0]->getType();
QualType ValueT = ValuesT->castAs<PointerType>()->getPointeeType();
- QualType KeysT = DictionaryWithObjectsMethod->param_begin()[1]->getType();
+ QualType KeysT = DictionaryWithObjectsMethod->parameters()[1]->getType();
QualType KeyT = KeysT->castAs<PointerType>()->getPointeeType();
// Check that each of the keys and values provided is valid in a collection
@@ -975,11 +974,68 @@ ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
return BuildObjCEncodeExpression(AtLoc, TInfo, RParenLoc);
}
+static bool HelperToDiagnoseMismatchedMethodsInGlobalPool(Sema &S,
+ SourceLocation AtLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc,
+ ObjCMethodDecl *Method,
+ ObjCMethodList &MethList) {
+ ObjCMethodList *M = &MethList;
+ bool Warned = false;
+ for (M = M->getNext(); M; M=M->getNext()) {
+ ObjCMethodDecl *MatchingMethodDecl = M->Method;
+ if (MatchingMethodDecl == Method ||
+ isa<ObjCImplDecl>(MatchingMethodDecl->getDeclContext()) ||
+ MatchingMethodDecl->getSelector() != Method->getSelector())
+ continue;
+ if (!S.MatchTwoMethodDeclarations(Method,
+ MatchingMethodDecl, Sema::MMS_loose)) {
+ if (!Warned) {
+ Warned = true;
+ S.Diag(AtLoc, diag::warning_multiple_selectors)
+ << Method->getSelector() << FixItHint::CreateInsertion(LParenLoc, "(")
+ << FixItHint::CreateInsertion(RParenLoc, ")");
+ S.Diag(Method->getLocation(), diag::note_method_declared_at)
+ << Method->getDeclName();
+ }
+ S.Diag(MatchingMethodDecl->getLocation(), diag::note_method_declared_at)
+ << MatchingMethodDecl->getDeclName();
+ }
+ }
+ return Warned;
+}
+
+static void DiagnoseMismatchedSelectors(Sema &S, SourceLocation AtLoc,
+ ObjCMethodDecl *Method,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc,
+ bool WarnMultipleSelectors) {
+ if (!WarnMultipleSelectors ||
+ S.Diags.isIgnored(diag::warning_multiple_selectors, SourceLocation()))
+ return;
+ bool Warned = false;
+ for (Sema::GlobalMethodPool::iterator b = S.MethodPool.begin(),
+ e = S.MethodPool.end(); b != e; b++) {
+ // first, instance methods
+ ObjCMethodList &InstMethList = b->second.first;
+ if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc, LParenLoc, RParenLoc,
+ Method, InstMethList))
+ Warned = true;
+
+ // second, class methods
+ ObjCMethodList &ClsMethList = b->second.second;
+ if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc, LParenLoc, RParenLoc,
+ Method, ClsMethList) || Warned)
+ return;
+ }
+}
+
ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
SourceLocation AtLoc,
SourceLocation SelLoc,
SourceLocation LParenLoc,
- SourceLocation RParenLoc) {
+ SourceLocation RParenLoc,
+ bool WarnMultipleSelectors) {
ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,
SourceRange(LParenLoc, RParenLoc), false, false);
if (!Method)
@@ -996,10 +1052,13 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
} else
Diag(SelLoc, diag::warn_undeclared_selector) << Sel;
- }
+ } else
+ DiagnoseMismatchedSelectors(*this, AtLoc, Method, LParenLoc, RParenLoc,
+ WarnMultipleSelectors);
- if (!Method ||
- Method->getImplementationControl() != ObjCMethodDecl::Optional) {
+ if (Method &&
+ Method->getImplementationControl() != ObjCMethodDecl::Optional &&
+ !getSourceManager().isInSystemHeader(Method->getLocation())) {
llvm::DenseMap<Selector, SourceLocation>::iterator Pos
= ReferencedSelectors.find(Sel);
if (Pos == ReferencedSelectors.end())
@@ -1063,7 +1122,7 @@ ObjCMethodDecl *Sema::tryCaptureObjCSelf(SourceLocation Loc) {
// still have a 'self', and we really do still need to capture it!
ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(DC);
if (!method)
- return 0;
+ return nullptr;
tryCaptureVariable(method->getSelfDecl(), Loc);
@@ -1120,7 +1179,8 @@ QualType Sema::getMessageSendResultType(QualType ReceiverType,
static const ObjCMethodDecl *
findExplicitInstancetypeDeclarer(const ObjCMethodDecl *MD,
QualType instancetype) {
- if (MD->getResultType() == instancetype) return MD;
+ if (MD->getReturnType() == instancetype)
+ return MD;
// For these purposes, a method in an @implementation overrides a
// declaration in the @interface.
@@ -1147,7 +1207,7 @@ findExplicitInstancetypeDeclarer(const ObjCMethodDecl *MD,
return result;
}
- return 0;
+ return nullptr;
}
void Sema::EmitRelatedResultTypeNoteForReturn(QualType destType) {
@@ -1155,7 +1215,7 @@ void Sema::EmitRelatedResultTypeNoteForReturn(QualType destType) {
// type doesn't match the method's declared return type.
ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CurContext);
if (!MD || !MD->hasRelatedResultType() ||
- Context.hasSameUnqualifiedType(destType, MD->getResultType()))
+ Context.hasSameUnqualifiedType(destType, MD->getReturnType()))
return;
// Look for a method overridden by this method which explicitly uses
@@ -1164,7 +1224,7 @@ void Sema::EmitRelatedResultTypeNoteForReturn(QualType destType) {
findExplicitInstancetypeDeclarer(MD, Context.getObjCInstanceType())) {
SourceLocation loc;
SourceRange range;
- if (TypeSourceInfo *TSI = overridden->getResultTypeSourceInfo()) {
+ if (TypeSourceInfo *TSI = overridden->getReturnTypeSourceInfo()) {
range = TSI->getTypeLoc().getSourceRange();
loc = range.getBegin();
}
@@ -1195,13 +1255,12 @@ void Sema::EmitRelatedResultTypeNote(const Expr *E) {
if (!Method->hasRelatedResultType())
return;
-
- if (Context.hasSameUnqualifiedType(Method->getResultType()
- .getNonReferenceType(),
- MsgSend->getType()))
+
+ if (Context.hasSameUnqualifiedType(
+ Method->getReturnType().getNonReferenceType(), MsgSend->getType()))
return;
-
- if (!Context.hasSameUnqualifiedType(Method->getResultType(),
+
+ if (!Context.hasSameUnqualifiedType(Method->getReturnType(),
Context.getObjCInstanceType()))
return;
@@ -1239,7 +1298,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
}
if (result.isInvalid())
return true;
- Args[i] = result.take();
+ Args[i] = result.get();
}
unsigned DiagID;
@@ -1287,7 +1346,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
ReturnType = getMessageSendResultType(ReceiverType, Method, isClassMessage,
isSuperMessage);
- VK = Expr::getValueKindForType(Method->getResultType());
+ VK = Expr::getValueKindForType(Method->getReturnType());
unsigned NumNamedArgs = Sel.getNumArgs();
// Method might have more arguments than selector indicates. This is due
@@ -1309,7 +1368,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
Expr *argExpr = Args[i];
- ParmVarDecl *param = Method->param_begin()[i];
+ ParmVarDecl *param = Method->parameters()[i];
assert(argExpr && "CheckMessageArgumentTypes(): missing expression");
// Strip the unbridged-cast placeholder expression off unless it's
@@ -1326,7 +1385,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
if (argE.isInvalid()) {
IsError = true;
} else {
- Args[i] = argE.take();
+ Args[i] = argE.get();
// Update the parameter type in-place.
param->setType(paramType);
@@ -1341,11 +1400,11 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
param);
- ExprResult ArgE = PerformCopyInitialization(Entity, SelLoc, Owned(argExpr));
+ ExprResult ArgE = PerformCopyInitialization(Entity, SelLoc, argExpr);
if (ArgE.isInvalid())
IsError = true;
else
- Args[i] = ArgE.takeAs<Expr>();
+ Args[i] = ArgE.getAs<Expr>();
}
// Promote additional arguments to variadic methods.
@@ -1355,9 +1414,9 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
continue;
ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod,
- 0);
+ nullptr);
IsError |= Arg.isInvalid();
- Args[i] = Arg.take();
+ Args[i] = Arg.get();
}
} else {
// Check for extra arguments to non-variadic methods.
@@ -1380,10 +1439,14 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
return IsError;
}
-bool Sema::isSelfExpr(Expr *receiver) {
+bool Sema::isSelfExpr(Expr *RExpr) {
// 'self' is objc 'self' in an objc method only.
- ObjCMethodDecl *method =
- dyn_cast_or_null<ObjCMethodDecl>(CurContext->getNonClosureAncestor());
+ ObjCMethodDecl *Method =
+ dyn_cast_or_null<ObjCMethodDecl>(CurContext->getNonClosureAncestor());
+ return isSelfExpr(RExpr, Method);
+}
+
+bool Sema::isSelfExpr(Expr *receiver, const ObjCMethodDecl *method) {
if (!method) return false;
receiver = receiver->IgnoreParenLValueCasts();
@@ -1409,12 +1472,11 @@ ObjCMethodDecl *Sema::LookupMethodInObjectType(Selector sel, QualType type,
}
// Check qualifiers.
- for (ObjCObjectType::qual_iterator
- i = objType->qual_begin(), e = objType->qual_end(); i != e; ++i)
- if (ObjCMethodDecl *method = (*i)->lookupMethod(sel, isInstance))
+ for (const auto *I : objType->quals())
+ if (ObjCMethodDecl *method = I->lookupMethod(sel, isInstance))
return method;
- return 0;
+ return nullptr;
}
/// LookupMethodInQualifiedType - Lookups up a method in protocol qualifier
@@ -1423,15 +1485,13 @@ ObjCMethodDecl *Sema::LookupMethodInQualifiedType(Selector Sel,
const ObjCObjectPointerType *OPT,
bool Instance)
{
- ObjCMethodDecl *MD = 0;
- for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(),
- E = OPT->qual_end(); I != E; ++I) {
- ObjCProtocolDecl *PROTO = (*I);
+ ObjCMethodDecl *MD = nullptr;
+ for (const auto *PROTO : OPT->quals()) {
if ((MD = PROTO->lookupMethod(Sel, Instance))) {
return MD;
}
}
- return 0;
+ return nullptr;
}
static void DiagnoseARCUseOfWeakReceiver(Sema &S, Expr *Receiver) {
@@ -1444,15 +1504,15 @@ static void DiagnoseARCUseOfWeakReceiver(Sema &S, Expr *Receiver) {
Expr *RExpr = Receiver->IgnoreParenImpCasts();
SourceLocation Loc = RExpr->getLocStart();
QualType T = RExpr->getType();
- const ObjCPropertyDecl *PDecl = 0;
- const ObjCMethodDecl *GDecl = 0;
+ const ObjCPropertyDecl *PDecl = nullptr;
+ const ObjCMethodDecl *GDecl = nullptr;
if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(RExpr)) {
RExpr = POE->getSyntacticForm();
if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(RExpr)) {
if (PRE->isImplicitProperty()) {
GDecl = PRE->getImplicitPropertyGetter();
if (GDecl) {
- T = GDecl->getResultType();
+ T = GDecl->getReturnType();
}
}
else {
@@ -1525,37 +1585,29 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
if (DiagnoseUseOfDecl(PD, MemberLoc))
return ExprError();
if (Super)
- return Owned(new (Context) ObjCPropertyRefExpr(PD, Context.PseudoObjectTy,
- VK_LValue, OK_ObjCProperty,
- MemberLoc,
- SuperLoc, SuperType));
+ return new (Context)
+ ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, VK_LValue,
+ OK_ObjCProperty, MemberLoc, SuperLoc, SuperType);
else
- return Owned(new (Context) ObjCPropertyRefExpr(PD, Context.PseudoObjectTy,
- VK_LValue, OK_ObjCProperty,
- MemberLoc, BaseExpr));
+ return new (Context)
+ ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, VK_LValue,
+ OK_ObjCProperty, MemberLoc, BaseExpr);
}
// Check protocols on qualified interfaces.
- for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(),
- E = OPT->qual_end(); I != E; ++I)
- if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) {
+ for (const auto *I : OPT->quals())
+ if (ObjCPropertyDecl *PD = I->FindPropertyDeclaration(Member)) {
// Check whether we can reference this property.
if (DiagnoseUseOfDecl(PD, MemberLoc))
return ExprError();
if (Super)
- return Owned(new (Context) ObjCPropertyRefExpr(PD,
- Context.PseudoObjectTy,
- VK_LValue,
- OK_ObjCProperty,
- MemberLoc,
- SuperLoc, SuperType));
+ return new (Context) ObjCPropertyRefExpr(
+ PD, Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty, MemberLoc,
+ SuperLoc, SuperType);
else
- return Owned(new (Context) ObjCPropertyRefExpr(PD,
- Context.PseudoObjectTy,
- VK_LValue,
- OK_ObjCProperty,
- MemberLoc,
- BaseExpr));
+ return new (Context)
+ ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, VK_LValue,
+ OK_ObjCProperty, MemberLoc, BaseExpr);
}
// If that failed, look for an "implicit" property by seeing if the nullary
// selector is implemented.
@@ -1601,24 +1653,21 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
if (Getter || Setter) {
if (Super)
- return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
- Context.PseudoObjectTy,
- VK_LValue, OK_ObjCProperty,
- MemberLoc,
- SuperLoc, SuperType));
+ return new (Context)
+ ObjCPropertyRefExpr(Getter, Setter, Context.PseudoObjectTy, VK_LValue,
+ OK_ObjCProperty, MemberLoc, SuperLoc, SuperType);
else
- return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
- Context.PseudoObjectTy,
- VK_LValue, OK_ObjCProperty,
- MemberLoc, BaseExpr));
+ return new (Context)
+ ObjCPropertyRefExpr(Getter, Setter, Context.PseudoObjectTy, VK_LValue,
+ OK_ObjCProperty, MemberLoc, BaseExpr);
}
// Attempt to correct for typos in property names.
DeclFilterCCC<ObjCPropertyDecl> Validator;
if (TypoCorrection Corrected = CorrectTypo(
- DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName, NULL,
- NULL, Validator, IFace, false, OPT)) {
+ DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName,
+ nullptr, nullptr, Validator, CTK_ErrorRecovery, IFace, false, OPT)) {
diagnoseTypo(Corrected, PDiag(diag::err_property_not_found_suggest)
<< MemberName << QualType(OPT, 0));
DeclarationName TypoResult = Corrected.getCorrection();
@@ -1665,7 +1714,7 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
receiverNameLoc);
bool IsSuper = false;
- if (IFace == 0) {
+ if (!IFace) {
// If the "receiver" is 'super' in a method, handle it as an expression-like
// property reference.
if (receiverNamePtr->isStr("super")) {
@@ -1683,9 +1732,9 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
}
QualType T = Context.getObjCInterfaceType(Super);
T = Context.getObjCObjectPointerType(T);
-
+
return HandleExprPropertyRefExpr(T->getAsObjCInterfacePointerType(),
- /*BaseExpr*/0,
+ /*BaseExpr*/nullptr,
SourceLocation()/*OpLoc*/,
&propertyName,
propertyNameLoc,
@@ -1697,9 +1746,10 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
IFace = CurMethod->getClassInterface()->getSuperClass();
}
}
-
- if (IFace == 0) {
- Diag(receiverNameLoc, diag::err_expected_ident_or_lparen);
+
+ if (!IFace) {
+ Diag(receiverNameLoc, diag::err_expected_either) << tok::identifier
+ << tok::l_paren;
return ExprError();
}
}
@@ -1710,10 +1760,7 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
// If this reference is in an @implementation, check for 'private' methods.
if (!Getter)
- if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
- if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
- if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
- Getter = ImpDecl->getClassMethod(Sel);
+ Getter = IFace->lookupPrivateClassMethod(Sel);
if (Getter) {
// FIXME: refactor/share with ActOnMemberReference().
@@ -1732,10 +1779,7 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
if (!Setter) {
// If this reference is in an @implementation, also check for 'private'
// methods.
- if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
- if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
- if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
- Setter = ImpDecl->getClassMethod(SetterSel);
+ Setter = IFace->lookupPrivateClassMethod(SetterSel);
}
// Look through local category implementations associated with the class.
if (!Setter)
@@ -1746,18 +1790,14 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
if (Getter || Setter) {
if (IsSuper)
- return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
- Context.PseudoObjectTy,
- VK_LValue, OK_ObjCProperty,
- propertyNameLoc,
- receiverNameLoc,
- Context.getObjCInterfaceType(IFace)));
-
- return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
- Context.PseudoObjectTy,
- VK_LValue, OK_ObjCProperty,
- propertyNameLoc,
- receiverNameLoc, IFace));
+ return new (Context)
+ ObjCPropertyRefExpr(Getter, Setter, Context.PseudoObjectTy, VK_LValue,
+ OK_ObjCProperty, propertyNameLoc, receiverNameLoc,
+ Context.getObjCInterfaceType(IFace));
+
+ return new (Context) ObjCPropertyRefExpr(
+ Getter, Setter, Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty,
+ propertyNameLoc, receiverNameLoc, IFace);
}
return ExprError(Diag(propertyNameLoc, diag::err_property_not_found)
<< &propertyName << Context.getObjCInterfaceType(IFace));
@@ -1773,7 +1813,7 @@ class ObjCInterfaceOrSuperCCC : public CorrectionCandidateCallback {
WantObjCSuper = Method->getClassInterface()->getSuperClass();
}
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
return candidate.getCorrectionDeclAs<ObjCInterfaceDecl>() ||
candidate.isKeyword("super");
}
@@ -1855,7 +1895,8 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
ObjCInterfaceOrSuperCCC Validator(getCurMethodDecl());
if (TypoCorrection Corrected =
CorrectTypo(Result.getLookupNameInfo(), Result.getLookupKind(), S,
- NULL, Validator, NULL, false, NULL, false)) {
+ nullptr, Validator, CTK_ErrorRecovery, nullptr, false,
+ nullptr, false)) {
if (Corrected.isKeyword()) {
// If we've found the keyword "super" (the only keyword that would be
// returned by CorrectTypo), this is a send to super.
@@ -1918,16 +1959,16 @@ ExprResult Sema::ActOnSuperMessage(Scope *S,
// message to the superclass instance.
QualType SuperTy = Context.getObjCInterfaceType(Super);
SuperTy = Context.getObjCObjectPointerType(SuperTy);
- return BuildInstanceMessage(0, SuperTy, SuperLoc,
- Sel, /*Method=*/0,
+ return BuildInstanceMessage(nullptr, SuperTy, SuperLoc,
+ Sel, /*Method=*/nullptr,
LBracLoc, SelectorLocs, RBracLoc, Args);
}
// Since we are in a class method, this is a class message to
// the superclass.
- return BuildClassMessage(/*ReceiverTypeInfo=*/0,
+ return BuildClassMessage(/*ReceiverTypeInfo=*/nullptr,
Context.getObjCInterfaceType(Super),
- SuperLoc, Sel, /*Method=*/0,
+ SuperLoc, Sel, /*Method=*/nullptr,
LBracLoc, SelectorLocs, RBracLoc, Args);
}
@@ -1938,7 +1979,7 @@ ExprResult Sema::BuildClassMessageImplicit(QualType ReceiverType,
Selector Sel,
ObjCMethodDecl *Method,
MultiExprArg Args) {
- TypeSourceInfo *receiverTypeInfo = 0;
+ TypeSourceInfo *receiverTypeInfo = nullptr;
if (!ReceiverType.isNull())
receiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType);
@@ -1954,7 +1995,7 @@ static void applyCocoaAPICheck(Sema &S, const ObjCMessageExpr *Msg,
bool (*refactor)(const ObjCMessageExpr *,
const NSAPI &, edit::Commit &)) {
SourceLocation MsgLoc = Msg->getExprLoc();
- if (S.Diags.getDiagnosticLevel(DiagID, MsgLoc) == DiagnosticsEngine::Ignored)
+ if (S.Diags.isIgnored(DiagID, MsgLoc))
return;
SourceManager &SM = S.SourceMgr;
@@ -2050,15 +2091,14 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
unsigned NumArgs = ArgsIn.size();
Expr **Args = ArgsIn.data();
assert(SuperLoc.isInvalid() && "Message to super with dependent type");
- return Owned(ObjCMessageExpr::Create(Context, ReceiverType,
- VK_RValue, LBracLoc, ReceiverTypeInfo,
- Sel, SelectorLocs, /*Method=*/0,
- makeArrayRef(Args, NumArgs),RBracLoc,
- isImplicit));
+ return ObjCMessageExpr::Create(
+ Context, ReceiverType, VK_RValue, LBracLoc, ReceiverTypeInfo, Sel,
+ SelectorLocs, /*Method=*/nullptr, makeArrayRef(Args, NumArgs), RBracLoc,
+ isImplicit);
}
// Find the class to which we are sending this message.
- ObjCInterfaceDecl *Class = 0;
+ ObjCInterfaceDecl *Class = nullptr;
const ObjCObjectType *ClassType = ReceiverType->getAs<ObjCObjectType>();
if (!ClassType || !(Class = ClassType->getInterface())) {
Diag(Loc, diag::err_invalid_receiver_class_message)
@@ -2110,8 +2150,8 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
ReturnType, VK))
return ExprError();
- if (Method && !Method->getResultType()->isVoidType() &&
- RequireCompleteType(LBracLoc, Method->getResultType(),
+ if (Method && !Method->getReturnType()->isVoidType() &&
+ RequireCompleteType(LBracLoc, Method->getReturnType(),
diag::err_illegal_message_expr_incomplete_type))
return ExprError();
@@ -2154,8 +2194,9 @@ ExprResult Sema::ActOnClassMessage(Scope *S,
ReceiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType, LBracLoc);
return BuildClassMessage(ReceiverTypeInfo, ReceiverType,
- /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0,
- LBracLoc, SelectorLocs, RBracLoc, Args);
+ /*SuperLoc=*/SourceLocation(), Sel,
+ /*Method=*/nullptr, LBracLoc, SelectorLocs, RBracLoc,
+ Args);
}
ExprResult Sema::BuildInstanceMessageImplicit(Expr *Receiver,
@@ -2234,7 +2275,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
else
Result = CheckPlaceholderExpr(Receiver);
if (Result.isInvalid()) return ExprError();
- Receiver = Result.take();
+ Receiver = Result.get();
}
if (Receiver->isTypeDependent()) {
@@ -2243,11 +2284,10 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
unsigned NumArgs = ArgsIn.size();
Expr **Args = ArgsIn.data();
assert(SuperLoc.isInvalid() && "Message to super with dependent type");
- return Owned(ObjCMessageExpr::Create(Context, Context.DependentTy,
- VK_RValue, LBracLoc, Receiver, Sel,
- SelectorLocs, /*Method=*/0,
- makeArrayRef(Args, NumArgs),
- RBracLoc, isImplicit));
+ return ObjCMessageExpr::Create(
+ Context, Context.DependentTy, VK_RValue, LBracLoc, Receiver, Sel,
+ SelectorLocs, /*Method=*/nullptr, makeArrayRef(Args, NumArgs),
+ RBracLoc, isImplicit);
}
// If necessary, apply function/array conversion to the receiver.
@@ -2255,7 +2295,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
ExprResult Result = DefaultFunctionArrayLvalueConversion(Receiver);
if (Result.isInvalid())
return ExprError();
- Receiver = Result.take();
+ Receiver = Result.get();
ReceiverType = Receiver->getType();
// If the receiver is an ObjC pointer, a block pointer, or an
@@ -2274,14 +2314,14 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
<< Receiver->getSourceRange();
if (ReceiverType->isPointerType()) {
Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(),
- CK_CPointerToObjCPointerCast).take();
+ CK_CPointerToObjCPointerCast).get();
} else {
// TODO: specialized warning on null receivers?
bool IsNull = Receiver->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull);
CastKind Kind = IsNull ? CK_NullToPointer : CK_IntegralToPointer;
Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(),
- Kind).take();
+ Kind).get();
}
ReceiverType = Receiver->getType();
} else if (getLangOpts().CPlusPlus) {
@@ -2292,7 +2332,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
ExprResult result = PerformContextuallyConvertToObjCPointer(Receiver);
if (result.isUsable()) {
- Receiver = result.take();
+ Receiver = result.get();
ReceiverType = Receiver->getType();
}
}
@@ -2369,7 +2409,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
}
}
} else {
- ObjCInterfaceDecl* ClassDecl = 0;
+ ObjCInterfaceDecl *ClassDecl = nullptr;
// We allow sending a message to a qualified ID ("id<foo>"), which is ok as
// long as one of the protocols implements the selector (if not, warn).
@@ -2389,7 +2429,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
// Try to complete the type. Under ARC, this is a hard error from which
// we don't try to recover.
- const ObjCInterfaceDecl *forwardClass = 0;
+ const ObjCInterfaceDecl *forwardClass = nullptr;
if (RequireCompleteType(Loc, OCIType->getPointeeType(),
getLangOpts().ObjCAutoRefCount
? diag::err_arc_receiver_forward_instance
@@ -2402,7 +2442,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
forwardClass = OCIType->getInterfaceDecl();
Diag(Receiver ? Receiver->getLocStart()
: SuperLoc, diag::note_receiver_is_id);
- Method = 0;
+ Method = nullptr;
} else {
Method = ClassDecl->lookupInstanceMethod(Sel);
}
@@ -2447,6 +2487,52 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
}
}
+ FunctionScopeInfo *DIFunctionScopeInfo =
+ (Method && Method->getMethodFamily() == OMF_init)
+ ? getEnclosingFunction() : nullptr;
+
+ if (DIFunctionScopeInfo &&
+ DIFunctionScopeInfo->ObjCIsDesignatedInit &&
+ (SuperLoc.isValid() || isSelfExpr(Receiver))) {
+ bool isDesignatedInitChain = false;
+ if (SuperLoc.isValid()) {
+ if (const ObjCObjectPointerType *
+ OCIType = ReceiverType->getAsObjCInterfacePointerType()) {
+ if (const ObjCInterfaceDecl *ID = OCIType->getInterfaceDecl()) {
+ // Either we know this is a designated initializer or we
+ // conservatively assume it because we don't know for sure.
+ if (!ID->declaresOrInheritsDesignatedInitializers() ||
+ ID->isDesignatedInitializer(Sel)) {
+ isDesignatedInitChain = true;
+ DIFunctionScopeInfo->ObjCWarnForNoDesignatedInitChain = false;
+ }
+ }
+ }
+ }
+ if (!isDesignatedInitChain) {
+ const ObjCMethodDecl *InitMethod = nullptr;
+ bool isDesignated =
+ getCurMethodDecl()->isDesignatedInitializerForTheInterface(&InitMethod);
+ assert(isDesignated && InitMethod);
+ (void)isDesignated;
+ Diag(SelLoc, SuperLoc.isValid() ?
+ diag::warn_objc_designated_init_non_designated_init_call :
+ diag::warn_objc_designated_init_non_super_designated_init_call);
+ Diag(InitMethod->getLocation(),
+ diag::note_objc_designated_init_marked_here);
+ }
+ }
+
+ if (DIFunctionScopeInfo &&
+ DIFunctionScopeInfo->ObjCIsSecondaryInit &&
+ (SuperLoc.isValid() || isSelfExpr(Receiver))) {
+ if (SuperLoc.isValid()) {
+ Diag(SelLoc, diag::warn_objc_secondary_init_super_init_call);
+ } else {
+ DIFunctionScopeInfo->ObjCWarnForNoInitDelegation = false;
+ }
+ }
+
// Check the message arguments.
unsigned NumArgs = ArgsIn.size();
Expr **Args = ArgsIn.data();
@@ -2459,9 +2545,9 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
ClassMessage, SuperLoc.isValid(),
LBracLoc, RBracLoc, ReturnType, VK))
return ExprError();
-
- if (Method && !Method->getResultType()->isVoidType() &&
- RequireCompleteType(LBracLoc, Method->getResultType(),
+
+ if (Method && !Method->getReturnType()->isVoidType() &&
+ RequireCompleteType(LBracLoc, Method->getReturnType(),
diag::err_illegal_message_expr_incomplete_type))
return ExprError();
@@ -2562,7 +2648,14 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
}
if (getLangOpts().ObjCAutoRefCount) {
- DiagnoseARCUseOfWeakReceiver(*this, Receiver);
+ // Do not warn about IBOutlet weak property receivers being set to null
+ // as this cannot asynchronously happen.
+ bool WarnWeakReceiver = true;
+ if (isImplicit && Method)
+ if (const ObjCPropertyDecl *PropertyDecl = Method->findPropertyDecl())
+ WarnWeakReceiver = !PropertyDecl->hasAttr<IBOutletAttr>();
+ if (WarnWeakReceiver)
+ DiagnoseARCUseOfWeakReceiver(*this, Receiver);
// In ARC, annotate delegate init calls.
if (Result->getMethodFamily() == OMF_init &&
@@ -2574,7 +2667,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
// The implicit assignment to self means we also don't want to
// consume the result.
Result->setDelegateInitCall(true);
- return Owned(Result);
+ return Result;
}
}
@@ -2588,19 +2681,13 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak;
if (!IsWeak && Sel.isUnarySelector())
IsWeak = ReturnType.getObjCLifetime() & Qualifiers::OCL_Weak;
-
- if (IsWeak) {
- DiagnosticsEngine::Level Level =
- Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
- LBracLoc);
- if (Level != DiagnosticsEngine::Ignored)
- getCurFunction()->recordUseOfWeak(Result, Prop);
-
- }
+ if (IsWeak &&
+ !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, LBracLoc))
+ getCurFunction()->recordUseOfWeak(Result, Prop);
}
}
}
-
+
return MaybeBindToTemporary(Result);
}
@@ -2633,7 +2720,7 @@ ExprResult Sema::ActOnInstanceMessage(Scope *S,
if (isa<ParenListExpr>(Receiver)) {
ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Receiver);
if (Result.isInvalid()) return ExprError();
- Receiver = Result.take();
+ Receiver = Result.get();
}
if (RespondsToSelectorSel.isNull()) {
@@ -2642,10 +2729,11 @@ ExprResult Sema::ActOnInstanceMessage(Scope *S,
}
if (Sel == RespondsToSelectorSel)
RemoveSelectorFromWarningCache(*this, Args[0]);
-
+
return BuildInstanceMessage(Receiver, Receiver->getType(),
- /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0,
- LBracLoc, SelectorLocs, RBracLoc, Args);
+ /*SuperLoc=*/SourceLocation(), Sel,
+ /*Method=*/nullptr, LBracLoc, SelectorLocs,
+ RBracLoc, Args);
}
enum ARCConversionTypeClass {
@@ -2859,7 +2947,7 @@ namespace {
ACCResult checkCallToFunction(FunctionDecl *fn) {
// Require a CF*Ref return type.
- if (!isCFType(fn->getResultType()))
+ if (!isCFType(fn->getReturnType()))
return ACC_invalid;
if (!isAnyRetainable(TargetClass))
@@ -2912,7 +3000,7 @@ namespace {
// Check for message sends to functions returning CF types. We
// just obey the Cocoa conventions with these, even though the
// return type is CF.
- if (!isAnyRetainable(TargetClass) || !isCFType(method->getResultType()))
+ if (!isAnyRetainable(TargetClass) || !isCFType(method->getReturnType()))
return ACC_invalid;
// If the method is explicitly marked not-retained, it's +0.
@@ -3045,6 +3133,31 @@ static void addFixitForObjCARCConversion(Sema &S,
}
}
+template <typename T>
+static inline T *getObjCBridgeAttr(const TypedefType *TD) {
+ TypedefNameDecl *TDNDecl = TD->getDecl();
+ QualType QT = TDNDecl->getUnderlyingType();
+ if (QT->isPointerType()) {
+ QT = QT->getPointeeType();
+ if (const RecordType *RT = QT->getAs<RecordType>())
+ if (RecordDecl *RD = RT->getDecl()->getMostRecentDecl())
+ return RD->getAttr<T>();
+ }
+ return nullptr;
+}
+
+static ObjCBridgeRelatedAttr *ObjCBridgeRelatedAttrFromType(QualType T,
+ TypedefNameDecl *&TDNDecl) {
+ while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) {
+ TDNDecl = TD->getDecl();
+ if (ObjCBridgeRelatedAttr *ObjCBAttr =
+ getObjCBridgeAttr<ObjCBridgeRelatedAttr>(TD))
+ return ObjCBAttr;
+ T = TDNDecl->getUnderlyingType();
+ }
+ return nullptr;
+}
+
static void
diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
QualType castType, ARCConversionTypeClass castACTC,
@@ -3059,6 +3172,12 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
return;
QualType castExprType = castExpr->getType();
+ TypedefNameDecl *TDNDecl = nullptr;
+ if ((castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable &&
+ ObjCBridgeRelatedAttrFromType(castType, TDNDecl)) ||
+ (exprACTC == ACTC_coreFoundation && castACTC == ACTC_retainable &&
+ ObjCBridgeRelatedAttrFromType(castExprType, TDNDecl)))
+ return;
unsigned srcKind = 0;
switch (exprACTC) {
@@ -3099,9 +3218,10 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
DiagnosticBuilder DiagB =
(CCK != Sema::CCK_OtherCast) ? S.Diag(noteLoc, diag::note_arc_bridge)
: S.Diag(noteLoc, diag::note_arc_cstyle_bridge);
-
+
addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
- castType, castExpr, realCast, "__bridge ", 0);
+ castType, castExpr, realCast, "__bridge ",
+ nullptr);
}
if (CreateRule != ACC_plusZero)
{
@@ -3111,15 +3231,15 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
S.Diag(br ? castExpr->getExprLoc() : noteLoc,
diag::note_arc_bridge_transfer)
<< castExprType << br;
-
+
addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
castType, castExpr, realCast, "__bridge_transfer ",
- br ? "CFBridgingRelease" : 0);
+ br ? "CFBridgingRelease" : nullptr);
}
return;
}
-
+
// Bridge from a CF type to an ARC type.
if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC)) {
bool br = S.isKnownName("CFBridgingRetain");
@@ -3140,7 +3260,8 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
(CCK != Sema::CCK_OtherCast) ? S.Diag(noteLoc, diag::note_arc_bridge)
: S.Diag(noteLoc, diag::note_arc_cstyle_bridge);
addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
- castType, castExpr, realCast, "__bridge ", 0);
+ castType, castExpr, realCast, "__bridge ",
+ nullptr);
}
if (CreateRule != ACC_plusZero)
{
@@ -3150,10 +3271,10 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
S.Diag(br ? castExpr->getExprLoc() : noteLoc,
diag::note_arc_bridge_retained)
<< castType << br;
-
+
addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
castType, castExpr, realCast, "__bridge_retained ",
- br ? "CFBridgingRetain" : 0);
+ br ? "CFBridgingRetain" : nullptr);
}
return;
@@ -3165,26 +3286,17 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
<< castRange << castExpr->getSourceRange();
}
-static inline ObjCBridgeAttr *getObjCBridgeAttr(const TypedefType *TD) {
- TypedefNameDecl *TDNDecl = TD->getDecl();
- QualType QT = TDNDecl->getUnderlyingType();
- if (QT->isPointerType()) {
- QT = QT->getPointeeType();
- if (const RecordType *RT = QT->getAs<RecordType>())
- if (RecordDecl *RD = RT->getDecl())
- if (RD->hasAttr<ObjCBridgeAttr>())
- return RD->getAttr<ObjCBridgeAttr>();
- }
- return 0;
-}
-
-static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr) {
+template <typename TB>
+static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr,
+ bool &HadTheAttribute, bool warn) {
QualType T = castExpr->getType();
+ HadTheAttribute = false;
while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) {
TypedefNameDecl *TDNDecl = TD->getDecl();
- if (ObjCBridgeAttr *ObjCBAttr = getObjCBridgeAttr(TD)) {
+ if (TB *ObjCBAttr = getObjCBridgeAttr<TB>(TD)) {
if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {
- NamedDecl *Target = 0;
+ HadTheAttribute = true;
+ NamedDecl *Target = nullptr;
// Check for an existing type with this name.
LookupResult R(S, DeclarationName(Parm), SourceLocation(),
Sema::LookupOrdinaryName);
@@ -3196,39 +3308,56 @@ static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr) {
castType->getAsObjCInterfacePointerType()) {
ObjCInterfaceDecl *CastClass
= InterfacePointerType->getObjectType()->getInterface();
- if ((CastClass == ExprClass) || (CastClass && ExprClass->isSuperClassOf(CastClass)))
+ if ((CastClass == ExprClass) ||
+ (CastClass && ExprClass->isSuperClassOf(CastClass)))
return true;
- S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge)
- << T << Target->getName() << castType->getPointeeType();
- return true;
- } else {
- S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge)
- << T << Target->getName() << castType;
+ if (warn)
+ S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge)
+ << T << Target->getName() << castType->getPointeeType();
+ return false;
+ } else if (castType->isObjCIdType() ||
+ (S.Context.ObjCObjectAdoptsQTypeProtocols(
+ castType, ExprClass)))
+ // ok to cast to 'id'.
+ // casting to id<p-list> is ok if bridge type adopts all of
+ // p-list protocols.
return true;
+ else {
+ if (warn) {
+ S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge)
+ << T << Target->getName() << castType;
+ S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ S.Diag(Target->getLocStart(), diag::note_declared_at);
+ }
+ return false;
}
}
}
S.Diag(castExpr->getLocStart(), diag::err_objc_cf_bridged_not_interface)
- << castExpr->getType() << Parm->getName();
+ << castExpr->getType() << Parm;
S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
if (Target)
S.Diag(Target->getLocStart(), diag::note_declared_at);
+ return true;
}
- return true;
+ return false;
}
T = TDNDecl->getUnderlyingType();
}
- return false;
+ return true;
}
-// (CFErrorRef)ns
-static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr) {
+template <typename TB>
+static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr,
+ bool &HadTheAttribute, bool warn) {
QualType T = castType;
+ HadTheAttribute = false;
while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) {
TypedefNameDecl *TDNDecl = TD->getDecl();
- if (ObjCBridgeAttr *ObjCBAttr = getObjCBridgeAttr(TD)) {
+ if (TB *ObjCBAttr = getObjCBridgeAttr<TB>(TD)) {
if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {
- NamedDecl *Target = 0;
+ HadTheAttribute = true;
+ NamedDecl *Target = nullptr;
// Check for an existing type with this name.
LookupResult R(S, DeclarationName(Parm), SourceLocation(),
Sema::LookupOrdinaryName);
@@ -3240,17 +3369,30 @@ static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr) {
castExpr->getType()->getAsObjCInterfacePointerType()) {
ObjCInterfaceDecl *ExprClass
= InterfacePointerType->getObjectType()->getInterface();
- if ((CastClass == ExprClass) || (ExprClass && CastClass->isSuperClassOf(ExprClass)))
+ if ((CastClass == ExprClass) ||
+ (ExprClass && CastClass->isSuperClassOf(ExprClass)))
return true;
- S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf)
- << castExpr->getType()->getPointeeType() << T;
- S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
- return true;
- } else {
- S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf)
- << castExpr->getType() << castType;
- S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ if (warn) {
+ S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf)
+ << castExpr->getType()->getPointeeType() << T;
+ S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ }
+ return false;
+ } else if (castExpr->getType()->isObjCIdType() ||
+ (S.Context.QIdProtocolsAdoptObjCObjectProtocols(
+ castExpr->getType(), CastClass)))
+ // ok to cast an 'id' expression to a CFtype.
+ // ok to cast an 'id<plist>' expression to CFtype provided plist
+ // adopts all of CFtype's ObjetiveC's class plist.
return true;
+ else {
+ if (warn) {
+ S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf)
+ << castExpr->getType() << castType;
+ S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ S.Diag(Target->getLocStart(), diag::note_declared_at);
+ }
+ return false;
}
}
}
@@ -3259,18 +3401,262 @@ static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr) {
S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
if (Target)
S.Diag(Target->getLocStart(), diag::note_declared_at);
+ return true;
}
- return true;
+ return false;
}
T = TDNDecl->getUnderlyingType();
}
+ return true;
+}
+
+void Sema::CheckTollFreeBridgeCast(QualType castType, Expr *castExpr) {
+ if (!getLangOpts().ObjC1)
+ return;
+ // warn in presence of __bridge casting to or from a toll free bridge cast.
+ ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExpr->getType());
+ ARCConversionTypeClass castACTC = classifyTypeForARCConversion(castType);
+ if (castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation) {
+ bool HasObjCBridgeAttr;
+ bool ObjCBridgeAttrWillNotWarn =
+ CheckObjCBridgeNSCast<ObjCBridgeAttr>(*this, castType, castExpr, HasObjCBridgeAttr,
+ false);
+ if (ObjCBridgeAttrWillNotWarn && HasObjCBridgeAttr)
+ return;
+ bool HasObjCBridgeMutableAttr;
+ bool ObjCBridgeMutableAttrWillNotWarn =
+ CheckObjCBridgeNSCast<ObjCBridgeMutableAttr>(*this, castType, castExpr,
+ HasObjCBridgeMutableAttr, false);
+ if (ObjCBridgeMutableAttrWillNotWarn && HasObjCBridgeMutableAttr)
+ return;
+
+ if (HasObjCBridgeAttr)
+ CheckObjCBridgeNSCast<ObjCBridgeAttr>(*this, castType, castExpr, HasObjCBridgeAttr,
+ true);
+ else if (HasObjCBridgeMutableAttr)
+ CheckObjCBridgeNSCast<ObjCBridgeMutableAttr>(*this, castType, castExpr,
+ HasObjCBridgeMutableAttr, true);
+ }
+ else if (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable) {
+ bool HasObjCBridgeAttr;
+ bool ObjCBridgeAttrWillNotWarn =
+ CheckObjCBridgeCFCast<ObjCBridgeAttr>(*this, castType, castExpr, HasObjCBridgeAttr,
+ false);
+ if (ObjCBridgeAttrWillNotWarn && HasObjCBridgeAttr)
+ return;
+ bool HasObjCBridgeMutableAttr;
+ bool ObjCBridgeMutableAttrWillNotWarn =
+ CheckObjCBridgeCFCast<ObjCBridgeMutableAttr>(*this, castType, castExpr,
+ HasObjCBridgeMutableAttr, false);
+ if (ObjCBridgeMutableAttrWillNotWarn && HasObjCBridgeMutableAttr)
+ return;
+
+ if (HasObjCBridgeAttr)
+ CheckObjCBridgeCFCast<ObjCBridgeAttr>(*this, castType, castExpr, HasObjCBridgeAttr,
+ true);
+ else if (HasObjCBridgeMutableAttr)
+ CheckObjCBridgeCFCast<ObjCBridgeMutableAttr>(*this, castType, castExpr,
+ HasObjCBridgeMutableAttr, true);
+ }
+}
+
+void Sema::CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr) {
+ QualType SrcType = castExpr->getType();
+ if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(castExpr)) {
+ if (PRE->isExplicitProperty()) {
+ if (ObjCPropertyDecl *PDecl = PRE->getExplicitProperty())
+ SrcType = PDecl->getType();
+ }
+ else if (PRE->isImplicitProperty()) {
+ if (ObjCMethodDecl *Getter = PRE->getImplicitPropertyGetter())
+ SrcType = Getter->getReturnType();
+
+ }
+ }
+
+ ARCConversionTypeClass srcExprACTC = classifyTypeForARCConversion(SrcType);
+ ARCConversionTypeClass castExprACTC = classifyTypeForARCConversion(castType);
+ if (srcExprACTC != ACTC_retainable || castExprACTC != ACTC_coreFoundation)
+ return;
+ CheckObjCBridgeRelatedConversions(castExpr->getLocStart(),
+ castType, SrcType, castExpr);
+ return;
+}
+
+bool Sema::CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr,
+ CastKind &Kind) {
+ if (!getLangOpts().ObjC1)
+ return false;
+ ARCConversionTypeClass exprACTC =
+ classifyTypeForARCConversion(castExpr->getType());
+ ARCConversionTypeClass castACTC = classifyTypeForARCConversion(castType);
+ if ((castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation) ||
+ (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable)) {
+ CheckTollFreeBridgeCast(castType, castExpr);
+ Kind = (castACTC == ACTC_coreFoundation) ? CK_BitCast
+ : CK_CPointerToObjCPointerCast;
+ return true;
+ }
+ return false;
+}
+
+bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc,
+ QualType DestType, QualType SrcType,
+ ObjCInterfaceDecl *&RelatedClass,
+ ObjCMethodDecl *&ClassMethod,
+ ObjCMethodDecl *&InstanceMethod,
+ TypedefNameDecl *&TDNDecl,
+ bool CfToNs) {
+ QualType T = CfToNs ? SrcType : DestType;
+ ObjCBridgeRelatedAttr *ObjCBAttr = ObjCBridgeRelatedAttrFromType(T, TDNDecl);
+ if (!ObjCBAttr)
+ return false;
+
+ IdentifierInfo *RCId = ObjCBAttr->getRelatedClass();
+ IdentifierInfo *CMId = ObjCBAttr->getClassMethod();
+ IdentifierInfo *IMId = ObjCBAttr->getInstanceMethod();
+ if (!RCId)
+ return false;
+ NamedDecl *Target = nullptr;
+ // Check for an existing type with this name.
+ LookupResult R(*this, DeclarationName(RCId), SourceLocation(),
+ Sema::LookupOrdinaryName);
+ if (!LookupName(R, TUScope)) {
+ Diag(Loc, diag::err_objc_bridged_related_invalid_class) << RCId
+ << SrcType << DestType;
+ Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ return false;
+ }
+ Target = R.getFoundDecl();
+ if (Target && isa<ObjCInterfaceDecl>(Target))
+ RelatedClass = cast<ObjCInterfaceDecl>(Target);
+ else {
+ Diag(Loc, diag::err_objc_bridged_related_invalid_class_name) << RCId
+ << SrcType << DestType;
+ Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ if (Target)
+ Diag(Target->getLocStart(), diag::note_declared_at);
+ return false;
+ }
+
+ // Check for an existing class method with the given selector name.
+ if (CfToNs && CMId) {
+ Selector Sel = Context.Selectors.getUnarySelector(CMId);
+ ClassMethod = RelatedClass->lookupMethod(Sel, false);
+ if (!ClassMethod) {
+ Diag(Loc, diag::err_objc_bridged_related_known_method)
+ << SrcType << DestType << Sel << false;
+ Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ return false;
+ }
+ }
+
+ // Check for an existing instance method with the given selector name.
+ if (!CfToNs && IMId) {
+ Selector Sel = Context.Selectors.getNullarySelector(IMId);
+ InstanceMethod = RelatedClass->lookupMethod(Sel, true);
+ if (!InstanceMethod) {
+ Diag(Loc, diag::err_objc_bridged_related_known_method)
+ << SrcType << DestType << Sel << true;
+ Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool
+Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc,
+ QualType DestType, QualType SrcType,
+ Expr *&SrcExpr) {
+ ARCConversionTypeClass rhsExprACTC = classifyTypeForARCConversion(SrcType);
+ ARCConversionTypeClass lhsExprACTC = classifyTypeForARCConversion(DestType);
+ bool CfToNs = (rhsExprACTC == ACTC_coreFoundation && lhsExprACTC == ACTC_retainable);
+ bool NsToCf = (rhsExprACTC == ACTC_retainable && lhsExprACTC == ACTC_coreFoundation);
+ if (!CfToNs && !NsToCf)
+ return false;
+
+ ObjCInterfaceDecl *RelatedClass;
+ ObjCMethodDecl *ClassMethod = nullptr;
+ ObjCMethodDecl *InstanceMethod = nullptr;
+ TypedefNameDecl *TDNDecl = nullptr;
+ if (!checkObjCBridgeRelatedComponents(Loc, DestType, SrcType, RelatedClass,
+ ClassMethod, InstanceMethod, TDNDecl, CfToNs))
+ return false;
+
+ if (CfToNs) {
+ // Implicit conversion from CF to ObjC object is needed.
+ if (ClassMethod) {
+ std::string ExpressionString = "[";
+ ExpressionString += RelatedClass->getNameAsString();
+ ExpressionString += " ";
+ ExpressionString += ClassMethod->getSelector().getAsString();
+ SourceLocation SrcExprEndLoc = PP.getLocForEndOfToken(SrcExpr->getLocEnd());
+ // Provide a fixit: [RelatedClass ClassMethod SrcExpr]
+ Diag(Loc, diag::err_objc_bridged_related_known_method)
+ << SrcType << DestType << ClassMethod->getSelector() << false
+ << FixItHint::CreateInsertion(SrcExpr->getLocStart(), ExpressionString)
+ << FixItHint::CreateInsertion(SrcExprEndLoc, "]");
+ Diag(RelatedClass->getLocStart(), diag::note_declared_at);
+ Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+
+ QualType receiverType =
+ Context.getObjCInterfaceType(RelatedClass);
+ // Argument.
+ Expr *args[] = { SrcExpr };
+ ExprResult msg = BuildClassMessageImplicit(receiverType, false,
+ ClassMethod->getLocation(),
+ ClassMethod->getSelector(), ClassMethod,
+ MultiExprArg(args, 1));
+ SrcExpr = msg.get();
+ return true;
+ }
+ }
+ else {
+ // Implicit conversion from ObjC type to CF object is needed.
+ if (InstanceMethod) {
+ std::string ExpressionString;
+ SourceLocation SrcExprEndLoc = PP.getLocForEndOfToken(SrcExpr->getLocEnd());
+ if (InstanceMethod->isPropertyAccessor())
+ if (const ObjCPropertyDecl *PDecl = InstanceMethod->findPropertyDecl()) {
+ // fixit: ObjectExpr.propertyname when it is aproperty accessor.
+ ExpressionString = ".";
+ ExpressionString += PDecl->getNameAsString();
+ Diag(Loc, diag::err_objc_bridged_related_known_method)
+ << SrcType << DestType << InstanceMethod->getSelector() << true
+ << FixItHint::CreateInsertion(SrcExprEndLoc, ExpressionString);
+ }
+ if (ExpressionString.empty()) {
+ // Provide a fixit: [ObjectExpr InstanceMethod]
+ ExpressionString = " ";
+ ExpressionString += InstanceMethod->getSelector().getAsString();
+ ExpressionString += "]";
+
+ Diag(Loc, diag::err_objc_bridged_related_known_method)
+ << SrcType << DestType << InstanceMethod->getSelector() << true
+ << FixItHint::CreateInsertion(SrcExpr->getLocStart(), "[")
+ << FixItHint::CreateInsertion(SrcExprEndLoc, ExpressionString);
+ }
+ Diag(RelatedClass->getLocStart(), diag::note_declared_at);
+ Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+
+ ExprResult msg =
+ BuildInstanceMessageImplicit(SrcExpr, SrcType,
+ InstanceMethod->getLocation(),
+ InstanceMethod->getSelector(),
+ InstanceMethod, None);
+ SrcExpr = msg.get();
+ return true;
+ }
+ }
return false;
}
Sema::ARCConversionResult
Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType,
Expr *&castExpr, CheckedConversionKind CCK,
- bool DiagnoseCFAudited) {
+ bool DiagnoseCFAudited,
+ BinaryOperatorKind Opc) {
QualType castExprType = castExpr->getType();
// For the purposes of the classification, we assume reference types
@@ -3324,17 +3710,6 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType,
if (castACTC == ACTC_indirectRetainable && exprACTC == ACTC_voidPtr &&
CCK != CCK_ImplicitConversion)
return ACR_okay;
-
- if (castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation &&
- (CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast))
- if (CheckObjCBridgeNSCast(*this, castType, castExpr))
- return ACR_okay;
-
- if (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable &&
- (CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast))
- if (CheckObjCBridgeCFCast(*this, castType, castExpr))
- return ACR_okay;
-
switch (ARCCastChecker(Context, exprACTC, castACTC, false).Visit(castExpr)) {
// For invalid casts, fall through.
@@ -3350,7 +3725,7 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType,
case ACC_plusOne:
castExpr = ImplicitCastExpr::Create(Context, castExpr->getType(),
CK_ARCConsumeObject, castExpr,
- 0, VK_RValue);
+ nullptr, VK_RValue);
ExprNeedsCleanups = true;
return ACR_okay;
}
@@ -3362,14 +3737,23 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType,
CCK != CCK_ImplicitConversion)
return ACR_unbridged;
+ // Do not issue bridge cast" diagnostic when implicit casting a cstring
+ // to 'NSString *'. Let caller issue a normal mismatched diagnostic with
+ // suitable fix-it.
+ if (castACTC == ACTC_retainable && exprACTC == ACTC_none &&
+ ConversionToObjCStringLiteralCheck(castType, castExpr))
+ return ACR_okay;
+
// Do not issue "bridge cast" diagnostic when implicit casting
// a retainable object to a CF type parameter belonging to an audited
// CF API function. Let caller issue a normal type mismatched diagnostic
// instead.
if (!DiagnoseCFAudited || exprACTC != ACTC_retainable ||
castACTC != ACTC_coreFoundation)
- diagnoseObjCARCConversion(*this, castRange, castType, castACTC,
- castExpr, castExpr, exprACTC, CCK);
+ if (!(exprACTC == ACTC_voidPtr && castACTC == ACTC_retainable &&
+ (Opc == BO_NE || Opc == BO_EQ)))
+ diagnoseObjCARCConversion(*this, castRange, castType, castACTC,
+ castExpr, castExpr, exprACTC, CCK);
return ACR_okay;
}
@@ -3486,7 +3870,7 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc,
Expr *SubExpr) {
ExprResult SubResult = UsualUnaryConversions(SubExpr);
if (SubResult.isInvalid()) return ExprError();
- SubExpr = SubResult.take();
+ SubExpr = SubResult.get();
QualType T = TSInfo->getType();
QualType FromType = SubExpr->getType();
@@ -3545,7 +3929,7 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc,
// Produce the object before casting it.
SubExpr = ImplicitCastExpr::Create(Context, FromType,
CK_ARCProduceObject,
- SubExpr, 0, VK_RValue);
+ SubExpr, nullptr, VK_RValue);
break;
case OBC_BridgeTransfer: {
@@ -3584,7 +3968,7 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc,
if (MustConsume) {
ExprNeedsCleanups = true;
Result = ImplicitCastExpr::Create(Context, T, CK_ARCConsumeObject, Result,
- 0, VK_RValue);
+ nullptr, VK_RValue);
}
return Result;
@@ -3597,8 +3981,10 @@ ExprResult Sema::ActOnObjCBridgedCast(Scope *S,
ParsedType Type,
SourceLocation RParenLoc,
Expr *SubExpr) {
- TypeSourceInfo *TSInfo = 0;
+ TypeSourceInfo *TSInfo = nullptr;
QualType T = GetTypeFromParser(Type, &TSInfo);
+ if (Kind == OBC_Bridge)
+ CheckTollFreeBridgeCast(T, SubExpr);
if (!TSInfo)
TSInfo = Context.getTrivialTypeSourceInfo(T, LParenLoc);
return BuildObjCBridgedCast(LParenLoc, Kind, BridgeKeywordLoc, TSInfo,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
index 034c1b6..06ca9ae 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
@@ -17,7 +17,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/TypeLoc.h"
-#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/Designator.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/SemaInternal.h"
@@ -70,7 +70,7 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT,
// Otherwise we can only handle string literals.
StringLiteral *SL = dyn_cast<StringLiteral>(Init);
- if (SL == 0)
+ if (!SL)
return SIF_Other;
const QualType ElemTy =
@@ -189,7 +189,7 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT,
// C99 6.7.8p14.
if (StrLength-1 > CAT->getSize().getZExtValue())
S.Diag(Str->getLocStart(),
- diag::warn_initializer_string_for_char_array_too_long)
+ diag::ext_initializer_string_for_char_array_too_long)
<< Str->getSourceRange();
}
@@ -313,15 +313,20 @@ class InitListChecker {
int numArrayElements(QualType DeclType);
int numStructUnionElements(QualType DeclType);
- void FillInValueInitForField(unsigned Init, FieldDecl *Field,
+ static ExprResult PerformEmptyInit(Sema &SemaRef,
+ SourceLocation Loc,
+ const InitializedEntity &Entity,
+ bool VerifyOnly);
+ void FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
const InitializedEntity &ParentEntity,
InitListExpr *ILE, bool &RequiresSecondPass);
- void FillInValueInitializations(const InitializedEntity &Entity,
+ void FillInEmptyInitializations(const InitializedEntity &Entity,
InitListExpr *ILE, bool &RequiresSecondPass);
bool CheckFlexibleArrayInit(const InitializedEntity &Entity,
Expr *InitExpr, FieldDecl *Field,
bool TopLevelObject);
- void CheckValueInitializable(const InitializedEntity &Entity);
+ void CheckEmptyInitializable(const InitializedEntity &Entity,
+ SourceLocation Loc);
public:
InitListChecker(Sema &S, const InitializedEntity &Entity,
@@ -334,33 +339,134 @@ public:
};
} // end anonymous namespace
-void InitListChecker::CheckValueInitializable(const InitializedEntity &Entity) {
- assert(VerifyOnly &&
- "CheckValueInitializable is only inteded for verification mode.");
-
- SourceLocation Loc;
+ExprResult InitListChecker::PerformEmptyInit(Sema &SemaRef,
+ SourceLocation Loc,
+ const InitializedEntity &Entity,
+ bool VerifyOnly) {
InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc,
true);
- InitializationSequence InitSeq(SemaRef, Entity, Kind, None);
- if (InitSeq.Failed())
+ MultiExprArg SubInit;
+ Expr *InitExpr;
+ InitListExpr DummyInitList(SemaRef.Context, Loc, None, Loc);
+
+ // C++ [dcl.init.aggr]p7:
+ // If there are fewer initializer-clauses in the list than there are
+ // members in the aggregate, then each member not explicitly initialized
+ // ...
+ bool EmptyInitList = SemaRef.getLangOpts().CPlusPlus11 &&
+ Entity.getType()->getBaseElementTypeUnsafe()->isRecordType();
+ if (EmptyInitList) {
+ // C++1y / DR1070:
+ // shall be initialized [...] from an empty initializer list.
+ //
+ // We apply the resolution of this DR to C++11 but not C++98, since C++98
+ // does not have useful semantics for initialization from an init list.
+ // We treat this as copy-initialization, because aggregate initialization
+ // always performs copy-initialization on its elements.
+ //
+ // Only do this if we're initializing a class type, to avoid filling in
+ // the initializer list where possible.
+ InitExpr = VerifyOnly ? &DummyInitList : new (SemaRef.Context)
+ InitListExpr(SemaRef.Context, Loc, None, Loc);
+ InitExpr->setType(SemaRef.Context.VoidTy);
+ SubInit = InitExpr;
+ Kind = InitializationKind::CreateCopy(Loc, Loc);
+ } else {
+ // C++03:
+ // shall be value-initialized.
+ }
+
+ InitializationSequence InitSeq(SemaRef, Entity, Kind, SubInit);
+ // libstdc++4.6 marks the vector default constructor as explicit in
+ // _GLIBCXX_DEBUG mode, so recover using the C++03 logic in that case.
+ // stlport does so too. Look for std::__debug for libstdc++, and for
+ // std:: for stlport. This is effectively a compiler-side implementation of
+ // LWG2193.
+ if (!InitSeq && EmptyInitList && InitSeq.getFailureKind() ==
+ InitializationSequence::FK_ExplicitConstructor) {
+ OverloadCandidateSet::iterator Best;
+ OverloadingResult O =
+ InitSeq.getFailedCandidateSet()
+ .BestViableFunction(SemaRef, Kind.getLocation(), Best);
+ (void)O;
+ assert(O == OR_Success && "Inconsistent overload resolution");
+ CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
+ CXXRecordDecl *R = CtorDecl->getParent();
+
+ if (CtorDecl->getMinRequiredArguments() == 0 &&
+ CtorDecl->isExplicit() && R->getDeclName() &&
+ SemaRef.SourceMgr.isInSystemHeader(CtorDecl->getLocation())) {
+
+
+ bool IsInStd = false;
+ for (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(R->getDeclContext());
+ ND && !IsInStd; ND = dyn_cast<NamespaceDecl>(ND->getParent())) {
+ if (SemaRef.getStdNamespace()->InEnclosingNamespaceSetOf(ND))
+ IsInStd = true;
+ }
+
+ if (IsInStd && llvm::StringSwitch<bool>(R->getName())
+ .Cases("basic_string", "deque", "forward_list", true)
+ .Cases("list", "map", "multimap", "multiset", true)
+ .Cases("priority_queue", "queue", "set", "stack", true)
+ .Cases("unordered_map", "unordered_set", "vector", true)
+ .Default(false)) {
+ InitSeq.InitializeFrom(
+ SemaRef, Entity,
+ InitializationKind::CreateValue(Loc, Loc, Loc, true),
+ MultiExprArg(), /*TopLevelOfInitList=*/false);
+ // Emit a warning for this. System header warnings aren't shown
+ // by default, but people working on system headers should see it.
+ if (!VerifyOnly) {
+ SemaRef.Diag(CtorDecl->getLocation(),
+ diag::warn_invalid_initializer_from_system_header);
+ SemaRef.Diag(Entity.getDecl()->getLocation(),
+ diag::note_used_in_initialization_here);
+ }
+ }
+ }
+ }
+ if (!InitSeq) {
+ if (!VerifyOnly) {
+ InitSeq.Diagnose(SemaRef, Entity, Kind, SubInit);
+ if (Entity.getKind() == InitializedEntity::EK_Member)
+ SemaRef.Diag(Entity.getDecl()->getLocation(),
+ diag::note_in_omitted_aggregate_initializer)
+ << /*field*/1 << Entity.getDecl();
+ else if (Entity.getKind() == InitializedEntity::EK_ArrayElement)
+ SemaRef.Diag(Loc, diag::note_in_omitted_aggregate_initializer)
+ << /*array element*/0 << Entity.getElementIndex();
+ }
+ return ExprError();
+ }
+
+ return VerifyOnly ? ExprResult(static_cast<Expr *>(nullptr))
+ : InitSeq.Perform(SemaRef, Entity, Kind, SubInit);
+}
+
+void InitListChecker::CheckEmptyInitializable(const InitializedEntity &Entity,
+ SourceLocation Loc) {
+ assert(VerifyOnly &&
+ "CheckEmptyInitializable is only inteded for verification mode.");
+ if (PerformEmptyInit(SemaRef, Loc, Entity, /*VerifyOnly*/true).isInvalid())
hadError = true;
}
-void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field,
+void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
const InitializedEntity &ParentEntity,
InitListExpr *ILE,
bool &RequiresSecondPass) {
- SourceLocation Loc = ILE->getLocStart();
+ SourceLocation Loc = ILE->getLocEnd();
unsigned NumInits = ILE->getNumInits();
InitializedEntity MemberEntity
= InitializedEntity::InitializeMember(Field, &ParentEntity);
if (Init >= NumInits || !ILE->getInit(Init)) {
- // If there's no explicit initializer but we have a default initializer, use
- // that. This only happens in C++1y, since classes with default
- // initializers are not aggregates in C++11.
+ // C++1y [dcl.init.aggr]p7:
+ // If there are fewer initializer-clauses in the list than there are
+ // members in the aggregate, then each member not explicitly initialized
+ // shall be initialized from its brace-or-equal-initializer [...]
if (Field->hasInClassInitializer()) {
- Expr *DIE = CXXDefaultInitExpr::Create(SemaRef.Context,
- ILE->getRBraceLoc(), Field);
+ Expr *DIE = CXXDefaultInitExpr::Create(SemaRef.Context, Loc, Field);
if (Init < NumInits)
ILE->setInit(Init, DIE);
else {
@@ -370,9 +476,6 @@ void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field,
return;
}
- // FIXME: We probably don't need to handle references
- // specially here, since value-initialization of references is
- // handled in InitializationSequence.
if (Field->getType()->isReferenceType()) {
// C++ [dcl.init.aggr]p9:
// If an incomplete or empty initializer-list leaves a
@@ -387,17 +490,8 @@ void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field,
return;
}
- InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc,
- true);
- InitializationSequence InitSeq(SemaRef, MemberEntity, Kind, None);
- if (!InitSeq) {
- InitSeq.Diagnose(SemaRef, MemberEntity, Kind, None);
- hadError = true;
- return;
- }
-
- ExprResult MemberInit
- = InitSeq.Perform(SemaRef, MemberEntity, Kind, None);
+ ExprResult MemberInit = PerformEmptyInit(SemaRef, Loc, MemberEntity,
+ /*VerifyOnly*/false);
if (MemberInit.isInvalid()) {
hadError = true;
return;
@@ -406,18 +500,18 @@ void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field,
if (hadError) {
// Do nothing
} else if (Init < NumInits) {
- ILE->setInit(Init, MemberInit.takeAs<Expr>());
- } else if (InitSeq.isConstructorInitialization()) {
- // Value-initialization requires a constructor call, so
+ ILE->setInit(Init, MemberInit.getAs<Expr>());
+ } else if (!isa<ImplicitValueInitExpr>(MemberInit.get())) {
+ // Empty initialization requires a constructor call, so
// extend the initializer list to include the constructor
// call and make a note that we'll need to take another pass
// through the initializer list.
- ILE->updateInit(SemaRef.Context, Init, MemberInit.takeAs<Expr>());
+ ILE->updateInit(SemaRef.Context, Init, MemberInit.getAs<Expr>());
RequiresSecondPass = true;
}
} else if (InitListExpr *InnerILE
= dyn_cast<InitListExpr>(ILE->getInit(Init)))
- FillInValueInitializations(MemberEntity, InnerILE,
+ FillInEmptyInitializations(MemberEntity, InnerILE,
RequiresSecondPass);
}
@@ -425,42 +519,35 @@ void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field,
/// with expressions that perform value-initialization of the
/// appropriate type.
void
-InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
+InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
InitListExpr *ILE,
bool &RequiresSecondPass) {
assert((ILE->getType() != SemaRef.Context.VoidTy) &&
"Should not have void type");
- SourceLocation Loc = ILE->getLocStart();
- if (ILE->getSyntacticForm())
- Loc = ILE->getSyntacticForm()->getLocStart();
if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) {
const RecordDecl *RDecl = RType->getDecl();
if (RDecl->isUnion() && ILE->getInitializedFieldInUnion())
- FillInValueInitForField(0, ILE->getInitializedFieldInUnion(),
+ FillInEmptyInitForField(0, ILE->getInitializedFieldInUnion(),
Entity, ILE, RequiresSecondPass);
else if (RDecl->isUnion() && isa<CXXRecordDecl>(RDecl) &&
cast<CXXRecordDecl>(RDecl)->hasInClassInitializer()) {
- for (RecordDecl::field_iterator Field = RDecl->field_begin(),
- FieldEnd = RDecl->field_end();
- Field != FieldEnd; ++Field) {
+ for (auto *Field : RDecl->fields()) {
if (Field->hasInClassInitializer()) {
- FillInValueInitForField(0, *Field, Entity, ILE, RequiresSecondPass);
+ FillInEmptyInitForField(0, Field, Entity, ILE, RequiresSecondPass);
break;
}
}
} else {
unsigned Init = 0;
- for (RecordDecl::field_iterator Field = RDecl->field_begin(),
- FieldEnd = RDecl->field_end();
- Field != FieldEnd; ++Field) {
+ for (auto *Field : RDecl->fields()) {
if (Field->isUnnamedBitfield())
continue;
if (hadError)
return;
- FillInValueInitForField(Init, *Field, Entity, ILE, RequiresSecondPass);
+ FillInEmptyInitForField(Init, Field, Entity, ILE, RequiresSecondPass);
if (hadError)
return;
@@ -494,7 +581,6 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
} else
ElementType = ILE->getType();
-
for (unsigned Init = 0; Init != NumElements; ++Init) {
if (hadError)
return;
@@ -503,19 +589,11 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
ElementEntity.getKind() == InitializedEntity::EK_VectorElement)
ElementEntity.setElementIndex(Init);
- Expr *InitExpr = (Init < NumInits ? ILE->getInit(Init) : 0);
+ Expr *InitExpr = (Init < NumInits ? ILE->getInit(Init) : nullptr);
if (!InitExpr && !ILE->hasArrayFiller()) {
- InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc,
- true);
- InitializationSequence InitSeq(SemaRef, ElementEntity, Kind, None);
- if (!InitSeq) {
- InitSeq.Diagnose(SemaRef, ElementEntity, Kind, None);
- hadError = true;
- return;
- }
-
- ExprResult ElementInit
- = InitSeq.Perform(SemaRef, ElementEntity, Kind, None);
+ ExprResult ElementInit = PerformEmptyInit(SemaRef, ILE->getLocEnd(),
+ ElementEntity,
+ /*VerifyOnly*/false);
if (ElementInit.isInvalid()) {
hadError = true;
return;
@@ -527,29 +605,29 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
// For arrays, just set the expression used for value-initialization
// of the "holes" in the array.
if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement)
- ILE->setArrayFiller(ElementInit.takeAs<Expr>());
+ ILE->setArrayFiller(ElementInit.getAs<Expr>());
else
- ILE->setInit(Init, ElementInit.takeAs<Expr>());
+ ILE->setInit(Init, ElementInit.getAs<Expr>());
} else {
// For arrays, just set the expression used for value-initialization
// of the rest of elements and exit.
if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement) {
- ILE->setArrayFiller(ElementInit.takeAs<Expr>());
+ ILE->setArrayFiller(ElementInit.getAs<Expr>());
return;
}
- if (InitSeq.isConstructorInitialization()) {
- // Value-initialization requires a constructor call, so
+ if (!isa<ImplicitValueInitExpr>(ElementInit.get())) {
+ // Empty initialization requires a constructor call, so
// extend the initializer list to include the constructor
// call and make a note that we'll need to take another pass
// through the initializer list.
- ILE->updateInit(SemaRef.Context, Init, ElementInit.takeAs<Expr>());
+ ILE->updateInit(SemaRef.Context, Init, ElementInit.getAs<Expr>());
RequiresSecondPass = true;
}
}
} else if (InitListExpr *InnerILE
= dyn_cast_or_null<InitListExpr>(InitExpr))
- FillInValueInitializations(ElementEntity, InnerILE, RequiresSecondPass);
+ FillInEmptyInitializations(ElementEntity, InnerILE, RequiresSecondPass);
}
}
@@ -561,15 +639,15 @@ InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
hadError = false;
FullyStructuredList =
- getStructuredSubobjectInit(IL, 0, T, 0, 0, IL->getSourceRange());
+ getStructuredSubobjectInit(IL, 0, T, nullptr, 0, IL->getSourceRange());
CheckExplicitInitList(Entity, IL, T, FullyStructuredList,
/*TopLevelObject=*/true);
if (!hadError && !VerifyOnly) {
bool RequiresSecondPass = false;
- FillInValueInitializations(Entity, FullyStructuredList, RequiresSecondPass);
+ FillInEmptyInitializations(Entity, FullyStructuredList, RequiresSecondPass);
if (RequiresSecondPass && !hadError)
- FillInValueInitializations(Entity, FullyStructuredList,
+ FillInEmptyInitializations(Entity, FullyStructuredList,
RequiresSecondPass);
}
}
@@ -587,13 +665,10 @@ int InitListChecker::numArrayElements(QualType DeclType) {
int InitListChecker::numStructUnionElements(QualType DeclType) {
RecordDecl *structDecl = DeclType->getAs<RecordType>()->getDecl();
int InitializableMembers = 0;
- for (RecordDecl::field_iterator
- Field = structDecl->field_begin(),
- FieldEnd = structDecl->field_end();
- Field != FieldEnd; ++Field) {
+ for (const auto *Field : structDecl->fields())
if (!Field->isUnnamedBitfield())
++InitializableMembers;
- }
+
if (structDecl->isUnion())
return std::min(InitializableMembers, 1);
return InitializableMembers - structDecl->hasFlexibleArrayMember();
@@ -661,13 +736,13 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
if (T->isArrayType() || T->isRecordType()) {
SemaRef.Diag(StructuredSubobjectInitList->getLocStart(),
diag::warn_missing_braces)
- << StructuredSubobjectInitList->getSourceRange()
- << FixItHint::CreateInsertion(
- StructuredSubobjectInitList->getLocStart(), "{")
- << FixItHint::CreateInsertion(
- SemaRef.PP.getLocForEndOfToken(
- StructuredSubobjectInitList->getLocEnd()),
- "}");
+ << StructuredSubobjectInitList->getSourceRange()
+ << FixItHint::CreateInsertion(
+ StructuredSubobjectInitList->getLocStart(), "{")
+ << FixItHint::CreateInsertion(
+ SemaRef.getLocForEndOfToken(
+ StructuredSubobjectInitList->getLocEnd()),
+ "}");
}
}
}
@@ -681,7 +756,6 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity,
InitListExpr *IList, QualType &T,
InitListExpr *StructuredList,
bool TopLevelObject) {
- assert(IList->isExplicit() && "Illegal Implicit InitListExpr");
if (!VerifyOnly) {
SyntacticToSemantic[IList] = StructuredList;
StructuredList->setSyntacticForm(IList);
@@ -714,7 +788,7 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity,
if (StructuredIndex == 1 &&
IsStringInit(StructuredList->getInit(0), T, SemaRef.Context) ==
SIF_None) {
- unsigned DK = diag::warn_excess_initializers_in_char_array_initializer;
+ unsigned DK = diag::ext_excess_initializers_in_char_array_initializer;
if (SemaRef.getLangOpts().CPlusPlus) {
DK = diag::err_excess_initializers_in_char_array_initializer;
hadError = true;
@@ -733,7 +807,7 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity,
CurrentObjectType->isUnionType()? 3 :
4;
- unsigned DK = diag::warn_excess_initializers;
+ unsigned DK = diag::ext_excess_initializers;
if (SemaRef.getLangOpts().CPlusPlus) {
DK = diag::err_excess_initializers;
hadError = true;
@@ -840,6 +914,15 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
assert(SemaRef.getLangOpts().CPlusPlus &&
"non-aggregate records are only possible in C++");
// C++ initialization is handled later.
+ } else if (isa<ImplicitValueInitExpr>(expr)) {
+ // This happens during template instantiation when we see an InitListExpr
+ // that we've already checked once.
+ assert(SemaRef.Context.hasSameType(expr->getType(), ElemType) &&
+ "found implicit initialization for the wrong type");
+ if (!VerifyOnly)
+ UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
+ ++Index;
+ return;
}
// FIXME: Need to handle atomic aggregate types with implicit init lists.
@@ -886,7 +969,7 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
hadError = true;
UpdateStructuredListElement(StructuredList, StructuredIndex,
- Result.takeAs<Expr>());
+ Result.getAs<Expr>());
}
++Index;
return;
@@ -902,7 +985,7 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
// compatible structure or union type. In the latter case, the
// initial value of the object, including unnamed members, is
// that of the expression.
- ExprResult ExprRes = SemaRef.Owned(expr);
+ ExprResult ExprRes = expr;
if ((ElemType->isRecordType() || ElemType->isVectorType()) &&
SemaRef.CheckSingleAssignmentConstraints(ElemType, ExprRes,
!VerifyOnly)
@@ -910,16 +993,16 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
if (ExprRes.isInvalid())
hadError = true;
else {
- ExprRes = SemaRef.DefaultFunctionArrayLvalueConversion(ExprRes.take());
+ ExprRes = SemaRef.DefaultFunctionArrayLvalueConversion(ExprRes.get());
if (ExprRes.isInvalid())
hadError = true;
}
UpdateStructuredListElement(StructuredList, StructuredIndex,
- ExprRes.takeAs<Expr>());
+ ExprRes.getAs<Expr>());
++Index;
return;
}
- ExprRes.release();
+ ExprRes.get();
// Fall through for subaggregate initialization
}
@@ -938,8 +1021,7 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
if (!VerifyOnly) {
// We cannot initialize this element, so let
// PerformCopyInitialization produce the appropriate diagnostic.
- SemaRef.PerformCopyInitialization(Entity, SourceLocation(),
- SemaRef.Owned(expr),
+ SemaRef.PerformCopyInitialization(Entity, SourceLocation(), expr,
/*TopLevelOfInitList=*/true);
}
hadError = true;
@@ -1005,9 +1087,11 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
Expr *expr = IList->getInit(Index);
if (InitListExpr *SubIList = dyn_cast<InitListExpr>(expr)) {
+ // FIXME: This is invalid, and accepting it causes overload resolution
+ // to pick the wrong overload in some corner cases.
if (!VerifyOnly)
SemaRef.Diag(SubIList->getLocStart(),
- diag::warn_many_braces_around_scalar_init)
+ diag::ext_many_braces_around_scalar_init)
<< SubIList->getSourceRange();
CheckScalarType(Entity, SubIList, DeclType, Index, StructuredList,
@@ -1025,23 +1109,22 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
}
if (VerifyOnly) {
- if (!SemaRef.CanPerformCopyInitialization(Entity, SemaRef.Owned(expr)))
+ if (!SemaRef.CanPerformCopyInitialization(Entity,expr))
hadError = true;
++Index;
return;
}
ExprResult Result =
- SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(),
- SemaRef.Owned(expr),
+ SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(), expr,
/*TopLevelOfInitList=*/true);
- Expr *ResultExpr = 0;
+ Expr *ResultExpr = nullptr;
if (Result.isInvalid())
hadError = true; // types weren't compatible.
else {
- ResultExpr = Result.takeAs<Expr>();
+ ResultExpr = Result.getAs<Expr>();
if (ResultExpr != expr) {
// The type was promoted, update initializer list.
@@ -1088,21 +1171,20 @@ void InitListChecker::CheckReferenceType(const InitializedEntity &Entity,
}
if (VerifyOnly) {
- if (!SemaRef.CanPerformCopyInitialization(Entity, SemaRef.Owned(expr)))
+ if (!SemaRef.CanPerformCopyInitialization(Entity,expr))
hadError = true;
++Index;
return;
}
ExprResult Result =
- SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(),
- SemaRef.Owned(expr),
- /*TopLevelOfInitList=*/true);
+ SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(), expr,
+ /*TopLevelOfInitList=*/true);
if (Result.isInvalid())
hadError = true;
- expr = Result.takeAs<Expr>();
+ expr = Result.getAs<Expr>();
IList->setInit(Index, expr);
if (hadError)
@@ -1125,8 +1207,9 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
if (Index >= IList->getNumInits()) {
// Make sure the element type can be value-initialized.
if (VerifyOnly)
- CheckValueInitializable(
- InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity));
+ CheckEmptyInitializable(
+ InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity),
+ IList->getLocEnd());
return;
}
@@ -1136,22 +1219,21 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
Expr *Init = IList->getInit(Index);
if (!isa<InitListExpr>(Init) && Init->getType()->isVectorType()) {
if (VerifyOnly) {
- if (!SemaRef.CanPerformCopyInitialization(Entity, SemaRef.Owned(Init)))
+ if (!SemaRef.CanPerformCopyInitialization(Entity, Init))
hadError = true;
++Index;
return;
}
- ExprResult Result =
- SemaRef.PerformCopyInitialization(Entity, Init->getLocStart(),
- SemaRef.Owned(Init),
- /*TopLevelOfInitList=*/true);
+ ExprResult Result =
+ SemaRef.PerformCopyInitialization(Entity, Init->getLocStart(), Init,
+ /*TopLevelOfInitList=*/true);
- Expr *ResultExpr = 0;
+ Expr *ResultExpr = nullptr;
if (Result.isInvalid())
hadError = true; // types weren't compatible.
else {
- ResultExpr = Result.takeAs<Expr>();
+ ResultExpr = Result.getAs<Expr>();
if (ResultExpr != Init) {
// The type was promoted, update initializer list.
@@ -1174,7 +1256,7 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
// Don't attempt to go past the end of the init list
if (Index >= IList->getNumInits()) {
if (VerifyOnly)
- CheckValueInitializable(ElementEntity);
+ CheckEmptyInitializable(ElementEntity, IList->getLocEnd());
break;
}
@@ -1182,6 +1264,46 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
CheckSubElementType(ElementEntity, IList, elementType, Index,
StructuredList, StructuredIndex);
}
+
+ if (VerifyOnly)
+ return;
+
+ bool isBigEndian = SemaRef.Context.getTargetInfo().isBigEndian();
+ const VectorType *T = Entity.getType()->getAs<VectorType>();
+ if (isBigEndian && (T->getVectorKind() == VectorType::NeonVector ||
+ T->getVectorKind() == VectorType::NeonPolyVector)) {
+ // The ability to use vector initializer lists is a GNU vector extension
+ // and is unrelated to the NEON intrinsics in arm_neon.h. On little
+ // endian machines it works fine, however on big endian machines it
+ // exhibits surprising behaviour:
+ //
+ // uint32x2_t x = {42, 64};
+ // return vget_lane_u32(x, 0); // Will return 64.
+ //
+ // Because of this, explicitly call out that it is non-portable.
+ //
+ SemaRef.Diag(IList->getLocStart(),
+ diag::warn_neon_vector_initializer_non_portable);
+
+ const char *typeCode;
+ unsigned typeSize = SemaRef.Context.getTypeSize(elementType);
+
+ if (elementType->isFloatingType())
+ typeCode = "f";
+ else if (elementType->isSignedIntegerType())
+ typeCode = "s";
+ else if (elementType->isUnsignedIntegerType())
+ typeCode = "u";
+ else
+ llvm_unreachable("Invalid element type!");
+
+ SemaRef.Diag(IList->getLocStart(),
+ SemaRef.Context.getTypeSize(VT) > 64 ?
+ diag::note_neon_vector_initializer_non_portable_q :
+ diag::note_neon_vector_initializer_non_portable)
+ << typeCode << typeSize;
+ }
+
return;
}
@@ -1293,7 +1415,7 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
// Handle this designated initializer. elementIndex will be
// updated to be the next array element we'll initialize.
if (CheckDesignatedInitializer(Entity, IList, DIE, 0,
- DeclType, 0, &elementIndex, Index,
+ DeclType, nullptr, &elementIndex, Index,
StructuredList, StructuredIndex, true,
false)) {
hadError = true;
@@ -1351,8 +1473,9 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
// If so, check if doing that is possible.
// FIXME: This needs to detect holes left by designated initializers too.
if (maxElementsKnown && elementIndex < maxElements)
- CheckValueInitializable(InitializedEntity::InitializeElement(
- SemaRef.Context, 0, Entity));
+ CheckEmptyInitializable(InitializedEntity::InitializeElement(
+ SemaRef.Context, 0, Entity),
+ IList->getLocEnd());
}
}
@@ -1437,8 +1560,9 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
Field != FieldEnd; ++Field) {
if (Field->getDeclName()) {
if (VerifyOnly)
- CheckValueInitializable(
- InitializedEntity::InitializeMember(*Field, &Entity));
+ CheckEmptyInitializable(
+ InitializedEntity::InitializeMember(*Field, &Entity),
+ IList->getLocEnd());
else
StructuredList->setInitializedFieldInUnion(*Field);
break;
@@ -1468,7 +1592,7 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
// Handle this designated initializer. Field will be updated to
// the next field that we'll be initializing.
if (CheckDesignatedInitializer(Entity, IList, DIE, 0,
- DeclType, &Field, 0, Index,
+ DeclType, &Field, nullptr, Index,
StructuredList, StructuredIndex,
true, TopLevelObject))
hadError = true;
@@ -1538,7 +1662,7 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
it != end; ++it) {
if (!it->isUnnamedBitfield() && !it->hasInClassInitializer()) {
SemaRef.Diag(IList->getSourceRange().getEnd(),
- diag::warn_missing_field_initializers) << it->getName();
+ diag::warn_missing_field_initializers) << *it;
break;
}
}
@@ -1550,8 +1674,9 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
// FIXME: Should check for holes left by designated initializers too.
for (; Field != FieldEnd && !hadError; ++Field) {
if (!Field->isUnnamedBitfield() && !Field->hasInClassInitializer())
- CheckValueInitializable(
- InitializedEntity::InitializeMember(*Field, &Entity));
+ CheckEmptyInitializable(
+ InitializedEntity::InitializeMember(*Field, &Entity),
+ IList->getLocEnd());
}
}
@@ -1592,12 +1717,12 @@ static void ExpandAnonymousFieldDesignator(Sema &SemaRef,
for (IndirectFieldDecl::chain_iterator PI = IndirectField->chain_begin(),
PE = IndirectField->chain_end(); PI != PE; ++PI) {
if (PI + 1 == PE)
- Replacements.push_back(Designator((IdentifierInfo *)0,
+ Replacements.push_back(Designator((IdentifierInfo *)nullptr,
DIE->getDesignator(DesigIdx)->getDotLoc(),
DIE->getDesignator(DesigIdx)->getFieldLoc()));
else
- Replacements.push_back(Designator((IdentifierInfo *)0, SourceLocation(),
- SourceLocation()));
+ Replacements.push_back(Designator((IdentifierInfo *)nullptr,
+ SourceLocation(), SourceLocation()));
assert(isa<FieldDecl>(*PI));
Replacements.back().setField(cast<FieldDecl>(*PI));
}
@@ -1614,7 +1739,7 @@ static void ExpandAnonymousFieldDesignator(Sema &SemaRef,
static IndirectFieldDecl *FindIndirectFieldDesignator(FieldDecl *AnonField,
IdentifierInfo *FieldName) {
if (!FieldName)
- return 0;
+ return nullptr;
assert(AnonField->isAnonymousStructOrUnion());
Decl *NextDecl = AnonField->getNextDeclInContext();
@@ -1624,7 +1749,7 @@ static IndirectFieldDecl *FindIndirectFieldDesignator(FieldDecl *AnonField,
return IF;
NextDecl = NextDecl->getNextDeclInContext();
}
- return 0;
+ return nullptr;
}
static DesignatedInitExpr *CloneDesignatedInitExpr(Sema &SemaRef,
@@ -1648,7 +1773,7 @@ class FieldInitializerValidatorCCC : public CorrectionCandidateCallback {
explicit FieldInitializerValidatorCCC(RecordDecl *RD)
: Record(RD) {}
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
FieldDecl *FD = candidate.getCorrectionDeclAs<FieldDecl>();
return FD && FD->getDeclContext()->getRedeclContext()->Equals(Record);
}
@@ -1813,15 +1938,15 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// may find nothing, or may find a member of an anonymous
// struct/union.
DeclContext::lookup_result Lookup = RT->getDecl()->lookup(FieldName);
- FieldDecl *ReplacementField = 0;
+ FieldDecl *ReplacementField = nullptr;
if (Lookup.empty()) {
// Name lookup didn't find anything. Determine whether this
// was a typo for another field name.
FieldInitializerValidatorCCC Validator(RT->getDecl());
if (TypoCorrection Corrected = SemaRef.CorrectTypo(
DeclarationNameInfo(FieldName, D->getFieldLoc()),
- Sema::LookupMemberName, /*Scope=*/ 0, /*SS=*/ 0, Validator,
- RT->getDecl())) {
+ Sema::LookupMemberName, /*Scope=*/ nullptr, /*SS=*/ nullptr,
+ Validator, Sema::CTK_ErrorRecovery, RT->getDecl())) {
SemaRef.diagnoseTypo(
Corrected,
SemaRef.PDiag(diag::err_field_designator_unknown_suggest)
@@ -1886,7 +2011,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// remove existing initializer
StructuredList->resizeInits(SemaRef.Context, 0);
- StructuredList->setInitializedFieldInUnion(0);
+ StructuredList->setInitializedFieldInUnion(nullptr);
}
StructuredList->setInitializedFieldInUnion(*Field);
@@ -1984,7 +2109,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
InitializedEntity MemberEntity =
InitializedEntity::InitializeMember(*Field, &Entity);
if (CheckDesignatedInitializer(MemberEntity, IList, DIE, DesigIdx + 1,
- FieldType, 0, 0, Index,
+ FieldType, nullptr, nullptr, Index,
StructuredList, newStructuredIndex,
true, false))
return true;
@@ -2043,7 +2168,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
return true;
}
- Expr *IndexExpr = 0;
+ Expr *IndexExpr = nullptr;
llvm::APSInt DesignatedStartIndex, DesignatedEndIndex;
if (D->isArrayDesignator()) {
IndexExpr = DIE->getArrayIndex(*D);
@@ -2128,7 +2253,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
Context, CodeUnit, PromotedCharTy, SubExpr->getExprLoc());
if (CharTy != PromotedCharTy)
Init = ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast,
- Init, 0, VK_RValue);
+ Init, nullptr, VK_RValue);
StructuredList->updateInit(Context, i, Init);
}
} else {
@@ -2150,7 +2275,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
Context, CodeUnit, PromotedCharTy, SubExpr->getExprLoc());
if (CharTy != PromotedCharTy)
Init = ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast,
- Init, 0, VK_RValue);
+ Init, nullptr, VK_RValue);
StructuredList->updateInit(Context, i, Init);
}
}
@@ -2180,7 +2305,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
ElementEntity.setElementIndex(ElementIndex);
if (CheckDesignatedInitializer(ElementEntity, IList, DIE, DesigIdx + 1,
- ElementType, 0, 0, Index,
+ ElementType, nullptr, nullptr, Index,
StructuredList, ElementIndex,
(DesignatedStartIndex == DesignatedEndIndex),
false))
@@ -2220,8 +2345,8 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
unsigned StructuredIndex,
SourceRange InitRange) {
if (VerifyOnly)
- return 0; // No structured list in verification-only mode.
- Expr *ExistingInit = 0;
+ return nullptr; // No structured list in verification-only mode.
+ Expr *ExistingInit = nullptr;
if (!StructuredList)
ExistingInit = SyntacticToSemantic.lookup(IList);
else if (StructuredIndex < StructuredList->getNumInits())
@@ -2291,8 +2416,7 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
if (RDecl->isUnion())
NumElements = 1;
else
- NumElements = std::distance(RDecl->field_begin(),
- RDecl->field_end());
+ NumElements = std::distance(RDecl->field_begin(), RDecl->field_end());
}
Result->reserveInits(SemaRef.Context, NumElements);
@@ -2380,7 +2504,7 @@ ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig,
Expr *Index = static_cast<Expr *>(D.getArrayIndex());
llvm::APSInt IndexValue;
if (!Index->isTypeDependent() && !Index->isValueDependent())
- Index = CheckArrayDesignatorExpr(*this, Index, IndexValue).take();
+ Index = CheckArrayDesignatorExpr(*this, Index, IndexValue).get();
if (!Index)
Invalid = true;
else {
@@ -2403,9 +2527,9 @@ ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig,
EndIndex->isValueDependent();
if (!StartDependent)
StartIndex =
- CheckArrayDesignatorExpr(*this, StartIndex, StartValue).take();
+ CheckArrayDesignatorExpr(*this, StartIndex, StartValue).get();
if (!EndDependent)
- EndIndex = CheckArrayDesignatorExpr(*this, EndIndex, EndValue).take();
+ EndIndex = CheckArrayDesignatorExpr(*this, EndIndex, EndValue).get();
if (!StartIndex || !EndIndex)
Invalid = true;
@@ -2447,13 +2571,13 @@ ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig,
= DesignatedInitExpr::Create(Context,
Designators.data(), Designators.size(),
InitExpressions, Loc, GNUSyntax,
- Init.takeAs<Expr>());
+ Init.getAs<Expr>());
if (!getLangOpts().C99)
Diag(DIE->getLocStart(), diag::ext_designated_init)
<< DIE->getSourceRange();
- return Owned(DIE);
+ return DIE;
}
//===----------------------------------------------------------------------===//
@@ -2484,7 +2608,7 @@ InitializedEntity::InitializeBase(ASTContext &Context,
bool IsInheritedVirtualBase) {
InitializedEntity Result;
Result.Kind = EK_Base;
- Result.Parent = 0;
+ Result.Parent = nullptr;
Result.Base = reinterpret_cast<uintptr_t>(Base);
if (IsInheritedVirtualBase)
Result.Base |= 0x01;
@@ -2549,7 +2673,7 @@ DeclaratorDecl *InitializedEntity::getDecl() const {
case EK_LambdaCapture:
case EK_CompoundLiteralInit:
case EK_RelatedResult:
- return 0;
+ return nullptr;
}
llvm_unreachable("Invalid EntityKind!");
@@ -2643,12 +2767,13 @@ void InitializationSequence::Step::Destroy() {
case SK_QualificationConversionRValue:
case SK_QualificationConversionXValue:
case SK_QualificationConversionLValue:
+ case SK_AtomicConversion:
case SK_LValueToRValue:
case SK_ListInitialization:
- case SK_ListConstructorCall:
case SK_UnwrapInitList:
case SK_RewrapInitList:
case SK_ConstructorInitialization:
+ case SK_ConstructorInitializationFromList:
case SK_ZeroInitialization:
case SK_CAssignment:
case SK_StringInit:
@@ -2659,6 +2784,7 @@ void InitializationSequence::Step::Destroy() {
case SK_PassByIndirectRestore:
case SK_ProduceObjCObject:
case SK_StdInitializerList:
+ case SK_StdInitializerListConstructorCall:
case SK_OCLSamplerInit:
case SK_OCLZeroEvent:
break;
@@ -2794,6 +2920,13 @@ void InitializationSequence::AddQualificationConversionStep(QualType Ty,
Steps.push_back(S);
}
+void InitializationSequence::AddAtomicConversionStep(QualType Ty) {
+ Step S;
+ S.Kind = SK_AtomicConversion;
+ S.Type = Ty;
+ Steps.push_back(S);
+}
+
void InitializationSequence::AddLValueToRValueStep(QualType Ty) {
assert(!Ty.hasQualifiers() && "rvalues may not have qualifiers");
@@ -2829,8 +2962,9 @@ InitializationSequence
bool HadMultipleCandidates,
bool FromInitList, bool AsInitList) {
Step S;
- S.Kind = FromInitList && !AsInitList ? SK_ListConstructorCall
- : SK_ConstructorInitialization;
+ S.Kind = FromInitList ? AsInitList ? SK_StdInitializerListConstructorCall
+ : SK_ConstructorInitializationFromList
+ : SK_ConstructorInitialization;
S.Type = T;
S.Function.HadMultipleCandidates = HadMultipleCandidates;
S.Function.Function = Constructor;
@@ -3026,7 +3160,7 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
bool SuppressUserConversions = false;
// Find the constructor (which may be a template).
- CXXConstructorDecl *Constructor = 0;
+ CXXConstructorDecl *Constructor = nullptr;
FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl)
Constructor = cast<CXXConstructorDecl>(
@@ -3057,7 +3191,7 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
(!OnlyListConstructors || S.isInitListConstructor(Constructor))) {
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
- /*ExplicitArgs*/ 0, Args,
+ /*ExplicitArgs*/ nullptr, Args,
CandidateSet, SuppressUserConversions);
else {
// C++ [over.match.copy]p1:
@@ -3243,7 +3377,7 @@ static void TryValueInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
InitializationSequence &Sequence,
- InitListExpr *InitList = 0);
+ InitListExpr *InitList = nullptr);
/// \brief Attempt list initialization of a reference.
static void TryReferenceListInitialization(Sema &S,
@@ -3442,7 +3576,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
bool AllowExplicit = Kind.AllowExplicit();
bool AllowExplicitConvs = Kind.allowExplicitConversionFunctionsInRefBinding();
- const RecordType *T1RecordType = 0;
+ const RecordType *T1RecordType = nullptr;
if (AllowRValues && (T1RecordType = T1->getAs<RecordType>()) &&
!S.RequireCompleteType(Kind.getLocation(), T1, 0)) {
// The type we're converting to is a class type. Enumerate its constructors
@@ -3460,7 +3594,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
// Find the constructor (which may be a template).
- CXXConstructorDecl *Constructor = 0;
+ CXXConstructorDecl *Constructor = nullptr;
FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl)
Constructor = cast<CXXConstructorDecl>(
@@ -3472,7 +3606,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
Constructor->isConvertingConstructor(AllowExplicit)) {
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
- /*ExplicitArgs*/ 0,
+ /*ExplicitArgs*/ nullptr,
Initializer, CandidateSet,
/*SuppressUserConversions=*/true);
else
@@ -3485,7 +3619,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
if (T1RecordType && T1RecordType->getDecl()->isInvalidDecl())
return OR_No_Viable_Function;
- const RecordType *T2RecordType = 0;
+ const RecordType *T2RecordType = nullptr;
if ((T2RecordType = T2->getAs<RecordType>()) &&
!S.RequireCompleteType(Kind.getLocation(), T2, 0)) {
// The type we're converting from is a class type, enumerate its conversion
@@ -3520,10 +3654,13 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
if (ConvTemplate)
S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(),
ActingDC, Initializer,
- DestType, CandidateSet);
+ DestType, CandidateSet,
+ /*AllowObjCConversionOnExplicit=*/
+ false);
else
S.AddConversionCandidate(Conv, I.getPair(), ActingDC,
- Initializer, DestType, CandidateSet);
+ Initializer, DestType, CandidateSet,
+ /*AllowObjCConversionOnExplicit=*/false);
}
}
}
@@ -3545,7 +3682,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
// Compute the returned type of the conversion.
if (isa<CXXConversionDecl>(Function))
- T2 = Function->getResultType();
+ T2 = Function->getReturnType();
else
T2 = cv1T1;
@@ -4045,12 +4182,11 @@ static void TryDefaultInitialization(Sema &S,
/// which enumerates all conversion functions and performs overload resolution
/// to select the best.
static void TryUserDefinedConversion(Sema &S,
- const InitializedEntity &Entity,
+ QualType DestType,
const InitializationKind &Kind,
Expr *Initializer,
InitializationSequence &Sequence,
bool TopLevelOfInitList) {
- QualType DestType = Entity.getType();
assert(!DestType->isReferenceType() && "References are handled elsewhere");
QualType SourceType = Initializer->getType();
assert((DestType->isRecordType() || SourceType->isRecordType()) &&
@@ -4085,7 +4221,7 @@ static void TryUserDefinedConversion(Sema &S,
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
// Find the constructor (which may be a template).
- CXXConstructorDecl *Constructor = 0;
+ CXXConstructorDecl *Constructor = nullptr;
FunctionTemplateDecl *ConstructorTmpl
= dyn_cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl)
@@ -4098,7 +4234,7 @@ static void TryUserDefinedConversion(Sema &S,
Constructor->isConvertingConstructor(AllowExplicit)) {
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
- /*ExplicitArgs*/ 0,
+ /*ExplicitArgs*/ nullptr,
Initializer, CandidateSet,
/*SuppressUserConversions=*/true);
else
@@ -4143,10 +4279,11 @@ static void TryUserDefinedConversion(Sema &S,
if (ConvTemplate)
S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(),
ActingDC, Initializer, DestType,
- CandidateSet);
+ CandidateSet, AllowExplicit);
else
S.AddConversionCandidate(Conv, I.getPair(), ActingDC,
- Initializer, DestType, CandidateSet);
+ Initializer, DestType, CandidateSet,
+ AllowExplicit);
}
}
}
@@ -4413,7 +4550,7 @@ InitializationSequence::InitializationSequence(Sema &S,
const InitializationKind &Kind,
MultiExprArg Args,
bool TopLevelOfInitList)
- : FailedCandidateSet(Kind.getLocation()) {
+ : FailedCandidateSet(Kind.getLocation(), OverloadCandidateSet::CSK_Normal) {
InitializeFrom(S, Entity, Kind, Args, TopLevelOfInitList);
}
@@ -4436,7 +4573,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
SetFailed(FK_PlaceholderType);
return;
}
- Args[I] = result.take();
+ Args[I] = result.get();
}
// C++0x [dcl.init]p16:
@@ -4457,9 +4594,16 @@ void InitializationSequence::InitializeFrom(Sema &S,
setSequenceKind(NormalSequence);
QualType SourceType;
- Expr *Initializer = 0;
+ Expr *Initializer = nullptr;
if (Args.size() == 1) {
Initializer = Args[0];
+ if (S.getLangOpts().ObjC1) {
+ if (S.CheckObjCBridgeRelatedConversions(Initializer->getLocStart(),
+ DestType, Initializer->getType(),
+ Initializer) ||
+ S.ConversionToObjCStringLiteralCheck(DestType, Initializer))
+ Args[0] = Initializer;
+ }
if (!isa<InitListExpr>(Initializer))
SourceType = Initializer->getType();
}
@@ -4603,7 +4747,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
(Context.hasSameUnqualifiedType(SourceType, DestType) ||
S.IsDerivedFrom(SourceType, DestType))))
TryConstructorInitialization(S, Entity, Kind, Args,
- Entity.getType(), *this);
+ DestType, *this);
// - Otherwise (i.e., for the remaining copy-initialization cases),
// user-defined conversion sequences that can convert from the source
// type to the destination type or (when a conversion function is
@@ -4611,7 +4755,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
// 13.3.1.4, and the best one is chosen through overload resolution
// (13.3).
else
- TryUserDefinedConversion(S, Entity, Kind, Initializer, *this,
+ TryUserDefinedConversion(S, DestType, Kind, Initializer, *this,
TopLevelOfInitList);
return;
}
@@ -4625,9 +4769,22 @@ void InitializationSequence::InitializeFrom(Sema &S,
// - Otherwise, if the source type is a (possibly cv-qualified) class
// type, conversion functions are considered.
if (!SourceType.isNull() && SourceType->isRecordType()) {
- TryUserDefinedConversion(S, Entity, Kind, Initializer, *this,
+ // For a conversion to _Atomic(T) from either T or a class type derived
+ // from T, initialize the T object then convert to _Atomic type.
+ bool NeedAtomicConversion = false;
+ if (const AtomicType *Atomic = DestType->getAs<AtomicType>()) {
+ if (Context.hasSameUnqualifiedType(SourceType, Atomic->getValueType()) ||
+ S.IsDerivedFrom(SourceType, Atomic->getValueType())) {
+ DestType = Atomic->getValueType();
+ NeedAtomicConversion = true;
+ }
+ }
+
+ TryUserDefinedConversion(S, DestType, Kind, Initializer, *this,
TopLevelOfInitList);
MaybeProduceObjCObject(S, *this, Entity);
+ if (!Failed() && NeedAtomicConversion)
+ AddAtomicConversionStep(Entity.getType());
return;
}
@@ -4636,16 +4793,16 @@ void InitializationSequence::InitializeFrom(Sema &S,
// conversions (Clause 4) will be used, if necessary, to convert the
// initializer expression to the cv-unqualified version of the
// destination type; no user-defined conversions are considered.
-
+
ImplicitConversionSequence ICS
- = S.TryImplicitConversion(Initializer, Entity.getType(),
+ = S.TryImplicitConversion(Initializer, DestType,
/*SuppressUserConversions*/true,
/*AllowExplicitConversions*/ false,
/*InOverloadResolution*/ false,
/*CStyle=*/Kind.isCStyleOrFunctionalCast(),
allowObjCWritebackConversion);
-
- if (ICS.isStandard() &&
+
+ if (ICS.isStandard() &&
ICS.Standard.Second == ICK_Writeback_Conversion) {
// Objective-C ARC writeback conversion.
@@ -4666,7 +4823,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
AddConversionSequenceStep(LvalueICS, ICS.Standard.getToType(0));
}
- AddPassByIndirectCopyRestoreStep(Entity.getType(), ShouldCopy);
+ AddPassByIndirectCopyRestoreStep(DestType, ShouldCopy);
} else if (ICS.isBad()) {
DeclAccessPair dap;
if (isLibstdcxxPointerReturnFalseHack(S, Entity, Initializer)) {
@@ -4678,7 +4835,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
else
SetFailed(InitializationSequence::FK_ConversionFailed);
} else {
- AddConversionSequenceStep(ICS, Entity.getType(), TopLevelOfInitList);
+ AddConversionSequenceStep(ICS, DestType, TopLevelOfInitList);
MaybeProduceObjCObject(S, *this, Entity);
}
@@ -4811,7 +4968,7 @@ static void LookupCopyAndMoveConstructors(Sema &S,
for (SmallVectorImpl<NamedDecl *>::iterator
CI = Ctors.begin(), CE = Ctors.end(); CI != CE; ++CI) {
NamedDecl *D = *CI;
- CXXConstructorDecl *Constructor = 0;
+ CXXConstructorDecl *Constructor = nullptr;
if ((Constructor = dyn_cast<CXXConstructorDecl>(D))) {
// Handle copy/moveconstructors, only.
@@ -4841,7 +4998,7 @@ static void LookupCopyAndMoveConstructors(Sema &S,
// candidates?
DeclAccessPair FoundDecl
= DeclAccessPair::make(ConstructorTmpl, ConstructorTmpl->getAccess());
- S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, 0,
+ S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, nullptr,
CurInitExpr, CandidateSet, true);
}
}
@@ -4907,7 +5064,7 @@ static ExprResult CopyObject(Sema &S,
bool IsExtraneousCopy) {
// Determine which class type we're copying to.
Expr *CurInitExpr = (Expr *)CurInit.get();
- CXXRecordDecl *Class = 0;
+ CXXRecordDecl *Class = nullptr;
if (const RecordType *Record = T->getAs<RecordType>())
Class = cast<CXXRecordDecl>(Record->getDecl());
if (!Class)
@@ -4939,7 +5096,7 @@ static ExprResult CopyObject(Sema &S,
// Only consider constructors and constructor templates. Per
// C++0x [dcl.init]p16, second bullet to class types, this initialization
// is direct-initialization.
- OverloadCandidateSet CandidateSet(Loc);
+ OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
LookupCopyAndMoveConstructors(S, CandidateSet, Class, CurInitExpr);
bool HadMultipleCandidates = (CandidateSet.size() > 1);
@@ -4977,7 +5134,7 @@ static ExprResult CopyObject(Sema &S,
CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function);
SmallVector<Expr*, 8> ConstructorArgs;
- CurInit.release(); // Ownership transferred into MultiExprArg, below.
+ CurInit.get(); // Ownership transferred into MultiExprArg, below.
S.CheckConstructorAccess(Loc, Constructor, Entity,
Best->FoundDecl.getAccess(), IsExtraneousCopy);
@@ -5005,7 +5162,7 @@ static ExprResult CopyObject(Sema &S,
S.BuildCXXDefaultArgExpr(Loc, Constructor, Parm);
}
- return S.Owned(CurInitExpr);
+ return CurInitExpr;
}
// Determine the arguments required to actually perform the
@@ -5019,13 +5176,14 @@ static ExprResult CopyObject(Sema &S,
ConstructorArgs,
HadMultipleCandidates,
/*ListInit*/ false,
+ /*StdInitListInit*/ false,
/*ZeroInit*/ false,
CXXConstructExpr::CK_Complete,
SourceRange());
// If we're supposed to bind temporaries, do so.
if (!CurInit.isInvalid() && shouldBindAsTemporary(Entity))
- CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
+ CurInit = S.MaybeBindToTemporary(CurInit.getAs<Expr>());
return CurInit;
}
@@ -5042,12 +5200,11 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S,
return;
SourceLocation Loc = getInitializationLoc(Entity, CurInitExpr);
- if (S.Diags.getDiagnosticLevel(diag::warn_cxx98_compat_temp_copy, Loc)
- == DiagnosticsEngine::Ignored)
+ if (S.Diags.isIgnored(diag::warn_cxx98_compat_temp_copy, Loc))
return;
// Find constructors which would have been considered.
- OverloadCandidateSet CandidateSet(Loc);
+ OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
LookupCopyAndMoveConstructors(
S, CandidateSet, cast<CXXRecordDecl>(Record->getDecl()), CurInitExpr);
@@ -5141,6 +5298,7 @@ PerformConstructorInitialization(Sema &S,
const InitializationSequence::Step& Step,
bool &ConstructorInitRequiresZeroInit,
bool IsListInitialization,
+ bool IsStdInitListInitialization,
SourceLocation LBraceLoc,
SourceLocation RBraceLoc) {
unsigned NumArgs = Args.size();
@@ -5164,7 +5322,7 @@ PerformConstructorInitialization(Sema &S,
S.DefineImplicitDefaultConstructor(Loc, Constructor);
}
- ExprResult CurInit = S.Owned((Expr *)0);
+ ExprResult CurInit((Expr *)nullptr);
// C++ [over.match.copy]p1:
// - When initializing a temporary to be bound to the first parameter
@@ -5199,13 +5357,10 @@ PerformConstructorInitialization(Sema &S,
? SourceRange(LBraceLoc, RBraceLoc)
: Kind.getParenRange();
- CurInit = S.Owned(
- new (S.Context) CXXTemporaryObjectExpr(S.Context, Constructor,
- TSInfo, ConstructorArgs,
- ParenOrBraceRange,
- HadMultipleCandidates,
- IsListInitialization,
- ConstructorInitRequiresZeroInit));
+ CurInit = new (S.Context) CXXTemporaryObjectExpr(
+ S.Context, Constructor, TSInfo, ConstructorArgs, ParenOrBraceRange,
+ HadMultipleCandidates, IsListInitialization,
+ IsStdInitListInitialization, ConstructorInitRequiresZeroInit);
} else {
CXXConstructExpr::ConstructionKind ConstructKind =
CXXConstructExpr::CK_Complete;
@@ -5218,10 +5373,13 @@ PerformConstructorInitialization(Sema &S,
ConstructKind = CXXConstructExpr::CK_Delegating;
}
- // Only get the parenthesis range if it is a direct construction.
- SourceRange parenRange =
- Kind.getKind() == InitializationKind::IK_Direct ?
- Kind.getParenRange() : SourceRange();
+ // Only get the parenthesis or brace range if it is a list initialization or
+ // direct construction.
+ SourceRange ParenOrBraceRange;
+ if (IsListInitialization)
+ ParenOrBraceRange = SourceRange(LBraceLoc, RBraceLoc);
+ else if (Kind.getKind() == InitializationKind::IK_Direct)
+ ParenOrBraceRange = Kind.getParenRange();
// If the entity allows NRVO, mark the construction as elidable
// unconditionally.
@@ -5231,18 +5389,20 @@ PerformConstructorInitialization(Sema &S,
ConstructorArgs,
HadMultipleCandidates,
IsListInitialization,
+ IsStdInitListInitialization,
ConstructorInitRequiresZeroInit,
ConstructKind,
- parenRange);
+ ParenOrBraceRange);
else
CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
Constructor,
ConstructorArgs,
HadMultipleCandidates,
IsListInitialization,
+ IsStdInitListInitialization,
ConstructorInitRequiresZeroInit,
ConstructKind,
- parenRange);
+ ParenOrBraceRange);
}
if (CurInit.isInvalid())
return ExprError();
@@ -5254,7 +5414,7 @@ PerformConstructorInitialization(Sema &S,
return ExprError();
if (shouldBindAsTemporary(Entity))
- CurInit = S.MaybeBindToTemporary(CurInit.take());
+ CurInit = S.MaybeBindToTemporary(CurInit.get());
return CurInit;
}
@@ -5302,25 +5462,25 @@ InitializedEntityOutlivesFullExpression(const InitializedEntity &Entity) {
/// 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 ValueDecl *
-getDeclForTemporaryLifetimeExtension(const InitializedEntity &Entity,
- const ValueDecl *FallbackDecl = 0) {
+static const InitializedEntity *getEntityForTemporaryLifetimeExtension(
+ const InitializedEntity *Entity,
+ const InitializedEntity *FallbackDecl = nullptr) {
// C++11 [class.temporary]p5:
- switch (Entity.getKind()) {
+ switch (Entity->getKind()) {
case InitializedEntity::EK_Variable:
// The temporary [...] persists for the lifetime of the reference
- return Entity.getDecl();
+ return Entity;
case InitializedEntity::EK_Member:
// For subobjects, we look at the complete object.
- if (Entity.getParent())
- return getDeclForTemporaryLifetimeExtension(*Entity.getParent(),
- Entity.getDecl());
+ if (Entity->getParent())
+ return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
+ Entity);
// except:
// -- A temporary bound to a reference member in a constructor's
// ctor-initializer persists until the constructor exits.
- return Entity.getDecl();
+ return Entity;
case InitializedEntity::EK_Parameter:
case InitializedEntity::EK_Parameter_CF_Audited:
@@ -5335,7 +5495,7 @@ getDeclForTemporaryLifetimeExtension(const InitializedEntity &Entity,
// -- A temporary bound to a reference in a new-initializer persists
// until the completion of the full-expression containing the
// new-initializer.
- return 0;
+ return nullptr;
case InitializedEntity::EK_Temporary:
case InitializedEntity::EK_CompoundLiteralInit:
@@ -5343,12 +5503,12 @@ getDeclForTemporaryLifetimeExtension(const InitializedEntity &Entity,
// 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 0;
+ return nullptr;
case InitializedEntity::EK_ArrayElement:
// For subobjects, we look at the complete object.
- return getDeclForTemporaryLifetimeExtension(*Entity.getParent(),
- FallbackDecl);
+ return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
+ FallbackDecl);
case InitializedEntity::EK_Base:
case InitializedEntity::EK_Delegating:
@@ -5363,17 +5523,20 @@ getDeclForTemporaryLifetimeExtension(const InitializedEntity &Entity,
case InitializedEntity::EK_Exception:
case InitializedEntity::EK_VectorElement:
case InitializedEntity::EK_ComplexElement:
- return 0;
+ return nullptr;
}
llvm_unreachable("unknown entity kind");
}
-static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD);
+static void performLifetimeExtension(Expr *Init,
+ const InitializedEntity *ExtendingEntity);
/// 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 ValueDecl *ExtendingD) {
+static bool
+performReferenceExtension(Expr *Init,
+ const InitializedEntity *ExtendingEntity) {
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
if (ILE->getNumInits() == 1 && ILE->isGLValue()) {
// This is just redundant braces around an initializer. Step over it.
@@ -5407,8 +5570,9 @@ static bool performReferenceExtension(Expr *Init, const ValueDecl *ExtendingD) {
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(ExtendingD);
- performLifetimeExtension(ME->GetTemporaryExpr(), ExtendingD);
+ ME->setExtendingDecl(ExtendingEntity->getDecl(),
+ ExtendingEntity->allocateManglingNumber());
+ performLifetimeExtension(ME->GetTemporaryExpr(), ExtendingEntity);
return true;
}
@@ -5417,7 +5581,8 @@ static bool performReferenceExtension(Expr *Init, const ValueDecl *ExtendingD) {
/// Update a prvalue expression that is going to be materialized as a
/// lifetime-extended temporary.
-static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD) {
+static void performLifetimeExtension(Expr *Init,
+ const InitializedEntity *ExtendingEntity) {
// Dig out the expression which constructs the extended temporary.
SmallVector<const Expr *, 2> CommaLHSs;
SmallVector<SubobjectAdjustment, 2> Adjustments;
@@ -5429,14 +5594,14 @@ static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD) {
if (CXXStdInitializerListExpr *ILE =
dyn_cast<CXXStdInitializerListExpr>(Init)) {
- performReferenceExtension(ILE->getSubExpr(), ExtendingD);
+ performReferenceExtension(ILE->getSubExpr(), ExtendingEntity);
return;
}
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
if (ILE->getType()->isArrayType()) {
for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
- performLifetimeExtension(ILE->getInit(I), ExtendingD);
+ performLifetimeExtension(ILE->getInit(I), ExtendingEntity);
return;
}
@@ -5448,25 +5613,23 @@ static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD) {
// bound to temporaries, those temporaries are also lifetime-extended.
if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
- performReferenceExtension(ILE->getInit(0), ExtendingD);
+ performReferenceExtension(ILE->getInit(0), ExtendingEntity);
else {
unsigned Index = 0;
- for (RecordDecl::field_iterator I = RD->field_begin(),
- E = RD->field_end();
- I != E; ++I) {
+ for (const auto *I : RD->fields()) {
if (Index >= ILE->getNumInits())
break;
if (I->isUnnamedBitfield())
continue;
Expr *SubInit = ILE->getInit(Index);
if (I->getType()->isReferenceType())
- performReferenceExtension(SubInit, ExtendingD);
+ 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,
// we should recursively lifetime-extend that initializer.
- performLifetimeExtension(SubInit, ExtendingD);
+ performLifetimeExtension(SubInit, ExtendingEntity);
++Index;
}
}
@@ -5555,7 +5718,7 @@ InitializationSequence::Perform(Sema &S,
*ResultType
= S.Context.getDependentSizedArrayType(ArrayT->getElementType(),
- /*NumElts=*/0,
+ /*NumElts=*/nullptr,
ArrayT->getSizeModifier(),
ArrayT->getIndexTypeCVRQualifiers(),
Brackets);
@@ -5578,7 +5741,7 @@ InitializationSequence::Perform(Sema &S,
// No steps means no initialization.
if (Steps.empty())
- return S.Owned((Expr *)0);
+ return ExprResult((Expr *)nullptr);
if (S.getLangOpts().CPlusPlus11 && Entity.getType()->isReferenceType() &&
Args.size() == 1 && isa<InitListExpr>(Args[0]) &&
@@ -5611,7 +5774,7 @@ InitializationSequence::Perform(Sema &S,
*ResultType = Entity.getDecl() ? Entity.getDecl()->getType() :
Entity.getType();
- ExprResult CurInit = S.Owned((Expr *)0);
+ ExprResult CurInit((Expr *)nullptr);
// For initialization steps that start with a single initializer,
// grab the only argument out the Args and place it into the "current"
@@ -5628,6 +5791,7 @@ InitializationSequence::Perform(Sema &S,
case SK_QualificationConversionLValue:
case SK_QualificationConversionXValue:
case SK_QualificationConversionRValue:
+ case SK_AtomicConversion:
case SK_LValueToRValue:
case SK_ConversionSequence:
case SK_ConversionSequenceNoNarrowing:
@@ -5652,7 +5816,8 @@ InitializationSequence::Perform(Sema &S,
}
case SK_ConstructorInitialization:
- case SK_ListConstructorCall:
+ case SK_ConstructorInitializationFromList:
+ case SK_StdInitializerListConstructorCall:
case SK_ZeroInitialization:
break;
}
@@ -5710,11 +5875,9 @@ InitializationSequence::Perform(Sema &S,
(Step->Kind == SK_CastDerivedToBaseXValue ?
VK_XValue :
VK_RValue);
- CurInit = S.Owned(ImplicitCastExpr::Create(S.Context,
- Step->Type,
- CK_DerivedToBase,
- CurInit.get(),
- &BasePath, VK));
+ CurInit =
+ ImplicitCastExpr::Create(S.Context, Step->Type, CK_DerivedToBase,
+ CurInit.get(), &BasePath, VK);
break;
}
@@ -5726,7 +5889,7 @@ InitializationSequence::Perform(Sema &S,
S.Diag(Kind.getLocation(), diag::err_reference_bind_to_bitfield)
<< Entity.getType().isVolatileQualified()
<< (BitField ? BitField->getDeclName() : DeclarationName())
- << (BitField != NULL)
+ << (BitField != nullptr)
<< CurInit.get()->getSourceRange();
if (BitField)
S.Diag(BitField->getLocation(), diag::note_bitfield_decl);
@@ -5752,12 +5915,12 @@ 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 ValueDecl *ExtendingDecl =
- getDeclForTemporaryLifetimeExtension(Entity)) {
- if (performReferenceExtension(CurInit.get(), ExtendingDecl))
- warnOnLifetimeExtension(S, Entity, CurInit.get(), false,
- ExtendingDecl);
- }
+ if (const InitializedEntity *ExtendingEntity =
+ getEntityForTemporaryLifetimeExtension(&Entity))
+ if (performReferenceExtension(CurInit.get(), ExtendingEntity))
+ warnOnLifetimeExtension(S, Entity, CurInit.get(),
+ /*IsInitializerList=*/false,
+ ExtendingEntity->getDecl());
break;
@@ -5769,19 +5932,18 @@ InitializationSequence::Perform(Sema &S,
if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType))
return ExprError();
- // Maybe lifetime-extend the temporary's subobjects to match the
- // entity's lifetime.
- const ValueDecl *ExtendingDecl =
- getDeclForTemporaryLifetimeExtension(Entity);
- if (ExtendingDecl) {
- performLifetimeExtension(CurInit.get(), ExtendingDecl);
- warnOnLifetimeExtension(S, Entity, CurInit.get(), false, ExtendingDecl);
- }
-
// Materialize the temporary into memory.
MaterializeTemporaryExpr *MTE = new (S.Context) MaterializeTemporaryExpr(
Entity.getType().getNonReferenceType(), CurInit.get(),
- Entity.getType()->isLValueReferenceType(), ExtendingDecl);
+ 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());
// If we're binding to an Objective-C object that has lifetime, we
// need cleanups. Likewise if we're extending this temporary to automatic
@@ -5793,7 +5955,7 @@ InitializationSequence::Perform(Sema &S,
MTE->getType().isDestructedType()))
S.ExprNeedsCleanups = true;
- CurInit = S.Owned(MTE);
+ CurInit = MTE;
break;
}
@@ -5815,7 +5977,7 @@ InitializationSequence::Perform(Sema &S,
// Build a call to the selected constructor.
SmallVector<Expr*, 8> ConstructorArgs;
SourceLocation Loc = CurInit.get()->getLocStart();
- CurInit.release(); // Ownership transferred into MultiExprArg, below.
+ CurInit.get(); // Ownership transferred into MultiExprArg, below.
// Determine the arguments required to actually perform the constructor
// call.
@@ -5830,6 +5992,7 @@ InitializationSequence::Perform(Sema &S,
ConstructorArgs,
HadMultipleCandidates,
/*ListInit*/ false,
+ /*StdInitListInit*/ false,
/*ZeroInit*/ false,
CXXConstructExpr::CK_Complete,
SourceRange());
@@ -5851,7 +6014,7 @@ InitializationSequence::Perform(Sema &S,
} else {
// Build a call to the conversion function.
CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Fn);
- S.CheckMemberOperatorAccess(Kind.getLocation(), CurInit.get(), 0,
+ S.CheckMemberOperatorAccess(Kind.getLocation(), CurInit.get(), nullptr,
FoundFn);
if (S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation()))
return ExprError();
@@ -5860,7 +6023,8 @@ InitializationSequence::Perform(Sema &S,
// 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.
ExprResult CurInitExprRes =
- S.PerformObjectArgumentInitialization(CurInit.take(), /*Qualifier=*/0,
+ S.PerformObjectArgumentInitialization(CurInit.get(),
+ /*Qualifier=*/nullptr,
FoundFn, Conversion);
if(CurInitExprRes.isInvalid())
return ExprError();
@@ -5874,7 +6038,7 @@ InitializationSequence::Perform(Sema &S,
CastKind = CK_UserDefinedConversion;
- CreatedObject = Conversion->getResultType()->isRecordType();
+ CreatedObject = Conversion->getReturnType()->isRecordType();
}
bool RequiresCopy = !IsCopy && !isReferenceBinding(Steps.back());
@@ -5893,12 +6057,11 @@ InitializationSequence::Perform(Sema &S,
}
}
- CurInit = S.Owned(ImplicitCastExpr::Create(S.Context,
- CurInit.get()->getType(),
- CastKind, CurInit.get(), 0,
- CurInit.get()->getValueKind()));
+ CurInit = ImplicitCastExpr::Create(S.Context, CurInit.get()->getType(),
+ CastKind, CurInit.get(), nullptr,
+ CurInit.get()->getValueKind());
if (MaybeBindToTemp)
- CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
+ CurInit = S.MaybeBindToTemporary(CurInit.getAs<Expr>());
if (RequiresCopy)
CurInit = CopyObject(S, Entity.getType().getNonReferenceType(), Entity,
CurInit, /*IsExtraneousCopy=*/false);
@@ -5915,17 +6078,22 @@ InitializationSequence::Perform(Sema &S,
(Step->Kind == SK_QualificationConversionXValue ?
VK_XValue :
VK_RValue);
- CurInit = S.ImpCastExprToType(CurInit.take(), Step->Type, CK_NoOp, VK);
+ CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type, CK_NoOp, VK);
+ break;
+ }
+
+ case SK_AtomicConversion: {
+ assert(CurInit.get()->isRValue() && "cannot convert glvalue to atomic");
+ CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type,
+ CK_NonAtomicToAtomic, VK_RValue);
break;
}
case SK_LValueToRValue: {
assert(CurInit.get()->isGLValue() && "cannot load from a prvalue");
- CurInit = S.Owned(ImplicitCastExpr::Create(S.Context, Step->Type,
- CK_LValueToRValue,
- CurInit.take(),
- /*BasePath=*/0,
- VK_RValue));
+ CurInit = ImplicitCastExpr::Create(S.Context, Step->Type,
+ CK_LValueToRValue, CurInit.get(),
+ /*BasePath=*/nullptr, VK_RValue);
break;
}
@@ -5978,14 +6146,14 @@ InitializationSequence::Perform(Sema &S,
InitListExpr *StructuredInitList =
PerformInitList.getFullyStructuredList();
- CurInit.release();
+ CurInit.get();
CurInit = shouldBindAsTemporary(InitEntity)
? S.MaybeBindToTemporary(StructuredInitList)
- : S.Owned(StructuredInitList);
+ : StructuredInitList;
break;
}
- case SK_ListConstructorCall: {
+ case SK_ConstructorInitializationFromList: {
// When an initializer list is passed for a parameter of type "reference
// to object", we don't get an EK_Temporary entity, but instead an
// EK_Parameter entity with reference type.
@@ -6004,29 +6172,31 @@ InitializationSequence::Perform(Sema &S,
Entity,
Kind, Arg, *Step,
ConstructorInitRequiresZeroInit,
- /*IsListInitialization*/ true,
+ /*IsListInitialization*/true,
+ /*IsStdInitListInit*/false,
InitList->getLBraceLoc(),
InitList->getRBraceLoc());
break;
}
case SK_UnwrapInitList:
- CurInit = S.Owned(cast<InitListExpr>(CurInit.take())->getInit(0));
+ CurInit = cast<InitListExpr>(CurInit.get())->getInit(0);
break;
case SK_RewrapInitList: {
- Expr *E = CurInit.take();
+ Expr *E = CurInit.get();
InitListExpr *Syntactic = Step->WrappingSyntacticList;
InitListExpr *ILE = new (S.Context) InitListExpr(S.Context,
Syntactic->getLBraceLoc(), E, Syntactic->getRBraceLoc());
ILE->setSyntacticForm(Syntactic);
ILE->setType(E->getType());
ILE->setValueKind(E->getValueKind());
- CurInit = S.Owned(ILE);
+ CurInit = ILE;
break;
}
- case SK_ConstructorInitialization: {
+ case SK_ConstructorInitialization:
+ case SK_StdInitializerListConstructorCall: {
// When an initializer list is passed for a parameter of type "reference
// to object", we don't get an EK_Temporary entity, but instead an
// EK_Parameter entity with reference type.
@@ -6036,13 +6206,15 @@ InitializationSequence::Perform(Sema &S,
InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(
Entity.getType().getNonReferenceType());
bool UseTemporary = Entity.getType()->isReferenceType();
- CurInit = PerformConstructorInitialization(S, UseTemporary ? TempEntity
- : Entity,
- Kind, Args, *Step,
- ConstructorInitRequiresZeroInit,
- /*IsListInitialization*/ false,
- /*LBraceLoc*/ SourceLocation(),
- /*RBraceLoc*/ SourceLocation());
+ bool IsStdInitListInit =
+ Step->Kind == SK_StdInitializerListConstructorCall;
+ CurInit = PerformConstructorInitialization(
+ S, UseTemporary ? TempEntity : Entity, Kind, Args, *Step,
+ ConstructorInitRequiresZeroInit,
+ /*IsListInitialization*/IsStdInitListInit,
+ /*IsStdInitListInitialization*/IsStdInitListInit,
+ /*LBraceLoc*/SourceLocation(),
+ /*RBraceLoc*/SourceLocation());
break;
}
@@ -6051,7 +6223,7 @@ InitializationSequence::Perform(Sema &S,
++NextStep;
if (NextStep != StepEnd &&
(NextStep->Kind == SK_ConstructorInitialization ||
- NextStep->Kind == SK_ListConstructorCall)) {
+ NextStep->Kind == SK_ConstructorInitializationFromList)) {
// The need for zero-initialization is recorded directly into
// the call to the object's constructor within the next step.
ConstructorInitRequiresZeroInit = true;
@@ -6063,12 +6235,11 @@ InitializationSequence::Perform(Sema &S,
TSInfo = S.Context.getTrivialTypeSourceInfo(Step->Type,
Kind.getRange().getBegin());
- CurInit = S.Owned(new (S.Context) CXXScalarValueInitExpr(
- TSInfo->getType().getNonLValueExprType(S.Context),
- TSInfo,
- Kind.getRange().getEnd()));
+ CurInit = new (S.Context) CXXScalarValueInitExpr(
+ TSInfo->getType().getNonLValueExprType(S.Context), TSInfo,
+ Kind.getRange().getEnd());
} else {
- CurInit = S.Owned(new (S.Context) ImplicitValueInitExpr(Step->Type));
+ CurInit = new (S.Context) ImplicitValueInitExpr(Step->Type);
}
break;
}
@@ -6115,7 +6286,7 @@ InitializationSequence::Perform(Sema &S,
}
case SK_ObjCObjectConversion:
- CurInit = S.ImpCastExprToType(CurInit.take(), Step->Type,
+ CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type,
CK_ObjCObjectLValueCast,
CurInit.get()->getValueKind());
break;
@@ -6153,15 +6324,15 @@ InitializationSequence::Perform(Sema &S,
case SK_PassByIndirectCopyRestore:
case SK_PassByIndirectRestore:
checkIndirectCopyRestoreSource(S, CurInit.get());
- CurInit = S.Owned(new (S.Context)
- ObjCIndirectCopyRestoreExpr(CurInit.take(), Step->Type,
- Step->Kind == SK_PassByIndirectCopyRestore));
+ CurInit = new (S.Context) ObjCIndirectCopyRestoreExpr(
+ CurInit.get(), Step->Type,
+ Step->Kind == SK_PassByIndirectCopyRestore);
break;
case SK_ProduceObjCObject:
- CurInit = S.Owned(ImplicitCastExpr::Create(S.Context, Step->Type,
- CK_ARCProduceObject,
- CurInit.take(), 0, VK_RValue));
+ CurInit =
+ ImplicitCastExpr::Create(S.Context, Step->Type, CK_ARCProduceObject,
+ CurInit.get(), nullptr, VK_RValue);
break;
case SK_StdInitializerList: {
@@ -6169,34 +6340,33 @@ InitializationSequence::Perform(Sema &S,
diag::warn_cxx98_compat_initializer_list_init)
<< CurInit.get()->getSourceRange();
- // Maybe lifetime-extend the array temporary's subobjects to match the
- // entity's lifetime.
- const ValueDecl *ExtendingDecl =
- getDeclForTemporaryLifetimeExtension(Entity);
- if (ExtendingDecl) {
- performLifetimeExtension(CurInit.get(), ExtendingDecl);
- warnOnLifetimeExtension(S, Entity, CurInit.get(), true, ExtendingDecl);
- }
-
// Materialize the temporary into memory.
MaterializeTemporaryExpr *MTE = new (S.Context)
MaterializeTemporaryExpr(CurInit.get()->getType(), CurInit.get(),
- /*lvalue reference*/ false, ExtendingDecl);
+ /*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 = S.Owned(
- new (S.Context) CXXStdInitializerListExpr(Step->Type, MTE));
+ CurInit = new (S.Context) CXXStdInitializerListExpr(Step->Type, MTE);
// Bind the result, in case the library has given initializer_list a
// non-trivial destructor.
if (shouldBindAsTemporary(Entity))
- CurInit = S.MaybeBindToTemporary(CurInit.take());
+ CurInit = S.MaybeBindToTemporary(CurInit.get());
break;
}
case SK_OCLSamplerInit: {
assert(Step->Type->isSamplerT() &&
- "Sampler initialization on non sampler type.");
+ "Sampler initialization on non-sampler type.");
QualType SourceType = CurInit.get()->getType();
@@ -6212,9 +6382,9 @@ InitializationSequence::Perform(Sema &S,
}
case SK_OCLZeroEvent: {
assert(Step->Type->isEventT() &&
- "Event initialization on non event type.");
+ "Event initialization on non-event type.");
- CurInit = S.ImpCastExprToType(CurInit.take(), Step->Type,
+ CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type,
CK_ZeroToOCLEvent,
CurInit.get()->getValueKind());
break;
@@ -6246,8 +6416,7 @@ static bool DiagnoseUninitializedReference(Sema &S, SourceLocation Loc,
if (!RD || !RD->hasUninitializedReferenceMember())
return false;
- for (CXXRecordDecl::field_iterator FI = RD->field_begin(),
- FE = RD->field_end(); FI != FE; ++FI) {
+ for (const auto *FI : RD->fields()) {
if (FI->isUnnamedBitfield())
continue;
@@ -6257,10 +6426,8 @@ static bool DiagnoseUninitializedReference(Sema &S, SourceLocation Loc,
}
}
- for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(),
- BE = RD->bases_end();
- BI != BE; ++BI) {
- if (DiagnoseUninitializedReference(S, BI->getLocStart(), BI->getType())) {
+ for (const auto &BI : RD->bases()) {
+ if (DiagnoseUninitializedReference(S, BI.getLocStart(), BI.getType())) {
S.Diag(Loc, diag::note_value_initialization_here) << RD;
return true;
}
@@ -6505,7 +6672,7 @@ bool InitializationSequence::Diagnose(Sema &S,
else
R = SourceRange(Args.front()->getLocEnd(), Args.back()->getLocEnd());
- R.setBegin(S.PP.getLocForEndOfToken(R.getBegin()));
+ R.setBegin(S.getLocForEndOfToken(R.getBegin()));
if (Kind.isCStyleOrFunctionalCast())
S.Diag(Kind.getLocation(), diag::err_builtin_func_cast_more_than_one_arg)
<< R;
@@ -6533,7 +6700,8 @@ bool InitializationSequence::Diagnose(Sema &S,
Args.back()->getLocEnd());
if (Failure == FK_ListConstructorOverloadFailed) {
- assert(Args.size() == 1 && "List construction from other than 1 argument.");
+ assert(Args.size() == 1 &&
+ "List construction from other than 1 argument.");
InitListExpr *InitList = cast<InitListExpr>(Args[0]);
Args = MultiExprArg(InitList->getInits(), InitList->getNumInits());
}
@@ -6578,7 +6746,8 @@ bool InitializationSequence::Diagnose(Sema &S,
<< S.Context.getTypeDeclType(Constructor->getParent())
<< /*member=*/1
<< Entity.getName();
- S.Diag(Entity.getDecl()->getLocation(), diag::note_field_decl);
+ S.Diag(Entity.getDecl()->getLocation(),
+ diag::note_member_declared_at);
if (const RecordType *Record
= Entity.getType()->getAs<RecordType>())
@@ -6870,6 +7039,10 @@ void InitializationSequence::dump(raw_ostream &OS) const {
OS << "qualification conversion (lvalue)";
break;
+ case SK_AtomicConversion:
+ OS << "non-atomic-to-atomic conversion";
+ break;
+
case SK_LValueToRValue:
OS << "load (lvalue to rvalue)";
break;
@@ -6890,10 +7063,6 @@ void InitializationSequence::dump(raw_ostream &OS) const {
OS << "list aggregate initialization";
break;
- case SK_ListConstructorCall:
- OS << "list initialization via constructor";
- break;
-
case SK_UnwrapInitList:
OS << "unwrap reference initializer list";
break;
@@ -6906,6 +7075,10 @@ void InitializationSequence::dump(raw_ostream &OS) const {
OS << "constructor initialization";
break;
+ case SK_ConstructorInitializationFromList:
+ OS << "list initialization via constructor";
+ break;
+
case SK_ZeroInitialization:
OS << "zero initialization";
break;
@@ -6946,6 +7119,10 @@ void InitializationSequence::dump(raw_ostream &OS) const {
OS << "std::initializer_list from initializer list";
break;
+ case SK_StdInitializerListConstructorCall:
+ OS << "list initialization from std::initializer_list";
+ break;
+
case SK_OCLSamplerInit:
OS << "OpenCL sampler_t from integer constant";
break;
@@ -6970,7 +7147,7 @@ static void DiagnoseNarrowingInInitList(Sema &S,
QualType PreNarrowingType,
QualType EntityType,
const Expr *PostInit) {
- const StandardConversionSequence *SCS = 0;
+ const StandardConversionSequence *SCS = nullptr;
switch (ICS.getKind()) {
case ImplicitConversionSequence::StandardConversion:
SCS = &ICS.Standard;
@@ -7047,11 +7224,11 @@ static void DiagnoseNarrowingInInitList(Sema &S,
return;
}
OS << ">(";
- S.Diag(PostInit->getLocStart(), diag::note_init_list_narrowing_override)
- << PostInit->getSourceRange()
- << FixItHint::CreateInsertion(PostInit->getLocStart(), OS.str())
- << FixItHint::CreateInsertion(
- S.getPreprocessor().getLocForEndOfToken(PostInit->getLocEnd()), ")");
+ S.Diag(PostInit->getLocStart(), diag::note_init_list_narrowing_silence)
+ << PostInit->getSourceRange()
+ << FixItHint::CreateInsertion(PostInit->getLocStart(), OS.str())
+ << FixItHint::CreateInsertion(
+ S.getLocForEndOfToken(PostInit->getLocEnd()), ")");
}
//===----------------------------------------------------------------------===//
@@ -7091,7 +7268,7 @@ Sema::PerformCopyInitialization(const InitializedEntity &Entity,
EqualLoc,
AllowExplicit);
InitializationSequence Seq(*this, Entity, Kind, InitE, TopLevelOfInitList);
- Init.release();
+ Init.get();
ExprResult Result = Seq.Perform(*this, Entity, Kind, InitE);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
index a7d5b65..0cf4ed7 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
@@ -11,125 +11,214 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Sema/DeclSpec.h"
+#include "TypeLocBuilder.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Lex/Preprocessor.h"
#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 "clang/Sema/SemaLambda.h"
-#include "TypeLocBuilder.h"
using namespace clang;
using namespace sema;
-// returns -1 if none of the lambdas on the scope stack can capture.
-// A lambda 'L' is capture-ready for a certain variable 'V' if,
-// - its enclosing context is non-dependent
-// - and if the chain of lambdas between L and the lambda in which
-// V is potentially used, call all capture or have captured V.
-static inline int GetScopeIndexOfNearestCaptureReadyLambda(
- ArrayRef<clang::sema::FunctionScopeInfo*> FunctionScopes,
- DeclContext *const CurContext, VarDecl *VD) {
+/// \brief 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
+/// of the capture-ready lambda's LambdaScopeInfo.
+///
+/// Climbs down the stack of lambdas (deepest nested lambda - i.e. current
+/// lambda - is on top) to determine the index of the nearest enclosing/outer
+/// lambda that is ready to capture the \p VarToCapture being referenced in
+/// the current lambda.
+/// As we climb down the stack, we want the index of the first such lambda -
+/// that is the lambda with the highest index that is 'capture-ready'.
+///
+/// A lambda 'L' is capture-ready for 'V' (var or this) if:
+/// - its enclosing context is non-dependent
+/// - and if the chain of lambdas between L and the lambda in which
+/// V is potentially used (i.e. the lambda at the top of the scope info
+/// stack), can all capture or have already captured V.
+/// If \p VarToCapture is 'null' then we are trying to capture 'this'.
+///
+/// Note that a lambda that is deemed 'capture-ready' still needs to be checked
+/// for whether it is 'capture-capable' (see
+/// getStackIndexOfNearestEnclosingCaptureCapableLambda), before it can truly
+/// capture.
+///
+/// \param FunctionScopes - Sema's stack of nested FunctionScopeInfo's (which a
+/// LambdaScopeInfo inherits from). The current/deepest/innermost lambda
+/// is at the top of the stack and has the highest index.
+/// \param VarToCapture - the variable to capture. If NULL, capture 'this'.
+///
+/// \returns An Optional<unsigned> Index that if evaluates to 'true' contains
+/// the index (into Sema's FunctionScopeInfo stack) of the innermost lambda
+/// which is capture-ready. If the return value evaluates to 'false' then
+/// no lambda is capture-ready for \p VarToCapture.
+
+static inline Optional<unsigned>
+getStackIndexOfNearestEnclosingCaptureReadyLambda(
+ ArrayRef<const clang::sema::FunctionScopeInfo *> FunctionScopes,
+ VarDecl *VarToCapture) {
+ // Label failure to capture.
+ const Optional<unsigned> NoLambdaIsCaptureReady;
+
+ assert(
+ isa<clang::sema::LambdaScopeInfo>(
+ FunctionScopes[FunctionScopes.size() - 1]) &&
+ "The function on the top of sema's function-info stack must be a lambda");
- DeclContext *EnclosingDC = CurContext;
- // If VD is null, we are attempting to capture 'this'
- const bool IsCapturingThis = !VD;
+ // If VarToCapture is null, we are attempting to capture 'this'.
+ const bool IsCapturingThis = !VarToCapture;
const bool IsCapturingVariable = !IsCapturingThis;
- int RetIndex = -1;
+
+ // Start with the current lambda at the top of the stack (highest index).
unsigned CurScopeIndex = FunctionScopes.size() - 1;
- while (!EnclosingDC->isTranslationUnit() &&
- EnclosingDC->isDependentContext() && isLambdaCallOperator(EnclosingDC)) {
- RetIndex = CurScopeIndex;
- clang::sema::LambdaScopeInfo *LSI =
- cast<sema::LambdaScopeInfo>(FunctionScopes[CurScopeIndex]);
- // We have crawled up to an intervening lambda that contains the
- // variable declaration - so not only does it not need to capture;
- // none of the enclosing lambdas need to capture it, and since all
- // other nested lambdas are dependent (otherwise we wouldn't have
- // arrived here) - we don't yet have a lambda that can capture the
+ DeclContext *EnclosingDC =
+ cast<sema::LambdaScopeInfo>(FunctionScopes[CurScopeIndex])->CallOperator;
+
+ do {
+ const clang::sema::LambdaScopeInfo *LSI =
+ cast<sema::LambdaScopeInfo>(FunctionScopes[CurScopeIndex]);
+ // IF we have climbed down to an intervening enclosing lambda that contains
+ // the variable declaration - it obviously can/must not capture the
// variable.
- if (IsCapturingVariable && VD->getDeclContext()->Equals(EnclosingDC))
- return -1;
- // All intervening lambda call operators have to be able to capture.
+ // Since its enclosing DC is dependent, all the lambdas between it and the
+ // innermost nested lambda are dependent (otherwise we wouldn't have
+ // arrived here) - so we don't yet have a lambda that can capture the
+ // variable.
+ if (IsCapturingVariable &&
+ VarToCapture->getDeclContext()->Equals(EnclosingDC))
+ return NoLambdaIsCaptureReady;
+
+ // For an enclosing lambda to be capture ready for an entity, all
+ // intervening lambda's have to be able to capture that entity. If even
+ // one of the intervening lambda's is not capable of capturing the entity
+ // then no enclosing lambda can ever capture that entity.
+ // For e.g.
+ // const int x = 10;
+ // [=](auto a) { #1
+ // [](auto b) { #2 <-- an intervening lambda that can never capture 'x'
+ // [=](auto c) { #3
+ // f(x, c); <-- can not lead to x's speculative capture by #1 or #2
+ // }; }; };
// If they do not have a default implicit capture, check to see
// if the entity has already been explicitly captured.
- // If even a single dependent enclosing lambda lacks the capability
- // to ever capture this variable, there is no further enclosing
+ // If even a single dependent enclosing lambda lacks the capability
+ // to ever capture this variable, there is no further enclosing
// non-dependent lambda that can capture this variable.
if (LSI->ImpCaptureStyle == sema::LambdaScopeInfo::ImpCap_None) {
- if (IsCapturingVariable && !LSI->isCaptured(VD))
- return -1;
+ if (IsCapturingVariable && !LSI->isCaptured(VarToCapture))
+ return NoLambdaIsCaptureReady;
if (IsCapturingThis && !LSI->isCXXThisCaptured())
- return -1;
+ return NoLambdaIsCaptureReady;
}
EnclosingDC = getLambdaAwareParentOfDeclContext(EnclosingDC);
+
+ assert(CurScopeIndex);
--CurScopeIndex;
- }
+ } while (!EnclosingDC->isTranslationUnit() &&
+ EnclosingDC->isDependentContext() &&
+ isLambdaCallOperator(EnclosingDC));
+
+ assert(CurScopeIndex < (FunctionScopes.size() - 1));
// If the enclosingDC is not dependent, then the immediately nested lambda
- // is capture-ready.
+ // (one index above) is capture-ready.
if (!EnclosingDC->isDependentContext())
- return RetIndex;
- return -1;
+ return CurScopeIndex + 1;
+ return NoLambdaIsCaptureReady;
}
-// Given a lambda's call operator and a variable (or null for 'this'),
-// compute the nearest enclosing lambda that is capture-ready (i.e
-// the enclosing context is not dependent, and all intervening lambdas can
-// either implicitly or explicitly capture Var)
-//
-// The approach is as follows, for the entity VD ('this' if null):
-// - start with the current lambda
-// - if it is non-dependent and can capture VD, return it.
-// - if it is dependent and has an implicit or explicit capture, check its parent
-// whether the parent is non-depdendent and all its intervening lambdas
-// can capture, if so return the child.
-// [Note: When we hit a generic lambda specialization, do not climb up
-// the scope stack any further since not only do we not need to,
-// the scope stack will often not be synchronized with any lambdas
-// enclosing the specialized generic lambda]
-//
-// Return the CallOperator of the capturable lambda and set function scope
-// index to the correct index within the function scope stack to correspond
-// to the capturable lambda.
-// If VarDecl *VD is null, we check for 'this' capture.
-CXXMethodDecl* clang::GetInnermostEnclosingCapturableLambda(
- ArrayRef<sema::FunctionScopeInfo*> FunctionScopes,
- unsigned &FunctionScopeIndex,
- DeclContext *const CurContext, VarDecl *VD,
- Sema &S) {
-
- const int IndexOfCaptureReadyLambda =
- GetScopeIndexOfNearestCaptureReadyLambda(FunctionScopes,CurContext, VD);
- if (IndexOfCaptureReadyLambda == -1) return 0;
- assert(IndexOfCaptureReadyLambda >= 0);
- const unsigned IndexOfCaptureReadyLambdaU =
- static_cast<unsigned>(IndexOfCaptureReadyLambda);
- sema::LambdaScopeInfo *const CaptureReadyLambdaLSI =
- cast<sema::LambdaScopeInfo>(FunctionScopes[IndexOfCaptureReadyLambdaU]);
- // If VD is null, we are attempting to capture 'this'
- const bool IsCapturingThis = !VD;
+
+/// \brief 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
+/// of the capture-capable lambda's LambdaScopeInfo.
+///
+/// Given the current stack of lambdas being processed by Sema and
+/// the variable of interest, to identify the nearest enclosing lambda (to the
+/// current lambda at the top of the stack) that can truly capture
+/// a variable, it has to have the following two properties:
+/// a) 'capture-ready' - be the innermost lambda that is 'capture-ready':
+/// - climb down the stack (i.e. starting from the innermost and examining
+/// each outer lambda step by step) checking if each enclosing
+/// lambda can either implicitly or explicitly capture the variable.
+/// Record the first such lambda that is enclosed in a non-dependent
+/// context. If no such lambda currently exists return failure.
+/// b) 'capture-capable' - make sure the 'capture-ready' lambda can truly
+/// capture the variable by checking all its enclosing lambdas:
+/// - check if all outer lambdas enclosing the 'capture-ready' lambda
+/// identified above in 'a' can also capture the variable (this is done
+/// via tryCaptureVariable for variables and CheckCXXThisCapture for
+/// 'this' by passing in the index of the Lambda identified in step 'a')
+///
+/// \param FunctionScopes - Sema's stack of nested FunctionScopeInfo's (which a
+/// LambdaScopeInfo inherits from). The current/deepest/innermost lambda
+/// is at the top of the stack.
+///
+/// \param VarToCapture - the variable to capture. If NULL, capture 'this'.
+///
+///
+/// \returns An Optional<unsigned> Index that if evaluates to 'true' contains
+/// the index (into Sema's FunctionScopeInfo stack) of the innermost lambda
+/// which is capture-capable. If the return value evaluates to 'false' then
+/// no lambda is capture-capable for \p VarToCapture.
+
+Optional<unsigned> clang::getStackIndexOfNearestEnclosingCaptureCapableLambda(
+ ArrayRef<const sema::FunctionScopeInfo *> FunctionScopes,
+ VarDecl *VarToCapture, Sema &S) {
+
+ const Optional<unsigned> NoLambdaIsCaptureCapable;
+
+ const Optional<unsigned> OptionalStackIndex =
+ getStackIndexOfNearestEnclosingCaptureReadyLambda(FunctionScopes,
+ VarToCapture);
+ if (!OptionalStackIndex)
+ return NoLambdaIsCaptureCapable;
+
+ const unsigned IndexOfCaptureReadyLambda = OptionalStackIndex.getValue();
+ assert(((IndexOfCaptureReadyLambda != (FunctionScopes.size() - 1)) ||
+ S.getCurGenericLambda()) &&
+ "The capture ready lambda for a potential capture can only be the "
+ "current lambda if it is a generic lambda");
+
+ const sema::LambdaScopeInfo *const CaptureReadyLambdaLSI =
+ cast<sema::LambdaScopeInfo>(FunctionScopes[IndexOfCaptureReadyLambda]);
+
+ // If VarToCapture is null, we are attempting to capture 'this'
+ const bool IsCapturingThis = !VarToCapture;
const bool IsCapturingVariable = !IsCapturingThis;
if (IsCapturingVariable) {
- // Now check to see if this lambda can truly capture, and also
- // if all enclosing lambdas of this lambda allow this capture.
+ // Check if the capture-ready lambda can truly capture the variable, by
+ // checking whether all enclosing lambdas of the capture-ready lambda allow
+ // the capture - i.e. make sure it is capture-capable.
QualType CaptureType, DeclRefType;
- const bool CanCaptureVariable = !S.tryCaptureVariable(VD,
- /*ExprVarIsUsedInLoc*/SourceLocation(), clang::Sema::TryCapture_Implicit,
- /*EllipsisLoc*/ SourceLocation(),
- /*BuildAndDiagnose*/false, CaptureType, DeclRefType,
- &IndexOfCaptureReadyLambdaU);
- if (!CanCaptureVariable) return 0;
- } else {
- const bool CanCaptureThis = !S.CheckCXXThisCapture(
- CaptureReadyLambdaLSI->PotentialThisCaptureLocation, false, false,
- &IndexOfCaptureReadyLambdaU);
- if (!CanCaptureThis) return 0;
- } // end 'this' capture test
- FunctionScopeIndex = IndexOfCaptureReadyLambdaU;
- return CaptureReadyLambdaLSI->CallOperator;
+ const bool CanCaptureVariable =
+ !S.tryCaptureVariable(VarToCapture,
+ /*ExprVarIsUsedInLoc*/ SourceLocation(),
+ clang::Sema::TryCapture_Implicit,
+ /*EllipsisLoc*/ SourceLocation(),
+ /*BuildAndDiagnose*/ false, CaptureType,
+ DeclRefType, &IndexOfCaptureReadyLambda);
+ if (!CanCaptureVariable)
+ return NoLambdaIsCaptureCapable;
+ } else {
+ // Check if the capture-ready lambda can truly capture 'this' by checking
+ // whether all enclosing lambdas of the capture-ready lambda can capture
+ // 'this'.
+ const bool CanCaptureThis =
+ !S.CheckCXXThisCapture(
+ CaptureReadyLambdaLSI->PotentialThisCaptureLocation,
+ /*Explicit*/ false, /*BuildAndDiagnose*/ false,
+ &IndexOfCaptureReadyLambda);
+ if (!CanCaptureThis)
+ return NoLambdaIsCaptureCapable;
+ }
+ return IndexOfCaptureReadyLambda;
}
static inline TemplateParameterList *
@@ -142,17 +231,14 @@ getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) {
SourceLocation LAngleLoc = IntroRange.getBegin();
SourceLocation RAngleLoc = IntroRange.getEnd();
LSI->GLTemplateParameterList = TemplateParameterList::Create(
- SemaRef.Context,
- /*Template kw loc*/SourceLocation(),
- LAngleLoc,
- (NamedDecl**)LSI->AutoTemplateParams.data(),
- LSI->AutoTemplateParams.size(), RAngleLoc);
+ SemaRef.Context,
+ /*Template kw loc*/ SourceLocation(), LAngleLoc,
+ (NamedDecl **)LSI->AutoTemplateParams.data(),
+ LSI->AutoTemplateParams.size(), RAngleLoc);
}
return LSI->GLTemplateParameterList;
}
-
-
CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange,
TypeSourceInfo *Info,
bool KnownDependent,
@@ -169,7 +255,7 @@ CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange,
IsGenericLambda,
CaptureDefault);
DC->addDecl(Class);
-
+
return Class;
}
@@ -230,18 +316,18 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC,
if ((IsInNonspecializedTemplate &&
!(ManglingContextDecl && isa<ParmVarDecl>(ManglingContextDecl))) ||
isInInlineFunction(CurContext)) {
- ManglingContextDecl = 0;
+ ManglingContextDecl = nullptr;
return &Context.getManglingNumberContext(DC);
}
- ManglingContextDecl = 0;
- return 0;
+ ManglingContextDecl = nullptr;
+ return nullptr;
case StaticDataMember:
// -- the initializers of nonspecialized static members of template classes
if (!IsInNonspecializedTemplate) {
- ManglingContextDecl = 0;
- return 0;
+ ManglingContextDecl = nullptr;
+ return nullptr;
}
// Fall through to get the current context.
@@ -277,10 +363,10 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
// dependent type.
if (Class->isDependentContext() || TemplateParams) {
const FunctionProtoType *FPT = MethodType->castAs<FunctionProtoType>();
- QualType Result = FPT->getResultType();
+ QualType Result = FPT->getReturnType();
if (Result->isUndeducedType()) {
Result = SubstAutoType(Result, Context.DependentTy);
- MethodType = Context.getFunctionType(Result, FPT->getArgTypes(),
+ MethodType = Context.getFunctionType(Result, FPT->getParamTypes(),
FPT->getExtProtoInfo());
}
}
@@ -317,7 +403,7 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
FunctionTemplateDecl::Create(Context, Class,
Method->getLocation(), MethodName,
TemplateParams,
- Method) : 0;
+ Method) : nullptr;
if (TemplateMethod) {
TemplateMethod->setLexicalDeclContext(CurContext);
TemplateMethod->setAccess(AS_public);
@@ -331,10 +417,8 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
const_cast<ParmVarDecl **>(Params.end()),
/*CheckParameterNames=*/false);
- for (CXXMethodDecl::param_iterator P = Method->param_begin(),
- PEnd = Method->param_end();
- P != PEnd; ++P)
- (*P)->setOwningFunction(Method);
+ for (auto P : Method->params())
+ P->setOwningFunction(Method);
}
Decl *ManglingContextDecl;
@@ -369,8 +453,8 @@ void Sema::buildLambdaScope(LambdaScopeInfo *LSI,
LSI->Mutable = Mutable;
if (ExplicitResultType) {
- LSI->ReturnType = CallOperator->getResultType();
-
+ LSI->ReturnType = CallOperator->getReturnType();
+
if (!LSI->ReturnType->isDependentType() &&
!LSI->ReturnType->isVoidType()) {
if (RequireCompleteType(CallOperator->getLocStart(), LSI->ReturnType,
@@ -420,7 +504,7 @@ static EnumDecl *findEnumForBlockReturn(Expr *E) {
= dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
return cast<EnumDecl>(D->getDeclContext());
}
- return 0;
+ return nullptr;
}
// - it is a comma expression whose RHS is an enumerator-like
@@ -428,7 +512,7 @@ static EnumDecl *findEnumForBlockReturn(Expr *E) {
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
if (BO->getOpcode() == BO_Comma)
return findEnumForBlockReturn(BO->getRHS());
- return 0;
+ return nullptr;
}
// - it is a statement-expression whose value expression is an
@@ -436,7 +520,7 @@ static EnumDecl *findEnumForBlockReturn(Expr *E) {
if (StmtExpr *SE = dyn_cast<StmtExpr>(E)) {
if (Expr *last = dyn_cast_or_null<Expr>(SE->getSubStmt()->body_back()))
return findEnumForBlockReturn(last);
- return 0;
+ return nullptr;
}
// - it is a ternary conditional operator (not the GNU ?:
@@ -446,7 +530,7 @@ static EnumDecl *findEnumForBlockReturn(Expr *E) {
if (EnumDecl *ED = findEnumForBlockReturn(CO->getTrueExpr()))
if (ED == findEnumForBlockReturn(CO->getFalseExpr()))
return ED;
- return 0;
+ return nullptr;
}
// (implicitly:)
@@ -467,7 +551,7 @@ static EnumDecl *findEnumForBlockReturn(Expr *E) {
}
// Otherwise, nope.
- return 0;
+ return nullptr;
}
/// Attempt to find a type T for which the returned expression of the
@@ -475,7 +559,7 @@ static EnumDecl *findEnumForBlockReturn(Expr *E) {
static EnumDecl *findEnumForBlockReturn(ReturnStmt *ret) {
if (Expr *retValue = ret->getRetValue())
return findEnumForBlockReturn(retValue);
- return 0;
+ return nullptr;
}
/// Attempt to find a common type T for which all of the returned
@@ -486,16 +570,16 @@ static EnumDecl *findCommonEnumForBlockReturns(ArrayRef<ReturnStmt*> returns) {
// Try to find one for the first return.
EnumDecl *ED = findEnumForBlockReturn(*i);
- if (!ED) return 0;
+ if (!ED) return nullptr;
// Check that the rest of the returns have the same enum.
for (++i; i != e; ++i) {
if (findEnumForBlockReturn(*i) != ED)
- return 0;
+ return nullptr;
}
// Never infer an anonymous enum type.
- if (!ED->hasNameForLinkage()) return 0;
+ if (!ED->hasNameForLinkage()) return nullptr;
return ED;
}
@@ -519,7 +603,7 @@ static void adjustBlockReturnsToEnum(Sema &S, ArrayRef<ReturnStmt*> returns,
Expr *E = (cleanups ? cleanups->getSubExpr() : retValue);
E = ImplicitCastExpr::Create(S.Context, returnType, CK_IntegralCast,
- E, /*base path*/ 0, VK_RValue);
+ E, /*base path*/ nullptr, VK_RValue);
if (cleanups) {
cleanups->setSubExpr(E);
} else {
@@ -651,6 +735,9 @@ QualType Sema::performLambdaInitCaptureInitialization(SourceLocation Loc,
return QualType();
} else {
DeduceInit = CXXDirectInit->getExpr(0);
+ if (isa<InitListExpr>(DeduceInit))
+ Diag(CXXDirectInit->getLocStart(), diag::err_init_capture_paren_braces)
+ << DeclarationName(Id) << Loc;
}
}
@@ -695,7 +782,7 @@ QualType Sema::performLambdaInitCaptureInitialization(SourceLocation Loc,
if (Result.isInvalid())
return QualType();
- Init = Result.takeAs<Expr>();
+ Init = Result.getAs<Expr>();
// The init-capture initialization is a full-expression that must be
// processed as one before we enter the declcontext of the lambda's
@@ -706,7 +793,7 @@ QualType Sema::performLambdaInitCaptureInitialization(SourceLocation Loc,
if (Result.isInvalid())
return QualType();
- Init = Result.takeAs<Expr>();
+ Init = Result.getAs<Expr>();
return DeducedType;
}
@@ -732,7 +819,8 @@ VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc,
FieldDecl *Sema::buildInitCaptureField(LambdaScopeInfo *LSI, VarDecl *Var) {
FieldDecl *Field = FieldDecl::Create(
Context, LSI->Lambda, Var->getLocation(), Var->getLocation(),
- 0, Var->getType(), Var->getTypeSourceInfo(), 0, false, ICIS_NoInit);
+ nullptr, Var->getType(), Var->getTypeSourceInfo(), nullptr, false,
+ ICIS_NoInit);
Field->setImplicit(true);
Field->setAccess(AS_private);
LSI->Lambda->addDecl(Field);
@@ -758,7 +846,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
// has template params, only then are we in a dependent scope.
if (TemplateParams) {
TmplScope = TmplScope->getParent();
- TmplScope = TmplScope ? TmplScope->getTemplateParamParent() : 0;
+ TmplScope = TmplScope ? TmplScope->getTemplateParamParent() : nullptr;
}
if (TmplScope && !TmplScope->decl_empty())
KnownDependent = true;
@@ -811,14 +899,10 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
ExplicitResultType = FTI.hasTrailingReturnType();
- if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
- cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType()) {
- // Empty arg list, don't push any params.
- checkVoidParamDecl(cast<ParmVarDecl>(FTI.ArgInfo[0].Param));
- } else {
- Params.reserve(FTI.NumArgs);
- for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i)
- Params.push_back(cast<ParmVarDecl>(FTI.ArgInfo[i].Param));
+ if (FTIHasNonVoidParameters(FTI)) {
+ Params.reserve(FTI.NumParams);
+ for (unsigned i = 0, e = FTI.NumParams; i != e; ++i)
+ Params.push_back(cast<ParmVarDecl>(FTI.Params[i].Param));
}
// Check for unexpanded parameter packs in the method type.
@@ -848,27 +932,40 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
ExplicitResultType,
!Method->isConst());
+ // C++11 [expr.prim.lambda]p9:
+ // A lambda-expression whose smallest enclosing scope is a block scope is a
+ // local lambda expression; any other lambda expression shall not have a
+ // capture-default or simple-capture in its lambda-introducer.
+ //
+ // For simple-captures, this is covered by the check below that any named
+ // entity is a variable that can be captured.
+ //
+ // For DR1632, we also allow a capture-default in any context where we can
+ // odr-use 'this' (in particular, in a default initializer for a non-static
+ // data member).
+ if (Intro.Default != LCD_None && !Class->getParent()->isFunctionOrMethod() &&
+ (getCurrentThisType().isNull() ||
+ CheckCXXThisCapture(SourceLocation(), /*Explicit*/true,
+ /*BuildAndDiagnose*/false)))
+ Diag(Intro.DefaultLoc, diag::err_capture_default_non_local);
+
// Distinct capture names, for diagnostics.
llvm::SmallSet<IdentifierInfo*, 8> CaptureNames;
// Handle explicit captures.
SourceLocation PrevCaptureLoc
= Intro.Default == LCD_None? Intro.Range.getBegin() : Intro.DefaultLoc;
- for (SmallVectorImpl<LambdaCapture>::const_iterator
- C = Intro.Captures.begin(),
- E = Intro.Captures.end();
- C != E;
+ for (auto C = Intro.Captures.begin(), E = Intro.Captures.end(); C != E;
PrevCaptureLoc = C->Loc, ++C) {
if (C->Kind == LCK_This) {
// C++11 [expr.prim.lambda]p8:
// An identifier or this shall not appear more than once in a
// lambda-capture.
if (LSI->isCXXThisCaptured()) {
- Diag(C->Loc, diag::err_capture_more_than_once)
- << "'this'"
- << SourceRange(LSI->getCXXThisCapture().getLocation())
- << FixItHint::CreateRemoval(
- SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
+ Diag(C->Loc, diag::err_capture_more_than_once)
+ << "'this'" << SourceRange(LSI->getCXXThisCapture().getLocation())
+ << FixItHint::CreateRemoval(
+ SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc));
continue;
}
@@ -877,8 +974,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
// lambda-capture shall not contain this [...].
if (Intro.Default == LCD_ByCopy) {
Diag(C->Loc, diag::err_this_capture_with_copy_default)
- << FixItHint::CreateRemoval(
- SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
+ << FixItHint::CreateRemoval(
+ SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc));
continue;
}
@@ -900,7 +997,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
if (C->Init.isInvalid())
continue;
- VarDecl *Var = 0;
+ VarDecl *Var = nullptr;
if (C->Init.isUsable()) {
Diag(C->Loc, getLangOpts().CPlusPlus1y
? diag::warn_cxx11_compat_init_capture
@@ -916,7 +1013,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
if (C->InitCaptureType.get().isNull())
continue;
Var = createLambdaInitCaptureVarDecl(C->Loc, C->InitCaptureType.get(),
- C->Id, C->Init.take());
+ C->Id, C->Init.get());
// C++1y [expr.prim.lambda]p11:
// An init-capture behaves as if it declares and explicitly
// captures a variable [...] whose declarative region is the
@@ -931,13 +1028,13 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
// each identifier it contains shall be preceded by &.
if (C->Kind == LCK_ByRef && Intro.Default == LCD_ByRef) {
Diag(C->Loc, diag::err_reference_capture_with_reference_default)
- << FixItHint::CreateRemoval(
- SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
+ << FixItHint::CreateRemoval(
+ SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc));
continue;
} else if (C->Kind == LCK_ByCopy && Intro.Default == LCD_ByCopy) {
Diag(C->Loc, diag::err_copy_capture_with_copy_default)
- << FixItHint::CreateRemoval(
- SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
+ << FixItHint::CreateRemoval(
+ SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc));
continue;
}
@@ -958,6 +1055,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
}
Var = R.getAsSingle<VarDecl>();
+ if (Var && DiagnoseUseOfDecl(Var, C->Loc))
+ continue;
}
// C++11 [expr.prim.lambda]p8:
@@ -966,9 +1065,9 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
if (!CaptureNames.insert(C->Id)) {
if (Var && LSI->isCaptured(Var)) {
Diag(C->Loc, diag::err_capture_more_than_once)
- << C->Id << SourceRange(LSI->getCapture(Var).getLocation())
- << FixItHint::CreateRemoval(
- SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
+ << C->Id << SourceRange(LSI->getCapture(Var).getLocation())
+ << FixItHint::CreateRemoval(
+ SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc));
} else
// Previous capture captured something different (one or both was
// an init-cpature): no fixit.
@@ -1033,6 +1132,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope,
bool IsInstantiation) {
+ LambdaScopeInfo *LSI = getCurLambda();
+
// Leave the expression-evaluation context.
DiscardCleanupsInEvaluationContext();
PopExpressionEvaluationContext();
@@ -1042,15 +1143,11 @@ void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope,
PopDeclContext();
// Finalize the lambda.
- LambdaScopeInfo *LSI = getCurLambda();
CXXRecordDecl *Class = LSI->Lambda;
Class->setInvalidDecl();
- SmallVector<Decl*, 4> Fields;
- for (RecordDecl::field_iterator i = Class->field_begin(),
- e = Class->field_end(); i != e; ++i)
- Fields.push_back(*i);
- ActOnFields(0, Class->getLocation(), Class, Fields,
- SourceLocation(), SourceLocation(), 0);
+ SmallVector<Decl*, 4> Fields(Class->fields());
+ ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(),
+ SourceLocation(), nullptr);
CheckCompletedCXXClass(Class);
PopFunctionScopeInfo();
@@ -1077,8 +1174,9 @@ static void addFunctionPointerConversion(Sema &S,
InvokerExtInfo.TypeQuals = 0;
assert(InvokerExtInfo.RefQualifier == RQ_None &&
"Lambda's call operator should not have a reference qualifier");
- InvokerFunctionTy = S.Context.getFunctionType(CallOpProto->getResultType(),
- CallOpProto->getArgTypes(), InvokerExtInfo);
+ InvokerFunctionTy =
+ S.Context.getFunctionType(CallOpProto->getReturnType(),
+ CallOpProto->getParamTypes(), InvokerExtInfo);
PtrToFunctionTy = S.Context.getPointerType(InvokerFunctionTy);
}
@@ -1122,7 +1220,7 @@ static void addFunctionPointerConversion(Sema &S,
ConvTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>();
// Get the result of the conversion function which is a pointer-to-function.
PointerTypeLoc PtrToFunctionTL =
- ConvTL.getResultLoc().getAs<PointerTypeLoc>();
+ ConvTL.getReturnLoc().getAs<PointerTypeLoc>();
// Do the same for the TypeSourceInfo that is used to name the conversion
// operator.
PointerTypeLoc ConvNamePtrToFunctionTL =
@@ -1156,9 +1254,9 @@ static void addFunctionPointerConversion(Sema &S,
From->getType(),
From->getTypeSourceInfo(),
From->getStorageClass(),
- /*DefaultArg=*/0));
- CallOpConvTL.setArg(I, From);
- CallOpConvNameTL.setArg(I, From);
+ /*DefaultArg=*/nullptr));
+ CallOpConvTL.setParam(I, From);
+ CallOpConvNameTL.setParam(I, From);
}
CXXConversionDecl *Conversion
@@ -1244,7 +1342,7 @@ static void addBlockPointerConversion(Sema &S,
FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo();
ExtInfo.TypeQuals = 0;
QualType FunctionTy = S.Context.getFunctionType(
- Proto->getResultType(), Proto->getArgTypes(), ExtInfo);
+ Proto->getReturnType(), Proto->getParamTypes(), ExtInfo);
BlockPtrTy = S.Context.getBlockPointerType(FunctionTy);
}
@@ -1276,7 +1374,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
Scope *CurScope,
bool IsInstantiation) {
// Collect information from the lambda scope.
- SmallVector<LambdaExpr::Capture, 4> Captures;
+ SmallVector<LambdaCapture, 4> Captures;
SmallVector<Expr *, 4> CaptureInits;
LambdaCaptureDefault CaptureDefault;
SourceLocation CaptureDefaultLoc;
@@ -1309,9 +1407,8 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
// Handle 'this' capture.
if (From.isThisCapture()) {
- Captures.push_back(LambdaExpr::Capture(From.getLocation(),
- IsImplicit,
- LCK_This));
+ Captures.push_back(
+ LambdaCapture(From.getLocation(), IsImplicit, LCK_This));
CaptureInits.push_back(new (Context) CXXThisExpr(From.getLocation(),
getCurrentThisType(),
/*isImplicit=*/true));
@@ -1320,8 +1417,8 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
VarDecl *Var = From.getVariable();
LambdaCaptureKind Kind = From.isCopyCapture()? LCK_ByCopy : LCK_ByRef;
- Captures.push_back(LambdaExpr::Capture(From.getLocation(), IsImplicit,
- Kind, Var, From.getEllipsisLoc()));
+ Captures.push_back(LambdaCapture(From.getLocation(), IsImplicit, Kind,
+ Var, From.getEllipsisLoc()));
CaptureInits.push_back(From.getInitExpr());
}
@@ -1369,7 +1466,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
const FunctionProtoType *Proto
= CallOperator->getType()->getAs<FunctionProtoType>();
QualType FunctionTy = Context.getFunctionType(
- LSI->ReturnType, Proto->getArgTypes(), Proto->getExtProtoInfo());
+ LSI->ReturnType, Proto->getParamTypes(), Proto->getExtProtoInfo());
CallOperator->setType(FunctionTy);
}
// C++ [expr.prim.lambda]p7:
@@ -1407,12 +1504,9 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
addBlockPointerConversion(*this, IntroducerRange, Class, CallOperator);
// Finalize the lambda class.
- SmallVector<Decl*, 4> Fields;
- for (RecordDecl::field_iterator i = Class->field_begin(),
- e = Class->field_end(); i != e; ++i)
- Fields.push_back(*i);
- ActOnFields(0, Class->getLocation(), Class, Fields,
- SourceLocation(), SourceLocation(), 0);
+ SmallVector<Decl*, 4> Fields(Class->fields());
+ ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(),
+ SourceLocation(), nullptr);
CheckCompletedCXXClass(Class);
}
@@ -1478,7 +1572,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
/*NRVO=*/false),
CurrentLocation, Src);
if (!Init.isInvalid())
- Init = ActOnFinishFullExpr(Init.take());
+ Init = ActOnFinishFullExpr(Init.get());
if (Init.isInvalid())
return ExprError();
@@ -1502,7 +1596,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
From->getType(),
From->getTypeSourceInfo(),
From->getStorageClass(),
- /*DefaultArg=*/0));
+ /*DefaultArg=*/nullptr));
}
Block->setParams(BlockParams);
@@ -1514,11 +1608,11 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
TypeSourceInfo *CapVarTSI =
Context.getTrivialTypeSourceInfo(Src->getType());
VarDecl *CapVar = VarDecl::Create(Context, Block, ConvLocation,
- ConvLocation, 0,
+ ConvLocation, nullptr,
Src->getType(), CapVarTSI,
SC_None);
BlockDecl::Capture Capture(/*Variable=*/CapVar, /*ByRef=*/false,
- /*Nested=*/false, /*Copy=*/Init.take());
+ /*Nested=*/false, /*Copy=*/Init.get());
Block->setCaptures(Context, &Capture, &Capture + 1,
/*CapturesCXXThis=*/false);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
index 919c6ad..fe2c816 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
@@ -23,6 +23,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Lex/ModuleLoader.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/Sema/Overload.h"
@@ -113,10 +114,8 @@ namespace {
if (Ctx && Ctx->isFileContext()) {
visit(Ctx, Ctx);
} else if (!Ctx || Ctx->isFunctionOrMethod()) {
- Scope::udir_iterator I = S->using_directives_begin(),
- End = S->using_directives_end();
- for (; I != End; ++I)
- visit(*I, InnermostFileDC);
+ for (auto *I : S->using_directives())
+ visit(I, InnermostFileDC);
}
}
}
@@ -153,9 +152,7 @@ namespace {
void addUsingDirectives(DeclContext *DC, DeclContext *EffectiveDC) {
SmallVector<DeclContext*,4> queue;
while (true) {
- DeclContext::udir_iterator I, End;
- for (llvm::tie(I, End) = DC->getUsingDirectives(); I != End; ++I) {
- UsingDirectiveDecl *UD = *I;
+ for (auto UD : DC->using_directives()) {
DeclContext *NS = UD->getNominatedNamespace();
if (visited.insert(NS)) {
addUsingDirective(UD, EffectiveDC);
@@ -248,10 +245,11 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind,
IDNS = Decl::IDNS_Tag;
}
break;
+
case Sema::LookupLabel:
IDNS = Decl::IDNS_Label;
break;
-
+
case Sema::LookupMemberName:
IDNS = Decl::IDNS_Member;
if (CPlusPlus)
@@ -267,8 +265,10 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind,
break;
case Sema::LookupUsingDeclName:
- IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag
- | Decl::IDNS_Member | Decl::IDNS_Using;
+ assert(Redeclaration && "should only be used for redecl lookup");
+ IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member |
+ Decl::IDNS_Using | Decl::IDNS_TagFriend | Decl::IDNS_OrdinaryFriend |
+ Decl::IDNS_LocalExtern;
break;
case Sema::LookupObjCProtocolName:
@@ -288,36 +288,33 @@ void LookupResult::configure() {
IDNS = getIDNS(LookupKind, SemaRef.getLangOpts().CPlusPlus,
isForRedeclaration());
- if (!isForRedeclaration()) {
- // If we're looking for one of the allocation or deallocation
- // operators, make sure that the implicitly-declared new and delete
- // operators can be found.
- switch (NameInfo.getName().getCXXOverloadedOperator()) {
- case OO_New:
- case OO_Delete:
- case OO_Array_New:
- case OO_Array_Delete:
- SemaRef.DeclareGlobalNewDelete();
- break;
+ // If we're looking for one of the allocation or deallocation
+ // operators, make sure that the implicitly-declared new and delete
+ // operators can be found.
+ switch (NameInfo.getName().getCXXOverloadedOperator()) {
+ case OO_New:
+ case OO_Delete:
+ case OO_Array_New:
+ case OO_Array_Delete:
+ SemaRef.DeclareGlobalNewDelete();
+ break;
- default:
- break;
- }
+ default:
+ break;
+ }
- // Compiler builtins are always visible, regardless of where they end
- // up being declared.
- if (IdentifierInfo *Id = NameInfo.getName().getAsIdentifierInfo()) {
- if (unsigned BuiltinID = Id->getBuiltinID()) {
- if (!SemaRef.Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
- AllowHidden = true;
- }
+ // Compiler builtins are always visible, regardless of where they end
+ // up being declared.
+ if (IdentifierInfo *Id = NameInfo.getName().getAsIdentifierInfo()) {
+ if (unsigned BuiltinID = Id->getBuiltinID()) {
+ if (!SemaRef.Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
+ AllowHidden = true;
}
}
}
-void LookupResult::sanityImpl() const {
- // Note that this function is never called by NDEBUG builds. See
- // LookupResult::sanity().
+bool LookupResult::sanity() const {
+ // This function is never called by NDEBUG builds.
assert(ResultKind != NotFound || Decls.size() == 0);
assert(ResultKind != Found || Decls.size() == 1);
assert(ResultKind != FoundOverloaded || Decls.size() > 1 ||
@@ -327,9 +324,10 @@ void LookupResult::sanityImpl() const {
assert(ResultKind != Ambiguous || Decls.size() > 1 ||
(Decls.size() == 1 && (Ambiguity == AmbiguousBaseSubobjects ||
Ambiguity == AmbiguousBaseSubobjectTypes)));
- assert((Paths != NULL) == (ResultKind == Ambiguous &&
- (Ambiguity == AmbiguousBaseSubobjectTypes ||
- Ambiguity == AmbiguousBaseSubobjects)));
+ assert((Paths != nullptr) == (ResultKind == Ambiguous &&
+ (Ambiguity == AmbiguousBaseSubobjectTypes ||
+ Ambiguity == AmbiguousBaseSubobjects)));
+ return true;
}
// Necessary because CXXBasePaths is not complete in Sema.h
@@ -544,14 +542,6 @@ static bool LookupBuiltin(Sema &S, LookupResult &R) {
R.addDecl(D);
return true;
}
-
- if (R.isForRedeclaration()) {
- // If we're redeclaring this function anyway, forget that
- // this was a builtin at all.
- S.Context.BuiltinInfo.ForgetBuiltin(BuiltinID, S.Context.Idents);
- }
-
- return false;
}
}
}
@@ -734,7 +724,7 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) {
// specialization into the result set. We do this to avoid forcing all
// callers to perform special deduction for conversion functions.
TemplateDeductionInfo Info(R.getNameLoc());
- FunctionDecl *Specialization = 0;
+ FunctionDecl *Specialization = nullptr;
const FunctionProtoType *ConvProto
= ConvTemplate->getTemplatedDecl()->getType()->getAs<FunctionProtoType>();
@@ -753,7 +743,7 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) {
// Perform template argument deduction against the type that we would
// expect the function to have.
- if (R.getSema().DeduceTemplateArguments(ConvTemplate, 0, ExpectedType,
+ if (R.getSema().DeduceTemplateArguments(ConvTemplate, nullptr, ExpectedType,
Specialization, Info)
== Sema::TDK_Success) {
R.addDecl(Specialization);
@@ -777,7 +767,7 @@ CppNamespaceLookup(Sema &S, LookupResult &R, ASTContext &Context,
// Perform direct name lookup into the namespaces nominated by the
// using directives whose common ancestor is this namespace.
UnqualUsingDirectiveSet::const_iterator UI, UEnd;
- llvm::tie(UI, UEnd) = UDirs.getNamespacesFor(NS);
+ std::tie(UI, UEnd) = UDirs.getNamespacesFor(NS);
for (; UI != UEnd; ++UI)
if (LookupDirect(S, R, UI->getNominatedNamespace()))
@@ -803,7 +793,7 @@ static bool isNamespaceOrTranslationUnitScope(Scope *S) {
// it leaves the current template parameter scope.
static std::pair<DeclContext *, bool> findOuterContext(Scope *S) {
DeclContext *DC = S->getEntity();
- DeclContext *Lexical = 0;
+ DeclContext *Lexical = nullptr;
for (Scope *OuterS = S->getParent(); OuterS;
OuterS = OuterS->getParent()) {
if (OuterS->getEntity()) {
@@ -926,7 +916,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
UnqualUsingDirectiveSet UDirs;
bool VisitedUsingDirectives = false;
bool LeftStartingScope = false;
- DeclContext *OutsideOfTemplateParamDC = 0;
+ DeclContext *OutsideOfTemplateParamDC = nullptr;
// When performing a scope lookup, we want to find local extern decls.
FindLocalExternScope FindLocals(R);
@@ -983,13 +973,13 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
// findOuterContext(). This implements the name lookup behavior
// of C++ [temp.local]p8.
Ctx = OutsideOfTemplateParamDC;
- OutsideOfTemplateParamDC = 0;
+ OutsideOfTemplateParamDC = nullptr;
}
if (Ctx) {
DeclContext *OuterCtx;
bool SearchAfterTemplateScope;
- llvm::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S);
+ std::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S);
if (SearchAfterTemplateScope)
OutsideOfTemplateParamDC = OuterCtx;
@@ -1126,13 +1116,13 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
// findOuterContext(). This implements the name lookup behavior
// of C++ [temp.local]p8.
Ctx = OutsideOfTemplateParamDC;
- OutsideOfTemplateParamDC = 0;
+ OutsideOfTemplateParamDC = nullptr;
}
if (Ctx) {
DeclContext *OuterCtx;
bool SearchAfterTemplateScope;
- llvm::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S);
+ std::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S);
if (SearchAfterTemplateScope)
OutsideOfTemplateParamDC = OuterCtx;
@@ -1224,7 +1214,7 @@ llvm::DenseSet<Module*> &Sema::getLookupModules() {
I != N; ++I) {
Module *M = getDefiningModule(ActiveTemplateInstantiations[I].Entity);
if (M && !LookupModulesCache.insert(M).second)
- M = 0;
+ M = nullptr;
ActiveTemplateInstantiationLookupModules.push_back(M);
}
return LookupModulesCache;
@@ -1278,15 +1268,14 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) {
static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
- for (Decl::redecl_iterator RD = D->redecls_begin(), RDEnd = D->redecls_end();
- RD != RDEnd; ++RD) {
- if (NamedDecl *ND = dyn_cast<NamedDecl>(*RD)) {
+ for (auto RD : D->redecls()) {
+ if (auto ND = dyn_cast<NamedDecl>(RD)) {
if (LookupResult::isVisible(SemaRef, ND))
return ND;
}
}
- return 0;
+ return nullptr;
}
NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const {
@@ -1381,10 +1370,10 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
// then we'll need to perform our checks based on the matching
// DeclContexts rather than matching scopes.
if (S && isNamespaceOrTranslationUnitScope(S))
- S = 0;
+ S = nullptr;
// Compute the DeclContext, if we need it.
- DeclContext *DC = 0;
+ DeclContext *DC = nullptr;
if (!S)
DC = (*I)->getDeclContext()->getRedeclContext();
@@ -1462,10 +1451,8 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
DeclContext *StartDC) {
assert(StartDC->isFileContext() && "start context is not a file context");
- DeclContext::udir_iterator I = StartDC->using_directives_begin();
- DeclContext::udir_iterator E = StartDC->using_directives_end();
-
- if (I == E) return false;
+ DeclContext::udir_range UsingDirectives = StartDC->using_directives();
+ if (UsingDirectives.begin() == UsingDirectives.end()) return false;
// We have at least added all these contexts to the queue.
llvm::SmallPtrSet<DeclContext*, 8> Visited;
@@ -1477,8 +1464,8 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
// We have already looked into the initial namespace; seed the queue
// with its using-children.
- for (; I != E; ++I) {
- NamespaceDecl *ND = (*I)->getNominatedNamespace()->getOriginalNamespace();
+ for (auto *I : UsingDirectives) {
+ NamespaceDecl *ND = I->getNominatedNamespace()->getOriginalNamespace();
if (Visited.insert(ND))
Queue.push_back(ND);
}
@@ -1525,8 +1512,8 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
continue;
}
- for (llvm::tie(I,E) = ND->getUsingDirectives(); I != E; ++I) {
- NamespaceDecl *Nom = (*I)->getNominatedNamespace();
+ for (auto I : ND->using_directives()) {
+ NamespaceDecl *Nom = I->getNominatedNamespace();
if (Visited.insert(Nom))
Queue.push_back(Nom);
}
@@ -1667,7 +1654,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
Paths.setOrigin(LookupRec);
// Look for this member in our base classes
- CXXRecordDecl::BaseMatchesCallback *BaseCallback = 0;
+ CXXRecordDecl::BaseMatchesCallback *BaseCallback = nullptr;
switch (R.getLookupKind()) {
case LookupObjCImplicitSelfParam:
case LookupOrdinaryName:
@@ -1736,7 +1723,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
!= Context.getCanonicalType(PathElement.Base->getType())) {
// We found members of the given name in two subobjects of
// different types. If the declaration sets aren't the same, this
- // this lookup is ambiguous.
+ // lookup is ambiguous.
if (HasOnlyStaticMembers(Path->Decls.begin(), Path->Decls.end())) {
CXXBasePaths::paths_iterator FirstPath = Paths.begin();
DeclContext::lookup_iterator FirstD = FirstPath->Decls.begin();
@@ -1780,9 +1767,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
// Lookup in a base class succeeded; return these results.
- DeclContext::lookup_result DR = Paths.front().Decls;
- for (DeclContext::lookup_iterator I = DR.begin(), E = DR.end(); I != E; ++I) {
- NamedDecl *D = *I;
+ for (auto *D : Paths.front().Decls) {
AccessSpecifier AS = CXXRecordDecl::MergeAccess(SubobjectAccess,
D->getAccess());
R.addDecl(D, AS);
@@ -1890,16 +1875,15 @@ void Sema::DiagnoseAmbiguousLookup(LookupResult &Result) {
llvm::SmallPtrSet<NamedDecl*,8> TagDecls;
- LookupResult::iterator DI, DE = Result.end();
- for (DI = Result.begin(); DI != DE; ++DI)
- if (TagDecl *TD = dyn_cast<TagDecl>(*DI)) {
+ for (auto *D : Result)
+ if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
TagDecls.insert(TD);
Diag(TD->getLocation(), diag::note_hidden_tag);
}
- for (DI = Result.begin(); DI != DE; ++DI)
- if (!isa<TagDecl>(*DI))
- Diag((*DI)->getLocation(), diag::note_hiding_object);
+ for (auto *D : Result)
+ if (!isa<TagDecl>(D))
+ Diag(D->getLocation(), diag::note_hiding_object);
// For recovery purposes, go ahead and implement the hiding.
LookupResult::Filter F = Result.makeFilter();
@@ -1914,9 +1898,8 @@ void Sema::DiagnoseAmbiguousLookup(LookupResult &Result) {
case LookupResult::AmbiguousReference: {
Diag(NameLoc, diag::err_ambiguous_reference) << Name << LookupRange;
- LookupResult::iterator DI = Result.begin(), DE = Result.end();
- for (; DI != DE; ++DI)
- Diag((*DI)->getLocation(), diag::note_ambiguous_candidate) << *DI;
+ for (auto *D : Result)
+ Diag(D->getLocation(), diag::note_ambiguous_candidate) << D;
break;
}
}
@@ -2003,10 +1986,8 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
break;
case TemplateArgument::Pack:
- for (TemplateArgument::pack_iterator P = Arg.pack_begin(),
- PEnd = Arg.pack_end();
- P != PEnd; ++P)
- addAssociatedClassesAndNamespaces(Result, *P);
+ for (const auto &P : Arg.pack_elements())
+ addAssociatedClassesAndNamespaces(Result, P);
break;
}
}
@@ -2039,6 +2020,10 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
// Add the class itself. If we've already seen this class, we don't
// need to visit base classes.
+ //
+ // FIXME: That's not correct, we may have added this class only because it
+ // was the enclosing class of another class, and in that case we won't have
+ // added its base classes yet.
if (!Result.Classes.insert(Class))
return;
@@ -2065,12 +2050,8 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
}
// Only recurse into base classes for complete types.
- if (!Class->hasDefinition()) {
- QualType type = Result.S.Context.getTypeDeclType(Class);
- if (Result.S.RequireCompleteType(Result.InstantiationLoc, type,
- /*no diagnostic*/ 0))
- return;
- }
+ if (!Class->hasDefinition())
+ return;
// Add direct and indirect base classes along with their associated
// namespaces.
@@ -2081,10 +2062,8 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
Class = Bases.pop_back_val();
// Visit the base classes.
- for (CXXRecordDecl::base_class_iterator Base = Class->bases_begin(),
- BaseEnd = Class->bases_end();
- Base != BaseEnd; ++Base) {
- const RecordType *BaseType = Base->getType()->getAs<RecordType>();
+ for (const auto &Base : Class->bases()) {
+ const RecordType *BaseType = Base.getType()->getAs<RecordType>();
// In dependent contexts, we do ADL twice, and the first time around,
// the base type might be a dependent TemplateSpecializationType, or a
// TemplateTypeParmType. If that happens, simply ignore it.
@@ -2164,6 +2143,8 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
// classes. Its associated namespaces are the namespaces in
// which its associated classes are defined.
case Type::Record: {
+ Result.S.RequireCompleteType(Result.InstantiationLoc, QualType(T, 0),
+ /*no diagnostic*/ 0);
CXXRecordDecl *Class
= cast<CXXRecordDecl>(cast<RecordType>(T)->getDecl());
addAssociatedClassesAndNamespaces(Result, Class);
@@ -2192,15 +2173,13 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
// types and those associated with the return type.
case Type::FunctionProto: {
const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
- for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
- ArgEnd = Proto->arg_type_end();
- Arg != ArgEnd; ++Arg)
- Queue.push_back(Arg->getTypePtr());
+ for (const auto &Arg : Proto->param_types())
+ Queue.push_back(Arg.getTypePtr());
// fallthrough
}
case Type::FunctionNoProto: {
const FunctionType *FnType = cast<FunctionType>(T);
- T = FnType->getResultType().getTypePtr();
+ T = FnType->getReturnType().getTypePtr();
continue;
}
@@ -2315,14 +2294,9 @@ void Sema::FindAssociatedClassesAndNamespaces(
UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Arg);
if (!ULE) continue;
- for (UnresolvedSetIterator I = ULE->decls_begin(), E = ULE->decls_end();
- I != E; ++I) {
+ for (const auto *D : ULE->decls()) {
// Look through any using declarations to find the underlying function.
- NamedDecl *Fn = (*I)->getUnderlyingDecl();
-
- FunctionDecl *FDecl = dyn_cast<FunctionDecl>(Fn);
- if (!FDecl)
- FDecl = cast<FunctionTemplateDecl>(Fn)->getTemplatedDecl();
+ const FunctionDecl *FDecl = D->getUnderlyingDecl()->getAsFunction();
// Add the classes and namespaces associated with the parameter
// types and return type of this function.
@@ -2331,43 +2305,6 @@ void Sema::FindAssociatedClassesAndNamespaces(
}
}
-/// IsAcceptableNonMemberOperatorCandidate - Determine whether Fn is
-/// an acceptable non-member overloaded operator for a call whose
-/// arguments have types T1 (and, if non-empty, T2). This routine
-/// implements the check in C++ [over.match.oper]p3b2 concerning
-/// enumeration types.
-static bool
-IsAcceptableNonMemberOperatorCandidate(FunctionDecl *Fn,
- QualType T1, QualType T2,
- ASTContext &Context) {
- if (T1->isDependentType() || (!T2.isNull() && T2->isDependentType()))
- return true;
-
- if (T1->isRecordType() || (!T2.isNull() && T2->isRecordType()))
- return true;
-
- const FunctionProtoType *Proto = Fn->getType()->getAs<FunctionProtoType>();
- if (Proto->getNumArgs() < 1)
- return false;
-
- if (T1->isEnumeralType()) {
- QualType ArgType = Proto->getArgType(0).getNonReferenceType();
- if (Context.hasSameUnqualifiedType(T1, ArgType))
- return true;
- }
-
- if (Proto->getNumArgs() < 2)
- return false;
-
- if (!T2.isNull() && T2->isEnumeralType()) {
- QualType ArgType = Proto->getArgType(1).getNonReferenceType();
- if (Context.hasSameUnqualifiedType(T2, ArgType))
- return true;
- }
-
- return false;
-}
-
NamedDecl *Sema::LookupSingleName(Scope *S, DeclarationName Name,
SourceLocation Loc,
LookupNameKind NameKind,
@@ -2394,37 +2331,13 @@ void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
// unqualified lookup of operator@ in the context of the
// expression according to the usual rules for name lookup in
// unqualified function calls (3.4.2) except that all member
- // functions are ignored. However, if no operand has a class
- // type, only those non-member functions in the lookup set
- // that have a first parameter of type T1 or "reference to
- // (possibly cv-qualified) T1", when T1 is an enumeration
- // type, or (if there is a right operand) a second parameter
- // of type T2 or "reference to (possibly cv-qualified) T2",
- // when T2 is an enumeration type, are candidate functions.
+ // functions are ignored.
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
LookupResult Operators(*this, OpName, SourceLocation(), LookupOperatorName);
LookupName(Operators, S);
assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous");
-
- if (Operators.empty())
- return;
-
- for (LookupResult::iterator Op = Operators.begin(), OpEnd = Operators.end();
- Op != OpEnd; ++Op) {
- NamedDecl *Found = (*Op)->getUnderlyingDecl();
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Found)) {
- if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context))
- Functions.addDecl(*Op, Op.getAccess()); // FIXME: canonical FD
- } else if (FunctionTemplateDecl *FunTmpl
- = dyn_cast<FunctionTemplateDecl>(Found)) {
- // FIXME: friend operators?
- // FIXME: do we need to check IsAcceptableNonMemberOperatorCandidate,
- // later?
- if (!FunTmpl->getDeclContext()->isRecord())
- Functions.addDecl(*Op, Op.getAccess());
- }
- }
+ Functions.append(Operators.begin(), Operators.end());
}
Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
@@ -2481,7 +2394,7 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
// if necessary and make sure that implicit functions are declared.
CanQualType CanTy = Context.getCanonicalType(Context.getTagDeclType(RD));
DeclarationName Name;
- Expr *Arg = 0;
+ Expr *Arg = nullptr;
unsigned NumArgs;
QualType ArgType = CanTy;
@@ -2545,7 +2458,7 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
// Now we perform lookup on the name we computed earlier and do overload
// resolution. Lookup is only performed directly into the class since there
// will always be a (possibly implicit) declaration to shadow any others.
- OverloadCandidateSet OCS((SourceLocation()));
+ OverloadCandidateSet OCS(RD->getLocation(), OverloadCandidateSet::CSK_Normal);
DeclContext::lookup_result R = RD->lookup(Name);
assert(!R.empty() &&
"lookup for a constructor or assignment operator was empty");
@@ -2554,11 +2467,7 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
// from an external source and invalidate lookup_result.
SmallVector<NamedDecl *, 8> Candidates(R.begin(), R.end());
- for (SmallVectorImpl<NamedDecl *>::iterator I = Candidates.begin(),
- E = Candidates.end();
- I != E; ++I) {
- NamedDecl *Cand = *I;
-
+ for (auto *Cand : Candidates) {
if (Cand->isInvalidDecl())
continue;
@@ -2585,12 +2494,12 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
dyn_cast<FunctionTemplateDecl>(Cand)) {
if (SM == CXXCopyAssignment || SM == CXXMoveAssignment)
AddMethodTemplateCandidate(Tmpl, DeclAccessPair::make(Tmpl, AS_public),
- RD, 0, ThisTy, Classification,
+ RD, nullptr, ThisTy, Classification,
llvm::makeArrayRef(&Arg, NumArgs),
OCS, true);
else
AddTemplateOverloadCandidate(Tmpl, DeclAccessPair::make(Tmpl, AS_public),
- 0, llvm::makeArrayRef(&Arg, NumArgs),
+ nullptr, llvm::makeArrayRef(&Arg, NumArgs),
OCS, true);
} else {
assert(isa<UsingDecl>(Cand) && "illegal Kind of operator = Decl");
@@ -2610,12 +2519,12 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
break;
case OR_Ambiguous:
- Result->setMethod(0);
+ Result->setMethod(nullptr);
Result->setKind(SpecialMemberOverloadResult::Ambiguous);
break;
case OR_No_Viable_Function:
- Result->setMethod(0);
+ Result->setMethod(nullptr);
Result->setKind(SpecialMemberOverloadResult::NoMemberOrDeleted);
break;
}
@@ -2812,14 +2721,8 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
// operator template, but not both.
if (FoundRaw && FoundTemplate) {
Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) << R.getLookupName();
- for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
- Decl *D = *I;
- if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
- D = USD->getTargetDecl();
- if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
- D = FunTmpl->getTemplatedDecl();
- NoteOverloadCandidate(cast<FunctionDecl>(D));
- }
+ for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
+ NoteOverloadCandidate((*I)->getUnderlyingDecl()->getAsFunction());
return LOLR_Error;
}
@@ -2845,20 +2748,14 @@ void ADLResult::insert(NamedDecl *New) {
// If we haven't yet seen a decl for this key, or the last decl
// was exactly this one, we're done.
- if (Old == 0 || Old == New) {
+ if (Old == nullptr || Old == New) {
Old = New;
return;
}
// Otherwise, decide which is a more recent redeclaration.
- FunctionDecl *OldFD, *NewFD;
- if (isa<FunctionTemplateDecl>(New)) {
- OldFD = cast<FunctionTemplateDecl>(Old)->getTemplatedDecl();
- NewFD = cast<FunctionTemplateDecl>(New)->getTemplatedDecl();
- } else {
- OldFD = cast<FunctionDecl>(Old);
- NewFD = cast<FunctionDecl>(New);
- }
+ FunctionDecl *OldFD = Old->getAsFunction();
+ FunctionDecl *NewFD = New->getAsFunction();
FunctionDecl *Cursor = NewFD;
while (true) {
@@ -2877,9 +2774,8 @@ void ADLResult::insert(NamedDecl *New) {
Old = New;
}
-void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
- SourceLocation Loc, ArrayRef<Expr *> Args,
- ADLResult &Result) {
+void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
+ ArrayRef<Expr *> Args, ADLResult &Result) {
// Find all of the associated namespaces and classes based on the
// arguments we have.
AssociatedNamespaceSet AssociatedNamespaces;
@@ -2888,13 +2784,6 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
AssociatedNamespaces,
AssociatedClasses);
- QualType T1, T2;
- if (Operator) {
- T1 = Args[0]->getType();
- if (Args.size() >= 2)
- T2 = Args[1]->getType();
- }
-
// C++ [basic.lookup.argdep]p3:
// Let X be the lookup set produced by unqualified lookup (3.4.1)
// and let Y be the lookup set produced by argument dependent
@@ -2906,9 +2795,7 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
//
// Here, we compute Y and add its members to the overloaded
// candidate set.
- for (AssociatedNamespaceSet::iterator NS = AssociatedNamespaces.begin(),
- NSEnd = AssociatedNamespaces.end();
- NS != NSEnd; ++NS) {
+ for (auto *NS : AssociatedNamespaces) {
// When considering an associated namespace, the lookup is the
// same as the lookup performed when the associated namespace is
// used as a qualifier (3.4.3.2) except that:
@@ -2920,10 +2807,8 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
// associated classes are visible within their respective
// namespaces even if they are not visible during an ordinary
// lookup (11.4).
- DeclContext::lookup_result R = (*NS)->lookup(Name);
- for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
- ++I) {
- NamedDecl *D = *I;
+ DeclContext::lookup_result R = NS->lookup(Name);
+ for (auto *D : R) {
// 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) {
@@ -2947,12 +2832,7 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
- if (isa<FunctionDecl>(D)) {
- if (Operator &&
- !IsAcceptableNonMemberOperatorCandidate(cast<FunctionDecl>(D),
- T1, T2, Context))
- continue;
- } else if (!isa<FunctionTemplateDecl>(D))
+ if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D))
continue;
Result.insert(D);
@@ -3045,35 +2925,33 @@ NamedDecl *VisibleDeclsRecord::checkHidden(NamedDecl *ND) {
if (Pos == SM->end())
continue;
- for (ShadowMapEntry::iterator I = Pos->second.begin(),
- IEnd = Pos->second.end();
- I != IEnd; ++I) {
+ for (auto *D : Pos->second) {
// A tag declaration does not hide a non-tag declaration.
- if ((*I)->hasTagIdentifierNamespace() &&
+ if (D->hasTagIdentifierNamespace() &&
(IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
Decl::IDNS_ObjCProtocol)))
continue;
// Protocols are in distinct namespaces from everything else.
- if ((((*I)->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
+ if (((D->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
|| (IDNS & Decl::IDNS_ObjCProtocol)) &&
- (*I)->getIdentifierNamespace() != IDNS)
+ D->getIdentifierNamespace() != IDNS)
continue;
// Functions and function templates in the same scope overload
// rather than hide. FIXME: Look for hiding based on function
// signatures!
- if ((*I)->isFunctionOrFunctionTemplate() &&
- ND->isFunctionOrFunctionTemplate() &&
+ if (D->getUnderlyingDecl()->isFunctionOrFunctionTemplate() &&
+ ND->getUnderlyingDecl()->isFunctionOrFunctionTemplate() &&
SM == ShadowMaps.rbegin())
continue;
// We've found a declaration that hides this one.
- return *I;
+ return D;
}
}
- return 0;
+ return nullptr;
}
static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
@@ -3092,13 +2970,9 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
Result.getSema().ForceDeclarationOfImplicitMembers(Class);
// Enumerate all of the results in this context.
- for (DeclContext::all_lookups_iterator L = Ctx->lookups_begin(),
- LEnd = Ctx->lookups_end();
- L != LEnd; ++L) {
- DeclContext::lookup_result R = *L;
- for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
- ++I) {
- if (NamedDecl *ND = dyn_cast<NamedDecl>(*I)) {
+ for (const auto &R : Ctx->lookups()) {
+ for (auto *I : R) {
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(I)) {
if ((ND = Result.getAcceptableDecl(ND))) {
Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
Visited.add(ND);
@@ -3110,9 +2984,8 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
// Traverse using directives for qualified name lookup.
if (QualifiedNameLookup) {
ShadowContextRAII Shadow(Visited);
- DeclContext::udir_iterator I, E;
- for (llvm::tie(I, E) = Ctx->getUsingDirectives(); I != E; ++I) {
- LookupVisibleDecls((*I)->getNominatedNamespace(), Result,
+ for (auto I : Ctx->using_directives()) {
+ LookupVisibleDecls(I->getNominatedNamespace(), Result,
QualifiedNameLookup, InBaseClass, Consumer, Visited);
}
}
@@ -3122,10 +2995,8 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
if (!Record->hasDefinition())
return;
- for (CXXRecordDecl::base_class_iterator B = Record->bases_begin(),
- BEnd = Record->bases_end();
- B != BEnd; ++B) {
- QualType BaseType = B->getType();
+ for (const auto &B : Record->bases()) {
+ QualType BaseType = B.getType();
// Don't look into dependent bases, because name lookup can't look
// there anyway.
@@ -3165,21 +3036,16 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
// Traverse the contexts of Objective-C classes.
if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Ctx)) {
// Traverse categories.
- for (ObjCInterfaceDecl::visible_categories_iterator
- Cat = IFace->visible_categories_begin(),
- CatEnd = IFace->visible_categories_end();
- Cat != CatEnd; ++Cat) {
+ for (auto *Cat : IFace->visible_categories()) {
ShadowContextRAII Shadow(Visited);
- LookupVisibleDecls(*Cat, Result, QualifiedNameLookup, false,
+ LookupVisibleDecls(Cat, Result, QualifiedNameLookup, false,
Consumer, Visited);
}
// Traverse protocols.
- for (ObjCInterfaceDecl::all_protocol_iterator
- I = IFace->all_referenced_protocol_begin(),
- E = IFace->all_referenced_protocol_end(); I != E; ++I) {
+ for (auto *I : IFace->all_referenced_protocols()) {
ShadowContextRAII Shadow(Visited);
- LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer,
+ LookupVisibleDecls(I, Result, QualifiedNameLookup, false, Consumer,
Visited);
}
@@ -3198,17 +3064,15 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
QualifiedNameLookup, InBaseClass, Consumer, Visited);
}
} else if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Ctx)) {
- for (ObjCProtocolDecl::protocol_iterator I = Protocol->protocol_begin(),
- E = Protocol->protocol_end(); I != E; ++I) {
+ for (auto *I : Protocol->protocols()) {
ShadowContextRAII Shadow(Visited);
- LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer,
+ LookupVisibleDecls(I, Result, QualifiedNameLookup, false, Consumer,
Visited);
}
} else if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Ctx)) {
- for (ObjCCategoryDecl::protocol_iterator I = Category->protocol_begin(),
- E = Category->protocol_end(); I != E; ++I) {
+ for (auto *I : Category->protocols()) {
ShadowContextRAII Shadow(Visited);
- LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer,
+ LookupVisibleDecls(I, Result, QualifiedNameLookup, false, Consumer,
Visited);
}
@@ -3234,18 +3098,17 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
(S->getEntity())->isFunctionOrMethod()) {
FindLocalExternScope FindLocals(Result);
// Walk through the declarations in this Scope.
- for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
- D != DEnd; ++D) {
- if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
+ for (auto *D : S->decls()) {
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
if ((ND = Result.getAcceptableDecl(ND))) {
- Consumer.FoundDecl(ND, Visited.checkHidden(ND), 0, false);
+ Consumer.FoundDecl(ND, Visited.checkHidden(ND), nullptr, false);
Visited.add(ND);
}
}
}
// FIXME: C++ [temp.local]p8
- DeclContext *Entity = 0;
+ DeclContext *Entity = nullptr;
if (S->getEntity()) {
// Look into this scope's declaration context, along with any of its
// parent lookup contexts (e.g., enclosing classes), up to the point
@@ -3297,7 +3160,7 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
// Lookup visible declarations in any namespaces found by using
// directives.
UnqualUsingDirectiveSet::const_iterator UI, UEnd;
- llvm::tie(UI, UEnd) = UDirs.getNamespacesFor(Entity);
+ std::tie(UI, UEnd) = UDirs.getNamespacesFor(Entity);
for (; UI != UEnd; ++UI)
LookupVisibleDecls(const_cast<DeclContext *>(UI->getNominatedNamespace()),
Result, /*QualifiedNameLookup=*/false,
@@ -3355,7 +3218,7 @@ void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
SourceLocation GnuLabelLoc) {
// Do a lookup to see if we have a label with this name already.
- NamedDecl *Res = 0;
+ NamedDecl *Res = nullptr;
if (GnuLabelLoc.isValid()) {
// Local label definitions always shadow existing labels.
@@ -3370,8 +3233,8 @@ LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
// If we found a label, check to see if it is in the same context as us.
// When in a Block, we don't want to reuse a label in an enclosing function.
if (Res && Res->getDeclContext() != CurContext)
- Res = 0;
- if (Res == 0) {
+ Res = nullptr;
+ if (!Res) {
// If not forward referenced or defined already, create the backing decl.
Res = LabelDecl::Create(Context, CurContext, Loc, II);
Scope *S = CurScope->getFnParent();
@@ -3385,54 +3248,106 @@ LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
// Typo correction
//===----------------------------------------------------------------------===//
-namespace {
+static bool isCandidateViable(CorrectionCandidateCallback &CCC,
+ TypoCorrection &Candidate) {
+ Candidate.setCallbackDistance(CCC.RankCandidate(Candidate));
+ return Candidate.getEditDistance(false) != TypoCorrection::InvalidDistance;
+}
-typedef SmallVector<TypoCorrection, 1> TypoResultList;
-typedef llvm::StringMap<TypoResultList, llvm::BumpPtrAllocator> TypoResultsMap;
-typedef std::map<unsigned, TypoResultsMap> TypoEditDistanceMap;
+static void LookupPotentialTypoResult(Sema &SemaRef,
+ LookupResult &Res,
+ IdentifierInfo *Name,
+ Scope *S, CXXScopeSpec *SS,
+ DeclContext *MemberContext,
+ bool EnteringContext,
+ bool isObjCIvarLookup,
+ bool FindHidden);
-static const unsigned MaxTypoDistanceResultSets = 5;
+// Fill the supplied vector with the IdentifierInfo pointers for each piece of
+// the given NestedNameSpecifier (i.e. given a NestedNameSpecifier "foo::bar::",
+// fill the vector with the IdentifierInfo pointers for "foo" and "bar").
+static void getNestedNameSpecifierIdentifiers(
+ NestedNameSpecifier *NNS,
+ SmallVectorImpl<const IdentifierInfo*> &Identifiers) {
+ if (NestedNameSpecifier *Prefix = NNS->getPrefix())
+ getNestedNameSpecifierIdentifiers(Prefix, Identifiers);
+ else
+ Identifiers.clear();
-class TypoCorrectionConsumer : public VisibleDeclConsumer {
- /// \brief The name written that is a typo in the source.
- StringRef Typo;
+ const IdentifierInfo *II = nullptr;
- /// \brief The results found that have the smallest edit distance
- /// found (so far) with the typo name.
- ///
- /// The pointer value being set to the current DeclContext indicates
- /// whether there is a keyword with this name.
- TypoEditDistanceMap CorrectionResults;
+ switch (NNS->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ II = NNS->getAsIdentifier();
+ break;
- Sema &SemaRef;
+ case NestedNameSpecifier::Namespace:
+ if (NNS->getAsNamespace()->isAnonymousNamespace())
+ return;
+ II = NNS->getAsNamespace()->getIdentifier();
+ break;
+
+ case NestedNameSpecifier::NamespaceAlias:
+ II = NNS->getAsNamespaceAlias()->getIdentifier();
+ break;
+
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ case NestedNameSpecifier::TypeSpec:
+ II = QualType(NNS->getAsType(), 0).getBaseTypeIdentifier();
+ break;
+
+ case NestedNameSpecifier::Global:
+ return;
+ }
+
+ if (II)
+ Identifiers.push_back(II);
+}
+
+namespace {
+
+static const unsigned MaxTypoDistanceResultSets = 5;
+
+class TypoCorrectionConsumer : public VisibleDeclConsumer {
+ typedef SmallVector<TypoCorrection, 1> TypoResultList;
+ typedef llvm::StringMap<TypoResultList> TypoResultsMap;
+ typedef std::map<unsigned, TypoResultsMap> TypoEditDistanceMap;
public:
- explicit TypoCorrectionConsumer(Sema &SemaRef, IdentifierInfo *Typo)
- : Typo(Typo->getName()),
- SemaRef(SemaRef) {}
+ explicit TypoCorrectionConsumer(Sema &SemaRef,
+ const DeclarationNameInfo &TypoName,
+ Sema::LookupNameKind LookupKind,
+ Scope *S, CXXScopeSpec *SS,
+ CorrectionCandidateCallback &CCC,
+ DeclContext *MemberContext,
+ bool EnteringContext)
+ : Typo(TypoName.getName().getAsIdentifierInfo()), SemaRef(SemaRef), S(S),
+ SS(SS), CorrectionValidator(CCC), MemberContext(MemberContext),
+ Result(SemaRef, TypoName, LookupKind),
+ Namespaces(SemaRef.Context, SemaRef.CurContext, SS),
+ EnteringContext(EnteringContext), SearchNamespaces(false) {
+ Result.suppressDiagnostics();
+ }
- bool includeHiddenDecls() const { return true; }
+ bool includeHiddenDecls() const override { return true; }
- virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
- bool InBaseClass);
+ // Methods for adding potential corrections to the consumer.
+ void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
+ bool InBaseClass) override;
void FoundName(StringRef Name);
void addKeywordResult(StringRef Keyword);
- void addName(StringRef Name, NamedDecl *ND, NestedNameSpecifier *NNS = NULL,
- bool isKeyword = false);
void addCorrection(TypoCorrection Correction);
- typedef TypoResultsMap::iterator result_iterator;
- typedef TypoEditDistanceMap::iterator distance_iterator;
- distance_iterator begin() { return CorrectionResults.begin(); }
- distance_iterator end() { return CorrectionResults.end(); }
- void erase(distance_iterator I) { CorrectionResults.erase(I); }
- unsigned size() const { return CorrectionResults.size(); }
bool empty() const { return CorrectionResults.empty(); }
+ /// \brief Return the list of TypoCorrections for the given identifier from
+ /// the set of corrections that have the closest edit distance, if any.
TypoResultList &operator[](StringRef Name) {
return CorrectionResults.begin()->second[Name];
}
+ /// \brief Return the edit distance of the corrections that have the
+ /// closest/best edit distance from the original typop.
unsigned getBestEditDistance(bool Normalized) {
if (CorrectionResults.empty())
return (std::numeric_limits<unsigned>::max)();
@@ -3441,10 +3356,101 @@ public:
return Normalized ? TypoCorrection::NormalizeEditDistance(BestED) : BestED;
}
- TypoResultsMap &getBestResults() {
- return CorrectionResults.begin()->second;
- }
+ /// \brief Set-up method to add to the consumer the set of namespaces to use
+ /// in performing corrections to nested name specifiers. This method also
+ /// implicitly adds all of the known classes in the current AST context to the
+ /// to the consumer for correcting nested name specifiers.
+ void
+ addNamespaces(const llvm::MapVector<NamespaceDecl *, bool> &KnownNamespaces);
+
+ /// \brief Return the next typo correction that passes all internal filters
+ /// and is deemed valid by the consumer's CorrectionCandidateCallback,
+ /// starting with the corrections that have the closest edit distance. An
+ /// empty TypoCorrection is returned once no more viable corrections remain
+ /// in the consumer.
+ TypoCorrection getNextCorrection();
+
+private:
+ class NamespaceSpecifierSet {
+ struct SpecifierInfo {
+ DeclContext* DeclCtx;
+ NestedNameSpecifier* NameSpecifier;
+ unsigned EditDistance;
+ };
+
+ typedef SmallVector<DeclContext*, 4> DeclContextList;
+ typedef SmallVector<SpecifierInfo, 16> SpecifierInfoList;
+
+ ASTContext &Context;
+ DeclContextList CurContextChain;
+ std::string CurNameSpecifier;
+ SmallVector<const IdentifierInfo*, 4> CurContextIdentifiers;
+ SmallVector<const IdentifierInfo*, 4> CurNameSpecifierIdentifiers;
+ bool isSorted;
+
+ SpecifierInfoList Specifiers;
+ llvm::SmallSetVector<unsigned, 4> Distances;
+ llvm::DenseMap<unsigned, SpecifierInfoList> DistanceMap;
+
+ /// \brief Helper for building the list of DeclContexts between the current
+ /// context and the top of the translation unit
+ static DeclContextList buildContextChain(DeclContext *Start);
+
+ void sortNamespaces();
+
+ unsigned buildNestedNameSpecifier(DeclContextList &DeclChain,
+ NestedNameSpecifier *&NNS);
+
+ public:
+ NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext,
+ CXXScopeSpec *CurScopeSpec);
+
+ /// \brief Add the DeclContext (a namespace or record) to the set, computing
+ /// the corresponding NestedNameSpecifier and its distance in the process.
+ void addNameSpecifier(DeclContext *Ctx);
+
+ typedef SpecifierInfoList::iterator iterator;
+ iterator begin() {
+ if (!isSorted) sortNamespaces();
+ return Specifiers.begin();
+ }
+ iterator end() { return Specifiers.end(); }
+ };
+
+ void addName(StringRef Name, NamedDecl *ND,
+ NestedNameSpecifier *NNS = nullptr, bool isKeyword = false);
+
+ /// \brief Find any visible decls for the given typo correction candidate.
+ /// If none are found, it to the set of candidates for which qualified lookups
+ /// will be performed to find possible nested name specifier changes.
+ bool resolveCorrection(TypoCorrection &Candidate);
+
+ /// \brief Perform qualified lookups on the queued set of typo correction
+ /// candidates and add the nested name specifier changes to each candidate if
+ /// a lookup succeeds (at which point the candidate will be returned to the
+ /// main pool of potential corrections).
+ void performQualifiedLookups();
+ /// \brief The name written that is a typo in the source.
+ IdentifierInfo *Typo;
+
+ /// \brief The results found that have the smallest edit distance
+ /// found (so far) with the typo name.
+ ///
+ /// The pointer value being set to the current DeclContext indicates
+ /// whether there is a keyword with this name.
+ TypoEditDistanceMap CorrectionResults;
+
+ Sema &SemaRef;
+ Scope *S;
+ CXXScopeSpec *SS;
+ CorrectionCandidateCallback &CorrectionValidator;
+ DeclContext *MemberContext;
+ LookupResult Result;
+ NamespaceSpecifierSet Namespaces;
+ SmallVector<TypoCorrection, 2> QualifiedResults;
+ bool EnteringContext;
+ bool SearchNamespaces;
};
}
@@ -3464,7 +3470,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->getName() != Typo &&
+ if (!LookupResult::isVisible(SemaRef, ND) && Name != Typo &&
!findAcceptableDecl(SemaRef, ND))
return;
@@ -3474,27 +3480,28 @@ void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding,
void TypoCorrectionConsumer::FoundName(StringRef Name) {
// Compute the edit distance between the typo and the name of this
// entity, and add the identifier to the list of results.
- addName(Name, NULL);
+ addName(Name, nullptr);
}
void TypoCorrectionConsumer::addKeywordResult(StringRef Keyword) {
// Compute the edit distance between the typo and this keyword,
// and add the keyword to the list of results.
- addName(Keyword, NULL, NULL, true);
+ addName(Keyword, nullptr, nullptr, true);
}
void TypoCorrectionConsumer::addName(StringRef Name, NamedDecl *ND,
NestedNameSpecifier *NNS, bool isKeyword) {
// Use a simple length-based heuristic to determine the minimum possible
// edit distance. If the minimum isn't good enough, bail out early.
- unsigned MinED = abs((int)Name.size() - (int)Typo.size());
- if (MinED && Typo.size() / MinED < 3)
+ StringRef TypoStr = Typo->getName();
+ unsigned MinED = abs((int)Name.size() - (int)TypoStr.size());
+ if (MinED && TypoStr.size() / MinED < 3)
return;
// Compute an upper bound on the allowable edit distance, so that the
// edit-distance algorithm can short-circuit.
- unsigned UpperBound = (Typo.size() + 2) / 3 + 1;
- unsigned ED = Typo.edit_distance(Name, true, UpperBound);
+ unsigned UpperBound = (TypoStr.size() + 2) / 3 + 1;
+ unsigned ED = TypoStr.edit_distance(Name, true, UpperBound);
if (ED >= UpperBound) return;
TypoCorrection TC(&SemaRef.Context.Idents.get(Name), ND, NNS, ED);
@@ -3503,7 +3510,21 @@ void TypoCorrectionConsumer::addName(StringRef Name, NamedDecl *ND,
}
void TypoCorrectionConsumer::addCorrection(TypoCorrection Correction) {
+ StringRef TypoStr = Typo->getName();
StringRef Name = Correction.getCorrectionAsIdentifierInfo()->getName();
+
+ // For very short typos, ignore potential corrections that have a different
+ // base identifier from the typo or which have a normalized edit distance
+ // longer than the typo itself.
+ if (TypoStr.size() < 3 &&
+ (Name != TypoStr || Correction.getEditDistance(true) > TypoStr.size()))
+ return;
+
+ // If the correction is resolved but is not viable, ignore it.
+ if (Correction.isResolved() &&
+ !isCandidateViable(CorrectionValidator, Correction))
+ return;
+
TypoResultList &CList =
CorrectionResults[Correction.getEditDistance(false)][Name];
@@ -3528,130 +3549,212 @@ void TypoCorrectionConsumer::addCorrection(TypoCorrection Correction) {
CList.push_back(Correction);
while (CorrectionResults.size() > MaxTypoDistanceResultSets)
- erase(llvm::prior(CorrectionResults.end()));
+ CorrectionResults.erase(std::prev(CorrectionResults.end()));
}
-// Fill the supplied vector with the IdentifierInfo pointers for each piece of
-// the given NestedNameSpecifier (i.e. given a NestedNameSpecifier "foo::bar::",
-// fill the vector with the IdentifierInfo pointers for "foo" and "bar").
-static void getNestedNameSpecifierIdentifiers(
- NestedNameSpecifier *NNS,
- SmallVectorImpl<const IdentifierInfo*> &Identifiers) {
- if (NestedNameSpecifier *Prefix = NNS->getPrefix())
- getNestedNameSpecifierIdentifiers(Prefix, Identifiers);
- else
- Identifiers.clear();
+void TypoCorrectionConsumer::addNamespaces(
+ const llvm::MapVector<NamespaceDecl *, bool> &KnownNamespaces) {
+ SearchNamespaces = true;
- const IdentifierInfo *II = NULL;
+ for (auto KNPair : KnownNamespaces)
+ Namespaces.addNameSpecifier(KNPair.first);
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- II = NNS->getAsIdentifier();
- break;
+ bool SSIsTemplate = false;
+ if (NestedNameSpecifier *NNS =
+ (SS && SS->isValid()) ? SS->getScopeRep() : nullptr) {
+ if (const Type *T = NNS->getAsType())
+ SSIsTemplate = T->getTypeClass() == Type::TemplateSpecialization;
+ }
+ for (const auto *TI : SemaRef.getASTContext().types()) {
+ if (CXXRecordDecl *CD = TI->getAsCXXRecordDecl()) {
+ CD = CD->getCanonicalDecl();
+ if (!CD->isDependentType() && !CD->isAnonymousStructOrUnion() &&
+ !CD->isUnion() && CD->getIdentifier() &&
+ (SSIsTemplate || !isa<ClassTemplateSpecializationDecl>(CD)) &&
+ (CD->isBeingDefined() || CD->isCompleteDefinition()))
+ Namespaces.addNameSpecifier(CD);
+ }
+ }
+}
- case NestedNameSpecifier::Namespace:
- if (NNS->getAsNamespace()->isAnonymousNamespace())
- return;
- II = NNS->getAsNamespace()->getIdentifier();
- break;
+TypoCorrection TypoCorrectionConsumer::getNextCorrection() {
+ while (!CorrectionResults.empty()) {
+ auto DI = CorrectionResults.begin();
+ if (DI->second.empty()) {
+ CorrectionResults.erase(DI);
+ continue;
+ }
- case NestedNameSpecifier::NamespaceAlias:
- II = NNS->getAsNamespaceAlias()->getIdentifier();
+ auto RI = DI->second.begin();
+ if (RI->second.empty()) {
+ DI->second.erase(RI);
+ performQualifiedLookups();
+ continue;
+ }
+
+ TypoCorrection TC = RI->second.pop_back_val();
+ if (TC.isResolved() || resolveCorrection(TC))
+ return TC;
+ }
+ return TypoCorrection();
+}
+
+bool TypoCorrectionConsumer::resolveCorrection(TypoCorrection &Candidate) {
+ IdentifierInfo *Name = Candidate.getCorrectionAsIdentifierInfo();
+ DeclContext *TempMemberContext = MemberContext;
+ CXXScopeSpec *TempSS = SS;
+retry_lookup:
+ LookupPotentialTypoResult(SemaRef, Result, Name, S, TempSS, TempMemberContext,
+ EnteringContext,
+ CorrectionValidator.IsObjCIvarLookup,
+ Name == Typo && !Candidate.WillReplaceSpecifier());
+ switch (Result.getResultKind()) {
+ case LookupResult::NotFound:
+ case LookupResult::NotFoundInCurrentInstantiation:
+ case LookupResult::FoundUnresolvedValue:
+ if (TempSS) {
+ // Immediately retry the lookup without the given CXXScopeSpec
+ TempSS = nullptr;
+ Candidate.WillReplaceSpecifier(true);
+ goto retry_lookup;
+ }
+ if (TempMemberContext) {
+ if (SS && !TempSS)
+ TempSS = SS;
+ TempMemberContext = nullptr;
+ goto retry_lookup;
+ }
+ if (SearchNamespaces)
+ QualifiedResults.push_back(Candidate);
break;
- case NestedNameSpecifier::TypeSpecWithTemplate:
- case NestedNameSpecifier::TypeSpec:
- II = QualType(NNS->getAsType(), 0).getBaseTypeIdentifier();
+ case LookupResult::Ambiguous:
+ // We don't deal with ambiguities.
break;
- case NestedNameSpecifier::Global:
- return;
+ case LookupResult::Found:
+ case LookupResult::FoundOverloaded:
+ // Store all of the Decls for overloaded symbols
+ for (auto *TRD : Result)
+ Candidate.addCorrectionDecl(TRD);
+ if (!isCandidateViable(CorrectionValidator, Candidate)) {
+ if (SearchNamespaces)
+ QualifiedResults.push_back(Candidate);
+ break;
+ }
+ return true;
}
-
- if (II)
- Identifiers.push_back(II);
+ return false;
}
-namespace {
-
-class SpecifierInfo {
- public:
- DeclContext* DeclCtx;
- NestedNameSpecifier* NameSpecifier;
- unsigned EditDistance;
+void TypoCorrectionConsumer::performQualifiedLookups() {
+ unsigned TypoLen = Typo->getName().size();
+ for (auto QR : QualifiedResults) {
+ for (auto NSI : Namespaces) {
+ DeclContext *Ctx = NSI.DeclCtx;
+ const Type *NSType = NSI.NameSpecifier->getAsType();
+
+ // If the current NestedNameSpecifier refers to a class and the
+ // current correction candidate is the name of that class, then skip
+ // it as it is unlikely a qualified version of the class' constructor
+ // is an appropriate correction.
+ if (CXXRecordDecl *NSDecl = NSType ? NSType->getAsCXXRecordDecl() : 0) {
+ if (NSDecl->getIdentifier() == QR.getCorrectionAsIdentifierInfo())
+ continue;
+ }
- SpecifierInfo(DeclContext *Ctx, NestedNameSpecifier *NNS, unsigned ED)
- : DeclCtx(Ctx), NameSpecifier(NNS), EditDistance(ED) {}
-};
+ TypoCorrection TC(QR);
+ TC.ClearCorrectionDecls();
+ TC.setCorrectionSpecifier(NSI.NameSpecifier);
+ TC.setQualifierDistance(NSI.EditDistance);
+ TC.setCallbackDistance(0); // Reset the callback distance
+
+ // If the current correction candidate and namespace combination are
+ // too far away from the original typo based on the normalized edit
+ // distance, then skip performing a qualified name lookup.
+ unsigned TmpED = TC.getEditDistance(true);
+ if (QR.getCorrectionAsIdentifierInfo() != Typo && TmpED &&
+ TypoLen / TmpED < 3)
+ continue;
-typedef SmallVector<DeclContext*, 4> DeclContextList;
-typedef SmallVector<SpecifierInfo, 16> SpecifierInfoList;
-
-class NamespaceSpecifierSet {
- ASTContext &Context;
- DeclContextList CurContextChain;
- std::string CurNameSpecifier;
- SmallVector<const IdentifierInfo*, 4> CurContextIdentifiers;
- SmallVector<const IdentifierInfo*, 4> CurNameSpecifierIdentifiers;
- bool isSorted;
-
- SpecifierInfoList Specifiers;
- llvm::SmallSetVector<unsigned, 4> Distances;
- llvm::DenseMap<unsigned, SpecifierInfoList> DistanceMap;
-
- /// \brief Helper for building the list of DeclContexts between the current
- /// context and the top of the translation unit
- static DeclContextList BuildContextChain(DeclContext *Start);
-
- void SortNamespaces();
-
- public:
- NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext,
- CXXScopeSpec *CurScopeSpec)
- : Context(Context), CurContextChain(BuildContextChain(CurContext)),
- isSorted(false) {
- if (NestedNameSpecifier *NNS =
- CurScopeSpec ? CurScopeSpec->getScopeRep() : 0) {
- llvm::raw_string_ostream SpecifierOStream(CurNameSpecifier);
- NNS->print(SpecifierOStream, Context.getPrintingPolicy());
+ Result.clear();
+ Result.setLookupName(QR.getCorrectionAsIdentifierInfo());
+ if (!SemaRef.LookupQualifiedName(Result, Ctx))
+ continue;
- getNestedNameSpecifierIdentifiers(NNS, CurNameSpecifierIdentifiers);
- }
- // Build the list of identifiers that would be used for an absolute
- // (from the global context) NestedNameSpecifier referring to the current
- // context.
- for (DeclContextList::reverse_iterator C = CurContextChain.rbegin(),
- CEnd = CurContextChain.rend();
- C != CEnd; ++C) {
- if (NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(*C))
- CurContextIdentifiers.push_back(ND->getIdentifier());
+ // Any corrections added below will be validated in subsequent
+ // iterations of the main while() loop over the Consumer's contents.
+ switch (Result.getResultKind()) {
+ case LookupResult::Found:
+ case LookupResult::FoundOverloaded: {
+ if (SS && SS->isValid()) {
+ std::string NewQualified = TC.getAsString(SemaRef.getLangOpts());
+ std::string OldQualified;
+ llvm::raw_string_ostream OldOStream(OldQualified);
+ SS->getScopeRep()->print(OldOStream, SemaRef.getPrintingPolicy());
+ OldOStream << Typo->getName();
+ // If correction candidate would be an identical written qualified
+ // identifer, then the existing CXXScopeSpec probably included a
+ // typedef that didn't get accounted for properly.
+ if (OldOStream.str() == NewQualified)
+ break;
+ }
+ for (LookupResult::iterator TRD = Result.begin(), TRDEnd = Result.end();
+ TRD != TRDEnd; ++TRD) {
+ if (SemaRef.CheckMemberAccess(TC.getCorrectionRange().getBegin(),
+ NSType ? NSType->getAsCXXRecordDecl()
+ : nullptr,
+ TRD.getPair()) == Sema::AR_accessible)
+ TC.addCorrectionDecl(*TRD);
+ }
+ if (TC.isResolved())
+ addCorrection(TC);
+ break;
+ }
+ case LookupResult::NotFound:
+ case LookupResult::NotFoundInCurrentInstantiation:
+ case LookupResult::Ambiguous:
+ case LookupResult::FoundUnresolvedValue:
+ break;
+ }
}
-
- // Add the global context as a NestedNameSpecifier
- Distances.insert(1);
- DistanceMap[1].push_back(
- SpecifierInfo(cast<DeclContext>(Context.getTranslationUnitDecl()),
- NestedNameSpecifier::GlobalSpecifier(Context), 1));
}
+ QualifiedResults.clear();
+}
- /// \brief Add the DeclContext (a namespace or record) to the set, computing
- /// the corresponding NestedNameSpecifier and its distance in the process.
- void AddNameSpecifier(DeclContext *Ctx);
+TypoCorrectionConsumer::NamespaceSpecifierSet::NamespaceSpecifierSet(
+ ASTContext &Context, DeclContext *CurContext, CXXScopeSpec *CurScopeSpec)
+ : Context(Context), CurContextChain(buildContextChain(CurContext)),
+ isSorted(false) {
+ if (NestedNameSpecifier *NNS =
+ CurScopeSpec ? CurScopeSpec->getScopeRep() : nullptr) {
+ llvm::raw_string_ostream SpecifierOStream(CurNameSpecifier);
+ NNS->print(SpecifierOStream, Context.getPrintingPolicy());
- typedef SpecifierInfoList::iterator iterator;
- iterator begin() {
- if (!isSorted) SortNamespaces();
- return Specifiers.begin();
+ getNestedNameSpecifierIdentifiers(NNS, CurNameSpecifierIdentifiers);
+ }
+ // Build the list of identifiers that would be used for an absolute
+ // (from the global context) NestedNameSpecifier referring to the current
+ // context.
+ for (DeclContextList::reverse_iterator C = CurContextChain.rbegin(),
+ CEnd = CurContextChain.rend();
+ C != CEnd; ++C) {
+ if (NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(*C))
+ CurContextIdentifiers.push_back(ND->getIdentifier());
}
- iterator end() { return Specifiers.end(); }
-};
+ // Add the global context as a NestedNameSpecifier
+ Distances.insert(1);
+ SpecifierInfo SI = {cast<DeclContext>(Context.getTranslationUnitDecl()),
+ NestedNameSpecifier::GlobalSpecifier(Context), 1};
+ DistanceMap[1].push_back(SI);
}
-DeclContextList NamespaceSpecifierSet::BuildContextChain(DeclContext *Start) {
+auto TypoCorrectionConsumer::NamespaceSpecifierSet::buildContextChain(
+ DeclContext *Start) -> DeclContextList {
assert(Start && "Building a context chain from a null context");
DeclContextList Chain;
- for (DeclContext *DC = Start->getPrimaryContext(); DC != NULL;
+ for (DeclContext *DC = Start->getPrimaryContext(); DC != nullptr;
DC = DC->getLookupParent()) {
NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(DC);
if (!DC->isInlineNamespace() && !DC->isTransparentContext() &&
@@ -3661,7 +3764,7 @@ DeclContextList NamespaceSpecifierSet::BuildContextChain(DeclContext *Start) {
return Chain;
}
-void NamespaceSpecifierSet::SortNamespaces() {
+void TypoCorrectionConsumer::NamespaceSpecifierSet::sortNamespaces() {
SmallVector<unsigned, 4> sortedDistances;
sortedDistances.append(Distances.begin(), Distances.end());
@@ -3669,19 +3772,17 @@ void NamespaceSpecifierSet::SortNamespaces() {
std::sort(sortedDistances.begin(), sortedDistances.end());
Specifiers.clear();
- for (SmallVectorImpl<unsigned>::iterator DI = sortedDistances.begin(),
- DIEnd = sortedDistances.end();
- DI != DIEnd; ++DI) {
- SpecifierInfoList &SpecList = DistanceMap[*DI];
+ for (auto D : sortedDistances) {
+ SpecifierInfoList &SpecList = DistanceMap[D];
Specifiers.append(SpecList.begin(), SpecList.end());
}
isSorted = true;
}
-static unsigned BuildNestedNameSpecifier(ASTContext &Context,
- DeclContextList &DeclChain,
- NestedNameSpecifier *&NNS) {
+unsigned
+TypoCorrectionConsumer::NamespaceSpecifierSet::buildNestedNameSpecifier(
+ DeclContextList &DeclChain, NestedNameSpecifier *&NNS) {
unsigned NumSpecifiers = 0;
for (DeclContextList::reverse_iterator C = DeclChain.rbegin(),
CEnd = DeclChain.rend();
@@ -3698,10 +3799,11 @@ static unsigned BuildNestedNameSpecifier(ASTContext &Context,
return NumSpecifiers;
}
-void NamespaceSpecifierSet::AddNameSpecifier(DeclContext *Ctx) {
- NestedNameSpecifier *NNS = NULL;
+void TypoCorrectionConsumer::NamespaceSpecifierSet::addNameSpecifier(
+ DeclContext *Ctx) {
+ NestedNameSpecifier *NNS = nullptr;
unsigned NumSpecifiers = 0;
- DeclContextList NamespaceDeclChain(BuildContextChain(Ctx));
+ DeclContextList NamespaceDeclChain(buildContextChain(Ctx));
DeclContextList FullNamespaceDeclChain(NamespaceDeclChain);
// Eliminate common elements from the two DeclContext chains.
@@ -3713,14 +3815,14 @@ void NamespaceSpecifierSet::AddNameSpecifier(DeclContext *Ctx) {
}
// Build the NestedNameSpecifier from what is left of the NamespaceDeclChain
- NumSpecifiers = BuildNestedNameSpecifier(Context, NamespaceDeclChain, NNS);
+ NumSpecifiers = buildNestedNameSpecifier(NamespaceDeclChain, NNS);
// Add an explicit leading '::' specifier if needed.
if (NamespaceDeclChain.empty()) {
// Rebuild the NestedNameSpecifier as a globally-qualified specifier.
NNS = NestedNameSpecifier::GlobalSpecifier(Context);
NumSpecifiers =
- BuildNestedNameSpecifier(Context, FullNamespaceDeclChain, NNS);
+ buildNestedNameSpecifier(FullNamespaceDeclChain, NNS);
} else if (NamedDecl *ND =
dyn_cast_or_null<NamedDecl>(NamespaceDeclChain.back())) {
IdentifierInfo *Name = ND->getIdentifier();
@@ -3742,7 +3844,7 @@ void NamespaceSpecifierSet::AddNameSpecifier(DeclContext *Ctx) {
// Rebuild the NestedNameSpecifier as a globally-qualified specifier.
NNS = NestedNameSpecifier::GlobalSpecifier(Context);
NumSpecifiers =
- BuildNestedNameSpecifier(Context, FullNamespaceDeclChain, NNS);
+ buildNestedNameSpecifier(FullNamespaceDeclChain, NNS);
}
}
@@ -3760,7 +3862,8 @@ void NamespaceSpecifierSet::AddNameSpecifier(DeclContext *Ctx) {
isSorted = false;
Distances.insert(NumSpecifiers);
- DistanceMap[NumSpecifiers].push_back(SpecifierInfo(Ctx, NNS, NumSpecifiers));
+ SpecifierInfo SI = {Ctx, NNS, NumSpecifiers};
+ DistanceMap[NumSpecifiers].push_back(SI);
}
/// \brief Perform name lookup for a possible result for typo correction.
@@ -3960,17 +4063,10 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
}
}
-static bool isCandidateViable(CorrectionCandidateCallback &CCC,
- TypoCorrection &Candidate) {
- Candidate.setCallbackDistance(CCC.RankCandidate(Candidate));
- return Candidate.getEditDistance(false) != TypoCorrection::InvalidDistance;
-}
-
/// \brief Check whether the declarations found for a typo correction are
/// visible, and if none of them are, convert the correction to an 'import
/// a module' correction.
-static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC,
- DeclarationName TypoName) {
+static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC) {
if (TC.begin() == TC.end())
return;
@@ -4045,6 +4141,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
Sema::LookupNameKind LookupKind,
Scope *S, CXXScopeSpec *SS,
CorrectionCandidateCallback &CCC,
+ CorrectTypoKind Mode,
DeclContext *MemberContext,
bool EnteringContext,
const ObjCObjectPointerType *OPT,
@@ -4064,7 +4161,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
// In Microsoft mode, don't perform typo correction in a template member
// function dependent context because it interferes with the "lookup into
// dependent bases of class templates" feature.
- if (getLangOpts().MicrosoftMode && CurContext->isDependentContext() &&
+ if (getLangOpts().MSVCCompat && CurContext->isDependentContext() &&
isa<CXXMethodDecl>(CurContext))
return TypoCorrection();
@@ -4099,9 +4196,17 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
if (getLangOpts().AltiVec && Typo->isStr("vector"))
return TypoCorrection();
- NamespaceSpecifierSet Namespaces(Context, CurContext, SS);
+ // If we're handling a missing symbol error, using modules, and the
+ // special search all modules option is used, look for a missing import.
+ if ((Mode == CTK_ErrorRecovery) && getLangOpts().Modules &&
+ getLangOpts().ModulesSearchAll) {
+ // The following has the side effect of loading the missing module.
+ getModuleLoader().lookupMissingImports(Typo->getName(),
+ TypoName.getLocStart());
+ }
- TypoCorrectionConsumer Consumer(*this, Typo);
+ TypoCorrectionConsumer Consumer(*this, TypoName, LookupKind, S, SS, CCC,
+ MemberContext, EnteringContext);
// If a callback object considers an empty typo correction candidate to be
// viable, assume it does not do any actual validation of the candidates.
@@ -4116,10 +4221,8 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
// Look in qualified interfaces.
if (OPT) {
- for (ObjCObjectPointerType::qual_iterator
- I = OPT->qual_begin(), E = OPT->qual_end();
- I != E; ++I)
- LookupVisibleDecls(*I, LookupKind, Consumer);
+ for (auto *I : OPT->quals())
+ LookupVisibleDecls(I, LookupKind, Consumer);
}
} else if (SS && SS->isSet()) {
QualifiedDC = computeDeclContext(*SS, EnteringContext);
@@ -4182,16 +4285,14 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
// For unqualified lookup, look through all of the names that we have
// seen in this translation unit.
// FIXME: Re-add the ability to skip very unlikely potential corrections.
- for (IdentifierTable::iterator I = Context.Idents.begin(),
- IEnd = Context.Idents.end();
- I != IEnd; ++I)
- Consumer.FoundName(I->getKey());
+ for (const auto &I : Context.Idents)
+ Consumer.FoundName(I.getKey());
// Walk through identifiers in external identifier sources.
// FIXME: Re-add the ability to skip very unlikely potential corrections.
if (IdentifierInfoLookup *External
= Context.Idents.getExternalIdentifierLookup()) {
- OwningPtr<IdentifierIterator> Iter(External->getIdentifiers());
+ std::unique_ptr<IdentifierIterator> Iter(External->getIdentifiers());
do {
StringRef Name = Iter->Next();
if (Name.empty())
@@ -4224,240 +4325,19 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
SmallVector<NamespaceDecl *, 4> ExternalKnownNamespaces;
LoadedExternalKnownNamespaces = true;
ExternalSource->ReadKnownNamespaces(ExternalKnownNamespaces);
- for (unsigned I = 0, N = ExternalKnownNamespaces.size(); I != N; ++I)
- KnownNamespaces[ExternalKnownNamespaces[I]] = true;
+ for (auto *N : ExternalKnownNamespaces)
+ KnownNamespaces[N] = true;
}
- for (llvm::MapVector<NamespaceDecl*, bool>::iterator
- KNI = KnownNamespaces.begin(),
- KNIEnd = KnownNamespaces.end();
- KNI != KNIEnd; ++KNI)
- Namespaces.AddNameSpecifier(KNI->first);
-
- for (ASTContext::type_iterator TI = Context.types_begin(),
- TIEnd = Context.types_end();
- TI != TIEnd; ++TI) {
- if (CXXRecordDecl *CD = (*TI)->getAsCXXRecordDecl()) {
- CD = CD->getCanonicalDecl();
- if (!CD->isDependentType() && !CD->isAnonymousStructOrUnion() &&
- !CD->isUnion() &&
- (CD->isBeingDefined() || CD->isCompleteDefinition()))
- Namespaces.AddNameSpecifier(CD);
- }
- }
+ Consumer.addNamespaces(KnownNamespaces);
}
- // Weed out any names that could not be found by name lookup or, if a
- // CorrectionCandidateCallback object was provided, failed validation.
- SmallVector<TypoCorrection, 16> QualifiedResults;
- LookupResult TmpRes(*this, TypoName, LookupKind);
- TmpRes.suppressDiagnostics();
- while (!Consumer.empty()) {
- TypoCorrectionConsumer::distance_iterator DI = Consumer.begin();
- for (TypoCorrectionConsumer::result_iterator I = DI->second.begin(),
- IEnd = DI->second.end();
- I != IEnd; /* Increment in loop. */) {
- // If we only want nested name specifier corrections, ignore potential
- // corrections that have a different base identifier from the typo.
- if (AllowOnlyNNSChanges &&
- I->second.front().getCorrectionAsIdentifierInfo() != Typo) {
- TypoCorrectionConsumer::result_iterator Prev = I;
- ++I;
- DI->second.erase(Prev);
- continue;
- }
-
- // If the item already has been looked up or is a keyword, keep it.
- // If a validator callback object was given, drop the correction
- // unless it passes validation.
- bool Viable = false;
- for (TypoResultList::iterator RI = I->second.begin();
- RI != I->second.end(); /* Increment in loop. */) {
- TypoResultList::iterator Prev = RI;
- ++RI;
- if (Prev->isResolved()) {
- if (!isCandidateViable(CCC, *Prev))
- RI = I->second.erase(Prev);
- else
- Viable = true;
- }
- }
- if (Viable || I->second.empty()) {
- TypoCorrectionConsumer::result_iterator Prev = I;
- ++I;
- if (!Viable)
- DI->second.erase(Prev);
- continue;
- }
- assert(I->second.size() == 1 && "Expected a single unresolved candidate");
-
- // Perform name lookup on this name.
- TypoCorrection &Candidate = I->second.front();
- IdentifierInfo *Name = Candidate.getCorrectionAsIdentifierInfo();
- DeclContext *TempMemberContext = MemberContext;
- CXXScopeSpec *TempSS = SS;
-retry_lookup:
- LookupPotentialTypoResult(*this, TmpRes, Name, S, TempSS,
- TempMemberContext, EnteringContext,
- CCC.IsObjCIvarLookup,
- Name == TypoName.getName() &&
- !Candidate.WillReplaceSpecifier());
-
- switch (TmpRes.getResultKind()) {
- case LookupResult::NotFound:
- case LookupResult::NotFoundInCurrentInstantiation:
- case LookupResult::FoundUnresolvedValue:
- if (TempSS) {
- // Immediately retry the lookup without the given CXXScopeSpec
- TempSS = NULL;
- Candidate.WillReplaceSpecifier(true);
- goto retry_lookup;
- }
- if (TempMemberContext) {
- if (SS && !TempSS)
- TempSS = SS;
- TempMemberContext = NULL;
- goto retry_lookup;
- }
- QualifiedResults.push_back(Candidate);
- // We didn't find this name in our scope, or didn't like what we found;
- // ignore it.
- {
- TypoCorrectionConsumer::result_iterator Next = I;
- ++Next;
- DI->second.erase(I);
- I = Next;
- }
- break;
-
- case LookupResult::Ambiguous:
- // We don't deal with ambiguities.
- return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
-
- case LookupResult::FoundOverloaded: {
- TypoCorrectionConsumer::result_iterator Prev = I;
- // Store all of the Decls for overloaded symbols
- for (LookupResult::iterator TRD = TmpRes.begin(),
- TRDEnd = TmpRes.end();
- TRD != TRDEnd; ++TRD)
- Candidate.addCorrectionDecl(*TRD);
- ++I;
- if (!isCandidateViable(CCC, Candidate)) {
- QualifiedResults.push_back(Candidate);
- DI->second.erase(Prev);
- }
- break;
- }
-
- case LookupResult::Found: {
- TypoCorrectionConsumer::result_iterator Prev = I;
- Candidate.setCorrectionDecl(TmpRes.getAsSingle<NamedDecl>());
- ++I;
- if (!isCandidateViable(CCC, Candidate)) {
- QualifiedResults.push_back(Candidate);
- DI->second.erase(Prev);
- }
- break;
- }
-
- }
- }
-
- if (DI->second.empty())
- Consumer.erase(DI);
- else if (!getLangOpts().CPlusPlus || QualifiedResults.empty() || !DI->first)
- // If there are results in the closest possible bucket, stop
- break;
-
- // Only perform the qualified lookups for C++
- if (SearchNamespaces) {
- TmpRes.suppressDiagnostics();
- for (SmallVector<TypoCorrection,
- 16>::iterator QRI = QualifiedResults.begin(),
- QRIEnd = QualifiedResults.end();
- QRI != QRIEnd; ++QRI) {
- for (NamespaceSpecifierSet::iterator NI = Namespaces.begin(),
- NIEnd = Namespaces.end();
- NI != NIEnd; ++NI) {
- DeclContext *Ctx = NI->DeclCtx;
- const Type *NSType = NI->NameSpecifier->getAsType();
-
- // If the current NestedNameSpecifier refers to a class and the
- // current correction candidate is the name of that class, then skip
- // it as it is unlikely a qualified version of the class' constructor
- // is an appropriate correction.
- if (CXXRecordDecl *NSDecl =
- NSType ? NSType->getAsCXXRecordDecl() : 0) {
- if (NSDecl->getIdentifier() == QRI->getCorrectionAsIdentifierInfo())
- continue;
- }
-
- TypoCorrection TC(*QRI);
- TC.ClearCorrectionDecls();
- TC.setCorrectionSpecifier(NI->NameSpecifier);
- TC.setQualifierDistance(NI->EditDistance);
- TC.setCallbackDistance(0); // Reset the callback distance
-
- // If the current correction candidate and namespace combination are
- // too far away from the original typo based on the normalized edit
- // distance, then skip performing a qualified name lookup.
- unsigned TmpED = TC.getEditDistance(true);
- if (QRI->getCorrectionAsIdentifierInfo() != Typo &&
- TmpED && TypoLen / TmpED < 3)
- continue;
-
- TmpRes.clear();
- TmpRes.setLookupName(QRI->getCorrectionAsIdentifierInfo());
- if (!LookupQualifiedName(TmpRes, Ctx)) continue;
-
- // Any corrections added below will be validated in subsequent
- // iterations of the main while() loop over the Consumer's contents.
- switch (TmpRes.getResultKind()) {
- case LookupResult::Found:
- case LookupResult::FoundOverloaded: {
- if (SS && SS->isValid()) {
- std::string NewQualified = TC.getAsString(getLangOpts());
- std::string OldQualified;
- llvm::raw_string_ostream OldOStream(OldQualified);
- SS->getScopeRep()->print(OldOStream, getPrintingPolicy());
- OldOStream << TypoName;
- // If correction candidate would be an identical written qualified
- // identifer, then the existing CXXScopeSpec probably included a
- // typedef that didn't get accounted for properly.
- if (OldOStream.str() == NewQualified)
- break;
- }
- for (LookupResult::iterator TRD = TmpRes.begin(),
- TRDEnd = TmpRes.end();
- TRD != TRDEnd; ++TRD) {
- if (CheckMemberAccess(TC.getCorrectionRange().getBegin(),
- NSType ? NSType->getAsCXXRecordDecl() : 0,
- TRD.getPair()) == AR_accessible)
- TC.addCorrectionDecl(*TRD);
- }
- if (TC.isResolved())
- Consumer.addCorrection(TC);
- break;
- }
- case LookupResult::NotFound:
- case LookupResult::NotFoundInCurrentInstantiation:
- case LookupResult::Ambiguous:
- case LookupResult::FoundUnresolvedValue:
- break;
- }
- }
- }
- }
-
- QualifiedResults.clear();
- }
-
- // No corrections remain...
- if (Consumer.empty())
+ TypoCorrection BestTC = Consumer.getNextCorrection();
+ TypoCorrection SecondBestTC = Consumer.getNextCorrection();
+ if (!BestTC)
return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
- TypoResultsMap &BestResults = Consumer.getBestResults();
- ED = Consumer.getBestEditDistance(true);
+ ED = BestTC.getEditDistance();
if (!AllowOnlyNNSChanges && ED > 0 && TypoLen / ED < 3) {
// If this was an unqualified lookup and we believe the callback
@@ -4468,11 +4348,9 @@ retry_lookup:
}
// If only a single name remains, return that result.
- if (BestResults.size() == 1) {
- const TypoResultList &CorrectionList = BestResults.begin()->second;
- const TypoCorrection &Result = CorrectionList.front();
- if (CorrectionList.size() != 1)
- return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
+ if (!SecondBestTC ||
+ SecondBestTC.getEditDistance(false) > BestTC.getEditDistance(false)) {
+ const TypoCorrection &Result = BestTC;
// Don't correct to a keyword that's the same as the typo; the keyword
// wasn't actually in scope.
@@ -4485,39 +4363,42 @@ retry_lookup:
TypoCorrection TC = Result;
TC.setCorrectionRange(SS, TypoName);
- checkCorrectionVisibility(*this, TC, TypoName.getName());
+ checkCorrectionVisibility(*this, TC);
return TC;
}
- else if (BestResults.size() > 1
- // Ugly hack equivalent to CTC == CTC_ObjCMessageReceiver;
- // WantObjCSuper is only true for CTC_ObjCMessageReceiver and for
- // some instances of CTC_Unknown, while WantRemainingKeywords is true
- // for CTC_Unknown but not for CTC_ObjCMessageReceiver.
- && CCC.WantObjCSuper && !CCC.WantRemainingKeywords
- && BestResults["super"].front().isKeyword()) {
+ // Ugly hack equivalent to CTC == CTC_ObjCMessageReceiver;
+ // WantObjCSuper is only true for CTC_ObjCMessageReceiver and for
+ // some instances of CTC_Unknown, while WantRemainingKeywords is true
+ // for CTC_Unknown but not for CTC_ObjCMessageReceiver.
+ else if (SecondBestTC && CCC.WantObjCSuper && !CCC.WantRemainingKeywords) {
// Prefer 'super' when we're completing in a message-receiver
// context.
+ if (BestTC.getCorrection().getAsString() != "super") {
+ if (SecondBestTC.getCorrection().getAsString() == "super")
+ BestTC = SecondBestTC;
+ else if (Consumer["super"].front().isKeyword())
+ BestTC = Consumer["super"].front();
+ }
// Don't correct to a keyword that's the same as the typo; the keyword
// wasn't actually in scope.
- if (ED == 0)
+ if (BestTC.getEditDistance() == 0 ||
+ BestTC.getCorrection().getAsString() != "super")
return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
// Record the correction for unqualified lookup.
if (IsUnqualifiedLookup)
- UnqualifiedTyposCorrected[Typo] = BestResults["super"].front();
+ UnqualifiedTyposCorrected[Typo] = BestTC;
- TypoCorrection TC = BestResults["super"].front();
- TC.setCorrectionRange(SS, TypoName);
- return TC;
+ BestTC.setCorrectionRange(SS, TypoName);
+ return BestTC;
}
- // If this was an unqualified lookup and we believe the callback object did
- // not filter out possible corrections, note that no correction was found.
- if (IsUnqualifiedLookup && !ValidatingCallback)
- (void)UnqualifiedTyposCorrected[Typo];
-
- return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
+ // Record the failure's location if needed and return an empty correction. If
+ // this was an unqualified lookup and we believe the callback object did not
+ // filter out possible corrections, also cache the failure for the typo.
+ return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure,
+ IsUnqualifiedLookup && !ValidatingCallback);
}
void TypoCorrection::addCorrectionDecl(NamedDecl *CDecl) {
@@ -4552,19 +4433,34 @@ bool CorrectionCandidateCallback::ValidateCandidate(const TypoCorrection &candid
return WantTypeSpecifiers || WantExpressionKeywords || WantCXXNamedCasts ||
WantRemainingKeywords || WantObjCSuper;
- for (TypoCorrection::const_decl_iterator CDecl = candidate.begin(),
- CDeclEnd = candidate.end();
- CDecl != CDeclEnd; ++CDecl) {
- if (!isa<TypeDecl>(*CDecl))
- return true;
+ bool HasNonType = false;
+ bool HasStaticMethod = false;
+ bool HasNonStaticMethod = false;
+ for (Decl *D : candidate) {
+ if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D))
+ D = FTD->getTemplatedDecl();
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+ if (Method->isStatic())
+ HasStaticMethod = true;
+ else
+ HasNonStaticMethod = true;
+ }
+ if (!isa<TypeDecl>(D))
+ HasNonType = true;
}
- return WantTypeSpecifiers;
+ if (IsAddressOfOperand && HasNonStaticMethod && !HasStaticMethod &&
+ !candidate.getCorrectionSpecifier())
+ return false;
+
+ return WantTypeSpecifiers || HasNonType;
}
FunctionCallFilterCCC::FunctionCallFilterCCC(Sema &SemaRef, unsigned NumArgs,
- bool HasExplicitTemplateArgs)
- : NumArgs(NumArgs), HasExplicitTemplateArgs(HasExplicitTemplateArgs) {
+ bool HasExplicitTemplateArgs,
+ MemberExpr *ME)
+ : NumArgs(NumArgs), HasExplicitTemplateArgs(HasExplicitTemplateArgs),
+ CurContext(SemaRef.CurContext), MemberFn(ME) {
WantTypeSpecifiers = SemaRef.getLangOpts().CPlusPlus;
WantRemainingKeywords = false;
}
@@ -4573,11 +4469,9 @@ bool FunctionCallFilterCCC::ValidateCandidate(const TypoCorrection &candidate) {
if (!candidate.getCorrectionDecl())
return candidate.isKeyword();
- for (TypoCorrection::const_decl_iterator DI = candidate.begin(),
- DIEnd = candidate.end();
- DI != DIEnd; ++DI) {
- FunctionDecl *FD = 0;
- NamedDecl *ND = (*DI)->getUnderlyingDecl();
+ for (auto *C : candidate) {
+ FunctionDecl *FD = nullptr;
+ NamedDecl *ND = C->getUnderlyingDecl();
if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND))
FD = FTD->getTemplatedDecl();
if (!HasExplicitTemplateArgs && !FD) {
@@ -4589,13 +4483,35 @@ bool FunctionCallFilterCCC::ValidateCandidate(const TypoCorrection &candidate) {
if (ValType->isAnyPointerType() || ValType->isReferenceType())
ValType = ValType->getPointeeType();
if (const FunctionProtoType *FPT = ValType->getAs<FunctionProtoType>())
- if (FPT->getNumArgs() == NumArgs)
+ if (FPT->getNumParams() == NumArgs)
return true;
}
}
- if (FD && FD->getNumParams() >= NumArgs &&
- FD->getMinRequiredArguments() <= NumArgs)
- return true;
+
+ // Skip the current candidate if it is not a FunctionDecl or does not accept
+ // the current number of arguments.
+ if (!FD || !(FD->getNumParams() >= NumArgs &&
+ FD->getMinRequiredArguments() <= NumArgs))
+ continue;
+
+ // If the current candidate is a non-static C++ method, skip the candidate
+ // unless the method being corrected--or the current DeclContext, if the
+ // function being corrected is not a method--is a method in the same class
+ // or a descendent class of the candidate's parent class.
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ if (MemberFn || !MD->isStatic()) {
+ CXXMethodDecl *CurMD =
+ MemberFn
+ ? dyn_cast_or_null<CXXMethodDecl>(MemberFn->getMemberDecl())
+ : dyn_cast_or_null<CXXMethodDecl>(CurContext);
+ CXXRecordDecl *CurRD =
+ CurMD ? CurMD->getParent()->getCanonicalDecl() : nullptr;
+ CXXRecordDecl *RD = MD->getParent()->getCanonicalDecl();
+ if (!CurRD || (CurRD != RD && !CurRD->isDerivedFrom(RD)))
+ continue;
+ }
+ }
+ return true;
}
return false;
}
@@ -4613,7 +4529,7 @@ static const NamedDecl *getDefinitionToImport(const NamedDecl *D) {
if (const VarDecl *VD = dyn_cast<VarDecl>(D))
return VD->getDefinition();
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- return FD->isDefined(FD) ? FD : 0;
+ return FD->isDefined(FD) ? FD : nullptr;
if (const TagDecl *TD = dyn_cast<TagDecl>(D))
return TD->getDefinition();
if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
@@ -4622,7 +4538,7 @@ static const NamedDecl *getDefinitionToImport(const NamedDecl *D) {
return PD->getDefinition();
if (const TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
return getDefinitionToImport(TD->getTemplatedDecl());
- return 0;
+ return nullptr;
}
/// \brief Diagnose a successfully-corrected typo. Separated from the correction
@@ -4665,9 +4581,9 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction,
Diag(Def->getLocation(), diag::note_previous_declaration);
// Recover by implicitly importing this module.
- if (!isSFINAEContext() && ErrorRecovery)
- createImplicitModuleImport(Correction.getCorrectionRange().getBegin(),
- Owner);
+ if (ErrorRecovery)
+ createImplicitModuleImportForErrorRecovery(
+ Correction.getCorrectionRange().getBegin(), Owner);
return;
}
@@ -4675,7 +4591,7 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction,
<< CorrectedQuotedStr << (ErrorRecovery ? FixTypo : FixItHint());
NamedDecl *ChosenDecl =
- Correction.isKeyword() ? 0 : Correction.getCorrectionDecl();
+ Correction.isKeyword() ? nullptr : Correction.getCorrectionDecl();
if (PrevNote.getDiagID() && ChosenDecl)
Diag(ChosenDecl->getLocation(), PrevNote)
<< CorrectedQuotedStr << (ErrorRecovery ? FixItHint() : FixTypo);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
index d9d9cec..8eb806b 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
@@ -19,7 +19,6 @@
#include "clang/AST/ExprObjC.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallString.h"
@@ -132,11 +131,8 @@ CheckPropertyAgainstProtocol(Sema &S, ObjCPropertyDecl *Prop,
}
// Check this property against any protocols we inherit.
- for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
- PEnd = Proto->protocol_end();
- P != PEnd; ++P) {
- CheckPropertyAgainstProtocol(S, Prop, *P, Known);
- }
+ for (auto *P : Proto->protocols())
+ CheckPropertyAgainstProtocol(S, Prop, P, Known);
}
Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
@@ -168,7 +164,7 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
// Proceed with constructing the ObjCPropertyDecls.
ObjCContainerDecl *ClassDecl = cast<ObjCContainerDecl>(CurContext);
- ObjCPropertyDecl *Res = 0;
+ ObjCPropertyDecl *Res = nullptr;
if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
if (CDecl->IsClassExtension()) {
Res = HandlePropertyInClassExtension(S, AtLoc, LParenLoc,
@@ -179,7 +175,7 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
isOverridingProperty, TSI,
MethodImplKind);
if (!Res)
- return 0;
+ return nullptr;
}
}
@@ -204,7 +200,8 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
// For a class, compare the property against a property in our superclass.
bool FoundInSuper = false;
- if (ObjCInterfaceDecl *Super = IFace->getSuperClass()) {
+ ObjCInterfaceDecl *CurrentInterfaceDecl = IFace;
+ while (ObjCInterfaceDecl *Super = CurrentInterfaceDecl->getSuperClass()) {
DeclContext::lookup_result R = Super->lookup(Res->getDeclName());
for (unsigned I = 0, N = R.size(); I != N; ++I) {
if (ObjCPropertyDecl *SuperProp = dyn_cast<ObjCPropertyDecl>(R[I])) {
@@ -213,37 +210,30 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
break;
}
}
+ if (FoundInSuper)
+ break;
+ else
+ CurrentInterfaceDecl = Super;
}
if (FoundInSuper) {
// Also compare the property against a property in our protocols.
- for (ObjCInterfaceDecl::protocol_iterator P = IFace->protocol_begin(),
- PEnd = IFace->protocol_end();
- P != PEnd; ++P) {
- CheckPropertyAgainstProtocol(*this, Res, *P, KnownProtos);
+ for (auto *P : CurrentInterfaceDecl->protocols()) {
+ CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos);
}
} else {
// Slower path: look in all protocols we referenced.
- for (ObjCInterfaceDecl::all_protocol_iterator
- P = IFace->all_referenced_protocol_begin(),
- PEnd = IFace->all_referenced_protocol_end();
- P != PEnd; ++P) {
- CheckPropertyAgainstProtocol(*this, Res, *P, KnownProtos);
+ for (auto *P : IFace->all_referenced_protocols()) {
+ CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos);
}
}
} else if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
- for (ObjCCategoryDecl::protocol_iterator P = Cat->protocol_begin(),
- PEnd = Cat->protocol_end();
- P != PEnd; ++P) {
- CheckPropertyAgainstProtocol(*this, Res, *P, KnownProtos);
- }
+ for (auto *P : Cat->protocols())
+ CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos);
} else {
ObjCProtocolDecl *Proto = cast<ObjCProtocolDecl>(ClassDecl);
- for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
- PEnd = Proto->protocol_end();
- P != PEnd; ++P) {
- CheckPropertyAgainstProtocol(*this, Res, *P, KnownProtos);
- }
+ for (auto *P : Proto->protocols())
+ CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos);
}
ActOnDocumentableDecl(Res);
@@ -302,8 +292,7 @@ static bool LocPropertyAttribute( ASTContext &Context, const char *attrName,
Token Tok;
do {
lexer.LexFromRawLexer(Tok);
- if (Tok.is(tok::raw_identifier) &&
- StringRef(Tok.getRawIdentifierData(), Tok.getLength()) == attrName) {
+ if (Tok.is(tok::raw_identifier) && Tok.getRawIdentifier() == attrName) {
Loc = Tok.getLocation();
return true;
}
@@ -321,21 +310,6 @@ static unsigned getOwnershipRule(unsigned attr) {
ObjCPropertyDecl::OBJC_PR_unsafe_unretained);
}
-static const char *NameOfOwnershipAttribute(unsigned attr) {
- if (attr & ObjCPropertyDecl::OBJC_PR_assign)
- return "assign";
- if (attr & ObjCPropertyDecl::OBJC_PR_retain )
- return "retain";
- if (attr & ObjCPropertyDecl::OBJC_PR_copy)
- return "copy";
- if (attr & ObjCPropertyDecl::OBJC_PR_weak)
- return "weak";
- if (attr & ObjCPropertyDecl::OBJC_PR_strong)
- return "strong";
- assert(attr & ObjCPropertyDecl::OBJC_PR_unsafe_unretained);
- return "unsafe_unretained";
-}
-
ObjCPropertyDecl *
Sema::HandlePropertyInClassExtension(Scope *S,
SourceLocation AtLoc,
@@ -358,15 +332,12 @@ Sema::HandlePropertyInClassExtension(Scope *S,
if (CCPrimary) {
// Check for duplicate declaration of this property in current and
// other class extensions.
- for (ObjCInterfaceDecl::known_extensions_iterator
- Ext = CCPrimary->known_extensions_begin(),
- ExtEnd = CCPrimary->known_extensions_end();
- Ext != ExtEnd; ++Ext) {
+ for (const auto *Ext : CCPrimary->known_extensions()) {
if (ObjCPropertyDecl *prevDecl
- = ObjCPropertyDecl::findPropertyDecl(*Ext, PropertyId)) {
+ = ObjCPropertyDecl::findPropertyDecl(Ext, PropertyId)) {
Diag(AtLoc, diag::err_duplicate_property);
Diag(prevDecl->getLocation(), diag::note_property_declare);
- return 0;
+ return nullptr;
}
}
}
@@ -398,7 +369,7 @@ Sema::HandlePropertyInClassExtension(Scope *S,
if (!CCPrimary) {
Diag(CDecl->getLocation(), diag::err_continuation_class);
*isOverridingProperty = true;
- return 0;
+ return nullptr;
}
// Find the property in continuation class's primary class only.
@@ -416,12 +387,14 @@ Sema::HandlePropertyInClassExtension(Scope *S,
// A case of continuation class adding a new property in the class. This
// is not what it was meant for. However, gcc supports it and so should we.
// Make sure setter/getters are declared here.
- ProcessPropertyDecl(PrimaryPDecl, CCPrimary, /* redeclaredProperty = */ 0,
+ ProcessPropertyDecl(PrimaryPDecl, CCPrimary,
+ /* redeclaredProperty = */ nullptr,
/* lexicalDC = */ CDecl);
PDecl->setGetterMethodDecl(PrimaryPDecl->getGetterMethodDecl());
PDecl->setSetterMethodDecl(PrimaryPDecl->getSetterMethodDecl());
if (ASTMutationListener *L = Context.getASTMutationListener())
- L->AddedObjCPropertyInClassExtension(PrimaryPDecl, /*OrigProp=*/0, CDecl);
+ L->AddedObjCPropertyInClassExtension(PrimaryPDecl, /*OrigProp=*/nullptr,
+ CDecl);
return PrimaryPDecl;
}
if (!Context.hasSameType(PIDecl->getType(), PDecl->getType())) {
@@ -441,7 +414,7 @@ Sema::HandlePropertyInClassExtension(Scope *S,
Diag(AtLoc,
diag::err_type_mismatch_continuation_class) << PDecl->getType();
Diag(PIDecl->getLocation(), diag::note_property_declare);
- return 0;
+ return nullptr;
}
}
@@ -478,6 +451,18 @@ Sema::HandlePropertyInClassExtension(Scope *S,
DeclContext *DC = cast<DeclContext>(CCPrimary);
if (!ObjCPropertyDecl::findPropertyDecl(DC,
PIDecl->getDeclName().getAsIdentifierInfo())) {
+ // In mrr mode, 'readwrite' property must have an explicit
+ // memory attribute. If none specified, select the default (assign).
+ if (!getLangOpts().ObjCAutoRefCount) {
+ if (!(PIkind & (ObjCDeclSpec::DQ_PR_assign |
+ ObjCDeclSpec::DQ_PR_retain |
+ ObjCDeclSpec::DQ_PR_strong |
+ ObjCDeclSpec::DQ_PR_copy |
+ ObjCDeclSpec::DQ_PR_unsafe_unretained |
+ ObjCDeclSpec::DQ_PR_weak)))
+ PIkind |= ObjCPropertyDecl::OBJC_PR_assign;
+ }
+
// Protocol is not in the primary class. Must build one for it.
ObjCDeclSpec ProtocolPropertyODS;
// FIXME. Assuming that ObjCDeclSpec::ObjCPropertyAttributeKind
@@ -520,7 +505,7 @@ Sema::HandlePropertyInClassExtension(Scope *S,
Diag(AtLoc, diag)
<< CCPrimary->getDeclName();
Diag(PIDecl->getLocation(), diag::note_property_declare);
- return 0;
+ return nullptr;
}
*isOverridingProperty = true;
// Make sure setter decl is synthesized, and added to primary class's list.
@@ -565,7 +550,7 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
if (T->isObjCObjectType()) {
SourceLocation StarLoc = TInfo->getTypeLoc().getLocEnd();
- StarLoc = PP.getLocForEndOfToken(StarLoc);
+ StarLoc = getLocForEndOfToken(StarLoc);
Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object)
<< FixItHint::CreateInsertion(StarLoc, "*");
T = Context.getObjCObjectPointerType(T);
@@ -763,18 +748,14 @@ DiagnosePropertyMismatchDeclInProtocols(Sema &S, SourceLocation AtLoc,
ObjCInterfaceDecl *ClassDecl,
ObjCPropertyDecl *Property) {
ObjCInterfaceDecl::ProtocolPropertyMap PropMap;
- for (ObjCInterfaceDecl::all_protocol_iterator
- PI = ClassDecl->all_referenced_protocol_begin(),
- E = ClassDecl->all_referenced_protocol_end(); PI != E; ++PI) {
- if (const ObjCProtocolDecl *PDecl = (*PI)->getDefinition())
+ for (const auto *PI : ClassDecl->all_referenced_protocols()) {
+ if (const ObjCProtocolDecl *PDecl = PI->getDefinition())
PDecl->collectInheritedProtocolProperties(Property, PropMap);
}
if (ObjCInterfaceDecl *SDecl = ClassDecl->getSuperClass())
while (SDecl) {
- for (ObjCInterfaceDecl::all_protocol_iterator
- PI = SDecl->all_referenced_protocol_begin(),
- E = SDecl->all_referenced_protocol_end(); PI != E; ++PI) {
- if (const ObjCProtocolDecl *PDecl = (*PI)->getDefinition())
+ for (const auto *PI : SDecl->all_referenced_protocols()) {
+ if (const ObjCProtocolDecl *PDecl = PI->getDefinition())
PDecl->collectInheritedProtocolProperties(Property, PropMap);
}
SDecl = SDecl->getSuperClass();
@@ -824,19 +805,19 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
// Make sure we have a context for the property implementation declaration.
if (!ClassImpDecl) {
Diag(AtLoc, diag::error_missing_property_context);
- return 0;
+ return nullptr;
}
if (PropertyIvarLoc.isInvalid())
PropertyIvarLoc = PropertyLoc;
SourceLocation PropertyDiagLoc = PropertyLoc;
if (PropertyDiagLoc.isInvalid())
PropertyDiagLoc = ClassImpDecl->getLocStart();
- ObjCPropertyDecl *property = 0;
- ObjCInterfaceDecl* IDecl = 0;
+ ObjCPropertyDecl *property = nullptr;
+ ObjCInterfaceDecl *IDecl = nullptr;
// Find the class or category class where this property must have
// a declaration.
- ObjCImplementationDecl *IC = 0;
- ObjCCategoryImplDecl* CatImplClass = 0;
+ ObjCImplementationDecl *IC = nullptr;
+ ObjCCategoryImplDecl *CatImplClass = nullptr;
if ((IC = dyn_cast<ObjCImplementationDecl>(ClassImpDecl))) {
IDecl = IC->getClassInterface();
// We always synthesize an interface for an implementation
@@ -848,7 +829,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
property = IDecl->FindPropertyDeclaration(PropertyId);
if (!property) {
Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName();
- return 0;
+ return nullptr;
}
unsigned PIkind = property->getPropertyAttributesAsWritten();
if ((PIkind & (ObjCPropertyDecl::OBJC_PR_atomic |
@@ -865,7 +846,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
if (!CD->IsClassExtension()) {
Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName();
Diag(property->getLocation(), diag::note_property_declare);
- return 0;
+ return nullptr;
}
}
if (Synthesize&&
@@ -875,9 +856,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
bool ReadWriteProperty = false;
// Search into the class extensions and see if 'readonly property is
// redeclared 'readwrite', then no warning is to be issued.
- for (ObjCInterfaceDecl::known_extensions_iterator
- Ext = IDecl->known_extensions_begin(),
- ExtEnd = IDecl->known_extensions_end(); Ext != ExtEnd; ++Ext) {
+ for (auto *Ext : IDecl->known_extensions()) {
DeclContext::lookup_result R = Ext->lookup(property->getDeclName());
if (!R.empty())
if (ObjCPropertyDecl *ExtProp = dyn_cast<ObjCPropertyDecl>(R[0])) {
@@ -891,7 +870,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
if (!ReadWriteProperty) {
Diag(property->getLocation(), diag::warn_auto_readonly_iboutlet_property)
- << property->getName();
+ << property;
SourceLocation readonlyLoc;
if (LocPropertyAttribute(Context, "readonly",
property->getLParenLoc(), readonlyLoc)) {
@@ -910,12 +889,12 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
} else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) {
if (Synthesize) {
Diag(AtLoc, diag::error_synthesize_category_decl);
- return 0;
+ return nullptr;
}
IDecl = CatImplClass->getClassInterface();
if (!IDecl) {
Diag(AtLoc, diag::error_missing_property_interface);
- return 0;
+ return nullptr;
}
ObjCCategoryDecl *Category =
IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier());
@@ -923,19 +902,19 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
// If category for this implementation not found, it is an error which
// has already been reported eralier.
if (!Category)
- return 0;
+ return nullptr;
// Look for this property declaration in @implementation's category
property = Category->FindPropertyDeclaration(PropertyId);
if (!property) {
Diag(PropertyLoc, diag::error_bad_category_property_decl)
<< Category->getDeclName();
- return 0;
+ return nullptr;
}
} else {
Diag(AtLoc, diag::error_bad_property_context);
- return 0;
+ return nullptr;
}
- ObjCIvarDecl *Ivar = 0;
+ ObjCIvarDecl *Ivar = nullptr;
bool CompleteTypeErr = false;
bool compat = true;
// Check that we have a valid, previously declared ivar for @synthesize
@@ -983,14 +962,14 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
// an ivar matching property name and issue warning; since this
// is the most common case of not using an ivar used for backing
// property in non-default synthesis case.
- ObjCInterfaceDecl *ClassDeclared=0;
+ ObjCInterfaceDecl *ClassDeclared=nullptr;
ObjCIvarDecl *originalIvar =
IDecl->lookupInstanceVariable(property->getIdentifier(),
ClassDeclared);
if (originalIvar) {
Diag(PropertyDiagLoc,
diag::warn_autosynthesis_property_ivar_match)
- << PropertyId << (Ivar == 0) << PropertyIvar
+ << PropertyId << (Ivar == nullptr) << PropertyIvar
<< originalIvar->getIdentifier();
Diag(property->getLocation(), diag::note_property_declare);
Diag(originalIvar->getLocation(), diag::note_ivar_decl);
@@ -1049,9 +1028,9 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl,
PropertyIvarLoc,PropertyIvarLoc, PropertyIvar,
- PropertyIvarType, /*Dinfo=*/0,
+ PropertyIvarType, /*Dinfo=*/nullptr,
ObjCIvarDecl::Private,
- (Expr *)0, true);
+ (Expr *)nullptr, true);
if (RequireNonAbstractType(PropertyIvarLoc,
PropertyIvarType,
diag::err_abstract_type_in_decl,
@@ -1163,21 +1142,23 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl();
DeclRefExpr *SelfExpr =
new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(),
- VK_RValue, PropertyDiagLoc);
+ VK_LValue, PropertyDiagLoc);
MarkDeclRefReferenced(SelfExpr);
+ Expr *LoadSelfExpr =
+ ImplicitCastExpr::Create(Context, SelfDecl->getType(),
+ CK_LValueToRValue, SelfExpr, nullptr,
+ VK_RValue);
Expr *IvarRefExpr =
new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc,
Ivar->getLocation(),
- SelfExpr, true, true);
- ExprResult Res =
- PerformCopyInitialization(InitializedEntity::InitializeResult(
- PropertyDiagLoc,
- getterMethod->getResultType(),
- /*NRVO=*/false),
- PropertyDiagLoc,
- Owned(IvarRefExpr));
+ LoadSelfExpr, true, true);
+ ExprResult Res = PerformCopyInitialization(
+ InitializedEntity::InitializeResult(PropertyDiagLoc,
+ getterMethod->getReturnType(),
+ /*NRVO=*/false),
+ PropertyDiagLoc, IvarRefExpr);
if (!Res.isInvalid()) {
- Expr *ResExpr = Res.takeAs<Expr>();
+ Expr *ResExpr = Res.getAs<Expr>();
if (ResExpr)
ResExpr = MaybeCreateExprWithCleanups(ResExpr);
PIDecl->setGetterCXXConstructor(ResExpr);
@@ -1211,12 +1192,16 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl();
DeclRefExpr *SelfExpr =
new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(),
- VK_RValue, PropertyDiagLoc);
+ VK_LValue, PropertyDiagLoc);
MarkDeclRefReferenced(SelfExpr);
+ Expr *LoadSelfExpr =
+ ImplicitCastExpr::Create(Context, SelfDecl->getType(),
+ CK_LValueToRValue, SelfExpr, nullptr,
+ VK_RValue);
Expr *lhs =
new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc,
Ivar->getLocation(),
- SelfExpr, true, true);
+ LoadSelfExpr, true, true);
ObjCMethodDecl::param_iterator P = setterMethod->param_begin();
ParmVarDecl *Param = (*P);
QualType T = Param->getType().getNonReferenceType();
@@ -1227,7 +1212,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
BO_Assign, lhs, rhs);
if (property->getPropertyAttributes() &
ObjCPropertyDecl::OBJC_PR_atomic) {
- Expr *callExpr = Res.takeAs<Expr>();
+ Expr *callExpr = Res.getAs<Expr>();
if (const CXXOperatorCallExpr *CXXCE =
dyn_cast_or_null<CXXOperatorCallExpr>(callExpr))
if (const FunctionDecl *FuncDecl = CXXCE->getDirectCallee())
@@ -1240,7 +1225,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
diag::note_callee_decl) << FuncDecl;
}
}
- PIDecl->setSetterCXXAssignment(Res.takeAs<Expr>());
+ PIDecl->setSetterCXXAssignment(Res.getAs<Expr>());
}
}
@@ -1258,7 +1243,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
= IC->FindPropertyImplDecl(PropertyId)) {
Diag(PropertyLoc, diag::error_property_implemented) << PropertyId;
Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
- return 0;
+ return nullptr;
}
IC->addPropertyImplementation(PIDecl);
if (getLangOpts().ObjCDefaultSynthProperties &&
@@ -1267,8 +1252,8 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
// Diagnose if an ivar was lazily synthesdized due to a previous
// use and if 1) property is @dynamic or 2) property is synthesized
// but it requires an ivar of different name.
- ObjCInterfaceDecl *ClassDeclared=0;
- ObjCIvarDecl *Ivar = 0;
+ ObjCInterfaceDecl *ClassDeclared=nullptr;
+ ObjCIvarDecl *Ivar = nullptr;
if (!Synthesize)
Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared);
else {
@@ -1297,7 +1282,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
CatImplClass->FindPropertyImplDecl(PropertyId)) {
Diag(PropertyDiagLoc, diag::error_property_implemented) << PropertyId;
Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
- return 0;
+ return nullptr;
}
CatImplClass->addPropertyImplementation(PIDecl);
}
@@ -1394,7 +1379,7 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property,
SourceLocation Loc) {
if (!GetterMethod)
return false;
- QualType GetterType = GetterMethod->getResultType().getNonReferenceType();
+ QualType GetterType = GetterMethod->getReturnType().getNonReferenceType();
QualType PropertyIvarType = property->getType().getNonReferenceType();
bool compat = Context.hasSameType(PropertyIvarType, GetterType);
if (!compat) {
@@ -1433,37 +1418,32 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property,
/// CollectImmediateProperties - This routine collects all properties in
/// the class and its conforming protocols; but not those in its super class.
-void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
- ObjCContainerDecl::PropertyMap &PropMap,
- ObjCContainerDecl::PropertyMap &SuperPropMap) {
+static void CollectImmediateProperties(ObjCContainerDecl *CDecl,
+ ObjCContainerDecl::PropertyMap &PropMap,
+ ObjCContainerDecl::PropertyMap &SuperPropMap,
+ bool IncludeProtocols = true) {
+
if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
- for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(),
- E = IDecl->prop_end(); P != E; ++P) {
- ObjCPropertyDecl *Prop = *P;
+ for (auto *Prop : IDecl->properties())
PropMap[Prop->getIdentifier()] = Prop;
+ if (IncludeProtocols) {
+ // Scan through class's protocols.
+ for (auto *PI : IDecl->all_referenced_protocols())
+ CollectImmediateProperties(PI, PropMap, SuperPropMap);
}
- // scan through class's protocols.
- for (ObjCInterfaceDecl::all_protocol_iterator
- PI = IDecl->all_referenced_protocol_begin(),
- E = IDecl->all_referenced_protocol_end(); PI != E; ++PI)
- CollectImmediateProperties((*PI), PropMap, SuperPropMap);
}
if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
if (!CATDecl->IsClassExtension())
- for (ObjCContainerDecl::prop_iterator P = CATDecl->prop_begin(),
- E = CATDecl->prop_end(); P != E; ++P) {
- ObjCPropertyDecl *Prop = *P;
+ for (auto *Prop : CATDecl->properties())
PropMap[Prop->getIdentifier()] = Prop;
- }
- // scan through class's protocols.
- for (ObjCCategoryDecl::protocol_iterator PI = CATDecl->protocol_begin(),
- E = CATDecl->protocol_end(); PI != E; ++PI)
- CollectImmediateProperties((*PI), PropMap, SuperPropMap);
+ if (IncludeProtocols) {
+ // Scan through class's protocols.
+ for (auto *PI : CATDecl->protocols())
+ CollectImmediateProperties(PI, PropMap, SuperPropMap);
+ }
}
else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) {
- for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
- E = PDecl->prop_end(); P != E; ++P) {
- ObjCPropertyDecl *Prop = *P;
+ for (auto *Prop : PDecl->properties()) {
ObjCPropertyDecl *PropertyFromSuper = SuperPropMap[Prop->getIdentifier()];
// Exclude property for protocols which conform to class's super-class,
// as super-class has to implement the property.
@@ -1475,9 +1455,8 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
}
}
// scan through protocol's protocols.
- for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
- E = PDecl->protocol_end(); PI != E; ++PI)
- CollectImmediateProperties((*PI), PropMap, SuperPropMap);
+ for (auto *PI : PDecl->protocols())
+ CollectImmediateProperties(PI, PropMap, SuperPropMap);
}
}
@@ -1510,17 +1489,35 @@ Sema::IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace,
// look up a property declaration whose one of its accessors is implemented
// by this method.
- for (ObjCContainerDecl::prop_iterator P = IFace->prop_begin(),
- E = IFace->prop_end(); P != E; ++P) {
- ObjCPropertyDecl *property = *P;
- if ((property->getGetterName() == IMD->getSelector() ||
- property->getSetterName() == IMD->getSelector()) &&
- (property->getPropertyIvarDecl() == IV))
+ for (const auto *Property : IFace->properties()) {
+ if ((Property->getGetterName() == IMD->getSelector() ||
+ Property->getSetterName() == IMD->getSelector()) &&
+ (Property->getPropertyIvarDecl() == IV))
return true;
}
return false;
}
+static bool SuperClassImplementsProperty(ObjCInterfaceDecl *IDecl,
+ ObjCPropertyDecl *Prop) {
+ bool SuperClassImplementsGetter = false;
+ bool SuperClassImplementsSetter = false;
+ if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly)
+ SuperClassImplementsSetter = true;
+
+ while (IDecl->getSuperClass()) {
+ ObjCInterfaceDecl *SDecl = IDecl->getSuperClass();
+ if (!SuperClassImplementsGetter && SDecl->getInstanceMethod(Prop->getGetterName()))
+ SuperClassImplementsGetter = true;
+
+ if (!SuperClassImplementsSetter && SDecl->getInstanceMethod(Prop->getSetterName()))
+ SuperClassImplementsSetter = true;
+ if (SuperClassImplementsGetter && SuperClassImplementsSetter)
+ return true;
+ IDecl = IDecl->getSuperClass();
+ }
+ return false;
+}
/// \brief Default synthesizes all properties which must be synthesized
/// in class's \@implementation.
@@ -1559,7 +1556,7 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl,
!IMPDecl->getInstanceMethod(Prop->getSetterName()) &&
!IDecl->HasUserDeclaredSetterMethod(Prop)) {
Diag(Prop->getLocation(), diag::warn_no_autosynthesis_property)
- << Prop->getIdentifier()->getName();
+ << Prop->getIdentifier();
Diag(PropInSuperClass->getLocation(), diag::note_property_declare);
}
continue;
@@ -1568,17 +1565,23 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl,
IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) {
if (PID->getPropertyDecl() != Prop) {
Diag(Prop->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property)
- << Prop->getIdentifier()->getName();
+ << Prop->getIdentifier();
if (!PID->getLocation().isInvalid())
Diag(PID->getLocation(), diag::note_property_synthesize);
}
continue;
}
- if (isa<ObjCProtocolDecl>(Prop->getDeclContext())) {
+ if (ObjCProtocolDecl *Proto =
+ dyn_cast<ObjCProtocolDecl>(Prop->getDeclContext())) {
// We won't auto-synthesize properties declared in protocols.
- Diag(IMPDecl->getLocation(),
- diag::warn_auto_synthesizing_protocol_property);
- Diag(Prop->getLocation(), diag::note_property_declare);
+ // Suppress the warning if class's superclass implements property's
+ // getter and implements property's setter (if readwrite property).
+ if (!SuperClassImplementsProperty(IDecl, Prop)) {
+ Diag(IMPDecl->getLocation(),
+ diag::warn_auto_synthesizing_protocol_property)
+ << Prop << Proto;
+ Diag(Prop->getLocation(), diag::note_property_declare);
+ }
continue;
}
@@ -1610,44 +1613,108 @@ void Sema::DefaultSynthesizeProperties(Scope *S, Decl *D) {
DefaultSynthesizeProperties(S, IC, IDecl);
}
+static void DiagnoseUnimplementedAccessor(Sema &S,
+ ObjCInterfaceDecl *PrimaryClass,
+ Selector Method,
+ ObjCImplDecl* IMPDecl,
+ ObjCContainerDecl *CDecl,
+ ObjCCategoryDecl *C,
+ ObjCPropertyDecl *Prop,
+ Sema::SelectorSet &SMap) {
+ // When reporting on missing property setter/getter implementation in
+ // categories, do not report when they are declared in primary class,
+ // class's protocol, or one of it super classes. This is because,
+ // the class is going to implement them.
+ if (!SMap.count(Method) &&
+ (PrimaryClass == nullptr ||
+ !PrimaryClass->lookupPropertyAccessor(Method, C))) {
+ S.Diag(IMPDecl->getLocation(),
+ isa<ObjCCategoryDecl>(CDecl) ?
+ diag::warn_setter_getter_impl_required_in_category :
+ diag::warn_setter_getter_impl_required)
+ << Prop->getDeclName() << Method;
+ S.Diag(Prop->getLocation(),
+ diag::note_property_declare);
+ if (S.LangOpts.ObjCDefaultSynthProperties &&
+ S.LangOpts.ObjCRuntime.isNonFragile())
+ if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CDecl))
+ if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs())
+ S.Diag(RID->getLocation(), diag::note_suppressed_class_declare);
+ }
+}
+
void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
- ObjCContainerDecl *CDecl) {
- ObjCContainerDecl::PropertyMap NoNeedToImplPropMap;
- ObjCInterfaceDecl *IDecl;
- // Gather properties which need not be implemented in this class
- // or category.
- if (!(IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)))
- if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {
- // For categories, no need to implement properties declared in
- // its primary class (and its super classes) if property is
- // declared in one of those containers.
- if ((IDecl = C->getClassInterface())) {
- ObjCInterfaceDecl::PropertyDeclOrder PO;
- IDecl->collectPropertiesToImplement(NoNeedToImplPropMap, PO);
+ ObjCContainerDecl *CDecl,
+ bool SynthesizeProperties) {
+ ObjCContainerDecl::PropertyMap PropMap;
+ ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
+
+ if (!SynthesizeProperties) {
+ ObjCContainerDecl::PropertyMap NoNeedToImplPropMap;
+ // Gather properties which need not be implemented in this class
+ // or category.
+ if (!IDecl)
+ if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {
+ // For categories, no need to implement properties declared in
+ // its primary class (and its super classes) if property is
+ // declared in one of those containers.
+ if ((IDecl = C->getClassInterface())) {
+ ObjCInterfaceDecl::PropertyDeclOrder PO;
+ IDecl->collectPropertiesToImplement(NoNeedToImplPropMap, PO);
+ }
+ }
+ if (IDecl)
+ CollectSuperClassPropertyImplementations(IDecl, NoNeedToImplPropMap);
+
+ CollectImmediateProperties(CDecl, PropMap, NoNeedToImplPropMap);
+ }
+
+ // Scan the @interface to see if any of the protocols it adopts
+ // require an explicit implementation, via attribute
+ // 'objc_protocol_requires_explicit_implementation'.
+ if (IDecl) {
+ std::unique_ptr<ObjCContainerDecl::PropertyMap> LazyMap;
+
+ for (auto *PDecl : IDecl->all_referenced_protocols()) {
+ if (!PDecl->hasAttr<ObjCExplicitProtocolImplAttr>())
+ continue;
+ // Lazily construct a set of all the properties in the @interface
+ // of the class, without looking at the superclass. We cannot
+ // use the call to CollectImmediateProperties() above as that
+ // utilizes information from the super class's properties as well
+ // as scans the adopted protocols. This work only triggers for protocols
+ // with the attribute, which is very rare, and only occurs when
+ // analyzing the @implementation.
+ if (!LazyMap) {
+ ObjCContainerDecl::PropertyMap NoNeedToImplPropMap;
+ LazyMap.reset(new ObjCContainerDecl::PropertyMap());
+ CollectImmediateProperties(CDecl, *LazyMap, NoNeedToImplPropMap,
+ /* IncludeProtocols */ false);
+ }
+ // Add the properties of 'PDecl' to the list of properties that
+ // need to be implemented.
+ for (auto *PropDecl : PDecl->properties()) {
+ if ((*LazyMap)[PropDecl->getIdentifier()])
+ continue;
+ PropMap[PropDecl->getIdentifier()] = PropDecl;
}
}
- if (IDecl)
- CollectSuperClassPropertyImplementations(IDecl, NoNeedToImplPropMap);
-
- ObjCContainerDecl::PropertyMap PropMap;
- CollectImmediateProperties(CDecl, PropMap, NoNeedToImplPropMap);
+ }
+
if (PropMap.empty())
return;
llvm::DenseSet<ObjCPropertyDecl *> PropImplMap;
- for (ObjCImplDecl::propimpl_iterator
- I = IMPDecl->propimpl_begin(),
- EI = IMPDecl->propimpl_end(); I != EI; ++I)
+ for (const auto *I : IMPDecl->property_impls())
PropImplMap.insert(I->getPropertyDecl());
SelectorSet InsMap;
// Collect property accessors implemented in current implementation.
- for (ObjCImplementationDecl::instmeth_iterator
- I = IMPDecl->instmeth_begin(), E = IMPDecl->instmeth_end(); I!=E; ++I)
- InsMap.insert((*I)->getSelector());
+ for (const auto *I : IMPDecl->instance_methods())
+ InsMap.insert(I->getSelector());
ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl);
- ObjCInterfaceDecl *PrimaryClass = 0;
+ ObjCInterfaceDecl *PrimaryClass = nullptr;
if (C && !C->IsClassExtension())
if ((PrimaryClass = C->getClassInterface()))
// Report unimplemented properties in the category as well.
@@ -1655,9 +1722,8 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
// When reporting on missing setter/getters, do not report when
// setter/getter is implemented in category's primary class
// implementation.
- for (ObjCImplementationDecl::instmeth_iterator
- I = IMP->instmeth_begin(), E = IMP->instmeth_end(); I!=E; ++I)
- InsMap.insert((*I)->getSelector());
+ for (const auto *I : IMP->instance_methods())
+ InsMap.insert(I->getSelector());
}
for (ObjCContainerDecl::PropertyMap::iterator
@@ -1669,45 +1735,14 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
PropImplMap.count(Prop) ||
Prop->getAvailability() == AR_Unavailable)
continue;
- // When reporting on missing property getter implementation in
- // categories, do not report when they are declared in primary class,
- // class's protocol, or one of it super classes. This is because,
- // the class is going to implement them.
- if (!InsMap.count(Prop->getGetterName()) &&
- (PrimaryClass == 0 ||
- !PrimaryClass->lookupPropertyAccessor(Prop->getGetterName(), C))) {
- Diag(IMPDecl->getLocation(),
- isa<ObjCCategoryDecl>(CDecl) ?
- diag::warn_setter_getter_impl_required_in_category :
- diag::warn_setter_getter_impl_required)
- << Prop->getDeclName() << Prop->getGetterName();
- Diag(Prop->getLocation(),
- diag::note_property_declare);
- if (LangOpts.ObjCDefaultSynthProperties && LangOpts.ObjCRuntime.isNonFragile())
- if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CDecl))
- if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs())
- Diag(RID->getLocation(), diag::note_suppressed_class_declare);
-
- }
- // When reporting on missing property setter implementation in
- // categories, do not report when they are declared in primary class,
- // class's protocol, or one of it super classes. This is because,
- // the class is going to implement them.
- if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName()) &&
- (PrimaryClass == 0 ||
- !PrimaryClass->lookupPropertyAccessor(Prop->getSetterName(), C))) {
- Diag(IMPDecl->getLocation(),
- isa<ObjCCategoryDecl>(CDecl) ?
- diag::warn_setter_getter_impl_required_in_category :
- diag::warn_setter_getter_impl_required)
- << Prop->getDeclName() << Prop->getSetterName();
- Diag(Prop->getLocation(),
- diag::note_property_declare);
- if (LangOpts.ObjCDefaultSynthProperties && LangOpts.ObjCRuntime.isNonFragile())
- if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CDecl))
- if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs())
- Diag(RID->getLocation(), diag::note_suppressed_class_declare);
- }
+
+ // Diagnose unimplemented getters and setters.
+ DiagnoseUnimplementedAccessor(*this,
+ PrimaryClass, Prop->getGetterName(), IMPDecl, CDecl, C, Prop, InsMap);
+ if (!Prop->isReadOnly())
+ DiagnoseUnimplementedAccessor(*this,
+ PrimaryClass, Prop->getSetterName(),
+ IMPDecl, CDecl, C, Prop, InsMap);
}
}
@@ -1717,12 +1752,9 @@ Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
// Rules apply in non-GC mode only
if (getLangOpts().getGC() != LangOptions::NonGC)
return;
- for (ObjCContainerDecl::prop_iterator I = IDecl->prop_begin(),
- E = IDecl->prop_end();
- I != E; ++I) {
- ObjCPropertyDecl *Property = *I;
- ObjCMethodDecl *GetterMethod = 0;
- ObjCMethodDecl *SetterMethod = 0;
+ for (const auto *Property : IDecl->properties()) {
+ ObjCMethodDecl *GetterMethod = nullptr;
+ ObjCMethodDecl *SetterMethod = nullptr;
bool LookedUpGetterSetter = false;
unsigned Attributes = Property->getPropertyAttributes();
@@ -1758,15 +1790,14 @@ Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
if (!LookedUpGetterSetter) {
GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName());
SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName());
- LookedUpGetterSetter = true;
}
if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) {
SourceLocation MethodLoc =
(GetterMethod ? GetterMethod->getLocation()
: SetterMethod->getLocation());
Diag(MethodLoc, diag::warn_atomic_property_rule)
- << Property->getIdentifier() << (GetterMethod != 0)
- << (SetterMethod != 0);
+ << Property->getIdentifier() << (GetterMethod != nullptr)
+ << (SetterMethod != nullptr);
// fixit stuff.
if (!AttributesAsWritten) {
if (Property->getLParenLoc().isValid()) {
@@ -1805,12 +1836,7 @@ void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D
if (getLangOpts().getGC() == LangOptions::GCOnly)
return;
- for (ObjCImplementationDecl::propimpl_iterator
- i = D->propimpl_begin(), e = D->propimpl_end(); i != e; ++i) {
- ObjCPropertyImplDecl *PID = *i;
- if (PID->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize)
- continue;
-
+ for (const auto *PID : D->property_impls()) {
const ObjCPropertyDecl *PD = PID->getPropertyDecl();
if (PD && !PD->hasAttr<NSReturnsNotRetainedAttr>() &&
!D->getInstanceMethod(PD->getGetterName())) {
@@ -1821,27 +1847,51 @@ void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D
if (family == OMF_alloc || family == OMF_copy ||
family == OMF_mutableCopy || family == OMF_new) {
if (getLangOpts().ObjCAutoRefCount)
- Diag(PID->getLocation(), diag::err_ownin_getter_rule);
+ Diag(PD->getLocation(), diag::err_cocoa_naming_owned_rule);
else
- Diag(PID->getLocation(), diag::warn_owning_getter_rule);
- Diag(PD->getLocation(), diag::note_property_declare);
+ Diag(PD->getLocation(), diag::warn_cocoa_naming_owned_rule);
}
}
}
}
+void Sema::DiagnoseMissingDesignatedInitOverrides(
+ const ObjCImplementationDecl *ImplD,
+ const ObjCInterfaceDecl *IFD) {
+ assert(IFD->hasDesignatedInitializers());
+ const ObjCInterfaceDecl *SuperD = IFD->getSuperClass();
+ if (!SuperD)
+ return;
+
+ SelectorSet InitSelSet;
+ for (const auto *I : ImplD->instance_methods())
+ if (I->getMethodFamily() == OMF_init)
+ InitSelSet.insert(I->getSelector());
+
+ SmallVector<const ObjCMethodDecl *, 8> DesignatedInits;
+ SuperD->getDesignatedInitializers(DesignatedInits);
+ for (SmallVector<const ObjCMethodDecl *, 8>::iterator
+ I = DesignatedInits.begin(), E = DesignatedInits.end(); I != E; ++I) {
+ const ObjCMethodDecl *MD = *I;
+ if (!InitSelSet.count(MD->getSelector())) {
+ Diag(ImplD->getLocation(),
+ diag::warn_objc_implementation_missing_designated_init_override)
+ << MD->getSelector();
+ Diag(MD->getLocation(), diag::note_objc_designated_init_marked_here);
+ }
+ }
+}
+
/// AddPropertyAttrs - Propagates attributes from a property to the
/// implicitly-declared getter or setter for that property.
static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod,
ObjCPropertyDecl *Property) {
// Should we just clone all attributes over?
- for (Decl::attr_iterator A = Property->attr_begin(),
- AEnd = Property->attr_end();
- A != AEnd; ++A) {
- if (isa<DeprecatedAttr>(*A) ||
- isa<UnavailableAttr>(*A) ||
- isa<AvailabilityAttr>(*A))
- PropertyMethod->addAttr((*A)->clone(S.Context));
+ for (const auto *A : Property->attrs()) {
+ if (isa<DeprecatedAttr>(A) ||
+ isa<UnavailableAttr>(A) ||
+ isa<AvailabilityAttr>(A))
+ PropertyMethod->addAttr(A->clone(S.Context));
}
}
@@ -1857,6 +1907,9 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
ObjCMethodDecl *GetterMethod, *SetterMethod;
+ if (CD->isInvalidDecl())
+ return;
+
GetterMethod = CD->getInstanceMethod(property->getGetterName());
SetterMethod = CD->getInstanceMethod(property->getSetterName());
DiagnosePropertyAccessorMismatch(property, GetterMethod,
@@ -1866,8 +1919,8 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
ObjCPropertyDecl::PropertyAttributeKind CAttr =
property->getPropertyAttributes();
if ((!(CAttr & ObjCPropertyDecl::OBJC_PR_readonly)) &&
- Context.getCanonicalType(SetterMethod->getResultType()) !=
- Context.VoidTy)
+ Context.getCanonicalType(SetterMethod->getReturnType()) !=
+ Context.VoidTy)
Diag(SetterMethod->getLocation(), diag::err_setter_type_void);
if (SetterMethod->param_size() != 1 ||
!Context.hasSameUnqualifiedType(
@@ -1897,8 +1950,9 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
GetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc,
property->getGetterName(),
- property->getType(), 0, CD, /*isInstance=*/true,
- /*isVariadic=*/false, /*isPropertyAccessor=*/true,
+ property->getType(), nullptr, CD,
+ /*isInstance=*/true, /*isVariadic=*/false,
+ /*isPropertyAccessor=*/true,
/*isImplicitlyDeclared=*/true, /*isDefined=*/false,
(property->getPropertyImplementation() ==
ObjCPropertyDecl::Optional) ?
@@ -1913,12 +1967,17 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
if (lexicalDC)
GetterMethod->setLexicalDeclContext(lexicalDC);
if (property->hasAttr<NSReturnsNotRetainedAttr>())
- GetterMethod->addAttr(
- ::new (Context) NSReturnsNotRetainedAttr(Loc, Context));
+ GetterMethod->addAttr(NSReturnsNotRetainedAttr::CreateImplicit(Context,
+ Loc));
if (property->hasAttr<ObjCReturnsInnerPointerAttr>())
GetterMethod->addAttr(
- ::new (Context) ObjCReturnsInnerPointerAttr(Loc, Context));
+ ObjCReturnsInnerPointerAttr::CreateImplicit(Context, Loc));
+
+ if (const SectionAttr *SA = property->getAttr<SectionAttr>())
+ GetterMethod->addAttr(
+ SectionAttr::CreateImplicit(Context, SectionAttr::GNU_section,
+ SA->getName(), Loc));
if (getLangOpts().ObjCAutoRefCount)
CheckARCMethodDecl(GetterMethod);
@@ -1941,8 +2000,9 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
SetterMethod =
ObjCMethodDecl::Create(Context, Loc, Loc,
- property->getSetterName(), Context.VoidTy, 0,
- CD, /*isInstance=*/true, /*isVariadic=*/false,
+ property->getSetterName(), Context.VoidTy,
+ nullptr, CD, /*isInstance=*/true,
+ /*isVariadic=*/false,
/*isPropertyAccessor=*/true,
/*isImplicitlyDeclared=*/true,
/*isDefined=*/false,
@@ -1957,9 +2017,9 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
Loc, Loc,
property->getIdentifier(),
property->getType().getUnqualifiedType(),
- /*TInfo=*/0,
+ /*TInfo=*/nullptr,
SC_None,
- 0);
+ nullptr);
SetterMethod->setMethodParams(Context, Argument, None);
AddPropertyAttrs(*this, SetterMethod, property);
@@ -1969,7 +2029,10 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
// and the real context should be the same.
if (lexicalDC)
SetterMethod->setLexicalDeclContext(lexicalDC);
-
+ if (const SectionAttr *SA = property->getAttr<SectionAttr>())
+ SetterMethod->addAttr(
+ SectionAttr::CreateImplicit(Context, SectionAttr::GNU_section,
+ SA->getName(), Loc));
// It's possible for the user to have set a very odd custom
// setter selector that causes it to have a method family.
if (getLangOpts().ObjCAutoRefCount)
@@ -2027,27 +2090,19 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
QualType PropertyTy = PropertyDecl->getType();
unsigned PropertyOwnership = getOwnershipRule(Attributes);
- if (Attributes & ObjCDeclSpec::DQ_PR_readonly) {
- if (getLangOpts().ObjCAutoRefCount &&
- PropertyTy->isObjCRetainableType() &&
- !PropertyOwnership) {
- // 'readonly' property with no obvious lifetime.
- // its life time will be determined by its backing ivar.
- return;
- }
- else if (PropertyOwnership) {
- if (!getSourceManager().isInSystemHeader(Loc))
- Diag(Loc, diag::warn_objc_property_attr_mutually_exclusive)
- << "readonly" << NameOfOwnershipAttribute(Attributes);
- return;
- }
- }
+ // 'readonly' property with no obvious lifetime.
+ // its life time will be determined by its backing ivar.
+ if (getLangOpts().ObjCAutoRefCount &&
+ Attributes & ObjCDeclSpec::DQ_PR_readonly &&
+ PropertyTy->isObjCRetainableType() &&
+ !PropertyOwnership)
+ return;
// Check for copy or retain on non-object types.
if ((Attributes & (ObjCDeclSpec::DQ_PR_weak | ObjCDeclSpec::DQ_PR_copy |
ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong)) &&
!PropertyTy->isObjCRetainableType() &&
- !PropertyDecl->getAttr<ObjCNSObjectAttr>()) {
+ !PropertyDecl->hasAttr<ObjCNSObjectAttr>()) {
Diag(Loc, diag::err_objc_property_requires_object)
<< (Attributes & ObjCDeclSpec::DQ_PR_weak ? "weak" :
Attributes & ObjCDeclSpec::DQ_PR_copy ? "copy" : "retain (or strong)");
@@ -2079,7 +2134,7 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
<< "assign" << "weak";
Attributes &= ~ObjCDeclSpec::DQ_PR_weak;
}
- if (PropertyDecl->getAttr<IBOutletCollectionAttr>())
+ if (PropertyDecl->hasAttr<IBOutletCollectionAttr>())
Diag(Loc, diag::warn_iboutletcollection_property_assign);
} else if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) {
if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
index c63caf4..7f2af68 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
@@ -1,4 +1,4 @@
-//===--- SemaOpenMP.cpp - Semantic Analysis for OpenMP constructs ----------===//
+//===--- SemaOpenMP.cpp - Semantic Analysis for OpenMP constructs ---------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,19 +12,20 @@
///
//===----------------------------------------------------------------------===//
-#include "clang/Basic/OpenMPKinds.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtOpenMP.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/OpenMPKinds.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
-#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/SemaInternal.h"
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -34,11 +35,31 @@ using namespace clang;
namespace {
/// \brief 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, /// \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'.
+};
+
+template <class T> struct MatchesAny {
+ explicit MatchesAny(ArrayRef<T> Arr) : Arr(std::move(Arr)) {}
+ bool operator()(T Kind) {
+ for (auto KindEl : Arr)
+ if (KindEl == Kind)
+ return true;
+ return false;
+ }
+
+private:
+ ArrayRef<T> Arr;
+};
+struct MatchesAlways {
+ MatchesAlways() {}
+ template <class T> bool operator()(T) { return true; }
};
+typedef MatchesAny<OpenMPClauseKind> MatchesAnyClause;
+typedef MatchesAny<OpenMPDirectiveKind> MatchesAnyDirective;
+
/// \brief Stack for tracking declarations used in OpenMP directives and
/// clauses and their data-sharing attributes.
class DSAStackTy {
@@ -47,47 +68,60 @@ public:
OpenMPDirectiveKind DKind;
OpenMPClauseKind CKind;
DeclRefExpr *RefExpr;
- DSAVarData() : DKind(OMPD_unknown), CKind(OMPC_unknown), RefExpr(0) { }
+ SourceLocation ImplicitDSALoc;
+ DSAVarData()
+ : DKind(OMPD_unknown), CKind(OMPC_unknown), RefExpr(nullptr),
+ ImplicitDSALoc() {}
};
+
private:
struct DSAInfo {
OpenMPClauseKind Attributes;
DeclRefExpr *RefExpr;
};
typedef llvm::SmallDenseMap<VarDecl *, DSAInfo, 64> DeclSAMapTy;
+ typedef llvm::SmallDenseMap<VarDecl *, DeclRefExpr *, 64> AlignedMapTy;
struct SharingMapTy {
DeclSAMapTy SharingMap;
+ AlignedMapTy AlignedMap;
DefaultDataSharingAttributes DefaultAttr;
+ SourceLocation DefaultAttrLoc;
OpenMPDirectiveKind Directive;
DeclarationNameInfo DirectiveName;
Scope *CurScope;
- SharingMapTy(OpenMPDirectiveKind DKind,
- const DeclarationNameInfo &Name,
- Scope *CurScope)
- : SharingMap(), DefaultAttr(DSA_unspecified), Directive(DKind),
- DirectiveName(Name), CurScope(CurScope) { }
+ SourceLocation ConstructLoc;
+ SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
+ Scope *CurScope, SourceLocation Loc)
+ : SharingMap(), AlignedMap(), DefaultAttr(DSA_unspecified),
+ Directive(DKind), DirectiveName(std::move(Name)), CurScope(CurScope),
+ ConstructLoc(Loc) {}
SharingMapTy()
- : SharingMap(), DefaultAttr(DSA_unspecified),
- Directive(OMPD_unknown), DirectiveName(),
- CurScope(0) { }
+ : SharingMap(), AlignedMap(), DefaultAttr(DSA_unspecified),
+ Directive(OMPD_unknown), DirectiveName(), CurScope(nullptr),
+ ConstructLoc() {}
};
typedef SmallVector<SharingMapTy, 64> StackTy;
/// \brief Stack of used declaration and their data-sharing attributes.
StackTy Stack;
- Sema &Actions;
+ Sema &SemaRef;
typedef SmallVector<SharingMapTy, 8>::reverse_iterator reverse_iterator;
DSAVarData getDSA(StackTy::reverse_iterator Iter, VarDecl *D);
+
+ /// \brief Checks if the variable is a local for OpenMP region.
+ bool isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter);
+
public:
- explicit DSAStackTy(Sema &S) : Stack(1), Actions(S) { }
+ explicit DSAStackTy(Sema &S) : Stack(1), SemaRef(S) {}
void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
- Scope *CurScope) {
- Stack.push_back(SharingMapTy(DKind, DirName, CurScope));
+ Scope *CurScope, SourceLocation Loc) {
+ Stack.push_back(SharingMapTy(DKind, DirName, CurScope, Loc));
+ Stack.back().DefaultAttrLoc = Loc;
}
void pop() {
@@ -95,51 +129,90 @@ public:
Stack.pop_back();
}
+ /// \brief 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.
+ DeclRefExpr *addUniqueAligned(VarDecl *D, DeclRefExpr *NewDE);
+
/// \brief Adds explicit data sharing attribute to the specified declaration.
void addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A);
- /// \brief Checks if the variable is a local for OpenMP region.
- bool isOpenMPLocal(VarDecl *D);
-
/// \brief Returns data sharing attributes from top of the stack for the
/// specified declaration.
- DSAVarData getTopDSA(VarDecl *D);
+ DSAVarData getTopDSA(VarDecl *D, bool FromParent);
/// \brief Returns data-sharing attributes for the specified declaration.
- DSAVarData getImplicitDSA(VarDecl *D);
- /// \brief Checks if the specified variables has \a CKind data-sharing
- /// attribute in \a DKind directive.
- DSAVarData hasDSA(VarDecl *D, OpenMPClauseKind CKind,
- OpenMPDirectiveKind DKind = OMPD_unknown);
-
+ DSAVarData getImplicitDSA(VarDecl *D, bool FromParent);
+ /// \brief Checks if the specified variables has data-sharing attributes which
+ /// match specified \a CPred predicate in any directive which matches \a DPred
+ /// predicate.
+ template <class ClausesPredicate, class DirectivesPredicate>
+ DSAVarData hasDSA(VarDecl *D, ClausesPredicate CPred,
+ DirectivesPredicate DPred, bool FromParent);
+ /// \brief Checks if the specified variables has data-sharing attributes which
+ /// match specified \a CPred predicate in any innermost directive which
+ /// matches \a DPred predicate.
+ template <class ClausesPredicate, class DirectivesPredicate>
+ DSAVarData hasInnermostDSA(VarDecl *D, ClausesPredicate CPred,
+ DirectivesPredicate DPred,
+ bool FromParent);
+ /// \brief Finds a directive which matches specified \a DPred predicate.
+ template <class NamedDirectivesPredicate>
+ bool hasDirective(NamedDirectivesPredicate DPred, bool FromParent);
/// \brief Returns currently analyzed directive.
OpenMPDirectiveKind getCurrentDirective() const {
return Stack.back().Directive;
}
+ /// \brief Returns parent directive.
+ OpenMPDirectiveKind getParentDirective() const {
+ if (Stack.size() > 2)
+ return Stack[Stack.size() - 2].Directive;
+ return OMPD_unknown;
+ }
/// \brief Set default data sharing attribute to none.
- void setDefaultDSANone() { Stack.back().DefaultAttr = DSA_none; }
+ void setDefaultDSANone(SourceLocation Loc) {
+ Stack.back().DefaultAttr = DSA_none;
+ Stack.back().DefaultAttrLoc = Loc;
+ }
/// \brief Set default data sharing attribute to shared.
- void setDefaultDSAShared() { Stack.back().DefaultAttr = DSA_shared; }
+ void setDefaultDSAShared(SourceLocation Loc) {
+ Stack.back().DefaultAttr = DSA_shared;
+ Stack.back().DefaultAttrLoc = Loc;
+ }
DefaultDataSharingAttributes getDefaultDSA() const {
return Stack.back().DefaultAttr;
}
+ SourceLocation getDefaultDSALocation() const {
+ return Stack.back().DefaultAttrLoc;
+ }
+ /// \brief Checks if the specified variable is a threadprivate.
+ bool isThreadPrivate(VarDecl *D) {
+ DSAVarData DVar = getTopDSA(D, false);
+ return isOpenMPThreadPrivate(DVar.CKind);
+ }
+
+ Scope *getCurScope() const { return Stack.back().CurScope; }
Scope *getCurScope() { return Stack.back().CurScope; }
+ SourceLocation getConstructLoc() { return Stack.back().ConstructLoc; }
};
-} // end anonymous namespace.
+bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) {
+ return isOpenMPParallelDirective(DKind) || DKind == OMPD_task ||
+ DKind == OMPD_unknown;
+}
+} // namespace
DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter,
VarDecl *D) {
DSAVarData DVar;
- if (Iter == Stack.rend() - 1) {
+ if (Iter == std::prev(Stack.rend())) {
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
// in a region but not in construct]
// File-scope or namespace-scope variables referenced in called routines
// in the region are shared unless they appear in a threadprivate
// directive.
- // TODO
if (!D->isFunctionOrMethodVarDecl())
DVar.CKind = OMPC_shared;
@@ -152,12 +225,24 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter,
return DVar;
}
+
DVar.DKind = Iter->Directive;
+ // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // in a Construct, C/C++, predetermined, p.1]
+ // Variables with automatic storage duration that are declared in a scope
+ // inside the construct are private.
+ if (isOpenMPLocal(D, Iter) && D->isLocalVarDecl() &&
+ (D->getStorageClass() == SC_Auto || D->getStorageClass() == SC_None)) {
+ DVar.CKind = OMPC_private;
+ return DVar;
+ }
+
// Explicitly specified attributes and local variables with predetermined
// attributes.
if (Iter->SharingMap.count(D)) {
DVar.RefExpr = Iter->SharingMap[D].RefExpr;
DVar.CKind = Iter->SharingMap[D].Attributes;
+ DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
return DVar;
}
@@ -168,6 +253,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter,
switch (Iter->DefaultAttr) {
case DSA_shared:
DVar.CKind = OMPC_shared;
+ DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
return DVar;
case DSA_none:
return DVar;
@@ -176,7 +262,8 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter,
// in a Construct, implicitly determined, p.2]
// In a parallel construct, if no default clause is present, these
// variables are shared.
- if (DVar.DKind == OMPD_parallel) {
+ DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
+ if (isOpenMPParallelDirective(DVar.DKind)) {
DVar.CKind = OMPC_shared;
return DVar;
}
@@ -186,29 +273,30 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter,
// In a task construct, if no default clause is present, a variable that in
// the enclosing context is determined to be shared by all implicit tasks
// bound to the current team is shared.
- // TODO
if (DVar.DKind == OMPD_task) {
DSAVarData DVarTemp;
- for (StackTy::reverse_iterator I = Iter + 1,
- EE = Stack.rend() - 1;
+ for (StackTy::reverse_iterator I = std::next(Iter),
+ EE = std::prev(Stack.rend());
I != EE; ++I) {
- // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
+ // Referenced
// in a Construct, implicitly determined, p.6]
// In a task construct, if no default clause is present, a variable
// whose data-sharing attribute is not determined by the rules above is
// firstprivate.
DVarTemp = getDSA(I, D);
if (DVarTemp.CKind != OMPC_shared) {
- DVar.RefExpr = 0;
+ DVar.RefExpr = nullptr;
DVar.DKind = OMPD_task;
DVar.CKind = OMPC_firstprivate;
return DVar;
}
- if (I->Directive == OMPD_parallel) break;
+ if (isParallelOrTaskRegion(I->Directive))
+ break;
}
DVar.DKind = OMPD_task;
DVar.CKind =
- (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
+ (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
return DVar;
}
}
@@ -217,7 +305,21 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter,
// For constructs other than task, if no default clause is present, these
// variables inherit their data-sharing attributes from the enclosing
// context.
- return getDSA(Iter + 1, D);
+ return getDSA(std::next(Iter), D);
+}
+
+DeclRefExpr *DSAStackTy::addUniqueAligned(VarDecl *D, DeclRefExpr *NewDE) {
+ assert(Stack.size() > 1 && "Data sharing attributes stack is empty");
+ auto It = Stack.back().AlignedMap.find(D);
+ if (It == Stack.back().AlignedMap.end()) {
+ assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
+ Stack.back().AlignedMap[D] = NewDE;
+ return nullptr;
+ } else {
+ assert(It->second && "Unexpected nullptr expr in the aligned map");
+ return It->second;
+ }
+ return nullptr;
}
void DSAStackTy::addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A) {
@@ -231,26 +333,26 @@ void DSAStackTy::addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A) {
}
}
-bool DSAStackTy::isOpenMPLocal(VarDecl *D) {
- Scope *CurScope = getCurScope();
- while (CurScope && !CurScope->isDeclScope(D))
- CurScope = CurScope->getParent();
- while (CurScope && !CurScope->isOpenMPDirectiveScope())
- CurScope = CurScope->getParent();
- bool isOpenMPLocal = !!CurScope;
- if (!isOpenMPLocal) {
- CurScope = getCurScope();
- while (CurScope && !CurScope->isOpenMPDirectiveScope())
+bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
+ if (Stack.size() > 2) {
+ reverse_iterator I = Iter, E = std::prev(Stack.rend());
+ Scope *TopScope = nullptr;
+ while (I != E && !isParallelOrTaskRegion(I->Directive)) {
+ ++I;
+ }
+ if (I == E)
+ return false;
+ TopScope = I->CurScope ? I->CurScope->getParent() : nullptr;
+ Scope *CurScope = getCurScope();
+ while (CurScope != TopScope && !CurScope->isDeclScope(D)) {
CurScope = CurScope->getParent();
- isOpenMPLocal =
- CurScope &&
- isa<CapturedDecl>(D->getDeclContext()) &&
- CurScope->getFnParent()->getEntity()->Encloses(D->getDeclContext());
+ }
+ return CurScope != TopScope;
}
- return isOpenMPLocal;
+ return false;
}
-DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D) {
+DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) {
DSAVarData DVar;
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
@@ -270,20 +372,29 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D) {
// in a Construct, C/C++, predetermined, p.1]
// Variables with automatic storage duration that are declared in a scope
// inside the construct are private.
- if (isOpenMPLocal(D) && D->isLocalVarDecl() &&
- (D->getStorageClass() == SC_Auto ||
- D->getStorageClass() == SC_None)) {
- DVar.CKind = OMPC_private;
- return DVar;
+ OpenMPDirectiveKind Kind =
+ FromParent ? getParentDirective() : getCurrentDirective();
+ auto StartI = std::next(Stack.rbegin());
+ auto EndI = std::prev(Stack.rend());
+ if (FromParent && StartI != EndI) {
+ StartI = std::next(StartI);
+ }
+ if (!isParallelOrTaskRegion(Kind)) {
+ if (isOpenMPLocal(D, StartI) && D->isLocalVarDecl() &&
+ (D->getStorageClass() == SC_Auto || D->getStorageClass() == SC_None)) {
+ DVar.CKind = OMPC_private;
+ return DVar;
+ }
}
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
// in a Construct, C/C++, predetermined, p.4]
- // Static data memebers are shared.
+ // Static data members are shared.
if (D->isStaticDataMember()) {
- // 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, OMPC_firstprivate);
+ // 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, MatchesAnyClause(OMPC_firstprivate),
+ MatchesAlways(), FromParent);
if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr)
return DVar;
@@ -292,7 +403,7 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D) {
}
QualType Type = D->getType().getNonReferenceType().getCanonicalType();
- bool IsConstant = Type.isConstant(Actions.getASTContext());
+ bool IsConstant = Type.isConstant(SemaRef.getASTContext());
while (Type->isArrayType()) {
QualType ElemType = cast<ArrayType>(Type.getTypePtr())->getElementType();
Type = ElemType.getNonReferenceType().getCanonicalType();
@@ -301,13 +412,14 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D) {
// in a Construct, C/C++, predetermined, p.6]
// Variables with const qualified type having no mutable member are
// shared.
- CXXRecordDecl *RD = Actions.getLangOpts().CPlusPlus ?
- Type->getAsCXXRecordDecl() : 0;
+ CXXRecordDecl *RD =
+ SemaRef.getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr;
if (IsConstant &&
- !(Actions.getLangOpts().CPlusPlus && RD && RD->hasMutableFields())) {
+ !(SemaRef.getLangOpts().CPlusPlus && RD && 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, OMPC_firstprivate);
+ DSAVarData DVarTemp = hasDSA(D, MatchesAnyClause(OMPC_firstprivate),
+ MatchesAlways(), FromParent);
if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr)
return DVar;
@@ -319,56 +431,151 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D) {
// in a Construct, C/C++, predetermined, p.7]
// Variables with static storage duration that are declared in a scope
// inside the construct are shared.
- if (isOpenMPLocal(D) && D->isStaticLocal()) {
+ if (D->isStaticLocal()) {
DVar.CKind = OMPC_shared;
return DVar;
}
// Explicitly specified attributes and local variables with predetermined
// attributes.
- if (Stack.back().SharingMap.count(D)) {
- DVar.RefExpr = Stack.back().SharingMap[D].RefExpr;
- DVar.CKind = Stack.back().SharingMap[D].Attributes;
+ auto I = std::prev(StartI);
+ if (I->SharingMap.count(D)) {
+ DVar.RefExpr = I->SharingMap[D].RefExpr;
+ DVar.CKind = I->SharingMap[D].Attributes;
+ DVar.ImplicitDSALoc = I->DefaultAttrLoc;
}
return DVar;
}
-DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(VarDecl *D) {
- return getDSA(Stack.rbegin() + 1, D);
+DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(VarDecl *D, bool FromParent) {
+ auto StartI = Stack.rbegin();
+ auto EndI = std::prev(Stack.rend());
+ if (FromParent && StartI != EndI) {
+ StartI = std::next(StartI);
+ }
+ return getDSA(StartI, D);
+}
+
+template <class ClausesPredicate, class DirectivesPredicate>
+DSAStackTy::DSAVarData DSAStackTy::hasDSA(VarDecl *D, ClausesPredicate CPred,
+ DirectivesPredicate DPred,
+ bool FromParent) {
+ auto StartI = std::next(Stack.rbegin());
+ auto EndI = std::prev(Stack.rend());
+ if (FromParent && StartI != EndI) {
+ StartI = std::next(StartI);
+ }
+ for (auto I = StartI, EE = EndI; I != EE; ++I) {
+ if (!DPred(I->Directive) && !isParallelOrTaskRegion(I->Directive))
+ continue;
+ DSAVarData DVar = getDSA(I, D);
+ if (CPred(DVar.CKind))
+ return DVar;
+ }
+ return DSAVarData();
}
-DSAStackTy::DSAVarData DSAStackTy::hasDSA(VarDecl *D, OpenMPClauseKind CKind,
- OpenMPDirectiveKind DKind) {
- for (StackTy::reverse_iterator I = Stack.rbegin() + 1,
- E = Stack.rend() - 1;
- I != E; ++I) {
- if (DKind != OMPD_unknown && DKind != I->Directive) continue;
+template <class ClausesPredicate, class DirectivesPredicate>
+DSAStackTy::DSAVarData
+DSAStackTy::hasInnermostDSA(VarDecl *D, ClausesPredicate CPred,
+ DirectivesPredicate DPred, bool FromParent) {
+ auto StartI = std::next(Stack.rbegin());
+ auto EndI = std::prev(Stack.rend());
+ if (FromParent && StartI != EndI) {
+ StartI = std::next(StartI);
+ }
+ for (auto I = StartI, EE = EndI; I != EE; ++I) {
+ if (!DPred(I->Directive))
+ break;
DSAVarData DVar = getDSA(I, D);
- if (DVar.CKind == CKind)
+ if (CPred(DVar.CKind))
return DVar;
+ return DSAVarData();
}
return DSAVarData();
}
+template <class NamedDirectivesPredicate>
+bool DSAStackTy::hasDirective(NamedDirectivesPredicate DPred, bool FromParent) {
+ auto StartI = std::next(Stack.rbegin());
+ auto EndI = std::prev(Stack.rend());
+ if (FromParent && StartI != EndI) {
+ StartI = std::next(StartI);
+ }
+ for (auto I = StartI, EE = EndI; I != EE; ++I) {
+ if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
+ return true;
+ }
+ return false;
+}
+
void Sema::InitDataSharingAttributesStack() {
VarDataSharingAttributesStack = new DSAStackTy(*this);
}
#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
-void Sema::DestroyDataSharingAttributesStack() {
- delete DSAStack;
-}
+void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; }
void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
const DeclarationNameInfo &DirName,
- Scope *CurScope) {
- DSAStack->push(DKind, DirName, CurScope);
+ Scope *CurScope, SourceLocation Loc) {
+ DSAStack->push(DKind, DirName, CurScope, Loc);
PushExpressionEvaluationContext(PotentiallyEvaluated);
}
void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
+ // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
+ // A variable of class type (or array thereof) that appears in a lastprivate
+ // 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 (auto Clause = dyn_cast<OMPLastprivateClause>(C)) {
+ for (auto VarRef : Clause->varlists()) {
+ if (VarRef->isValueDependent() || VarRef->isTypeDependent())
+ continue;
+ auto VD = cast<VarDecl>(cast<DeclRefExpr>(VarRef)->getDecl());
+ auto DVar = DSAStack->getTopDSA(VD, false);
+ if (DVar.CKind == OMPC_lastprivate) {
+ SourceLocation ELoc = VarRef->getExprLoc();
+ auto Type = VarRef->getType();
+ if (Type->isArrayType())
+ Type = QualType(Type->getArrayElementTypeNoTypeQual(), 0);
+ CXXRecordDecl *RD =
+ getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr;
+ // FIXME This code must be replaced by actual constructing of the
+ // lastprivate variable.
+ if (RD) {
+ CXXConstructorDecl *CD = LookupDefaultConstructor(RD);
+ PartialDiagnostic PD =
+ PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
+ if (!CD ||
+ CheckConstructorAccess(
+ ELoc, CD, InitializedEntity::InitializeTemporary(Type),
+ CD->getAccess(), PD) == AR_inaccessible ||
+ CD->isDeleted()) {
+ Diag(ELoc, diag::err_omp_required_method)
+ << getOpenMPClauseName(OMPC_lastprivate) << 0;
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl
+ : diag::note_defined_here)
+ << VD;
+ Diag(RD->getLocation(), diag::note_previous_decl) << RD;
+ continue;
+ }
+ MarkFunctionReferenced(ELoc, CD);
+ DiagnoseUseOfDecl(CD, ELoc);
+ }
+ }
+ }
+ }
+ }
+ }
+
DSAStack->pop();
DiscardCleanupsInEvaluationContext();
PopExpressionEvaluationContext();
@@ -378,20 +585,21 @@ namespace {
class VarDeclFilterCCC : public CorrectionCandidateCallback {
private:
- Sema &Actions;
+ Sema &SemaRef;
+
public:
- VarDeclFilterCCC(Sema &S) : Actions(S) { }
- virtual bool ValidateCandidate(const TypoCorrection &Candidate) {
+ explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
+ bool ValidateCandidate(const TypoCorrection &Candidate) override {
NamedDecl *ND = Candidate.getCorrectionDecl();
if (VarDecl *VD = dyn_cast_or_null<VarDecl>(ND)) {
return VD->hasGlobalStorage() &&
- Actions.isDeclInScope(ND, Actions.getCurLexicalContext(),
- Actions.getCurScope());
+ SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
+ SemaRef.getCurScope());
}
return false;
}
};
-}
+} // namespace
ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
CXXScopeSpec &ScopeSpec,
@@ -405,12 +613,14 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
VarDecl *VD;
if (!Lookup.isSingleResult()) {
VarDeclFilterCCC Validator(*this);
- if (TypoCorrection Corrected = CorrectTypo(Id, LookupOrdinaryName, CurScope,
- 0, Validator)) {
+ if (TypoCorrection Corrected =
+ CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, Validator,
+ CTK_ErrorRecovery)) {
diagnoseTypo(Corrected,
- PDiag(Lookup.empty()? diag::err_undeclared_var_use_suggest
- : diag::err_omp_expected_var_arg_suggest)
- << Id.getName());
+ PDiag(Lookup.empty()
+ ? diag::err_undeclared_var_use_suggest
+ : diag::err_omp_expected_var_arg_suggest)
+ << Id.getName());
VD = Corrected.getCorrectionDeclAs<VarDecl>();
} else {
Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
@@ -420,8 +630,7 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
}
} else {
if (!(VD = Lookup.getAsSingle<VarDecl>())) {
- Diag(Id.getLoc(), diag::err_omp_expected_var_arg)
- << Id.getName();
+ Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
return ExprError();
}
@@ -432,12 +641,12 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
// Variables must be file-scope, namespace-scope, or static block-scope.
if (!VD->hasGlobalStorage()) {
Diag(Id.getLoc(), diag::err_omp_global_var_arg)
- << getOpenMPDirectiveName(OMPD_threadprivate)
- << !VD->isStaticLocal();
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
+ << getOpenMPDirectiveName(OMPD_threadprivate) << !VD->isStaticLocal();
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here) << VD;
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
return ExprError();
}
@@ -449,11 +658,12 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
!getCurLexicalContext()->isTranslationUnit()) {
Diag(Id.getLoc(), diag::err_omp_var_scope)
- << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
- diag::note_defined_here) << VD;
+ << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
return ExprError();
}
// OpenMP [2.9.2, Restrictions, C/C++, p.3]
@@ -463,11 +673,12 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
if (CanonicalVD->isStaticDataMember() &&
!CanonicalVD->getDeclContext()->Equals(getCurLexicalContext())) {
Diag(Id.getLoc(), diag::err_omp_var_scope)
- << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
- diag::note_defined_here) << VD;
+ << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
return ExprError();
}
// OpenMP [2.9.2, Restrictions, C/C++, p.4]
@@ -478,11 +689,12 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
(!getCurLexicalContext()->isFileContext() ||
!getCurLexicalContext()->Encloses(CanonicalVD->getDeclContext()))) {
Diag(Id.getLoc(), diag::err_omp_var_scope)
- << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
- diag::note_defined_here) << VD;
+ << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
return ExprError();
}
// OpenMP [2.9.2, Restrictions, C/C++, p.6]
@@ -491,11 +703,12 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
if (CanonicalVD->isStaticLocal() && CurScope &&
!isDeclInScope(ND, getCurLexicalContext(), CurScope)) {
Diag(Id.getLoc(), diag::err_omp_var_scope)
- << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
- diag::note_defined_here) << VD;
+ << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
return ExprError();
}
@@ -504,19 +717,18 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
// of the variables in its list.
if (VD->isUsed()) {
Diag(Id.getLoc(), diag::err_omp_var_used)
- << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
+ << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
return ExprError();
}
QualType ExprType = VD->getType().getNonReferenceType();
- ExprResult DE = BuildDeclRefExpr(VD, ExprType, VK_RValue, Id.getLoc());
- DSAStack->addDSA(VD, cast<DeclRefExpr>(DE.get()), OMPC_threadprivate);
+ ExprResult DE = BuildDeclRefExpr(VD, ExprType, VK_LValue, Id.getLoc());
return DE;
}
-Sema::DeclGroupPtrTy Sema::ActOnOpenMPThreadprivateDirective(
- SourceLocation Loc,
- ArrayRef<Expr *> VarList) {
+Sema::DeclGroupPtrTy
+Sema::ActOnOpenMPThreadprivateDirective(SourceLocation Loc,
+ ArrayRef<Expr *> VarList) {
if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
CurContext->addDecl(D);
return DeclGroupPtrTy::make(DeclGroupRef(D));
@@ -524,14 +736,40 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPThreadprivateDirective(
return DeclGroupPtrTy();
}
-OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl(
- SourceLocation Loc,
- ArrayRef<Expr *> VarList) {
+namespace {
+class LocalVarRefChecker : public ConstStmtVisitor<LocalVarRefChecker, bool> {
+ Sema &SemaRef;
+
+public:
+ bool VisitDeclRefExpr(const DeclRefExpr *E) {
+ if (auto VD = dyn_cast<VarDecl>(E->getDecl())) {
+ if (VD->hasLocalStorage()) {
+ SemaRef.Diag(E->getLocStart(),
+ diag::err_omp_local_var_in_threadprivate_init)
+ << E->getSourceRange();
+ SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
+ << VD << VD->getSourceRange();
+ return true;
+ }
+ }
+ return false;
+ }
+ bool VisitStmt(const Stmt *S) {
+ for (auto Child : S->children()) {
+ if (Child && Visit(Child))
+ return true;
+ }
+ return false;
+ }
+ explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
+};
+} // namespace
+
+OMPThreadPrivateDecl *
+Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
SmallVector<Expr *, 8> Vars;
- for (ArrayRef<Expr *>::iterator I = VarList.begin(),
- E = VarList.end();
- I != E; ++I) {
- DeclRefExpr *DE = cast<DeclRefExpr>(*I);
+ for (auto &RefExpr : VarList) {
+ DeclRefExpr *DE = cast<DeclRefExpr>(RefExpr);
VarDecl *VD = cast<VarDecl>(DE->getDecl());
SourceLocation ILoc = DE->getExprLoc();
@@ -546,64 +784,130 @@ OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl(
// A threadprivate variable must not have a reference type.
if (VD->getType()->isReferenceType()) {
Diag(ILoc, diag::err_omp_ref_type_arg)
- << getOpenMPDirectiveName(OMPD_threadprivate)
- << VD->getType();
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
- diag::note_defined_here) << VD;
+ << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
continue;
}
// Check if this is a TLS variable.
if (VD->getTLSKind()) {
Diag(ILoc, diag::err_omp_var_thread_local) << VD;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
- diag::note_defined_here) << VD;
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
continue;
}
- Vars.push_back(*I);
+ // Check if initial value of threadprivate variable reference variable with
+ // local storage (it is not supported by runtime).
+ if (auto Init = VD->getAnyInitializer()) {
+ LocalVarRefChecker Checker(*this);
+ if (Checker.Visit(Init))
+ continue;
+ }
+
+ Vars.push_back(RefExpr);
+ DSAStack->addDSA(VD, DE, OMPC_threadprivate);
+ }
+ OMPThreadPrivateDecl *D = nullptr;
+ if (!Vars.empty()) {
+ D = OMPThreadPrivateDecl::Create(Context, getCurLexicalContext(), Loc,
+ Vars);
+ D->setAccess(AS_public);
+ }
+ return D;
+}
+
+static void ReportOriginalDSA(Sema &SemaRef, DSAStackTy *Stack,
+ const VarDecl *VD, DSAStackTy::DSAVarData DVar,
+ bool IsLoopIterVar = false) {
+ if (DVar.RefExpr) {
+ SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
+ << getOpenMPClauseName(DVar.CKind);
+ return;
+ }
+ enum {
+ PDSA_StaticMemberShared,
+ PDSA_StaticLocalVarShared,
+ PDSA_LoopIterVarPrivate,
+ PDSA_LoopIterVarLinear,
+ PDSA_LoopIterVarLastprivate,
+ PDSA_ConstVarShared,
+ PDSA_GlobalVarShared,
+ PDSA_TaskVarFirstprivate,
+ PDSA_LocalVarPrivate,
+ PDSA_Implicit
+ } Reason = PDSA_Implicit;
+ bool ReportHint = false;
+ auto ReportLoc = VD->getLocation();
+ if (IsLoopIterVar) {
+ if (DVar.CKind == OMPC_private)
+ Reason = PDSA_LoopIterVarPrivate;
+ else if (DVar.CKind == OMPC_lastprivate)
+ Reason = PDSA_LoopIterVarLastprivate;
+ else
+ Reason = PDSA_LoopIterVarLinear;
+ } else if (DVar.DKind == OMPD_task && DVar.CKind == OMPC_firstprivate) {
+ Reason = PDSA_TaskVarFirstprivate;
+ ReportLoc = DVar.ImplicitDSALoc;
+ } else if (VD->isStaticLocal())
+ Reason = PDSA_StaticLocalVarShared;
+ else if (VD->isStaticDataMember())
+ Reason = PDSA_StaticMemberShared;
+ else if (VD->isFileVarDecl())
+ Reason = PDSA_GlobalVarShared;
+ else if (VD->getType().isConstant(SemaRef.getASTContext()))
+ Reason = PDSA_ConstVarShared;
+ else if (VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
+ ReportHint = true;
+ Reason = PDSA_LocalVarPrivate;
+ }
+ if (Reason != PDSA_Implicit) {
+ SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
+ << Reason << ReportHint
+ << getOpenMPDirectiveName(Stack->getCurrentDirective());
+ } else if (DVar.ImplicitDSALoc.isValid()) {
+ SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
+ << getOpenMPClauseName(DVar.CKind);
}
- return Vars.empty() ?
- 0 : OMPThreadPrivateDecl::Create(Context,
- getCurLexicalContext(),
- Loc, Vars);
}
namespace {
class DSAAttrChecker : public StmtVisitor<DSAAttrChecker, void> {
DSAStackTy *Stack;
- Sema &Actions;
+ Sema &SemaRef;
bool ErrorFound;
CapturedStmt *CS;
llvm::SmallVector<Expr *, 8> ImplicitFirstprivate;
+ llvm::DenseMap<VarDecl *, Expr *> VarsWithInheritedDSA;
+
public:
void VisitDeclRefExpr(DeclRefExpr *E) {
- if(VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) {
+ if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
// Skip internally declared variables.
- if (VD->isLocalVarDecl() && !CS->capturesVariable(VD)) return;
+ if (VD->isLocalVarDecl() && !CS->capturesVariable(VD))
+ return;
- SourceLocation ELoc = E->getExprLoc();
+ auto DVar = Stack->getTopDSA(VD, false);
+ // Check if the variable has explicit DSA set and stop analysis if it so.
+ if (DVar.RefExpr) return;
- OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
- DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD);
- if (DVar.CKind != OMPC_unknown) {
- if (DKind == OMPD_task && DVar.CKind != OMPC_shared &&
- DVar.CKind != OMPC_threadprivate && !DVar.RefExpr)
- ImplicitFirstprivate.push_back(DVar.RefExpr);
- return;
- }
+ auto ELoc = E->getExprLoc();
+ auto 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
// by being listed in a data-sharing attribute clause.
if (DVar.CKind == OMPC_unknown && Stack->getDefaultDSA() == DSA_none &&
- (DKind == OMPD_parallel || DKind == OMPD_task)) {
- ErrorFound = true;
- Actions.Diag(ELoc, diag::err_omp_no_dsa_for_variable) << VD;
+ isParallelOrTaskRegion(DKind) &&
+ VarsWithInheritedDSA.count(VD) == 0) {
+ VarsWithInheritedDSA[VD] = E;
return;
}
@@ -611,84 +915,593 @@ public:
// 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.
- // TODO:
+ DVar = Stack->hasInnermostDSA(VD, MatchesAnyClause(OMPC_reduction),
+ [](OpenMPDirectiveKind K) -> bool {
+ return isOpenMPParallelDirective(K) ||
+ isOpenMPWorksharingDirective(K);
+ },
+ false);
+ if (DKind == OMPD_task && DVar.CKind == OMPC_reduction) {
+ ErrorFound = true;
+ SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
+ ReportOriginalDSA(SemaRef, Stack, VD, DVar);
+ return;
+ }
// Define implicit data-sharing attributes for task.
- DVar = Stack->getImplicitDSA(VD);
+ DVar = Stack->getImplicitDSA(VD, false);
if (DKind == OMPD_task && DVar.CKind != OMPC_shared)
- ImplicitFirstprivate.push_back(DVar.RefExpr);
+ ImplicitFirstprivate.push_back(E);
}
}
void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
- for (ArrayRef<OMPClause *>::iterator I = S->clauses().begin(),
- E = S->clauses().end();
- I != E; ++I)
- if (OMPClause *C = *I)
- for (StmtRange R = C->children(); R; ++R)
- if (Stmt *Child = *R)
- Visit(Child);
+ for (auto *C : S->clauses()) {
+ // Skip analysis of arguments of implicitly defined firstprivate clause
+ // for task directives.
+ if (C && (!isa<OMPFirstprivateClause>(C) || C->getLocStart().isValid()))
+ for (auto *CC : C->children()) {
+ if (CC)
+ Visit(CC);
+ }
+ }
}
void VisitStmt(Stmt *S) {
- for (Stmt::child_iterator I = S->child_begin(), E = S->child_end();
- I != E; ++I)
- if (Stmt *Child = *I)
- if (!isa<OMPExecutableDirective>(Child))
- Visit(Child);
+ for (auto *C : S->children()) {
+ if (C && !isa<OMPExecutableDirective>(C))
+ Visit(C);
}
+ }
bool isErrorFound() { return ErrorFound; }
ArrayRef<Expr *> getImplicitFirstprivate() { return ImplicitFirstprivate; }
+ llvm::DenseMap<VarDecl *, Expr *> &getVarsWithInheritedDSA() {
+ return VarsWithInheritedDSA;
+ }
- DSAAttrChecker(DSAStackTy *S, Sema &Actions, CapturedStmt *CS)
- : Stack(S), Actions(Actions), ErrorFound(false), CS(CS) { }
+ DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
+ : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {}
};
+} // namespace
+
+void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
+ switch (DKind) {
+ case OMPD_parallel: {
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
+ QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty);
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(".global_tid.", KmpInt32PtrTy),
+ std::make_pair(".bound_tid.", KmpInt32PtrTy),
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
+ case OMPD_simd: {
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
+ case OMPD_for: {
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
+ case OMPD_sections: {
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
+ case OMPD_section: {
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
+ case OMPD_single: {
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
+ case OMPD_master: {
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
+ case OMPD_critical: {
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
+ case OMPD_parallel_for: {
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
+ QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty);
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(".global_tid.", KmpInt32PtrTy),
+ std::make_pair(".bound_tid.", KmpInt32PtrTy),
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
+ case OMPD_parallel_sections: {
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
+ case OMPD_task: {
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
+ case OMPD_taskyield: {
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
+ case OMPD_barrier: {
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
+ case OMPD_taskwait: {
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
+ case OMPD_flush: {
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
+ case OMPD_threadprivate:
+ llvm_unreachable("OpenMP Directive is not allowed");
+ case OMPD_unknown:
+ llvm_unreachable("Unknown OpenMP directive");
+ }
+}
+
+static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
+ OpenMPDirectiveKind CurrentRegion,
+ const DeclarationNameInfo &CurrentName,
+ SourceLocation StartLoc) {
+ // Allowed nesting of constructs
+ // +------------------+-----------------+------------------------------------+
+ // | Parent directive | Child directive | Closely (!), No-Closely(+), Both(*)|
+ // +------------------+-----------------+------------------------------------+
+ // | parallel | parallel | * |
+ // | parallel | for | * |
+ // | parallel | master | * |
+ // | parallel | critical | * |
+ // | parallel | simd | * |
+ // | parallel | sections | * |
+ // | parallel | section | + |
+ // | parallel | single | * |
+ // | parallel | parallel for | * |
+ // | parallel |parallel sections| * |
+ // | parallel | task | * |
+ // | parallel | taskyield | * |
+ // | parallel | barrier | * |
+ // | parallel | taskwait | * |
+ // | parallel | flush | * |
+ // +------------------+-----------------+------------------------------------+
+ // | for | parallel | * |
+ // | for | for | + |
+ // | for | master | + |
+ // | for | critical | * |
+ // | for | simd | * |
+ // | for | sections | + |
+ // | for | section | + |
+ // | for | single | + |
+ // | for | parallel for | * |
+ // | for |parallel sections| * |
+ // | for | task | * |
+ // | for | taskyield | * |
+ // | for | barrier | + |
+ // | for | taskwait | * |
+ // | for | flush | * |
+ // +------------------+-----------------+------------------------------------+
+ // | master | parallel | * |
+ // | master | for | + |
+ // | master | master | * |
+ // | master | critical | * |
+ // | master | simd | * |
+ // | master | sections | + |
+ // | master | section | + |
+ // | master | single | + |
+ // | master | parallel for | * |
+ // | master |parallel sections| * |
+ // | master | task | * |
+ // | master | taskyield | * |
+ // | master | barrier | + |
+ // | master | taskwait | * |
+ // | master | flush | * |
+ // +------------------+-----------------+------------------------------------+
+ // | critical | parallel | * |
+ // | critical | for | + |
+ // | critical | master | * |
+ // | critical | critical | * (should have dirrerent names) |
+ // | critical | simd | * |
+ // | critical | sections | + |
+ // | critical | section | + |
+ // | critical | single | + |
+ // | critical | parallel for | * |
+ // | critical |parallel sections| * |
+ // | critical | task | * |
+ // | critical | taskyield | * |
+ // | critical | barrier | + |
+ // | critical | taskwait | * |
+ // +------------------+-----------------+------------------------------------+
+ // | simd | parallel | |
+ // | simd | for | |
+ // | simd | master | |
+ // | simd | critical | |
+ // | simd | simd | |
+ // | simd | sections | |
+ // | simd | section | |
+ // | simd | single | |
+ // | simd | parallel for | |
+ // | simd |parallel sections| |
+ // | simd | task | |
+ // | simd | taskyield | |
+ // | simd | barrier | |
+ // | simd | taskwait | |
+ // | simd | flush | |
+ // +------------------+-----------------+------------------------------------+
+ // | sections | parallel | * |
+ // | sections | for | + |
+ // | sections | master | + |
+ // | sections | critical | * |
+ // | sections | simd | * |
+ // | sections | sections | + |
+ // | sections | section | * |
+ // | sections | single | + |
+ // | sections | parallel for | * |
+ // | sections |parallel sections| * |
+ // | sections | task | * |
+ // | sections | taskyield | * |
+ // | sections | barrier | + |
+ // | sections | taskwait | * |
+ // | sections | flush | * |
+ // +------------------+-----------------+------------------------------------+
+ // | section | parallel | * |
+ // | section | for | + |
+ // | section | master | + |
+ // | section | critical | * |
+ // | section | simd | * |
+ // | section | sections | + |
+ // | section | section | + |
+ // | section | single | + |
+ // | section | parallel for | * |
+ // | section |parallel sections| * |
+ // | section | task | * |
+ // | section | taskyield | * |
+ // | section | barrier | + |
+ // | section | taskwait | * |
+ // | section | flush | * |
+ // +------------------+-----------------+------------------------------------+
+ // | single | parallel | * |
+ // | single | for | + |
+ // | single | master | + |
+ // | single | critical | * |
+ // | single | simd | * |
+ // | single | sections | + |
+ // | single | section | + |
+ // | single | single | + |
+ // | single | parallel for | * |
+ // | single |parallel sections| * |
+ // | single | task | * |
+ // | single | taskyield | * |
+ // | single | barrier | + |
+ // | single | taskwait | * |
+ // | single | flush | * |
+ // +------------------+-----------------+------------------------------------+
+ // | parallel for | parallel | * |
+ // | parallel for | for | + |
+ // | parallel for | master | + |
+ // | parallel for | critical | * |
+ // | parallel for | simd | * |
+ // | parallel for | sections | + |
+ // | parallel for | section | + |
+ // | parallel for | single | + |
+ // | parallel for | parallel for | * |
+ // | parallel for |parallel sections| * |
+ // | parallel for | task | * |
+ // | parallel for | taskyield | * |
+ // | parallel for | barrier | + |
+ // | parallel for | taskwait | * |
+ // | parallel for | flush | * |
+ // +------------------+-----------------+------------------------------------+
+ // | parallel sections| parallel | * |
+ // | parallel sections| for | + |
+ // | parallel sections| master | + |
+ // | parallel sections| critical | + |
+ // | parallel sections| simd | * |
+ // | parallel sections| sections | + |
+ // | parallel sections| section | * |
+ // | parallel sections| single | + |
+ // | parallel sections| parallel for | * |
+ // | parallel sections|parallel sections| * |
+ // | parallel sections| task | * |
+ // | parallel sections| taskyield | * |
+ // | parallel sections| barrier | + |
+ // | parallel sections| taskwait | * |
+ // | parallel sections| flush | * |
+ // +------------------+-----------------+------------------------------------+
+ // | task | parallel | * |
+ // | task | for | + |
+ // | task | master | + |
+ // | task | critical | * |
+ // | task | simd | * |
+ // | task | sections | + |
+ // | task | section | + |
+ // | task | single | + |
+ // | task | parallel for | * |
+ // | task |parallel sections| * |
+ // | task | task | * |
+ // | task | taskyield | * |
+ // | task | barrier | + |
+ // | task | taskwait | * |
+ // | task | flush | * |
+ // +------------------+-----------------+------------------------------------+
+ if (Stack->getCurScope()) {
+ auto ParentRegion = Stack->getParentDirective();
+ bool NestingProhibited = false;
+ bool CloseNesting = true;
+ bool ShouldBeInParallelRegion = false;
+ if (isOpenMPSimdDirective(ParentRegion)) {
+ // OpenMP [2.16, Nesting of Regions]
+ // OpenMP constructs may not be nested inside a simd region.
+ SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_simd);
+ return true;
+ }
+ if (CurrentRegion == OMPD_section) {
+ // OpenMP [2.7.2, sections Construct, Restrictions]
+ // Orphaned section directives are prohibited. That is, the section
+ // directives must appear within the sections construct and must not be
+ // encountered elsewhere in the sections region.
+ if (ParentRegion != OMPD_sections &&
+ ParentRegion != OMPD_parallel_sections) {
+ SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
+ << (ParentRegion != OMPD_unknown)
+ << getOpenMPDirectiveName(ParentRegion);
+ return true;
+ }
+ return false;
+ }
+ if (CurrentRegion == OMPD_master) {
+ // OpenMP [2.16, Nesting of Regions]
+ // A master region may not be closely nested inside a worksharing,
+ // atomic (TODO), or explicit task region.
+ NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
+ ParentRegion == OMPD_task;
+ } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
+ // OpenMP [2.16, Nesting of Regions]
+ // A critical region may not be nested (closely or otherwise) inside a
+ // critical region with the same name. Note that this restriction is not
+ // sufficient to prevent deadlock.
+ SourceLocation PreviousCriticalLoc;
+ bool DeadLock =
+ Stack->hasDirective([CurrentName, &PreviousCriticalLoc](
+ OpenMPDirectiveKind K,
+ const DeclarationNameInfo &DNI,
+ SourceLocation Loc)
+ ->bool {
+ if (K == OMPD_critical &&
+ DNI.getName() == CurrentName.getName()) {
+ PreviousCriticalLoc = Loc;
+ return true;
+ } else
+ return false;
+ },
+ false /* skip top directive */);
+ if (DeadLock) {
+ SemaRef.Diag(StartLoc,
+ diag::err_omp_prohibited_region_critical_same_name)
+ << CurrentName.getName();
+ if (PreviousCriticalLoc.isValid())
+ SemaRef.Diag(PreviousCriticalLoc,
+ diag::note_omp_previous_critical_region);
+ return true;
+ }
+ } else if (CurrentRegion == OMPD_barrier) {
+ // OpenMP [2.16, Nesting of Regions]
+ // A barrier region may not be closely nested inside a worksharing,
+ // explicit task, critical, ordered(TODO), atomic(TODO), or master
+ // region.
+ NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
+ ParentRegion == OMPD_task ||
+ ParentRegion == OMPD_master ||
+ ParentRegion == OMPD_critical;
+ } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
+ !isOpenMPParallelDirective(CurrentRegion) &&
+ !isOpenMPSimdDirective(CurrentRegion)) {
+ // OpenMP [2.16, Nesting of Regions]
+ // A worksharing region may not be closely nested inside a worksharing,
+ // explicit task, critical, ordered, atomic, or master region.
+ // TODO
+ NestingProhibited = (isOpenMPWorksharingDirective(ParentRegion) &&
+ !isOpenMPSimdDirective(ParentRegion)) ||
+ ParentRegion == OMPD_task ||
+ ParentRegion == OMPD_master ||
+ ParentRegion == OMPD_critical;
+ ShouldBeInParallelRegion = true;
+ }
+ if (NestingProhibited) {
+ SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
+ << CloseNesting << getOpenMPDirectiveName(ParentRegion)
+ << ShouldBeInParallelRegion << getOpenMPDirectiveName(CurrentRegion);
+ return true;
+ }
+ }
+ return false;
}
StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
+ const DeclarationNameInfo &DirName,
ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
-
StmtResult Res = StmtError();
-
- // Check default data sharing attributes for referenced variables.
- DSAAttrChecker DSAChecker(DSAStack, *this, cast<CapturedStmt>(AStmt));
- DSAChecker.Visit(cast<CapturedStmt>(AStmt)->getCapturedStmt());
- if (DSAChecker.isErrorFound())
+ if (CheckNestingOfRegions(*this, DSAStack, Kind, DirName, StartLoc))
return StmtError();
- // Generate list of implicitly defined firstprivate variables.
+
llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
+ llvm::DenseMap<VarDecl *, Expr *> VarsWithInheritedDSA;
+ bool ErrorFound = false;
ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
+ if (AStmt) {
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- bool ErrorFound = false;
- if (!DSAChecker.getImplicitFirstprivate().empty()) {
- if (OMPClause *Implicit =
- ActOnOpenMPFirstprivateClause(DSAChecker.getImplicitFirstprivate(),
- SourceLocation(), SourceLocation(),
- SourceLocation())) {
- ClausesWithImplicit.push_back(Implicit);
- ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
- DSAChecker.getImplicitFirstprivate().size();
- } else
- ErrorFound = true;
+ // Check default data sharing attributes for referenced variables.
+ DSAAttrChecker DSAChecker(DSAStack, *this, cast<CapturedStmt>(AStmt));
+ DSAChecker.Visit(cast<CapturedStmt>(AStmt)->getCapturedStmt());
+ if (DSAChecker.isErrorFound())
+ return StmtError();
+ // Generate list of implicitly defined firstprivate variables.
+ VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
+
+ if (!DSAChecker.getImplicitFirstprivate().empty()) {
+ if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause(
+ DSAChecker.getImplicitFirstprivate(), SourceLocation(),
+ SourceLocation(), SourceLocation())) {
+ ClausesWithImplicit.push_back(Implicit);
+ ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
+ DSAChecker.getImplicitFirstprivate().size();
+ } else
+ ErrorFound = true;
+ }
}
switch (Kind) {
case OMPD_parallel:
- Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt,
- StartLoc, EndLoc);
+ Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
+ EndLoc);
+ break;
+ case OMPD_simd:
+ Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
+ VarsWithInheritedDSA);
+ break;
+ case OMPD_for:
+ Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
+ VarsWithInheritedDSA);
+ break;
+ case OMPD_sections:
+ Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
+ EndLoc);
+ break;
+ case OMPD_section:
+ assert(ClausesWithImplicit.empty() &&
+ "No clauses are allowed for 'omp section' directive");
+ Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
+ break;
+ case OMPD_single:
+ Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
+ EndLoc);
+ break;
+ case OMPD_master:
+ assert(ClausesWithImplicit.empty() &&
+ "No clauses are allowed for 'omp master' directive");
+ Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
+ break;
+ case OMPD_critical:
+ assert(ClausesWithImplicit.empty() &&
+ "No clauses are allowed for 'omp critical' directive");
+ Res = ActOnOpenMPCriticalDirective(DirName, AStmt, StartLoc, EndLoc);
+ break;
+ case OMPD_parallel_for:
+ Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
+ EndLoc, VarsWithInheritedDSA);
+ break;
+ case OMPD_parallel_sections:
+ Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
+ StartLoc, EndLoc);
break;
- case OMPD_threadprivate:
case OMPD_task:
+ Res =
+ ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
+ break;
+ case OMPD_taskyield:
+ assert(ClausesWithImplicit.empty() &&
+ "No clauses are allowed for 'omp taskyield' directive");
+ assert(AStmt == nullptr &&
+ "No associated statement allowed for 'omp taskyield' directive");
+ Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
+ break;
+ case OMPD_barrier:
+ assert(ClausesWithImplicit.empty() &&
+ "No clauses are allowed for 'omp barrier' directive");
+ assert(AStmt == nullptr &&
+ "No associated statement allowed for 'omp barrier' directive");
+ Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
+ break;
+ case OMPD_taskwait:
+ assert(ClausesWithImplicit.empty() &&
+ "No clauses are allowed for 'omp taskwait' directive");
+ assert(AStmt == nullptr &&
+ "No associated statement allowed for 'omp taskwait' directive");
+ Res = ActOnOpenMPTaskwaitDirective(StartLoc, EndLoc);
+ break;
+ case OMPD_flush:
+ assert(AStmt == nullptr &&
+ "No associated statement allowed for 'omp flush' directive");
+ Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
+ break;
+ case OMPD_threadprivate:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
- case NUM_OPENMP_DIRECTIVES:
llvm_unreachable("Unknown OpenMP directive");
}
- if (ErrorFound) return StmtError();
+ for (auto P : VarsWithInheritedDSA) {
+ Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
+ << P.first << P.second->getSourceRange();
+ }
+ if (!VarsWithInheritedDSA.empty())
+ return StmtError();
+
+ if (ErrorFound)
+ return StmtError();
return Res;
}
@@ -696,31 +1509,1004 @@ StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
+ assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ CapturedStmt *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();
+
getCurFunction()->setHasBranchProtectedScope();
- return Owned(OMPParallelDirective::Create(Context, StartLoc, EndLoc,
- Clauses, AStmt));
+ return OMPParallelDirective::Create(Context, StartLoc, EndLoc, Clauses,
+ AStmt);
}
-OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
- unsigned Argument,
- SourceLocation ArgumentLoc,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc) {
- OMPClause *Res = 0;
+namespace {
+/// \brief 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.
+ Sema &SemaRef;
+ /// \brief A location for diagnostics (when there is no some better location).
+ SourceLocation DefaultLoc;
+ /// \brief A location for diagnostics (when increment is not compatible).
+ SourceLocation ConditionLoc;
+ /// \brief A source location for referring to condition later.
+ SourceRange ConditionSrcRange;
+ /// \brief Loop variable.
+ VarDecl *Var;
+ /// \brief Lower bound (initializer for the var).
+ Expr *LB;
+ /// \brief Upper bound.
+ Expr *UB;
+ /// \brief Loop step (increment).
+ Expr *Step;
+ /// \brief This flag is true when condition is one of:
+ /// Var < UB
+ /// Var <= UB
+ /// UB > Var
+ /// UB >= Var
+ bool TestIsLessOp;
+ /// \brief This flag is true when condition is strict ( < or > ).
+ bool TestIsStrictOp;
+ /// \brief This flag is true when step is subtracted on each iteration.
+ bool SubtractStep;
+
+public:
+ OpenMPIterationSpaceChecker(Sema &SemaRef, SourceLocation DefaultLoc)
+ : SemaRef(SemaRef), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
+ ConditionSrcRange(SourceRange()), Var(nullptr), LB(nullptr),
+ UB(nullptr), Step(nullptr), TestIsLessOp(false), TestIsStrictOp(false),
+ SubtractStep(false) {}
+ /// \brief Check init-expr for canonical loop form and save loop counter
+ /// variable - #Var and its initialization value - #LB.
+ bool CheckInit(Stmt *S);
+ /// \brief 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
+ /// does not conform, otherwise save loop step (#Step).
+ bool CheckInc(Expr *S);
+ /// \brief Return the loop counter variable.
+ VarDecl *GetLoopVar() const { return Var; }
+ /// \brief Return true if any expression is dependent.
+ bool Dependent() const;
+
+private:
+ /// \brief 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 SetVarAndLB(VarDecl *NewVar, Expr *NewLB);
+ /// \brief Helper to set upper bound.
+ bool SetUB(Expr *NewUB, bool LessOp, bool StrictOp, const SourceRange &SR,
+ const SourceLocation &SL);
+ /// \brief Helper to set loop increment.
+ bool SetStep(Expr *NewStep, bool Subtract);
+};
+
+bool OpenMPIterationSpaceChecker::Dependent() const {
+ if (!Var) {
+ assert(!LB && !UB && !Step);
+ return false;
+ }
+ return Var->getType()->isDependentType() || (LB && LB->isValueDependent()) ||
+ (UB && UB->isValueDependent()) || (Step && Step->isValueDependent());
+}
+
+bool OpenMPIterationSpaceChecker::SetVarAndLB(VarDecl *NewVar, Expr *NewLB) {
+ // State consistency checking to ensure correct usage.
+ assert(Var == nullptr && LB == nullptr && UB == nullptr && Step == nullptr &&
+ !TestIsLessOp && !TestIsStrictOp);
+ if (!NewVar || !NewLB)
+ return true;
+ Var = NewVar;
+ LB = NewLB;
+ return false;
+}
+
+bool OpenMPIterationSpaceChecker::SetUB(Expr *NewUB, bool LessOp, bool StrictOp,
+ const SourceRange &SR,
+ const SourceLocation &SL) {
+ // State consistency checking to ensure correct usage.
+ assert(Var != nullptr && LB != nullptr && UB == nullptr && Step == nullptr &&
+ !TestIsLessOp && !TestIsStrictOp);
+ if (!NewUB)
+ return true;
+ UB = NewUB;
+ TestIsLessOp = LessOp;
+ TestIsStrictOp = StrictOp;
+ ConditionSrcRange = SR;
+ ConditionLoc = SL;
+ return false;
+}
+
+bool OpenMPIterationSpaceChecker::SetStep(Expr *NewStep, bool Subtract) {
+ // State consistency checking to ensure correct usage.
+ assert(Var != nullptr && LB != nullptr && Step == nullptr);
+ if (!NewStep)
+ return true;
+ if (!NewStep->isValueDependent()) {
+ // Check that the step is integer expression.
+ SourceLocation StepLoc = NewStep->getLocStart();
+ ExprResult Val =
+ SemaRef.PerformOpenMPImplicitIntegerConversion(StepLoc, NewStep);
+ if (Val.isInvalid())
+ return true;
+ NewStep = Val.get();
+
+ // OpenMP [2.6, Canonical Loop Form, Restrictions]
+ // If test-expr is of form var relational-op b and relational-op is < or
+ // <= then incr-expr must cause var to increase on each iteration of the
+ // loop. If test-expr is of form var relational-op b and relational-op is
+ // > or >= then incr-expr must cause var to decrease on each iteration of
+ // the loop.
+ // If test-expr is of form b relational-op var and relational-op is < or
+ // <= then incr-expr must cause var to decrease on each iteration of the
+ // loop. If test-expr is of form b relational-op var and relational-op is
+ // > or >= then incr-expr must cause var to increase on each iteration of
+ // the loop.
+ llvm::APSInt Result;
+ bool IsConstant = NewStep->isIntegerConstantExpr(Result, SemaRef.Context);
+ bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
+ bool IsConstNeg =
+ IsConstant && Result.isSigned() && (Subtract != Result.isNegative());
+ bool IsConstZero = IsConstant && !Result.getBoolValue();
+ if (UB && (IsConstZero ||
+ (TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
+ : (!IsConstNeg || (IsUnsigned && !Subtract))))) {
+ SemaRef.Diag(NewStep->getExprLoc(),
+ diag::err_omp_loop_incr_not_compatible)
+ << Var << TestIsLessOp << NewStep->getSourceRange();
+ SemaRef.Diag(ConditionLoc,
+ diag::note_omp_loop_cond_requres_compatible_incr)
+ << TestIsLessOp << ConditionSrcRange;
+ return true;
+ }
+ }
+
+ Step = NewStep;
+ SubtractStep = Subtract;
+ return false;
+}
+
+bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S) {
+ // 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:
+ // var = lb
+ // integer-type var = lb
+ // random-access-iterator-type var = lb
+ // pointer-type var = lb
+ //
+ if (!S) {
+ SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
+ return true;
+ }
+ if (Expr *E = dyn_cast<Expr>(S))
+ S = E->IgnoreParens();
+ if (auto BO = dyn_cast<BinaryOperator>(S)) {
+ if (BO->getOpcode() == BO_Assign)
+ if (auto DRE = dyn_cast<DeclRefExpr>(BO->getLHS()->IgnoreParens()))
+ return SetVarAndLB(dyn_cast<VarDecl>(DRE->getDecl()), BO->getLHS());
+ } else if (auto DS = dyn_cast<DeclStmt>(S)) {
+ if (DS->isSingleDecl()) {
+ if (auto Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
+ if (Var->hasInit()) {
+ // Accept non-canonical init form here but emit ext. warning.
+ if (Var->getInitStyle() != VarDecl::CInit)
+ SemaRef.Diag(S->getLocStart(),
+ diag::ext_omp_loop_not_canonical_init)
+ << S->getSourceRange();
+ return SetVarAndLB(Var, Var->getInit());
+ }
+ }
+ }
+ } else if (auto CE = dyn_cast<CXXOperatorCallExpr>(S))
+ if (CE->getOperator() == OO_Equal)
+ if (auto DRE = dyn_cast<DeclRefExpr>(CE->getArg(0)))
+ return SetVarAndLB(dyn_cast<VarDecl>(DRE->getDecl()), CE->getArg(1));
+
+ SemaRef.Diag(S->getLocStart(), diag::err_omp_loop_not_canonical_init)
+ << S->getSourceRange();
+ return true;
+}
+
+/// \brief Ignore parenthesizes, implicit casts, copy constructor and return the
+/// variable (which may be the loop variable) if possible.
+static const VarDecl *GetInitVarDecl(const Expr *E) {
+ if (!E)
+ return nullptr;
+ E = E->IgnoreParenImpCasts();
+ if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
+ if (const CXXConstructorDecl *Ctor = CE->getConstructor())
+ if (Ctor->isCopyConstructor() && CE->getNumArgs() == 1 &&
+ CE->getArg(0) != nullptr)
+ E = CE->getArg(0)->IgnoreParenImpCasts();
+ auto DRE = dyn_cast_or_null<DeclRefExpr>(E);
+ if (!DRE)
+ return nullptr;
+ return dyn_cast<VarDecl>(DRE->getDecl());
+}
+
+bool OpenMPIterationSpaceChecker::CheckCond(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:
+ // var relational-op b
+ // b relational-op var
+ //
+ if (!S) {
+ SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond) << Var;
+ return true;
+ }
+ S = S->IgnoreParenImpCasts();
+ SourceLocation CondLoc = S->getLocStart();
+ if (auto BO = dyn_cast<BinaryOperator>(S)) {
+ if (BO->isRelationalOp()) {
+ if (GetInitVarDecl(BO->getLHS()) == Var)
+ 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 (GetInitVarDecl(BO->getRHS()) == Var)
+ return SetUB(BO->getLHS(),
+ (BO->getOpcode() == BO_GT || BO->getOpcode() == BO_GE),
+ (BO->getOpcode() == BO_LT || BO->getOpcode() == BO_GT),
+ BO->getSourceRange(), BO->getOperatorLoc());
+ }
+ } else if (auto CE = dyn_cast<CXXOperatorCallExpr>(S)) {
+ if (CE->getNumArgs() == 2) {
+ auto Op = CE->getOperator();
+ switch (Op) {
+ case OO_Greater:
+ case OO_GreaterEqual:
+ case OO_Less:
+ case OO_LessEqual:
+ if (GetInitVarDecl(CE->getArg(0)) == Var)
+ return SetUB(CE->getArg(1), Op == OO_Less || Op == OO_LessEqual,
+ Op == OO_Less || Op == OO_Greater, CE->getSourceRange(),
+ CE->getOperatorLoc());
+ if (GetInitVarDecl(CE->getArg(1)) == Var)
+ return SetUB(CE->getArg(0), Op == OO_Greater || Op == OO_GreaterEqual,
+ Op == OO_Less || Op == OO_Greater, CE->getSourceRange(),
+ CE->getOperatorLoc());
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
+ << S->getSourceRange() << Var;
+ return true;
+}
+
+bool OpenMPIterationSpaceChecker::CheckIncRHS(Expr *RHS) {
+ // RHS of canonical loop form increment can be:
+ // var + incr
+ // incr + var
+ // var - incr
+ //
+ RHS = RHS->IgnoreParenImpCasts();
+ if (auto BO = dyn_cast<BinaryOperator>(RHS)) {
+ if (BO->isAdditiveOp()) {
+ bool IsAdd = BO->getOpcode() == BO_Add;
+ if (GetInitVarDecl(BO->getLHS()) == Var)
+ return SetStep(BO->getRHS(), !IsAdd);
+ if (IsAdd && GetInitVarDecl(BO->getRHS()) == Var)
+ return SetStep(BO->getLHS(), 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 (GetInitVarDecl(CE->getArg(0)) == Var)
+ return SetStep(CE->getArg(1), !IsAdd);
+ if (IsAdd && GetInitVarDecl(CE->getArg(1)) == Var)
+ return SetStep(CE->getArg(0), false);
+ }
+ }
+ SemaRef.Diag(RHS->getLocStart(), diag::err_omp_loop_not_canonical_incr)
+ << RHS->getSourceRange() << Var;
+ return true;
+}
+
+bool OpenMPIterationSpaceChecker::CheckInc(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:
+ // ++var
+ // var++
+ // --var
+ // var--
+ // var += incr
+ // var -= incr
+ // var = var + incr
+ // var = incr + var
+ // var = var - incr
+ //
+ if (!S) {
+ SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << Var;
+ return true;
+ }
+ S = S->IgnoreParens();
+ if (auto UO = dyn_cast<UnaryOperator>(S)) {
+ if (UO->isIncrementDecrementOp() && GetInitVarDecl(UO->getSubExpr()) == Var)
+ return SetStep(
+ SemaRef.ActOnIntegerConstant(UO->getLocStart(),
+ (UO->isDecrementOp() ? -1 : 1)).get(),
+ false);
+ } else if (auto BO = dyn_cast<BinaryOperator>(S)) {
+ switch (BO->getOpcode()) {
+ case BO_AddAssign:
+ case BO_SubAssign:
+ if (GetInitVarDecl(BO->getLHS()) == Var)
+ return SetStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
+ break;
+ case BO_Assign:
+ if (GetInitVarDecl(BO->getLHS()) == Var)
+ return CheckIncRHS(BO->getRHS());
+ break;
+ default:
+ break;
+ }
+ } else if (auto CE = dyn_cast<CXXOperatorCallExpr>(S)) {
+ switch (CE->getOperator()) {
+ case OO_PlusPlus:
+ case OO_MinusMinus:
+ if (GetInitVarDecl(CE->getArg(0)) == Var)
+ return SetStep(
+ SemaRef.ActOnIntegerConstant(
+ CE->getLocStart(),
+ ((CE->getOperator() == OO_MinusMinus) ? -1 : 1)).get(),
+ false);
+ break;
+ case OO_PlusEqual:
+ case OO_MinusEqual:
+ if (GetInitVarDecl(CE->getArg(0)) == Var)
+ return SetStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
+ break;
+ case OO_Equal:
+ if (GetInitVarDecl(CE->getArg(0)) == Var)
+ return CheckIncRHS(CE->getArg(1));
+ break;
+ default:
+ break;
+ }
+ }
+ SemaRef.Diag(S->getLocStart(), diag::err_omp_loop_not_canonical_incr)
+ << S->getSourceRange() << Var;
+ return true;
+}
+} // namespace
+
+/// \brief Called on a for stmt to check and extract its iteration space
+/// for further processing (such as collapsing).
+static bool CheckOpenMPIterationSpace(
+ OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
+ unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
+ Expr *NestedLoopCountExpr,
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+ // OpenMP [2.6, Canonical Loop Form]
+ // for (init-expr; test-expr; incr-expr) structured-block
+ auto For = dyn_cast_or_null<ForStmt>(S);
+ if (!For) {
+ SemaRef.Diag(S->getLocStart(), diag::err_omp_not_for)
+ << (NestedLoopCountExpr != nullptr) << getOpenMPDirectiveName(DKind)
+ << NestedLoopCount << (CurrentNestedLoopCount > 0)
+ << CurrentNestedLoopCount;
+ if (NestedLoopCount > 1)
+ SemaRef.Diag(NestedLoopCountExpr->getExprLoc(),
+ diag::note_omp_collapse_expr)
+ << NestedLoopCountExpr->getSourceRange();
+ return true;
+ }
+ assert(For->getBody());
+
+ OpenMPIterationSpaceChecker ISC(SemaRef, For->getForLoc());
+
+ // Check init.
+ auto Init = For->getInit();
+ if (ISC.CheckInit(Init)) {
+ return true;
+ }
+
+ bool HasErrors = false;
+
+ // Check loop variable's type.
+ auto Var = ISC.GetLoopVar();
+
+ // 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 = Var->getType();
+ if (!VarType->isDependentType() && !VarType->isIntegerType() &&
+ !VarType->isPointerType() &&
+ !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
+ SemaRef.Diag(Init->getLocStart(), diag::err_omp_loop_variable_type)
+ << SemaRef.getLangOpts().CPlusPlus;
+ HasErrors = true;
+ }
+
+ // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in a
+ // Construct
+ // The loop iteration variable(s) in the associated for-loop(s) of a for or
+ // parallel for construct is (are) private.
+ // The loop iteration variable in the associated for-loop of a simd construct
+ // with just one associated for-loop is linear with a constant-linear-step
+ // that is the increment of the associated for-loop.
+ // Exclude loop var from the list of variables with implicitly defined data
+ // sharing attributes.
+ while (VarsWithImplicitDSA.count(Var) > 0)
+ VarsWithImplicitDSA.erase(Var);
+
+ // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced in
+ // a Construct, C/C++].
+ // The loop iteration variable in the associated for-loop of a simd construct
+ // with just one associated for-loop may be listed in a linear clause with a
+ // constant-linear-step that is the increment of the associated for-loop.
+ // The loop iteration variable(s) in the associated for-loop(s) of a for or
+ // parallel for construct may be listed in a private or lastprivate clause.
+ DSAStackTy::DSAVarData DVar = DSA.getTopDSA(Var, false);
+ auto PredeterminedCKind =
+ isOpenMPSimdDirective(DKind)
+ ? ((NestedLoopCount == 1) ? OMPC_linear : OMPC_lastprivate)
+ : OMPC_private;
+ if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
+ DVar.CKind != PredeterminedCKind) ||
+ (isOpenMPWorksharingDirective(DKind) && DVar.CKind != OMPC_unknown &&
+ DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
+ (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
+ SemaRef.Diag(Init->getLocStart(), diag::err_omp_loop_var_dsa)
+ << getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind)
+ << getOpenMPClauseName(PredeterminedCKind);
+ ReportOriginalDSA(SemaRef, &DSA, Var, DVar, true);
+ HasErrors = true;
+ } else {
+ // Make the loop iteration variable private (for worksharing constructs),
+ // linear (for simd directives with the only one associated loop) or
+ // lastprivate (for simd directives with several collapsed loops).
+ DSA.addDSA(Var, nullptr, PredeterminedCKind);
+ }
+
+ assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
+
+ // Check test-expr.
+ HasErrors |= ISC.CheckCond(For->getCond());
+
+ // Check incr-expr.
+ HasErrors |= ISC.CheckInc(For->getInc());
+
+ if (ISC.Dependent())
+ return HasErrors;
+
+ // FIXME: Build loop's iteration space representation.
+ return HasErrors;
+}
+
+/// \brief A helper routine to skip no-op (attributed, compound) stmts get the
+/// next nested for loop. If \a IgnoreCaptured is true, it skips captured stmt
+/// to get the first for loop.
+static Stmt *IgnoreContainerStmts(Stmt *S, bool IgnoreCaptured) {
+ if (IgnoreCaptured)
+ if (auto CapS = dyn_cast_or_null<CapturedStmt>(S))
+ S = CapS->getCapturedStmt();
+ // OpenMP [2.8.1, simd construct, Restrictions]
+ // All loops associated with the construct must be perfectly nested; that is,
+ // there must be no intervening code nor any OpenMP directive between any two
+ // loops.
+ while (true) {
+ if (auto AS = dyn_cast_or_null<AttributedStmt>(S))
+ S = AS->getSubStmt();
+ else if (auto CS = dyn_cast_or_null<CompoundStmt>(S)) {
+ if (CS->size() != 1)
+ break;
+ S = CS->body_back();
+ } else
+ break;
+ }
+ return S;
+}
+
+/// \brief 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 *NestedLoopCountExpr,
+ Stmt *AStmt, Sema &SemaRef, DSAStackTy &DSA,
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+ unsigned NestedLoopCount = 1;
+ if (NestedLoopCountExpr) {
+ // Found 'collapse' clause - calculate collapse number.
+ llvm::APSInt Result;
+ if (NestedLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext()))
+ NestedLoopCount = Result.getLimitedValue();
+ }
+ // This is helper routine for loop directives (e.g., 'for', 'simd',
+ // 'for simd', etc.).
+ Stmt *CurStmt = IgnoreContainerStmts(AStmt, true);
+ for (unsigned Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
+ if (CheckOpenMPIterationSpace(DKind, CurStmt, SemaRef, DSA, Cnt,
+ NestedLoopCount, NestedLoopCountExpr,
+ VarsWithImplicitDSA))
+ return 0;
+ // Move on to the next nested for loop, or to the loop body.
+ CurStmt = IgnoreContainerStmts(cast<ForStmt>(CurStmt)->getBody(), false);
+ }
+
+ // FIXME: Build resulting iteration space for IR generation (collapsing
+ // iteration spaces when loop count > 1 ('collapse' clause)).
+ return NestedLoopCount;
+}
+
+static Expr *GetCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) {
+ auto CollapseFilter = [](const OMPClause *C) -> bool {
+ return C->getClauseKind() == OMPC_collapse;
+ };
+ OMPExecutableDirective::filtered_clause_iterator<decltype(CollapseFilter)> I(
+ Clauses, CollapseFilter);
+ if (I)
+ return cast<OMPCollapseClause>(*I)->getNumForLoops();
+ return nullptr;
+}
+
+StmtResult Sema::ActOnOpenMPSimdDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+ // In presence of clause 'collapse', it will define the nested loops number.
+ unsigned NestedLoopCount =
+ CheckOpenMPLoop(OMPD_simd, GetCollapseNumberExpr(Clauses), AStmt, *this,
+ *DSAStack, VarsWithImplicitDSA);
+ if (NestedLoopCount == 0)
+ return StmtError();
+
+ getCurFunction()->setHasBranchProtectedScope();
+ return OMPSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
+ Clauses, AStmt);
+}
+
+StmtResult Sema::ActOnOpenMPForDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+ // In presence of clause 'collapse', it will define the nested loops number.
+ unsigned NestedLoopCount =
+ CheckOpenMPLoop(OMPD_for, GetCollapseNumberExpr(Clauses), AStmt, *this,
+ *DSAStack, VarsWithImplicitDSA);
+ if (NestedLoopCount == 0)
+ return StmtError();
+
+ getCurFunction()->setHasBranchProtectedScope();
+ return OMPForDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
+ Clauses, AStmt);
+}
+
+StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ auto BaseStmt = AStmt;
+ while (CapturedStmt *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
+ BaseStmt = CS->getCapturedStmt();
+ if (auto C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
+ auto S = C->children();
+ if (!S)
+ return StmtError();
+ // All associated statements must be '#pragma omp section' except for
+ // the first one.
+ for (++S; S; ++S) {
+ auto SectionStmt = *S;
+ if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
+ if (SectionStmt)
+ Diag(SectionStmt->getLocStart(),
+ diag::err_omp_sections_substmt_not_section);
+ return StmtError();
+ }
+ }
+ } else {
+ Diag(AStmt->getLocStart(), diag::err_omp_sections_not_compound_stmt);
+ return StmtError();
+ }
+
+ getCurFunction()->setHasBranchProtectedScope();
+
+ return OMPSectionsDirective::Create(Context, StartLoc, EndLoc, Clauses,
+ AStmt);
+}
+
+StmtResult Sema::ActOnOpenMPSectionDirective(Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+
+ getCurFunction()->setHasBranchProtectedScope();
+
+ return OMPSectionDirective::Create(Context, StartLoc, EndLoc, AStmt);
+}
+
+StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+
+ getCurFunction()->setHasBranchProtectedScope();
+
+ return OMPSingleDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
+}
+
+StmtResult Sema::ActOnOpenMPMasterDirective(Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+
+ getCurFunction()->setHasBranchProtectedScope();
+
+ return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt);
+}
+
+StmtResult
+Sema::ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+
+ getCurFunction()->setHasBranchProtectedScope();
+
+ return OMPCriticalDirective::Create(Context, DirName, StartLoc, EndLoc,
+ AStmt);
+}
+
+StmtResult Sema::ActOnOpenMPParallelForDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+ assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ CapturedStmt *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();
+
+ // In presence of clause 'collapse', it will define the nested loops number.
+ unsigned NestedLoopCount =
+ CheckOpenMPLoop(OMPD_parallel_for, GetCollapseNumberExpr(Clauses), AStmt,
+ *this, *DSAStack, VarsWithImplicitDSA);
+ if (NestedLoopCount == 0)
+ return StmtError();
+
+ getCurFunction()->setHasBranchProtectedScope();
+ return OMPParallelForDirective::Create(Context, StartLoc, EndLoc,
+ NestedLoopCount, Clauses, AStmt);
+}
+
+StmtResult
+Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ auto BaseStmt = AStmt;
+ while (CapturedStmt *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
+ BaseStmt = CS->getCapturedStmt();
+ if (auto C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
+ auto S = C->children();
+ if (!S)
+ return StmtError();
+ // All associated statements must be '#pragma omp section' except for
+ // the first one.
+ for (++S; S; ++S) {
+ auto SectionStmt = *S;
+ if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
+ if (SectionStmt)
+ Diag(SectionStmt->getLocStart(),
+ diag::err_omp_parallel_sections_substmt_not_section);
+ return StmtError();
+ }
+ }
+ } else {
+ Diag(AStmt->getLocStart(),
+ diag::err_omp_parallel_sections_not_compound_stmt);
+ return StmtError();
+ }
+
+ getCurFunction()->setHasBranchProtectedScope();
+
+ return OMPParallelSectionsDirective::Create(Context, StartLoc, EndLoc,
+ Clauses, AStmt);
+}
+
+StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ CapturedStmt *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();
+
+ getCurFunction()->setHasBranchProtectedScope();
+
+ return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
+}
+
+StmtResult Sema::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return OMPTaskyieldDirective::Create(Context, StartLoc, EndLoc);
+}
+
+StmtResult Sema::ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return OMPBarrierDirective::Create(Context, StartLoc, EndLoc);
+}
+
+StmtResult Sema::ActOnOpenMPTaskwaitDirective(SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return OMPTaskwaitDirective::Create(Context, StartLoc, EndLoc);
+}
+
+StmtResult Sema::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ assert(Clauses.size() <= 1 && "Extra clauses in flush directive");
+ return OMPFlushDirective::Create(Context, StartLoc, EndLoc, Clauses);
+}
+
+OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ OMPClause *Res = nullptr;
+ switch (Kind) {
+ case OMPC_if:
+ Res = ActOnOpenMPIfClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_final:
+ Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_num_threads:
+ Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_safelen:
+ Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_collapse:
+ Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_default:
+ case OMPC_proc_bind:
+ case OMPC_schedule:
+ case OMPC_private:
+ case OMPC_firstprivate:
+ case OMPC_lastprivate:
+ case OMPC_shared:
+ case OMPC_reduction:
+ case OMPC_linear:
+ case OMPC_aligned:
+ case OMPC_copyin:
+ case OMPC_copyprivate:
+ case OMPC_ordered:
+ case OMPC_nowait:
+ case OMPC_untied:
+ case OMPC_mergeable:
+ case OMPC_threadprivate:
+ case OMPC_flush:
+ case OMPC_unknown:
+ llvm_unreachable("Clause is not allowed.");
+ }
+ return Res;
+}
+
+OMPClause *Sema::ActOnOpenMPIfClause(Expr *Condition, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ Expr *ValExpr = Condition;
+ if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
+ !Condition->isInstantiationDependent() &&
+ !Condition->containsUnexpandedParameterPack()) {
+ ExprResult Val = ActOnBooleanCondition(DSAStack->getCurScope(),
+ Condition->getExprLoc(), Condition);
+ if (Val.isInvalid())
+ return nullptr;
+
+ ValExpr = Val.get();
+ }
+
+ return new (Context) OMPIfClause(ValExpr, StartLoc, LParenLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPFinalClause(Expr *Condition,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ Expr *ValExpr = Condition;
+ if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
+ !Condition->isInstantiationDependent() &&
+ !Condition->containsUnexpandedParameterPack()) {
+ ExprResult Val = ActOnBooleanCondition(DSAStack->getCurScope(),
+ Condition->getExprLoc(), Condition);
+ if (Val.isInvalid())
+ return nullptr;
+
+ ValExpr = Val.get();
+ }
+
+ return new (Context) OMPFinalClause(ValExpr, StartLoc, LParenLoc, EndLoc);
+}
+
+ExprResult Sema::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,
+ Expr *Op) {
+ if (!Op)
+ return ExprError();
+
+ class IntConvertDiagnoser : public ICEConvertDiagnoser {
+ public:
+ IntConvertDiagnoser()
+ : ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false, false, true) {}
+ SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
+ QualType T) override {
+ return S.Diag(Loc, diag::err_omp_not_integral) << T;
+ }
+ SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
+ QualType T) override {
+ return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
+ }
+ SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
+ QualType T,
+ QualType ConvTy) override {
+ return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
+ }
+ SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
+ QualType ConvTy) override {
+ return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
+ << ConvTy->isEnumeralType() << ConvTy;
+ }
+ SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
+ QualType T) override {
+ return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
+ }
+ SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
+ QualType ConvTy) override {
+ return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
+ << ConvTy->isEnumeralType() << ConvTy;
+ }
+ SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
+ QualType) override {
+ llvm_unreachable("conversion functions are permitted");
+ }
+ } ConvertDiagnoser;
+ return PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
+}
+
+OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ Expr *ValExpr = NumThreads;
+ if (!NumThreads->isValueDependent() && !NumThreads->isTypeDependent() &&
+ !NumThreads->isInstantiationDependent() &&
+ !NumThreads->containsUnexpandedParameterPack()) {
+ SourceLocation NumThreadsLoc = NumThreads->getLocStart();
+ ExprResult Val =
+ PerformOpenMPImplicitIntegerConversion(NumThreadsLoc, NumThreads);
+ if (Val.isInvalid())
+ return nullptr;
+
+ ValExpr = Val.get();
+
+ // OpenMP [2.5, Restrictions]
+ // The num_threads expression must evaluate to a positive integer value.
+ llvm::APSInt Result;
+ if (ValExpr->isIntegerConstantExpr(Result, Context) && Result.isSigned() &&
+ !Result.isStrictlyPositive()) {
+ Diag(NumThreadsLoc, diag::err_omp_negative_expression_in_clause)
+ << "num_threads" << NumThreads->getSourceRange();
+ return nullptr;
+ }
+ }
+
+ return new (Context)
+ OMPNumThreadsClause(ValExpr, StartLoc, LParenLoc, EndLoc);
+}
+
+ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
+ OpenMPClauseKind CKind) {
+ if (!E)
+ return ExprError();
+ if (E->isValueDependent() || E->isTypeDependent() ||
+ E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
+ return E;
+ llvm::APSInt Result;
+ ExprResult ICE = VerifyIntegerConstantExpression(E, &Result);
+ if (ICE.isInvalid())
+ return ExprError();
+ if (!Result.isStrictlyPositive()) {
+ Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
+ << getOpenMPClauseName(CKind) << E->getSourceRange();
+ return ExprError();
+ }
+ return ICE;
+}
+
+OMPClause *Sema::ActOnOpenMPSafelenClause(Expr *Len, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ // OpenMP [2.8.1, simd construct, Description]
+ // The parameter of the safelen clause must be a constant
+ // positive integer expression.
+ ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
+ if (Safelen.isInvalid())
+ return nullptr;
+ return new (Context)
+ OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPCollapseClause(Expr *NumForLoops,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ // OpenMP [2.7.1, loop construct, Description]
+ // OpenMP [2.8.1, simd construct, Description]
+ // OpenMP [2.9.6, distribute construct, Description]
+ // The parameter of the collapse clause must be a constant
+ // positive integer expression.
+ ExprResult NumForLoopsResult =
+ VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
+ if (NumForLoopsResult.isInvalid())
+ return nullptr;
+ return new (Context)
+ OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPSimpleClause(
+ OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
+ SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
+ OMPClause *Res = nullptr;
switch (Kind) {
case OMPC_default:
Res =
- ActOnOpenMPDefaultClause(static_cast<OpenMPDefaultClauseKind>(Argument),
- ArgumentLoc, StartLoc, LParenLoc, EndLoc);
+ ActOnOpenMPDefaultClause(static_cast<OpenMPDefaultClauseKind>(Argument),
+ ArgumentLoc, StartLoc, LParenLoc, EndLoc);
break;
+ case OMPC_proc_bind:
+ Res = ActOnOpenMPProcBindClause(
+ static_cast<OpenMPProcBindClauseKind>(Argument), ArgumentLoc, StartLoc,
+ LParenLoc, EndLoc);
+ break;
+ case OMPC_if:
+ case OMPC_final:
+ case OMPC_num_threads:
+ case OMPC_safelen:
+ case OMPC_collapse:
+ case OMPC_schedule:
case OMPC_private:
case OMPC_firstprivate:
+ case OMPC_lastprivate:
case OMPC_shared:
+ case OMPC_reduction:
+ case OMPC_linear:
+ case OMPC_aligned:
+ case OMPC_copyin:
+ case OMPC_copyprivate:
+ case OMPC_ordered:
+ case OMPC_nowait:
+ case OMPC_untied:
+ case OMPC_mergeable:
case OMPC_threadprivate:
+ case OMPC_flush:
case OMPC_unknown:
- case NUM_OPENMP_CLAUSES:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -733,17 +2519,18 @@ OMPClause *Sema::ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind,
SourceLocation EndLoc) {
if (Kind == OMPC_DEFAULT_unknown) {
std::string Values;
- std::string Sep(NUM_OPENMP_DEFAULT_KINDS > 1 ? ", " : "");
- for (unsigned i = OMPC_DEFAULT_unknown + 1;
- i < NUM_OPENMP_DEFAULT_KINDS; ++i) {
+ static_assert(OMPC_DEFAULT_unknown > 0,
+ "OMPC_DEFAULT_unknown not greater than 0");
+ std::string Sep(", ");
+ for (unsigned i = 0; i < OMPC_DEFAULT_unknown; ++i) {
Values += "'";
Values += getOpenMPSimpleClauseTypeName(OMPC_default, i);
Values += "'";
switch (i) {
- case NUM_OPENMP_DEFAULT_KINDS - 2:
+ case OMPC_DEFAULT_unknown - 2:
Values += " or ";
break;
- case NUM_OPENMP_DEFAULT_KINDS - 1:
+ case OMPC_DEFAULT_unknown - 1:
break;
default:
Values += Sep;
@@ -751,29 +2538,219 @@ OMPClause *Sema::ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind,
}
}
Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
- << Values << getOpenMPClauseName(OMPC_default);
- return 0;
+ << Values << getOpenMPClauseName(OMPC_default);
+ return nullptr;
}
switch (Kind) {
case OMPC_DEFAULT_none:
- DSAStack->setDefaultDSANone();
+ DSAStack->setDefaultDSANone(KindKwLoc);
break;
case OMPC_DEFAULT_shared:
- DSAStack->setDefaultDSAShared();
+ DSAStack->setDefaultDSAShared(KindKwLoc);
break;
- default:
+ case OMPC_DEFAULT_unknown:
+ llvm_unreachable("Clause kind is not allowed.");
break;
}
- return new (Context) OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc,
- EndLoc);
+ return new (Context)
+ OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
}
-OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
- ArrayRef<Expr *> VarList,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
+OMPClause *Sema::ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind,
+ SourceLocation KindKwLoc,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ if (Kind == OMPC_PROC_BIND_unknown) {
+ std::string Values;
+ std::string Sep(", ");
+ for (unsigned i = 0; i < OMPC_PROC_BIND_unknown; ++i) {
+ Values += "'";
+ Values += getOpenMPSimpleClauseTypeName(OMPC_proc_bind, i);
+ Values += "'";
+ switch (i) {
+ case OMPC_PROC_BIND_unknown - 2:
+ Values += " or ";
+ break;
+ case OMPC_PROC_BIND_unknown - 1:
+ break;
+ default:
+ Values += Sep;
+ break;
+ }
+ }
+ Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
+ << Values << getOpenMPClauseName(OMPC_proc_bind);
+ return nullptr;
+ }
+ return new (Context)
+ OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
+ OpenMPClauseKind Kind, unsigned Argument, Expr *Expr,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation ArgumentLoc, SourceLocation CommaLoc,
+ SourceLocation EndLoc) {
+ OMPClause *Res = nullptr;
+ switch (Kind) {
+ case OMPC_schedule:
+ Res = ActOnOpenMPScheduleClause(
+ static_cast<OpenMPScheduleClauseKind>(Argument), Expr, StartLoc,
+ LParenLoc, ArgumentLoc, CommaLoc, EndLoc);
+ break;
+ case OMPC_if:
+ case OMPC_final:
+ case OMPC_num_threads:
+ case OMPC_safelen:
+ case OMPC_collapse:
+ case OMPC_default:
+ case OMPC_proc_bind:
+ case OMPC_private:
+ case OMPC_firstprivate:
+ case OMPC_lastprivate:
+ case OMPC_shared:
+ case OMPC_reduction:
+ case OMPC_linear:
+ case OMPC_aligned:
+ case OMPC_copyin:
+ case OMPC_copyprivate:
+ case OMPC_ordered:
+ case OMPC_nowait:
+ case OMPC_untied:
+ case OMPC_mergeable:
+ case OMPC_threadprivate:
+ case OMPC_flush:
+ case OMPC_unknown:
+ llvm_unreachable("Clause is not allowed.");
+ }
+ return Res;
+}
+
+OMPClause *Sema::ActOnOpenMPScheduleClause(
+ OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
+ SourceLocation EndLoc) {
+ if (Kind == OMPC_SCHEDULE_unknown) {
+ std::string Values;
+ std::string Sep(", ");
+ for (unsigned i = 0; i < OMPC_SCHEDULE_unknown; ++i) {
+ Values += "'";
+ Values += getOpenMPSimpleClauseTypeName(OMPC_schedule, i);
+ Values += "'";
+ switch (i) {
+ case OMPC_SCHEDULE_unknown - 2:
+ Values += " or ";
+ break;
+ case OMPC_SCHEDULE_unknown - 1:
+ break;
+ default:
+ Values += Sep;
+ break;
+ }
+ }
+ Diag(KindLoc, diag::err_omp_unexpected_clause_value)
+ << Values << getOpenMPClauseName(OMPC_schedule);
+ return nullptr;
+ }
+ Expr *ValExpr = ChunkSize;
+ if (ChunkSize) {
+ if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
+ !ChunkSize->isInstantiationDependent() &&
+ !ChunkSize->containsUnexpandedParameterPack()) {
+ SourceLocation ChunkSizeLoc = ChunkSize->getLocStart();
+ ExprResult Val =
+ PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
+ if (Val.isInvalid())
+ return nullptr;
+
+ ValExpr = Val.get();
+
+ // OpenMP [2.7.1, Restrictions]
+ // chunk_size must be a loop invariant integer expression with a positive
+ // value.
+ llvm::APSInt Result;
+ if (ValExpr->isIntegerConstantExpr(Result, Context) &&
+ Result.isSigned() && !Result.isStrictlyPositive()) {
+ Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
+ << "schedule" << ChunkSize->getSourceRange();
+ return nullptr;
+ }
+ }
+ }
+
+ return new (Context) OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc,
+ EndLoc, Kind, ValExpr);
+}
+
+OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ OMPClause *Res = nullptr;
+ switch (Kind) {
+ case OMPC_ordered:
+ Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
+ break;
+ case OMPC_nowait:
+ Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
+ break;
+ case OMPC_untied:
+ Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
+ break;
+ case OMPC_mergeable:
+ Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
+ break;
+ case OMPC_if:
+ case OMPC_final:
+ case OMPC_num_threads:
+ case OMPC_safelen:
+ case OMPC_collapse:
+ case OMPC_schedule:
+ case OMPC_private:
+ case OMPC_firstprivate:
+ case OMPC_lastprivate:
+ case OMPC_shared:
+ case OMPC_reduction:
+ case OMPC_linear:
+ case OMPC_aligned:
+ case OMPC_copyin:
+ case OMPC_copyprivate:
+ case OMPC_default:
+ case OMPC_proc_bind:
+ case OMPC_threadprivate:
+ case OMPC_flush:
+ case OMPC_unknown:
+ llvm_unreachable("Clause is not allowed.");
+ }
+ return Res;
+}
+
+OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
SourceLocation EndLoc) {
- OMPClause *Res = 0;
+ return new (Context) OMPOrderedClause(StartLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPNowaitClause(SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return new (Context) OMPNowaitClause(StartLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPUntiedClause(SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return new (Context) OMPUntiedClause(StartLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPMergeableClause(SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return new (Context) OMPMergeableClause(StartLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPVarListClause(
+ OpenMPClauseKind Kind, ArrayRef<Expr *> VarList, Expr *TailExpr,
+ SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
+ SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec,
+ const DeclarationNameInfo &ReductionId) {
+ OMPClause *Res = nullptr;
switch (Kind) {
case OMPC_private:
Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
@@ -781,13 +2758,47 @@ OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
case OMPC_firstprivate:
Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
break;
+ case OMPC_lastprivate:
+ Res = ActOnOpenMPLastprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
+ break;
case OMPC_shared:
Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
break;
+ case OMPC_reduction:
+ Res = ActOnOpenMPReductionClause(VarList, StartLoc, LParenLoc, ColonLoc,
+ EndLoc, ReductionIdScopeSpec, ReductionId);
+ break;
+ case OMPC_linear:
+ Res = ActOnOpenMPLinearClause(VarList, TailExpr, StartLoc, LParenLoc,
+ ColonLoc, EndLoc);
+ break;
+ case OMPC_aligned:
+ Res = ActOnOpenMPAlignedClause(VarList, TailExpr, StartLoc, LParenLoc,
+ ColonLoc, EndLoc);
+ break;
+ case OMPC_copyin:
+ Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_copyprivate:
+ Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_flush:
+ Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_if:
+ case OMPC_final:
+ case OMPC_num_threads:
+ case OMPC_safelen:
+ case OMPC_collapse:
case OMPC_default:
+ case OMPC_proc_bind:
+ case OMPC_schedule:
+ case OMPC_ordered:
+ case OMPC_nowait:
+ case OMPC_untied:
+ case OMPC_mergeable:
case OMPC_threadprivate:
case OMPC_unknown:
- case NUM_OPENMP_CLAUSES:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -798,25 +2809,23 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
- for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end();
- I != E; ++I) {
- assert(*I && "NULL expr in OpenMP private clause.");
- if (isa<DependentScopeDeclRefExpr>(*I)) {
+ for (auto &RefExpr : VarList) {
+ assert(RefExpr && "NULL expr in OpenMP private clause.");
+ if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
- Vars.push_back(*I);
+ Vars.push_back(RefExpr);
continue;
}
- SourceLocation ELoc = (*I)->getExprLoc();
+ SourceLocation ELoc = RefExpr->getExprLoc();
// OpenMP [2.1, C/C++]
// A list item is a variable name.
// OpenMP [2.9.3.3, Restrictions, p.1]
// A variable that is part of another variable (as an array or
// structure element) cannot appear in a private clause.
- DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(*I);
+ DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
if (!DE || !isa<VarDecl>(DE->getDecl())) {
- Diag(ELoc, diag::err_omp_expected_var_name)
- << (*I)->getSourceRange();
+ Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange();
continue;
}
Decl *D = DE->getDecl();
@@ -838,39 +2847,44 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
}
if (Type->isReferenceType()) {
Diag(ELoc, diag::err_omp_clause_ref_type_arg)
- << getOpenMPClauseName(OMPC_private) << Type;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
- diag::note_defined_here) << VD;
+ << getOpenMPClauseName(OMPC_private) << Type;
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
continue;
}
// OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
// A variable of class type (or array thereof) that appears in a private
- // clause requires an accesible, unambiguous default constructor for the
+ // clause requires an accessible, unambiguous default constructor for the
// class type.
while (Type.getNonReferenceType()->isArrayType()) {
- Type = cast<ArrayType>(
- Type.getNonReferenceType().getTypePtr())->getElementType();
+ Type = cast<ArrayType>(Type.getNonReferenceType().getTypePtr())
+ ->getElementType();
}
- CXXRecordDecl *RD = getLangOpts().CPlusPlus ?
- Type.getNonReferenceType()->getAsCXXRecordDecl() : 0;
+ CXXRecordDecl *RD = getLangOpts().CPlusPlus
+ ? Type.getNonReferenceType()->getAsCXXRecordDecl()
+ : nullptr;
+ // FIXME This code must be replaced by actual constructing/destructing of
+ // the private variable.
if (RD) {
CXXConstructorDecl *CD = LookupDefaultConstructor(RD);
PartialDiagnostic PD =
- PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
+ PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
if (!CD ||
CheckConstructorAccess(ELoc, CD,
InitializedEntity::InitializeTemporary(Type),
CD->getAccess(), PD) == AR_inaccessible ||
CD->isDeleted()) {
Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_private) << 0;
+ << getOpenMPClauseName(OMPC_private) << 0;
bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
- diag::note_defined_here) << VD;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
Diag(RD->getLocation(), diag::note_previous_decl) << RD;
continue;
}
@@ -882,11 +2896,12 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible ||
DD->isDeleted()) {
Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_private) << 4;
+ << getOpenMPClauseName(OMPC_private) << 4;
bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
- diag::note_defined_here) << VD;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
Diag(RD->getLocation(), diag::note_previous_decl) << RD;
continue;
}
@@ -902,18 +2917,11 @@ 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(VD);
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false);
if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
- Diag(ELoc, diag::err_omp_wrong_dsa)
- << getOpenMPClauseName(DVar.CKind)
- << getOpenMPClauseName(OMPC_private);
- if (DVar.RefExpr) {
- Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
- << getOpenMPClauseName(DVar.CKind);
- } else {
- Diag(VD->getLocation(), diag::note_omp_predetermined_dsa)
- << getOpenMPClauseName(DVar.CKind);
- }
+ Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
+ << getOpenMPClauseName(OMPC_private);
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
continue;
}
@@ -921,7 +2929,8 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
Vars.push_back(DE);
}
- if (Vars.empty()) return 0;
+ if (Vars.empty())
+ return nullptr;
return OMPPrivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
}
@@ -931,25 +2940,28 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
- for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end();
- I != E; ++I) {
- assert(*I && "NULL expr in OpenMP firstprivate clause.");
- if (isa<DependentScopeDeclRefExpr>(*I)) {
+ bool IsImplicitClause =
+ StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
+ auto ImplicitClauseLoc = DSAStack->getConstructLoc();
+
+ for (auto &RefExpr : VarList) {
+ assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
+ if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
- Vars.push_back(*I);
+ Vars.push_back(RefExpr);
continue;
}
- SourceLocation ELoc = (*I)->getExprLoc();
+ SourceLocation ELoc = IsImplicitClause ? ImplicitClauseLoc
+ : RefExpr->getExprLoc();
// OpenMP [2.1, C/C++]
// A list item is a variable name.
// OpenMP [2.9.3.3, Restrictions, p.1]
// A variable that is part of another variable (as an array or
// structure element) cannot appear in a private clause.
- DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(*I);
+ DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
if (!DE || !isa<VarDecl>(DE->getDecl())) {
- Diag(ELoc, diag::err_omp_expected_var_name)
- << (*I)->getSourceRange();
+ Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange();
continue;
}
Decl *D = DE->getDecl();
@@ -970,37 +2982,56 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
continue;
}
if (Type->isReferenceType()) {
- Diag(ELoc, diag::err_omp_clause_ref_type_arg)
- << getOpenMPClauseName(OMPC_firstprivate) << Type;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
- diag::note_defined_here) << VD;
+ if (IsImplicitClause) {
+ Diag(ImplicitClauseLoc,
+ diag::err_omp_task_predetermined_firstprivate_ref_type_arg)
+ << Type;
+ Diag(RefExpr->getExprLoc(), diag::note_used_here);
+ } else {
+ Diag(ELoc, diag::err_omp_clause_ref_type_arg)
+ << getOpenMPClauseName(OMPC_firstprivate) << Type;
+ }
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
continue;
}
// OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
// A variable of class type (or array thereof) that appears in a private
- // clause requires an accesible, unambiguous copy constructor for the
+ // clause requires an accessible, unambiguous copy constructor for the
// class type.
Type = Context.getBaseElementType(Type);
- CXXRecordDecl *RD = getLangOpts().CPlusPlus ?
- Type.getNonReferenceType()->getAsCXXRecordDecl() : 0;
+ CXXRecordDecl *RD = getLangOpts().CPlusPlus
+ ? Type.getNonReferenceType()->getAsCXXRecordDecl()
+ : nullptr;
+ // FIXME This code must be replaced by actual constructing/destructing of
+ // the firstprivate variable.
if (RD) {
CXXConstructorDecl *CD = LookupCopyingConstructor(RD, 0);
PartialDiagnostic PD =
- PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
+ PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
if (!CD ||
CheckConstructorAccess(ELoc, CD,
InitializedEntity::InitializeTemporary(Type),
CD->getAccess(), PD) == AR_inaccessible ||
CD->isDeleted()) {
- Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_firstprivate) << 1;
+ if (IsImplicitClause) {
+ Diag(ImplicitClauseLoc,
+ diag::err_omp_task_predetermined_firstprivate_required_method)
+ << 0;
+ Diag(RefExpr->getExprLoc(), diag::note_used_here);
+ } else {
+ Diag(ELoc, diag::err_omp_required_method)
+ << getOpenMPClauseName(OMPC_firstprivate) << 1;
+ }
bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
- diag::note_defined_here) << VD;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
Diag(RD->getLocation(), diag::note_previous_decl) << RD;
continue;
}
@@ -1011,12 +3042,20 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
if (DD) {
if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible ||
DD->isDeleted()) {
- Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_firstprivate) << 4;
+ if (IsImplicitClause) {
+ Diag(ImplicitClauseLoc,
+ diag::err_omp_task_predetermined_firstprivate_required_method)
+ << 1;
+ Diag(RefExpr->getExprLoc(), diag::note_used_here);
+ } else {
+ Diag(ELoc, diag::err_omp_required_method)
+ << getOpenMPClauseName(OMPC_firstprivate) << 4;
+ }
bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
VarDecl::DeclarationOnly;
- Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
- diag::note_defined_here) << VD;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
Diag(RD->getLocation(), diag::note_previous_decl) << RD;
continue;
}
@@ -1025,10 +3064,9 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
}
}
- // If StartLoc and EndLoc are invalid - this is an implicit firstprivate
- // variable and it was checked already.
- if (StartLoc.isValid() && EndLoc.isValid()) {
- DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
+ // If an implicit firstprivate variable found it was checked already.
+ if (!IsImplicitClause) {
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false);
Type = Type.getNonReferenceType().getCanonicalType();
bool IsConstant = Type.isConstant(Context);
Type = Context.getBaseElementType(Type);
@@ -1036,14 +3074,12 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
// A list item that specifies a given variable may not appear in more
// than one clause on the same directive, except that a variable may be
// specified in both firstprivate and lastprivate clauses.
- // TODO: add processing for lastprivate.
if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
- DVar.RefExpr) {
+ DVar.CKind != OMPC_lastprivate && DVar.RefExpr) {
Diag(ELoc, diag::err_omp_wrong_dsa)
- << getOpenMPClauseName(DVar.CKind)
- << getOpenMPClauseName(OMPC_firstprivate);
- Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
- << getOpenMPClauseName(DVar.CKind);
+ << getOpenMPClauseName(DVar.CKind)
+ << getOpenMPClauseName(OMPC_firstprivate);
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
continue;
}
@@ -1061,18 +3097,31 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
if (!(IsConstant || VD->isStaticDataMember()) && !DVar.RefExpr &&
DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
Diag(ELoc, diag::err_omp_wrong_dsa)
- << getOpenMPClauseName(DVar.CKind)
- << getOpenMPClauseName(OMPC_firstprivate);
- Diag(VD->getLocation(), diag::note_omp_predetermined_dsa)
- << getOpenMPClauseName(DVar.CKind);
+ << getOpenMPClauseName(DVar.CKind)
+ << getOpenMPClauseName(OMPC_firstprivate);
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
continue;
}
+ OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
// OpenMP [2.9.3.4, Restrictions, p.2]
// A list item that is private within a parallel region must not appear
// in a firstprivate clause on a worksharing construct if any of the
// worksharing regions arising from the worksharing construct ever bind
// to any of the parallel regions arising from the parallel construct.
+ if (isOpenMPWorksharingDirective(CurrDir) &&
+ !isOpenMPParallelDirective(CurrDir)) {
+ DVar = DSAStack->getImplicitDSA(VD, true);
+ if (DVar.CKind != OMPC_shared &&
+ (isOpenMPParallelDirective(DVar.DKind) ||
+ DVar.DKind == OMPD_unknown)) {
+ Diag(ELoc, diag::err_omp_required_access)
+ << getOpenMPClauseName(OMPC_firstprivate)
+ << getOpenMPClauseName(OMPC_shared);
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
+ continue;
+ }
+ }
// OpenMP [2.9.3.4, Restrictions, p.3]
// A list item that appears in a reduction clause of a parallel construct
// must not appear in a firstprivate clause on a worksharing or task
@@ -1084,43 +3133,214 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
// construct must not appear in a firstprivate clause in a task construct
// encountered during execution of any of the worksharing regions arising
// from the worksharing construct.
- // TODO:
+ if (CurrDir == OMPD_task) {
+ DVar =
+ DSAStack->hasInnermostDSA(VD, MatchesAnyClause(OMPC_reduction),
+ [](OpenMPDirectiveKind K) -> bool {
+ return isOpenMPParallelDirective(K) ||
+ isOpenMPWorksharingDirective(K);
+ },
+ false);
+ if (DVar.CKind == OMPC_reduction &&
+ (isOpenMPParallelDirective(DVar.DKind) ||
+ isOpenMPWorksharingDirective(DVar.DKind))) {
+ Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
+ << getOpenMPDirectiveName(DVar.DKind);
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
+ continue;
+ }
+ }
}
DSAStack->addDSA(VD, DE, OMPC_firstprivate);
Vars.push_back(DE);
}
- if (Vars.empty()) return 0;
+ if (Vars.empty())
+ return nullptr;
return OMPFirstprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
Vars);
}
+OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ SmallVector<Expr *, 8> Vars;
+ for (auto &RefExpr : VarList) {
+ assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
+ if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
+ // It will be analyzed later.
+ Vars.push_back(RefExpr);
+ continue;
+ }
+
+ SourceLocation ELoc = RefExpr->getExprLoc();
+ // OpenMP [2.1, C/C++]
+ // A list item is a variable name.
+ // OpenMP [2.14.3.5, Restrictions, p.1]
+ // A variable that is part of another variable (as an array or structure
+ // element) cannot appear in a lastprivate clause.
+ DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
+ if (!DE || !isa<VarDecl>(DE->getDecl())) {
+ Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange();
+ continue;
+ }
+ Decl *D = DE->getDecl();
+ VarDecl *VD = cast<VarDecl>(D);
+
+ QualType Type = VD->getType();
+ if (Type->isDependentType() || Type->isInstantiationDependentType()) {
+ // It will be analyzed later.
+ Vars.push_back(DE);
+ continue;
+ }
+
+ // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
+ // A variable that appears in a lastprivate clause must not have an
+ // incomplete type or a reference type.
+ if (RequireCompleteType(ELoc, Type,
+ diag::err_omp_lastprivate_incomplete_type)) {
+ continue;
+ }
+ if (Type->isReferenceType()) {
+ Diag(ELoc, diag::err_omp_clause_ref_type_arg)
+ << getOpenMPClauseName(OMPC_lastprivate) << Type;
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ continue;
+ }
+
+ // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // in a Construct]
+ // Variables with the predetermined data-sharing attributes may not be
+ // listed in data-sharing attributes clauses, except for the cases
+ // listed below.
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false);
+ if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
+ DVar.CKind != OMPC_firstprivate &&
+ (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
+ Diag(ELoc, diag::err_omp_wrong_dsa)
+ << getOpenMPClauseName(DVar.CKind)
+ << getOpenMPClauseName(OMPC_lastprivate);
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
+ continue;
+ }
+
+ OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
+ // OpenMP [2.14.3.5, Restrictions, p.2]
+ // A list item that is private within a parallel region, or that appears in
+ // the reduction clause of a parallel construct, must not appear in a
+ // lastprivate clause on a worksharing construct if any of the corresponding
+ // worksharing regions ever binds to any of the corresponding parallel
+ // regions.
+ if (isOpenMPWorksharingDirective(CurrDir) &&
+ !isOpenMPParallelDirective(CurrDir)) {
+ DVar = DSAStack->getImplicitDSA(VD, true);
+ if (DVar.CKind != OMPC_shared) {
+ Diag(ELoc, diag::err_omp_required_access)
+ << getOpenMPClauseName(OMPC_lastprivate)
+ << getOpenMPClauseName(OMPC_shared);
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
+ continue;
+ }
+ }
+ // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
+ // A variable of class type (or array thereof) that appears in a
+ // lastprivate clause requires an accessible, unambiguous default
+ // constructor for the class type, unless the list item is also specified
+ // in a firstprivate clause.
+ // A variable of class type (or array thereof) that appears in a
+ // lastprivate clause requires an accessible, unambiguous copy assignment
+ // operator for the class type.
+ while (Type.getNonReferenceType()->isArrayType())
+ Type = cast<ArrayType>(Type.getNonReferenceType().getTypePtr())
+ ->getElementType();
+ CXXRecordDecl *RD = getLangOpts().CPlusPlus
+ ? Type.getNonReferenceType()->getAsCXXRecordDecl()
+ : nullptr;
+ // FIXME This code must be replaced by actual copying and destructing of the
+ // lastprivate variable.
+ if (RD) {
+ CXXMethodDecl *MD = LookupCopyingAssignment(RD, 0, false, 0);
+ DeclAccessPair FoundDecl = DeclAccessPair::make(MD, MD->getAccess());
+ if (MD) {
+ if (CheckMemberAccess(ELoc, RD, FoundDecl) == AR_inaccessible ||
+ MD->isDeleted()) {
+ Diag(ELoc, diag::err_omp_required_method)
+ << getOpenMPClauseName(OMPC_lastprivate) << 2;
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ Diag(RD->getLocation(), diag::note_previous_decl) << RD;
+ continue;
+ }
+ MarkFunctionReferenced(ELoc, MD);
+ DiagnoseUseOfDecl(MD, ELoc);
+ }
+
+ CXXDestructorDecl *DD = RD->getDestructor();
+ if (DD) {
+ PartialDiagnostic PD =
+ PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
+ if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible ||
+ DD->isDeleted()) {
+ Diag(ELoc, diag::err_omp_required_method)
+ << getOpenMPClauseName(OMPC_lastprivate) << 4;
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ Diag(RD->getLocation(), diag::note_previous_decl) << RD;
+ continue;
+ }
+ MarkFunctionReferenced(ELoc, DD);
+ DiagnoseUseOfDecl(DD, ELoc);
+ }
+ }
+
+ if (DVar.CKind != OMPC_firstprivate)
+ DSAStack->addDSA(VD, DE, OMPC_lastprivate);
+ Vars.push_back(DE);
+ }
+
+ if (Vars.empty())
+ return nullptr;
+
+ return OMPLastprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
+ Vars);
+}
+
OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
- for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end();
- I != E; ++I) {
- assert(*I && "NULL expr in OpenMP shared clause.");
- if (isa<DependentScopeDeclRefExpr>(*I)) {
+ for (auto &RefExpr : VarList) {
+ assert(RefExpr && "NULL expr in OpenMP shared clause.");
+ if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
- Vars.push_back(*I);
+ Vars.push_back(RefExpr);
continue;
}
- SourceLocation ELoc = (*I)->getExprLoc();
+ SourceLocation ELoc = RefExpr->getExprLoc();
// OpenMP [2.1, C/C++]
// A list item is a variable name.
- // OpenMP [2.9.3.4, Restrictions, p.1]
- // A variable that is part of another variable (as an array or
- // structure element) cannot appear in a private clause.
- DeclRefExpr *DE = dyn_cast<DeclRefExpr>(*I);
+ // OpenMP [2.14.3.2, Restrictions, p.1]
+ // A variable that is part of another variable (as an array or structure
+ // element) cannot appear in a shared unless it is a static data member
+ // of a C++ class.
+ DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr);
if (!DE || !isa<VarDecl>(DE->getDecl())) {
- Diag(ELoc, diag::err_omp_expected_var_name)
- << (*I)->getSourceRange();
+ Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange();
continue;
}
Decl *D = DE->getDecl();
@@ -1140,13 +3360,12 @@ 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(VD);
- if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared && DVar.RefExpr) {
- Diag(ELoc, diag::err_omp_wrong_dsa)
- << getOpenMPClauseName(DVar.CKind)
- << getOpenMPClauseName(OMPC_shared);
- Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
- << getOpenMPClauseName(DVar.CKind);
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, 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, VD, DVar);
continue;
}
@@ -1154,9 +3373,730 @@ OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
Vars.push_back(DE);
}
- if (Vars.empty()) return 0;
+ if (Vars.empty())
+ return nullptr;
return OMPSharedClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
}
+namespace {
+class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
+ DSAStackTy *Stack;
+
+public:
+ bool VisitDeclRefExpr(DeclRefExpr *E) {
+ if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) {
+ DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, false);
+ if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
+ return false;
+ if (DVar.CKind != OMPC_unknown)
+ return true;
+ DSAStackTy::DSAVarData DVarPrivate =
+ Stack->hasDSA(VD, isOpenMPPrivate, MatchesAlways(), false);
+ if (DVarPrivate.CKind != OMPC_unknown)
+ return true;
+ return false;
+ }
+ return false;
+ }
+ bool VisitStmt(Stmt *S) {
+ for (auto Child : S->children()) {
+ if (Child && Visit(Child))
+ return true;
+ }
+ return false;
+ }
+ explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
+};
+} // namespace
+
+OMPClause *Sema::ActOnOpenMPReductionClause(
+ ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation ColonLoc, SourceLocation EndLoc,
+ CXXScopeSpec &ReductionIdScopeSpec,
+ const DeclarationNameInfo &ReductionId) {
+ // TODO: Allow scope specification search when 'declare reduction' is
+ // supported.
+ assert(ReductionIdScopeSpec.isEmpty() &&
+ "No support for scoped reduction identifiers yet.");
+
+ auto DN = ReductionId.getName();
+ auto OOK = DN.getCXXOverloadedOperator();
+ BinaryOperatorKind BOK = BO_Comma;
+
+ // OpenMP [2.14.3.6, reduction clause]
+ // C
+ // reduction-identifier is either an identifier or one of the following
+ // operators: +, -, *, &, |, ^, && and ||
+ // C++
+ // reduction-identifier is either an id-expression or one of the following
+ // operators: +, -, *, &, |, ^, && and ||
+ // FIXME: Only 'min' and 'max' identifiers are supported for now.
+ switch (OOK) {
+ case OO_Plus:
+ case OO_Minus:
+ BOK = BO_AddAssign;
+ break;
+ case OO_Star:
+ BOK = BO_MulAssign;
+ break;
+ case OO_Amp:
+ BOK = BO_AndAssign;
+ break;
+ case OO_Pipe:
+ BOK = BO_OrAssign;
+ break;
+ case OO_Caret:
+ BOK = BO_XorAssign;
+ break;
+ case OO_AmpAmp:
+ BOK = BO_LAnd;
+ break;
+ case OO_PipePipe:
+ BOK = BO_LOr;
+ break;
+ default:
+ if (auto II = DN.getAsIdentifierInfo()) {
+ if (II->isStr("max"))
+ BOK = BO_GT;
+ else if (II->isStr("min"))
+ BOK = BO_LT;
+ }
+ break;
+ }
+ SourceRange ReductionIdRange;
+ if (ReductionIdScopeSpec.isValid()) {
+ ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
+ }
+ ReductionIdRange.setEnd(ReductionId.getEndLoc());
+ if (BOK == BO_Comma) {
+ // Not allowed reduction identifier is found.
+ Diag(ReductionId.getLocStart(), diag::err_omp_unknown_reduction_identifier)
+ << ReductionIdRange;
+ return nullptr;
+ }
+
+ SmallVector<Expr *, 8> Vars;
+ for (auto RefExpr : VarList) {
+ assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
+ if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
+ // It will be analyzed later.
+ Vars.push_back(RefExpr);
+ continue;
+ }
+
+ if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
+ RefExpr->isInstantiationDependent() ||
+ RefExpr->containsUnexpandedParameterPack()) {
+ // It will be analyzed later.
+ Vars.push_back(RefExpr);
+ continue;
+ }
+
+ auto ELoc = RefExpr->getExprLoc();
+ auto ERange = RefExpr->getSourceRange();
+ // OpenMP [2.1, C/C++]
+ // A list item is a variable or array section, subject to the restrictions
+ // specified in Section 2.4 on page 42 and in each of the sections
+ // describing clauses and directives for which a list appears.
+ // OpenMP [2.14.3.3, Restrictions, p.1]
+ // A variable that is part of another variable (as an array or
+ // structure element) cannot appear in a private clause.
+ auto DE = dyn_cast<DeclRefExpr>(RefExpr);
+ if (!DE || !isa<VarDecl>(DE->getDecl())) {
+ Diag(ELoc, diag::err_omp_expected_var_name) << ERange;
+ continue;
+ }
+ auto D = DE->getDecl();
+ auto VD = cast<VarDecl>(D);
+ auto Type = VD->getType();
+ // 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 (RequireCompleteType(ELoc, Type,
+ diag::err_omp_reduction_incomplete_type))
+ continue;
+ // OpenMP [2.14.3.6, reduction clause, Restrictions]
+ // Arrays may not appear in a reduction clause.
+ if (Type.getNonReferenceType()->isArrayType()) {
+ Diag(ELoc, diag::err_omp_reduction_type_array) << Type << ERange;
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ continue;
+ }
+ // OpenMP [2.14.3.6, reduction clause, Restrictions]
+ // A list item that appears in a reduction clause must not be
+ // const-qualified.
+ if (Type.getNonReferenceType().isConstant(Context)) {
+ Diag(ELoc, diag::err_omp_const_variable)
+ << getOpenMPClauseName(OMPC_reduction) << Type << ERange;
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ continue;
+ }
+ // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
+ // If a list-item is a reference type then it must bind to the same object
+ // for all threads of the team.
+ VarDecl *VDDef = VD->getDefinition();
+ if (Type->isReferenceType() && VDDef) {
+ DSARefChecker Check(DSAStack);
+ if (Check.Visit(VDDef->getInit())) {
+ Diag(ELoc, diag::err_omp_reduction_ref_type_arg) << ERange;
+ Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
+ continue;
+ }
+ }
+ // OpenMP [2.14.3.6, reduction clause, Restrictions]
+ // The type of a list item that appears in a reduction clause must be valid
+ // for the reduction-identifier. For a max or min reduction in C, the type
+ // of the list item must be an allowed arithmetic data type: char, int,
+ // float, double, or _Bool, possibly modified with long, short, signed, or
+ // unsigned. For a max or min reduction in C++, the type of the list item
+ // must be an allowed arithmetic data type: char, wchar_t, int, float,
+ // double, or bool, possibly modified with long, short, signed, or unsigned.
+ if ((BOK == BO_GT || BOK == BO_LT) &&
+ !(Type->isScalarType() ||
+ (getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
+ Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
+ << getLangOpts().CPlusPlus;
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ continue;
+ }
+ if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
+ !getLangOpts().CPlusPlus && Type->isFloatingType()) {
+ Diag(ELoc, diag::err_omp_clause_floating_type_arg);
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ continue;
+ }
+ bool Suppress = getDiagnostics().getSuppressAllDiagnostics();
+ getDiagnostics().setSuppressAllDiagnostics(true);
+ ExprResult ReductionOp =
+ BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(), BOK,
+ RefExpr, RefExpr);
+ getDiagnostics().setSuppressAllDiagnostics(Suppress);
+ if (ReductionOp.isInvalid()) {
+ Diag(ELoc, diag::err_omp_reduction_id_not_compatible) << Type
+ << ReductionIdRange;
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ continue;
+ }
+
+ // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // in a Construct]
+ // Variables with the predetermined data-sharing attributes may not be
+ // listed in data-sharing attributes clauses, except for the cases
+ // listed below. For these exceptions only, listing a predetermined
+ // variable in a data-sharing attribute clause is allowed and overrides
+ // the variable's predetermined data-sharing attributes.
+ // OpenMP [2.14.3.6, Restrictions, p.3]
+ // Any number of reduction clauses can be specified on the directive,
+ // but a list item can appear only once in the reduction clauses for that
+ // directive.
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false);
+ if (DVar.CKind == OMPC_reduction) {
+ Diag(ELoc, diag::err_omp_once_referenced)
+ << getOpenMPClauseName(OMPC_reduction);
+ if (DVar.RefExpr) {
+ Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
+ }
+ } else if (DVar.CKind != OMPC_unknown) {
+ Diag(ELoc, diag::err_omp_wrong_dsa)
+ << getOpenMPClauseName(DVar.CKind)
+ << getOpenMPClauseName(OMPC_reduction);
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
+ continue;
+ }
+
+ // OpenMP [2.14.3.6, Restrictions, p.1]
+ // A list item that appears in a reduction clause of a worksharing
+ // construct must be shared in the parallel regions to which any of the
+ // worksharing regions arising from the worksharing construct bind.
+ OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
+ if (isOpenMPWorksharingDirective(CurrDir) &&
+ !isOpenMPParallelDirective(CurrDir)) {
+ DVar = DSAStack->getImplicitDSA(VD, true);
+ if (DVar.CKind != OMPC_shared) {
+ Diag(ELoc, diag::err_omp_required_access)
+ << getOpenMPClauseName(OMPC_reduction)
+ << getOpenMPClauseName(OMPC_shared);
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
+ continue;
+ }
+ }
+
+ CXXRecordDecl *RD = getLangOpts().CPlusPlus
+ ? Type.getNonReferenceType()->getAsCXXRecordDecl()
+ : nullptr;
+ // FIXME This code must be replaced by actual constructing/destructing of
+ // the reduction variable.
+ if (RD) {
+ CXXConstructorDecl *CD = LookupDefaultConstructor(RD);
+ PartialDiagnostic PD =
+ PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
+ if (!CD ||
+ CheckConstructorAccess(ELoc, CD,
+ InitializedEntity::InitializeTemporary(Type),
+ CD->getAccess(), PD) == AR_inaccessible ||
+ CD->isDeleted()) {
+ Diag(ELoc, diag::err_omp_required_method)
+ << getOpenMPClauseName(OMPC_reduction) << 0;
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ Diag(RD->getLocation(), diag::note_previous_decl) << RD;
+ continue;
+ }
+ MarkFunctionReferenced(ELoc, CD);
+ DiagnoseUseOfDecl(CD, ELoc);
+
+ CXXDestructorDecl *DD = RD->getDestructor();
+ if (DD) {
+ if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible ||
+ DD->isDeleted()) {
+ Diag(ELoc, diag::err_omp_required_method)
+ << getOpenMPClauseName(OMPC_reduction) << 4;
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ Diag(RD->getLocation(), diag::note_previous_decl) << RD;
+ continue;
+ }
+ MarkFunctionReferenced(ELoc, DD);
+ DiagnoseUseOfDecl(DD, ELoc);
+ }
+ }
+
+ DSAStack->addDSA(VD, DE, OMPC_reduction);
+ Vars.push_back(DE);
+ }
+
+ if (Vars.empty())
+ return nullptr;
+
+ return OMPReductionClause::Create(
+ Context, StartLoc, LParenLoc, ColonLoc, EndLoc, Vars,
+ ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId);
+}
+
+OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation ColonLoc,
+ SourceLocation EndLoc) {
+ SmallVector<Expr *, 8> Vars;
+ for (auto &RefExpr : VarList) {
+ assert(RefExpr && "NULL expr in OpenMP linear clause.");
+ if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
+ // It will be analyzed later.
+ Vars.push_back(RefExpr);
+ continue;
+ }
+
+ // OpenMP [2.14.3.7, linear clause]
+ // A list item that appears in a linear clause is subject to the private
+ // clause semantics described in Section 2.14.3.3 on page 159 except as
+ // noted. In addition, the value of the new list item on each iteration
+ // of the associated loop(s) corresponds to the value of the original
+ // list item before entering the construct plus the logical number of
+ // the iteration times linear-step.
+
+ SourceLocation ELoc = RefExpr->getExprLoc();
+ // OpenMP [2.1, C/C++]
+ // A list item is a variable name.
+ // OpenMP [2.14.3.3, Restrictions, p.1]
+ // A variable that is part of another variable (as an array or
+ // structure element) cannot appear in a private clause.
+ DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr);
+ if (!DE || !isa<VarDecl>(DE->getDecl())) {
+ Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange();
+ continue;
+ }
+
+ VarDecl *VD = cast<VarDecl>(DE->getDecl());
+
+ // OpenMP [2.14.3.7, linear clause]
+ // 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(VD, false);
+ if (DVar.RefExpr) {
+ Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
+ << getOpenMPClauseName(OMPC_linear);
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
+ continue;
+ }
+
+ QualType QType = VD->getType();
+ if (QType->isDependentType() || QType->isInstantiationDependentType()) {
+ // It will be analyzed later.
+ Vars.push_back(DE);
+ continue;
+ }
+
+ // A variable must not have an incomplete type or a reference type.
+ if (RequireCompleteType(ELoc, QType,
+ diag::err_omp_linear_incomplete_type)) {
+ continue;
+ }
+ if (QType->isReferenceType()) {
+ Diag(ELoc, diag::err_omp_clause_ref_type_arg)
+ << getOpenMPClauseName(OMPC_linear) << QType;
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ continue;
+ }
+
+ // A list item must not be const-qualified.
+ if (QType.isConstant(Context)) {
+ Diag(ELoc, diag::err_omp_const_variable)
+ << getOpenMPClauseName(OMPC_linear);
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ continue;
+ }
+
+ // A list item must be of integral or pointer type.
+ QType = QType.getUnqualifiedType().getCanonicalType();
+ const Type *Ty = QType.getTypePtrOrNull();
+ if (!Ty || (!Ty->isDependentType() && !Ty->isIntegralType(Context) &&
+ !Ty->isPointerType())) {
+ Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << QType;
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ continue;
+ }
+
+ DSAStack->addDSA(VD, DE, OMPC_linear);
+ Vars.push_back(DE);
+ }
+
+ if (Vars.empty())
+ return nullptr;
+
+ Expr *StepExpr = Step;
+ if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
+ !Step->isInstantiationDependent() &&
+ !Step->containsUnexpandedParameterPack()) {
+ SourceLocation StepLoc = Step->getLocStart();
+ ExprResult Val = PerformOpenMPImplicitIntegerConversion(StepLoc, Step);
+ if (Val.isInvalid())
+ return nullptr;
+ StepExpr = Val.get();
+
+ // Warn about zero linear step (it would be probably better specified as
+ // making corresponding variables 'const').
+ llvm::APSInt Result;
+ if (StepExpr->isIntegerConstantExpr(Result, Context) &&
+ !Result.isNegative() && !Result.isStrictlyPositive())
+ Diag(StepLoc, diag::warn_omp_linear_step_zero) << Vars[0]
+ << (Vars.size() > 1);
+ }
+
+ return OMPLinearClause::Create(Context, StartLoc, LParenLoc, ColonLoc, EndLoc,
+ Vars, StepExpr);
+}
+
+OMPClause *Sema::ActOnOpenMPAlignedClause(
+ ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
+
+ SmallVector<Expr *, 8> Vars;
+ for (auto &RefExpr : VarList) {
+ assert(RefExpr && "NULL expr in OpenMP aligned clause.");
+ if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
+ // It will be analyzed later.
+ Vars.push_back(RefExpr);
+ continue;
+ }
+
+ SourceLocation ELoc = RefExpr->getExprLoc();
+ // OpenMP [2.1, C/C++]
+ // A list item is a variable name.
+ DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr);
+ if (!DE || !isa<VarDecl>(DE->getDecl())) {
+ Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange();
+ continue;
+ }
+
+ VarDecl *VD = cast<VarDecl>(DE->getDecl());
+
+ // OpenMP [2.8.1, simd construct, Restrictions]
+ // The type of list items appearing in the aligned clause must be
+ // array, pointer, reference to array, or reference to pointer.
+ QualType QType = DE->getType()
+ .getNonReferenceType()
+ .getUnqualifiedType()
+ .getCanonicalType();
+ const Type *Ty = QType.getTypePtrOrNull();
+ if (!Ty || (!Ty->isDependentType() && !Ty->isArrayType() &&
+ !Ty->isPointerType())) {
+ Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
+ << QType << getLangOpts().CPlusPlus << RefExpr->getSourceRange();
+ bool IsDecl =
+ VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ continue;
+ }
+
+ // OpenMP [2.8.1, simd construct, Restrictions]
+ // A list-item cannot appear in more than one aligned clause.
+ if (DeclRefExpr *PrevRef = DSAStack->addUniqueAligned(VD, DE)) {
+ Diag(ELoc, diag::err_omp_aligned_twice) << RefExpr->getSourceRange();
+ Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
+ << getOpenMPClauseName(OMPC_aligned);
+ continue;
+ }
+
+ Vars.push_back(DE);
+ }
+
+ // OpenMP [2.8.1, simd construct, Description]
+ // The parameter of the aligned clause, alignment, must be a constant
+ // positive integer expression.
+ // If no optional parameter is specified, implementation-defined default
+ // alignments for SIMD instructions on the target platforms are assumed.
+ if (Alignment != nullptr) {
+ ExprResult AlignResult =
+ VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
+ if (AlignResult.isInvalid())
+ return nullptr;
+ Alignment = AlignResult.get();
+ }
+ if (Vars.empty())
+ return nullptr;
+
+ return OMPAlignedClause::Create(Context, StartLoc, LParenLoc, ColonLoc,
+ EndLoc, Vars, Alignment);
+}
+
+OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ SmallVector<Expr *, 8> Vars;
+ for (auto &RefExpr : VarList) {
+ assert(RefExpr && "NULL expr in OpenMP copyin clause.");
+ if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
+ // It will be analyzed later.
+ Vars.push_back(RefExpr);
+ continue;
+ }
+
+ SourceLocation ELoc = RefExpr->getExprLoc();
+ // OpenMP [2.1, C/C++]
+ // 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);
+ if (!DE || !isa<VarDecl>(DE->getDecl())) {
+ Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange();
+ continue;
+ }
+
+ Decl *D = DE->getDecl();
+ VarDecl *VD = cast<VarDecl>(D);
+
+ QualType Type = VD->getType();
+ if (Type->isDependentType() || Type->isInstantiationDependentType()) {
+ // It will be analyzed later.
+ Vars.push_back(DE);
+ continue;
+ }
+
+ // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
+ // A list item that appears in a copyin clause must be threadprivate.
+ if (!DSAStack->isThreadPrivate(VD)) {
+ Diag(ELoc, diag::err_omp_required_access)
+ << getOpenMPClauseName(OMPC_copyin)
+ << getOpenMPDirectiveName(OMPD_threadprivate);
+ continue;
+ }
+
+ // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
+ // 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.
+ Type = Context.getBaseElementType(Type);
+ CXXRecordDecl *RD =
+ getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr;
+ // FIXME This code must be replaced by actual assignment of the
+ // threadprivate variable.
+ if (RD) {
+ CXXMethodDecl *MD = LookupCopyingAssignment(RD, 0, false, 0);
+ DeclAccessPair FoundDecl = DeclAccessPair::make(MD, MD->getAccess());
+ if (MD) {
+ if (CheckMemberAccess(ELoc, RD, FoundDecl) == AR_inaccessible ||
+ MD->isDeleted()) {
+ Diag(ELoc, diag::err_omp_required_method)
+ << getOpenMPClauseName(OMPC_copyin) << 2;
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ Diag(RD->getLocation(), diag::note_previous_decl) << RD;
+ continue;
+ }
+ MarkFunctionReferenced(ELoc, MD);
+ DiagnoseUseOfDecl(MD, ELoc);
+ }
+ }
+
+ DSAStack->addDSA(VD, DE, OMPC_copyin);
+ Vars.push_back(DE);
+ }
+
+ if (Vars.empty())
+ return nullptr;
+
+ return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
+}
+
+OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ SmallVector<Expr *, 8> Vars;
+ for (auto &RefExpr : VarList) {
+ assert(RefExpr && "NULL expr in OpenMP copyprivate clause.");
+ if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
+ // It will be analyzed later.
+ Vars.push_back(RefExpr);
+ continue;
+ }
+
+ SourceLocation ELoc = RefExpr->getExprLoc();
+ // OpenMP [2.1, C/C++]
+ // 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);
+ if (!DE || !isa<VarDecl>(DE->getDecl())) {
+ Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange();
+ continue;
+ }
+
+ Decl *D = DE->getDecl();
+ VarDecl *VD = cast<VarDecl>(D);
+
+ QualType Type = VD->getType();
+ if (Type->isDependentType() || Type->isInstantiationDependentType()) {
+ // It will be analyzed later.
+ Vars.push_back(DE);
+ continue;
+ }
+
+ // OpenMP [2.14.4.2, Restrictions, p.2]
+ // A list item that appears in a copyprivate clause may not appear in a
+ // private or firstprivate clause on the single construct.
+ if (!DSAStack->isThreadPrivate(VD)) {
+ auto DVar = DSAStack->getTopDSA(VD, false);
+ if (DVar.CKind != OMPC_copyprivate && DVar.CKind != OMPC_unknown &&
+ !(DVar.CKind == OMPC_private && !DVar.RefExpr)) {
+ Diag(ELoc, diag::err_omp_wrong_dsa)
+ << getOpenMPClauseName(DVar.CKind)
+ << getOpenMPClauseName(OMPC_copyprivate);
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
+ continue;
+ }
+
+ // OpenMP [2.11.4.2, Restrictions, p.1]
+ // All list items that appear in a copyprivate clause must be either
+ // threadprivate or private in the enclosing context.
+ if (DVar.CKind == OMPC_unknown) {
+ DVar = DSAStack->getImplicitDSA(VD, false);
+ if (DVar.CKind == OMPC_shared) {
+ Diag(ELoc, diag::err_omp_required_access)
+ << getOpenMPClauseName(OMPC_copyprivate)
+ << "threadprivate or private in the enclosing context";
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
+ continue;
+ }
+ }
+ }
+
+ // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
+ // 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.
+ Type = Context.getBaseElementType(Type);
+ CXXRecordDecl *RD =
+ getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr;
+ // FIXME This code must be replaced by actual assignment of the
+ // threadprivate variable.
+ if (RD) {
+ CXXMethodDecl *MD = LookupCopyingAssignment(RD, 0, false, 0);
+ DeclAccessPair FoundDecl = DeclAccessPair::make(MD, MD->getAccess());
+ if (MD) {
+ if (CheckMemberAccess(ELoc, RD, FoundDecl) == AR_inaccessible ||
+ MD->isDeleted()) {
+ Diag(ELoc, diag::err_omp_required_method)
+ << getOpenMPClauseName(OMPC_copyprivate) << 2;
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ Diag(RD->getLocation(), diag::note_previous_decl) << RD;
+ continue;
+ }
+ MarkFunctionReferenced(ELoc, MD);
+ DiagnoseUseOfDecl(MD, ELoc);
+ }
+ }
+
+ // No need to mark vars as copyprivate, they are already threadprivate or
+ // implicitly private.
+ Vars.push_back(DE);
+ }
+
+ if (Vars.empty())
+ return nullptr;
+
+ return OMPCopyprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
+}
+
+OMPClause *Sema::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ if (VarList.empty())
+ return nullptr;
+
+ return OMPFlushClause::Create(Context, StartLoc, LParenLoc, EndLoc, VarList);
+}
+
#undef DSAStack
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
index 802f2b7..03001d8 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
@@ -20,9 +20,9 @@
#include "clang/AST/ExprObjC.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/SemaInternal.h"
@@ -33,6 +33,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include <algorithm>
+#include <cstdlib>
namespace clang {
using namespace sema;
@@ -60,8 +61,8 @@ CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, NamedDecl *FoundDecl,
S.MarkDeclRefReferenced(DRE);
- ExprResult E = S.Owned(DRE);
- E = S.DefaultFunctionArrayConversion(E.take());
+ ExprResult E = DRE;
+ E = S.DefaultFunctionArrayConversion(E.get());
if (E.isInvalid())
return ExprError();
return E;
@@ -215,7 +216,7 @@ void StandardConversionSequence::setAsIdentityConversion() {
BindsToRvalue = false;
BindsImplicitObjectArgumentWithoutRefQualifier = false;
ObjCLifetimeConversionBinding = false;
- CopyConstructor = 0;
+ CopyConstructor = nullptr;
}
/// getRank - Retrieve the rank of this standard conversion sequence
@@ -573,7 +574,7 @@ DeductionFailureInfo MakeDeductionFailureInfo(ASTContext &Context,
DeductionFailureInfo Result;
Result.Result = static_cast<unsigned>(TDK);
Result.HasDiagnostic = false;
- Result.Data = 0;
+ Result.Data = nullptr;
switch (TDK) {
case Sema::TDK_Success:
case Sema::TDK_Invalid:
@@ -644,12 +645,12 @@ void DeductionFailureInfo::Destroy() {
case Sema::TDK_Underqualified:
case Sema::TDK_NonDeducedMismatch:
// FIXME: Destroy the data?
- Data = 0;
+ Data = nullptr;
break;
case Sema::TDK_SubstitutionFailure:
// FIXME: Destroy the template argument list?
- Data = 0;
+ Data = nullptr;
if (PartialDiagnosticAt *Diag = getSFINAEDiagnostic()) {
Diag->~PartialDiagnosticAt();
HasDiagnostic = false;
@@ -665,7 +666,7 @@ void DeductionFailureInfo::Destroy() {
PartialDiagnosticAt *DeductionFailureInfo::getSFINAEDiagnostic() {
if (HasDiagnostic)
return static_cast<PartialDiagnosticAt*>(static_cast<void*>(Diagnostic));
- return 0;
+ return nullptr;
}
TemplateParameter DeductionFailureInfo::getTemplateParameter() {
@@ -709,7 +710,7 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() {
case Sema::TDK_Underqualified:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
- return 0;
+ return nullptr;
case Sema::TDK_SubstitutionFailure:
return static_cast<TemplateArgumentList*>(Data);
@@ -719,7 +720,7 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() {
break;
}
- return 0;
+ return nullptr;
}
const TemplateArgument *DeductionFailureInfo::getFirstArg() {
@@ -733,7 +734,7 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() {
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_FailedOverloadResolution:
- return 0;
+ return nullptr;
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
@@ -745,7 +746,7 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() {
break;
}
- return 0;
+ return nullptr;
}
const TemplateArgument *DeductionFailureInfo::getSecondArg() {
@@ -759,7 +760,7 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() {
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_FailedOverloadResolution:
- return 0;
+ return nullptr;
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
@@ -771,7 +772,7 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() {
break;
}
- return 0;
+ return nullptr;
}
Expr *DeductionFailureInfo::getExpr() {
@@ -779,7 +780,7 @@ Expr *DeductionFailureInfo::getExpr() {
Sema::TDK_FailedOverloadResolution)
return static_cast<Expr*>(Data);
- return 0;
+ return nullptr;
}
void OverloadCandidateSet::destroyCandidates() {
@@ -829,8 +830,9 @@ namespace {
/// without this, they will be immediately diagnosed as errors
///
/// Return true on unrecoverable error.
-static bool checkPlaceholderForOverload(Sema &S, Expr *&E,
- UnbridgedCastsSet *unbridgedCasts = 0) {
+static bool
+checkPlaceholderForOverload(Sema &S, Expr *&E,
+ UnbridgedCastsSet *unbridgedCasts = nullptr) {
if (const BuiltinType *placeholder = E->getType()->getAsPlaceholderType()) {
// We can't handle overloaded expressions here because overload
// resolution might reasonably tweak them.
@@ -849,7 +851,7 @@ static bool checkPlaceholderForOverload(Sema &S, Expr *&E,
if (result.isInvalid())
return true;
- E = result.take();
+ E = result.get();
return false;
}
@@ -930,24 +932,15 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
(OldIsUsingDecl || NewIsUsingDecl) && CurContext->isRecord() &&
!New->getFriendObjectKind();
- if (FunctionTemplateDecl *OldT = dyn_cast<FunctionTemplateDecl>(OldD)) {
- if (!IsOverload(New, OldT->getTemplatedDecl(), UseMemberUsingDeclRules)) {
- if (UseMemberUsingDeclRules && OldIsUsingDecl) {
- HideUsingShadowDecl(S, cast<UsingShadowDecl>(*I));
- continue;
- }
-
- Match = *I;
- return Ovl_Match;
- }
- } else if (FunctionDecl *OldF = dyn_cast<FunctionDecl>(OldD)) {
+ if (FunctionDecl *OldF = OldD->getAsFunction()) {
if (!IsOverload(New, OldF, UseMemberUsingDeclRules)) {
if (UseMemberUsingDeclRules && OldIsUsingDecl) {
HideUsingShadowDecl(S, cast<UsingShadowDecl>(*I));
continue;
}
- if (!shouldLinkPossiblyHiddenDecl(*I, New))
+ if (!isa<FunctionTemplateDecl>(OldD) &&
+ !shouldLinkPossiblyHiddenDecl(*I, New))
continue;
Match = *I;
@@ -991,7 +984,7 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
// C++ [temp.fct]p2:
// A function template can be overloaded with other function templates
// and with normal (non-template) functions.
- if ((OldTemplate == 0) != (NewTemplate == 0))
+ if ((OldTemplate == nullptr) != (NewTemplate == nullptr))
return true;
// Is the function New an overload of the function Old?
@@ -1008,16 +1001,16 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
isa<FunctionNoProtoType>(NewQType.getTypePtr()))
return false;
- const FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType);
- const FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType);
+ const FunctionProtoType *OldType = cast<FunctionProtoType>(OldQType);
+ const FunctionProtoType *NewType = cast<FunctionProtoType>(NewQType);
// The signature of a function includes the types of its
// parameters (C++ 1.3.10), which includes the presence or absence
// of the ellipsis; see C++ DR 357).
if (OldQType != NewQType &&
- (OldType->getNumArgs() != NewType->getNumArgs() ||
+ (OldType->getNumParams() != NewType->getNumParams() ||
OldType->isVariadic() != NewType->isVariadic() ||
- !FunctionArgTypesAreEqual(OldType, NewType)))
+ !FunctionParamTypesAreEqual(OldType, NewType)))
return true;
// C++ [temp.over.link]p4:
@@ -1036,7 +1029,7 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
(!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
OldTemplate->getTemplateParameters(),
false, TPL_TemplateMatch) ||
- OldType->getResultType() != NewType->getResultType()))
+ OldType->getReturnType() != NewType->getReturnType()))
return true;
// If the function is a class member, its signature includes the
@@ -1085,6 +1078,22 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
return true;
}
+ // enable_if attributes are an order-sensitive part of the signature.
+ for (specific_attr_iterator<EnableIfAttr>
+ NewI = New->specific_attr_begin<EnableIfAttr>(),
+ NewE = New->specific_attr_end<EnableIfAttr>(),
+ OldI = Old->specific_attr_begin<EnableIfAttr>(),
+ OldE = Old->specific_attr_end<EnableIfAttr>();
+ NewI != NewE || OldI != OldE; ++NewI, ++OldI) {
+ if (NewI == NewE || OldI == OldE)
+ return true;
+ llvm::FoldingSetNodeID NewID, OldID;
+ NewI->getCond()->Profile(NewID, Context, true);
+ OldI->getCond()->Profile(OldID, Context, true);
+ if (NewID != OldID)
+ return true;
+ }
+
// The signatures match; this is not an overload.
return false;
}
@@ -1120,13 +1129,15 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
}
// Attempt user-defined conversion.
- OverloadCandidateSet Conversions(From->getExprLoc());
+ OverloadCandidateSet Conversions(From->getExprLoc(),
+ OverloadCandidateSet::CSK_Normal);
OverloadingResult UserDefResult
= IsUserDefinedConversion(S, From, ToType, ICS.UserDefined, Conversions,
AllowExplicit, AllowObjCConversionOnExplicit);
if (UserDefResult == OR_Success) {
ICS.setUserDefined();
+ ICS.UserDefined.Before.setAsIdentityConversion();
// C++ [over.ics.user]p4:
// A conversion of an expression of class type to the same class
// type is given Exact Match rank, and a conversion of an
@@ -1153,17 +1164,6 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
ICS.Standard.Second = ICK_Derived_To_Base;
}
}
-
- // C++ [over.best.ics]p4:
- // However, when considering the argument of a user-defined
- // conversion function that is a candidate by 13.3.1.3 when
- // invoked for the copying of the temporary in the second step
- // of a class copy-initialization, or by 13.3.1.4, 13.3.1.5, or
- // 13.3.1.6 in all cases, only standard conversion sequences and
- // ellipsis conversion sequences are allowed.
- if (SuppressUserConversions && ICS.isUserDefined()) {
- ICS.setBad(BadConversionSequence::suppressed_user, From, ToType);
- }
} else if (UserDefResult == OR_Ambiguous && !SuppressUserConversions) {
ICS.setAmbiguous();
ICS.Ambiguous.setFromType(From->getType());
@@ -1246,7 +1246,7 @@ TryImplicitConversion(Sema &S, Expr *From, QualType ToType,
// copy/move constructor, since overloading just assumes that it
// exists. When we actually perform initialization, we'll find the
// appropriate constructor to copy the returned object, if needed.
- ICS.Standard.CopyConstructor = 0;
+ ICS.Standard.CopyConstructor = nullptr;
// Determine whether this is considered a derived-to-base conversion.
if (!S.Context.hasSameUnqualifiedType(FromType, ToType))
@@ -1298,7 +1298,9 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
bool AllowObjCWritebackConversion
= getLangOpts().ObjCAutoRefCount &&
(Action == AA_Passing || Action == AA_Sending);
-
+ if (getLangOpts().ObjC1)
+ CheckObjCBridgeRelatedConversions(From->getLocStart(),
+ ToType, From->getType(), From);
ICS = clang::TryImplicitConversion(*this, From, ToType,
/*SuppressUserConversions=*/false,
AllowExplicit,
@@ -1362,7 +1364,7 @@ bool Sema::IsNoReturnConversion(QualType FromType, QualType ToType,
///
/// \param ICK Will be set to the vector conversion kind, if this is a vector
/// conversion.
-static bool IsVectorConversion(ASTContext &Context, QualType FromType,
+static bool IsVectorConversion(Sema &S, QualType FromType,
QualType ToType, ImplicitConversionKind &ICK) {
// We need at least one of these types to be a vector type to have a vector
// conversion.
@@ -1370,7 +1372,7 @@ static bool IsVectorConversion(ASTContext &Context, QualType FromType,
return false;
// Identical types require no conversions.
- if (Context.hasSameUnqualifiedType(FromType, ToType))
+ if (S.Context.hasSameUnqualifiedType(FromType, ToType))
return false;
// There are no conversions between extended vector types, only identity.
@@ -1392,9 +1394,8 @@ static bool IsVectorConversion(ASTContext &Context, QualType FromType,
// 2)lax vector conversions are permitted and the vector types are of the
// same size
if (ToType->isVectorType() && FromType->isVectorType()) {
- if (Context.areCompatibleVectorTypes(FromType, ToType) ||
- (Context.getLangOpts().LaxVectorConversions &&
- (Context.getTypeSize(FromType) == Context.getTypeSize(ToType)))) {
+ if (S.Context.areCompatibleVectorTypes(FromType, ToType) ||
+ S.isLaxVectorConversion(FromType, ToType)) {
ICK = ICK_Vector_Conversion;
return true;
}
@@ -1425,10 +1426,9 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
// Standard conversions (C++ [conv])
SCS.setAsIdentityConversion();
- SCS.DeprecatedStringLiteralToCharPtr = false;
SCS.IncompatibleObjC = false;
SCS.setFromType(FromType);
- SCS.CopyConstructor = 0;
+ SCS.CopyConstructor = nullptr;
// There are no standard conversions for class types in C++, so
// abort early. When overloading in C, however, we do permit
@@ -1524,7 +1524,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
FromType = S.Context.getArrayDecayedType(FromType);
if (S.IsStringLiteralToNonConstPointerConversion(From, ToType)) {
- // This conversion is deprecated. (C++ D.4).
+ // This conversion is deprecated in C++03 (D.4)
SCS.DeprecatedStringLiteralToCharPtr = true;
// For the purpose of ranking in overload resolution
@@ -1624,7 +1624,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
InOverloadResolution, FromType)) {
// Pointer to member conversions (4.11).
SCS.Second = ICK_Pointer_Member;
- } else if (IsVectorConversion(S.Context, FromType, ToType, SecondICK)) {
+ } else if (IsVectorConversion(S, FromType, ToType, SecondICK)) {
SCS.Second = SecondICK;
FromType = ToType.getUnqualifiedType();
} else if (!S.getLangOpts().CPlusPlus &&
@@ -1707,9 +1707,7 @@ IsTransparentUnionStandardConversion(Sema &S, Expr* From,
// The field to initialize within the transparent union.
RecordDecl *UD = UT->getDecl();
// It's compatible if the expression matches any of the fields.
- for (RecordDecl::field_iterator it = UD->field_begin(),
- itend = UD->field_end();
- it != itend; ++it) {
+ for (const auto *it : UD->fields()) {
if (IsStandardConversion(S, From, it->getType(), InOverloadResolution, SCS,
CStyle, /*ObjCWritebackConversion=*/false)) {
ToType = it->getType();
@@ -1914,7 +1912,7 @@ bool Sema::IsComplexPromotion(QualType FromType, QualType ToType) {
return IsFloatingPointPromotion(FromComplex->getElementType(),
ToComplex->getElementType()) ||
- IsIntegralPromotion(0, FromComplex->getElementType(),
+ IsIntegralPromotion(nullptr, FromComplex->getElementType(),
ToComplex->getElementType());
}
@@ -2288,17 +2286,17 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
// Perform the quick checks that will tell us whether these
// function types are obviously different.
- if (FromFunctionType->getNumArgs() != ToFunctionType->getNumArgs() ||
+ if (FromFunctionType->getNumParams() != ToFunctionType->getNumParams() ||
FromFunctionType->isVariadic() != ToFunctionType->isVariadic() ||
FromFunctionType->getTypeQuals() != ToFunctionType->getTypeQuals())
return false;
bool HasObjCConversion = false;
- if (Context.getCanonicalType(FromFunctionType->getResultType())
- == Context.getCanonicalType(ToFunctionType->getResultType())) {
+ if (Context.getCanonicalType(FromFunctionType->getReturnType()) ==
+ Context.getCanonicalType(ToFunctionType->getReturnType())) {
// Okay, the types match exactly. Nothing to do.
- } else if (isObjCPointerConversion(FromFunctionType->getResultType(),
- ToFunctionType->getResultType(),
+ } else if (isObjCPointerConversion(FromFunctionType->getReturnType(),
+ ToFunctionType->getReturnType(),
ConvertedType, IncompatibleObjC)) {
// Okay, we have an Objective-C pointer conversion.
HasObjCConversion = true;
@@ -2308,10 +2306,10 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
}
// Check argument types.
- for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumArgs();
+ for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumParams();
ArgIdx != NumArgs; ++ArgIdx) {
- QualType FromArgType = FromFunctionType->getArgType(ArgIdx);
- QualType ToArgType = ToFunctionType->getArgType(ArgIdx);
+ QualType FromArgType = FromFunctionType->getParamType(ArgIdx);
+ QualType ToArgType = ToFunctionType->getParamType(ArgIdx);
if (Context.getCanonicalType(FromArgType)
== Context.getCanonicalType(ToArgType)) {
// Okay, the types match exactly. Nothing to do.
@@ -2436,7 +2434,7 @@ bool Sema::IsBlockPointerConversion(QualType FromType, QualType ToType,
// Perform the quick checks that will tell us whether these
// function types are obviously different.
- if (FromFunctionType->getNumArgs() != ToFunctionType->getNumArgs() ||
+ if (FromFunctionType->getNumParams() != ToFunctionType->getNumParams() ||
FromFunctionType->isVariadic() != ToFunctionType->isVariadic())
return false;
@@ -2446,12 +2444,12 @@ bool Sema::IsBlockPointerConversion(QualType FromType, QualType ToType,
return false;
bool IncompatibleObjC = false;
- if (Context.hasSameType(FromFunctionType->getResultType(),
- ToFunctionType->getResultType())) {
+ if (Context.hasSameType(FromFunctionType->getReturnType(),
+ ToFunctionType->getReturnType())) {
// Okay, the types match exactly. Nothing to do.
} else {
- QualType RHS = FromFunctionType->getResultType();
- QualType LHS = ToFunctionType->getResultType();
+ QualType RHS = FromFunctionType->getReturnType();
+ QualType LHS = ToFunctionType->getReturnType();
if ((!getLangOpts().CPlusPlus || !RHS->isRecordType()) &&
!RHS.hasQualifiers() && LHS.hasQualifiers())
LHS = LHS.getUnqualifiedType();
@@ -2469,11 +2467,11 @@ bool Sema::IsBlockPointerConversion(QualType FromType, QualType ToType,
}
// Check argument types.
- for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumArgs();
+ for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumParams();
ArgIdx != NumArgs; ++ArgIdx) {
IncompatibleObjC = false;
- QualType FromArgType = FromFunctionType->getArgType(ArgIdx);
- QualType ToArgType = ToFunctionType->getArgType(ArgIdx);
+ QualType FromArgType = FromFunctionType->getParamType(ArgIdx);
+ QualType ToArgType = ToFunctionType->getParamType(ArgIdx);
if (Context.hasSameType(FromArgType, ToArgType)) {
// Okay, the types match exactly. Nothing to do.
} else if (isObjCPointerConversion(ToArgType, FromArgType,
@@ -2518,7 +2516,7 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
if (FromType->isMemberPointerType() && ToType->isMemberPointerType()) {
const MemberPointerType *FromMember = FromType->getAs<MemberPointerType>(),
*ToMember = ToType->getAs<MemberPointerType>();
- if (FromMember->getClass() != ToMember->getClass()) {
+ if (!Context.hasSameType(FromMember->getClass(), ToMember->getClass())) {
PDiag << ft_different_class << QualType(ToMember->getClass(), 0)
<< QualType(FromMember->getClass(), 0);
return;
@@ -2558,26 +2556,26 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
return;
}
- if (FromFunction->getNumArgs() != ToFunction->getNumArgs()) {
- PDiag << ft_parameter_arity << ToFunction->getNumArgs()
- << FromFunction->getNumArgs();
+ if (FromFunction->getNumParams() != ToFunction->getNumParams()) {
+ PDiag << ft_parameter_arity << ToFunction->getNumParams()
+ << FromFunction->getNumParams();
return;
}
// Handle different parameter types.
unsigned ArgPos;
- if (!FunctionArgTypesAreEqual(FromFunction, ToFunction, &ArgPos)) {
+ if (!FunctionParamTypesAreEqual(FromFunction, ToFunction, &ArgPos)) {
PDiag << ft_parameter_mismatch << ArgPos + 1
- << ToFunction->getArgType(ArgPos)
- << FromFunction->getArgType(ArgPos);
+ << ToFunction->getParamType(ArgPos)
+ << FromFunction->getParamType(ArgPos);
return;
}
// Handle different return type.
- if (!Context.hasSameType(FromFunction->getResultType(),
- ToFunction->getResultType())) {
- PDiag << ft_return_type << ToFunction->getResultType()
- << FromFunction->getResultType();
+ if (!Context.hasSameType(FromFunction->getReturnType(),
+ ToFunction->getReturnType())) {
+ PDiag << ft_return_type << ToFunction->getReturnType()
+ << FromFunction->getReturnType();
return;
}
@@ -2592,19 +2590,21 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
PDiag << ft_default;
}
-/// FunctionArgTypesAreEqual - This routine checks two function proto types
+/// FunctionParamTypesAreEqual - This routine checks two function proto types
/// for equality of their argument types. Caller has already checked that
/// they have same number of arguments. If the parameters are different,
/// ArgPos will have the parameter index of the first different parameter.
-bool Sema::FunctionArgTypesAreEqual(const FunctionProtoType *OldType,
- const FunctionProtoType *NewType,
- unsigned *ArgPos) {
- for (FunctionProtoType::arg_type_iterator O = OldType->arg_type_begin(),
- N = NewType->arg_type_begin(),
- E = OldType->arg_type_end(); O && (O != E); ++O, ++N) {
+bool Sema::FunctionParamTypesAreEqual(const FunctionProtoType *OldType,
+ const FunctionProtoType *NewType,
+ unsigned *ArgPos) {
+ for (FunctionProtoType::param_type_iterator O = OldType->param_type_begin(),
+ N = NewType->param_type_begin(),
+ E = OldType->param_type_end();
+ O && (O != E); ++O, ++N) {
if (!Context.hasSameType(O->getUnqualifiedType(),
N->getUnqualifiedType())) {
- if (ArgPos) *ArgPos = O - OldType->arg_type_begin();
+ if (ArgPos)
+ *ArgPos = O - OldType->param_type_begin();
return false;
}
}
@@ -2919,8 +2919,8 @@ static bool isFirstArgumentCompatibleWithType(ASTContext &Context,
QualType Type) {
const FunctionProtoType *CtorType =
Constructor->getType()->getAs<FunctionProtoType>();
- if (CtorType->getNumArgs() > 0) {
- QualType FirstArg = CtorType->getArgType(0);
+ if (CtorType->getNumParams() > 0) {
+ QualType FirstArg = CtorType->getParamType(0);
if (Context.hasSameUnqualifiedType(Type, FirstArg.getNonReferenceType()))
return true;
}
@@ -2940,7 +2940,7 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType,
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
// Find the constructor (which may be a template).
- CXXConstructorDecl *Constructor = 0;
+ CXXConstructorDecl *Constructor = nullptr;
FunctionTemplateDecl *ConstructorTmpl
= dyn_cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl)
@@ -2959,7 +2959,7 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType,
isFirstArgumentCompatibleWithType(S.Context, Constructor, ToType);
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
- /*ExplicitArgs*/ 0,
+ /*ExplicitArgs*/ nullptr,
From, CandidateSet,
SuppressUserConversions);
else
@@ -3075,7 +3075,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
// Find the constructor (which may be a template).
- CXXConstructorDecl *Constructor = 0;
+ CXXConstructorDecl *Constructor = nullptr;
FunctionTemplateDecl *ConstructorTmpl
= dyn_cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl)
@@ -3102,7 +3102,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
}
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
- /*ExplicitArgs*/ 0,
+ /*ExplicitArgs*/ nullptr,
llvm::makeArrayRef(Args, NumArgs),
CandidateSet, SuppressUserConversions);
else
@@ -3236,23 +3236,21 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
bool
Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
ImplicitConversionSequence ICS;
- OverloadCandidateSet CandidateSet(From->getExprLoc());
+ OverloadCandidateSet CandidateSet(From->getExprLoc(),
+ OverloadCandidateSet::CSK_Normal);
OverloadingResult OvResult =
IsUserDefinedConversion(*this, From, ToType, ICS.UserDefined,
CandidateSet, false, false);
if (OvResult == OR_Ambiguous)
- Diag(From->getLocStart(),
- diag::err_typecheck_ambiguous_condition)
- << From->getType() << ToType << From->getSourceRange();
+ Diag(From->getLocStart(), diag::err_typecheck_ambiguous_condition)
+ << From->getType() << ToType << From->getSourceRange();
else if (OvResult == OR_No_Viable_Function && !CandidateSet.empty()) {
if (!RequireCompleteType(From->getLocStart(), ToType,
- diag::err_typecheck_nonviable_condition_incomplete,
+ diag::err_typecheck_nonviable_condition_incomplete,
From->getType(), From->getSourceRange()))
- Diag(From->getLocStart(),
- diag::err_typecheck_nonviable_condition)
- << From->getType() << From->getSourceRange() << ToType;
- }
- else
+ Diag(From->getLocStart(), diag::err_typecheck_nonviable_condition)
+ << From->getType() << From->getSourceRange() << ToType;
+ } else
return false;
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, From);
return true;
@@ -3262,37 +3260,43 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
/// of two user-defined conversion sequences to determine whether any ordering
/// is possible.
static ImplicitConversionSequence::CompareKind
-compareConversionFunctions(Sema &S,
- FunctionDecl *Function1,
+compareConversionFunctions(Sema &S, FunctionDecl *Function1,
FunctionDecl *Function2) {
if (!S.getLangOpts().ObjC1 || !S.getLangOpts().CPlusPlus11)
return ImplicitConversionSequence::Indistinguishable;
-
+
// Objective-C++:
// If both conversion functions are implicitly-declared conversions from
- // a lambda closure type to a function pointer and a block pointer,
+ // a lambda closure type to a function pointer and a block pointer,
// respectively, always prefer the conversion to a function pointer,
// because the function pointer is more lightweight and is more likely
// to keep code working.
- CXXConversionDecl *Conv1 = dyn_cast<CXXConversionDecl>(Function1);
+ CXXConversionDecl *Conv1 = dyn_cast_or_null<CXXConversionDecl>(Function1);
if (!Conv1)
return ImplicitConversionSequence::Indistinguishable;
-
+
CXXConversionDecl *Conv2 = dyn_cast<CXXConversionDecl>(Function2);
if (!Conv2)
return ImplicitConversionSequence::Indistinguishable;
-
+
if (Conv1->getParent()->isLambda() && Conv2->getParent()->isLambda()) {
bool Block1 = Conv1->getConversionType()->isBlockPointerType();
bool Block2 = Conv2->getConversionType()->isBlockPointerType();
if (Block1 != Block2)
- return Block1? ImplicitConversionSequence::Worse
- : ImplicitConversionSequence::Better;
+ return Block1 ? ImplicitConversionSequence::Worse
+ : ImplicitConversionSequence::Better;
}
return ImplicitConversionSequence::Indistinguishable;
}
-
+
+static bool hasDeprecatedStringLiteralToCharPtrConversion(
+ const ImplicitConversionSequence &ICS) {
+ return (ICS.isStandard() && ICS.Standard.DeprecatedStringLiteralToCharPtr) ||
+ (ICS.isUserDefined() &&
+ ICS.UserDefined.Before.DeprecatedStringLiteralToCharPtr);
+}
+
/// CompareImplicitConversionSequences - Compare two implicit
/// conversion sequences to determine whether one is better than the
/// other or if they are indistinguishable (C++ 13.3.3.2).
@@ -3315,6 +3319,32 @@ CompareImplicitConversionSequences(Sema &S,
// described in 13.3.3.2, the ambiguous conversion sequence is
// treated as a user-defined sequence that is indistinguishable
// from any other user-defined conversion sequence.
+
+ // String literal to 'char *' conversion has been deprecated in C++03. It has
+ // been removed from C++11. We still accept this conversion, if it happens at
+ // the best viable function. Otherwise, this conversion is considered worse
+ // than ellipsis conversion. Consider this as an extension; this is not in the
+ // standard. For example:
+ //
+ // int &f(...); // #1
+ // void f(char*); // #2
+ // void g() { int &r = f("foo"); }
+ //
+ // In C++03, we pick #2 as the best viable function.
+ // In C++11, we pick #1 as the best viable function, because ellipsis
+ // conversion is better than string-literal to char* conversion (since there
+ // is no such conversion in C++11). If there was no #1 at all or #1 couldn't
+ // convert arguments, #2 would be the best viable function in C++11.
+ // If the best viable function has this conversion, a warning will be issued
+ // in C++03, or an ExtWarn (+SFINAE failure) will be issued in C++11.
+
+ if (S.getLangOpts().CPlusPlus11 && !S.getLangOpts().WritableStrings &&
+ hasDeprecatedStringLiteralToCharPtrConversion(ICS1) !=
+ hasDeprecatedStringLiteralToCharPtrConversion(ICS2))
+ return hasDeprecatedStringLiteralToCharPtrConversion(ICS1)
+ ? ImplicitConversionSequence::Worse
+ : ImplicitConversionSequence::Better;
+
if (ICS1.getKindRank() < ICS2.getKindRank())
return ImplicitConversionSequence::Better;
if (ICS2.getKindRank() < ICS1.getKindRank())
@@ -3424,8 +3454,9 @@ compareStandardConversionSubsets(ASTContext &Context,
/// \brief 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,
- const StandardConversionSequence &SCS2) {
+static bool
+isBetterReferenceBindingKind(const StandardConversionSequence &SCS1,
+ const StandardConversionSequence &SCS2) {
// C++0x [over.ics.rank]p3b4:
// -- S1 and S2 are reference bindings (8.5.3) and neither refers to an
// implicit object parameter of a non-static member function declared
@@ -3446,7 +3477,7 @@ static bool isBetterReferenceBindingKind(const StandardConversionSequence &SCS1,
return (!SCS1.IsLvalueReference && SCS1.BindsToRvalue &&
SCS2.IsLvalueReference) ||
(SCS1.IsLvalueReference && SCS1.BindsToFunctionLvalue &&
- !SCS2.IsLvalueReference);
+ !SCS2.IsLvalueReference && SCS2.BindsToFunctionLvalue);
}
/// CompareStandardConversionSequences - Compare two standard
@@ -3613,11 +3644,10 @@ CompareStandardConversionSequences(Sema &S,
// }
// Here, MSVC will call f(int) instead of generating a compile error
// as clang will do in standard mode.
- if (S.getLangOpts().MicrosoftMode &&
- SCS1.Second == ICK_Integral_Conversion &&
- SCS2.Second == ICK_Floating_Integral &&
+ if (S.getLangOpts().MSVCCompat && SCS1.Second == ICK_Integral_Conversion &&
+ SCS2.Second == ICK_Floating_Integral &&
S.Context.getTypeSize(SCS1.getFromType()) ==
- S.Context.getTypeSize(SCS1.getToType(2)))
+ S.Context.getTypeSize(SCS1.getToType(2)))
return ImplicitConversionSequence::Better;
return ImplicitConversionSequence::Indistinguishable;
@@ -4035,7 +4065,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
CXXRecordDecl *T2RecordDecl
= dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl());
- OverloadCandidateSet CandidateSet(DeclLoc);
+ OverloadCandidateSet CandidateSet(DeclLoc, OverloadCandidateSet::CSK_Normal);
std::pair<CXXRecordDecl::conversion_iterator,
CXXRecordDecl::conversion_iterator>
Conversions = T2RecordDecl->getVisibleConversionFunctions();
@@ -4226,7 +4256,8 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
ICS.Standard.BindsToRvalue = false;
ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
ICS.Standard.ObjCLifetimeConversionBinding = ObjCLifetimeConversion;
- ICS.Standard.CopyConstructor = 0;
+ ICS.Standard.CopyConstructor = nullptr;
+ ICS.Standard.DeprecatedStringLiteralToCharPtr = false;
// Nothing more to do: the inaccessibility/ambiguity check for
// derived-to-base conversions is suppressed when we're
@@ -4294,13 +4325,14 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
// standard library implementors; therefore, we need the xvalue check here.
ICS.Standard.DirectBinding =
S.getLangOpts().CPlusPlus11 ||
- (InitCategory.isPRValue() && !T2->isRecordType());
+ !(InitCategory.isPRValue() || T2->isRecordType());
ICS.Standard.IsLvalueReference = !isRValRef;
ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
ICS.Standard.BindsToRvalue = InitCategory.isRValue();
ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
ICS.Standard.ObjCLifetimeConversionBinding = ObjCLifetimeConversion;
- ICS.Standard.CopyConstructor = 0;
+ ICS.Standard.CopyConstructor = nullptr;
+ ICS.Standard.DeprecatedStringLiteralToCharPtr = false;
return ICS;
}
@@ -4330,6 +4362,10 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
return ICS;
}
+ // A temporary of function type cannot be created; don't even try.
+ if (T1->isFunctionType())
+ return ICS;
+
// -- Otherwise, a temporary of type "cv1 T1" is created and
// initialized from the initializer expression using the
// rules for a non-reference copy initialization (8.5). The
@@ -4391,28 +4427,34 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
if (ICS.isStandard()) {
ICS.Standard.ReferenceBinding = true;
ICS.Standard.IsLvalueReference = !isRValRef;
- ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
+ ICS.Standard.BindsToFunctionLvalue = false;
ICS.Standard.BindsToRvalue = true;
ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
ICS.Standard.ObjCLifetimeConversionBinding = false;
} else if (ICS.isUserDefined()) {
- // Don't allow rvalue references to bind to lvalues.
- if (DeclType->isRValueReferenceType()) {
- if (const ReferenceType *RefType
- = ICS.UserDefined.ConversionFunction->getResultType()
- ->getAs<LValueReferenceType>()) {
- if (!RefType->getPointeeType()->isFunctionType()) {
- ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, Init,
- DeclType);
- return ICS;
- }
- }
+ const ReferenceType *LValRefType =
+ ICS.UserDefined.ConversionFunction->getReturnType()
+ ->getAs<LValueReferenceType>();
+
+ // C++ [over.ics.ref]p3:
+ // Except for an implicit object parameter, for which see 13.3.1, a
+ // standard conversion sequence cannot be formed if it requires [...]
+ // binding an rvalue reference to an lvalue other than a function
+ // lvalue.
+ // Note that the function case is not possible here.
+ if (DeclType->isRValueReferenceType() && LValRefType) {
+ // FIXME: This is the wrong BadConversionSequence. The problem is binding
+ // an rvalue reference to a (non-function) lvalue, not binding an lvalue
+ // reference to an rvalue!
+ ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, Init, DeclType);
+ return ICS;
}
-
+
+ ICS.UserDefined.Before.setAsIdentityConversion();
ICS.UserDefined.After.ReferenceBinding = true;
ICS.UserDefined.After.IsLvalueReference = !isRValRef;
- ICS.UserDefined.After.BindsToFunctionLvalue = T2->isFunctionType();
- ICS.UserDefined.After.BindsToRvalue = true;
+ ICS.UserDefined.After.BindsToFunctionLvalue = false;
+ ICS.UserDefined.After.BindsToRvalue = !LValRefType;
ICS.UserDefined.After.BindsImplicitObjectArgumentWithoutRefQualifier = false;
ICS.UserDefined.After.ObjCLifetimeConversionBinding = false;
}
@@ -4515,7 +4557,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
InitializedEntity Entity =
InitializedEntity::InitializeParameter(S.Context, ToType,
/*Consumed=*/false);
- if (S.CanPerformCopyInitialization(Entity, S.Owned(From))) {
+ if (S.CanPerformCopyInitialization(Entity, From)) {
Result.setUserDefined();
Result.UserDefined.Before.setAsIdentityConversion();
// Initializer lists don't have a type.
@@ -4525,7 +4567,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
Result.UserDefined.After.setAsIdentityConversion();
Result.UserDefined.After.setFromType(ToType);
Result.UserDefined.After.setAllToTypes(ToType);
- Result.UserDefined.ConversionFunction = 0;
+ Result.UserDefined.ConversionFunction = nullptr;
}
return Result;
}
@@ -4836,13 +4878,13 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
PerformObjectMemberConversion(From, Qualifier, FoundDecl, Method);
if (FromRes.isInvalid())
return ExprError();
- From = FromRes.take();
+ From = FromRes.get();
}
if (!Context.hasSameType(From->getType(), DestType))
From = ImpCastExprToType(From, DestType, CK_NoOp,
- From->getValueKind()).take();
- return Owned(From);
+ From->getValueKind()).get();
+ return From;
}
/// TryContextuallyConvertToBool - Attempt to contextually convert the
@@ -4954,7 +4996,7 @@ ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
/*InOverloadResolution=*/false,
/*CStyle=*/false,
/*AllowObjcWritebackConversion=*/false);
- StandardConversionSequence *SCS = 0;
+ StandardConversionSequence *SCS = nullptr;
switch (ICS.getKind()) {
case ImplicitConversionSequence::StandardConversion:
if (!CheckConvertedConstantConversions(*this, ICS.Standard))
@@ -5124,7 +5166,7 @@ diagnoseAmbiguousConversion(Sema &SemaRef, SourceLocation Loc, Expr *From,
QualType ConvTy = Conv->getConversionType().getNonReferenceType();
Converter.noteAmbiguous(SemaRef, Conv, ConvTy);
}
- return SemaRef.Owned(From);
+ return From;
}
static bool
@@ -5147,7 +5189,7 @@ diagnoseNoViableConversion(Sema &SemaRef, SourceLocation Loc, Expr *&From,
<< FixItHint::CreateInsertion(From->getLocStart(),
"static_cast<" + TypeStr + ">(")
<< FixItHint::CreateInsertion(
- SemaRef.PP.getLocForEndOfToken(From->getLocEnd()), ")");
+ SemaRef.getLocForEndOfToken(From->getLocEnd()), ")");
Converter.noteExplicitConv(SemaRef, Conversion, ConvTy);
// If we aren't in a SFINAE context, build a call to the
@@ -5155,15 +5197,15 @@ diagnoseNoViableConversion(Sema &SemaRef, SourceLocation Loc, Expr *&From,
if (SemaRef.isSFINAEContext())
return true;
- SemaRef.CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found);
+ SemaRef.CheckMemberOperatorAccess(From->getExprLoc(), From, nullptr, Found);
ExprResult Result = SemaRef.BuildCXXMemberCallExpr(From, Found, Conversion,
HadMultipleCandidates);
if (Result.isInvalid())
return true;
// Record usage of conversion in an implicit cast.
From = ImplicitCastExpr::Create(SemaRef.Context, Result.get()->getType(),
- CK_UserDefinedConversion, Result.get(), 0,
- Result.get()->getValueKind());
+ CK_UserDefinedConversion, Result.get(),
+ nullptr, Result.get()->getValueKind());
}
return false;
}
@@ -5174,7 +5216,7 @@ static bool recordConversion(Sema &SemaRef, SourceLocation Loc, Expr *&From,
DeclAccessPair &Found) {
CXXConversionDecl *Conversion =
cast<CXXConversionDecl>(Found->getUnderlyingDecl());
- SemaRef.CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found);
+ SemaRef.CheckMemberOperatorAccess(From->getExprLoc(), From, nullptr, Found);
QualType ToType = Conversion->getConversionType().getNonReferenceType();
if (!Converter.SuppressConversion) {
@@ -5191,8 +5233,8 @@ static bool recordConversion(Sema &SemaRef, SourceLocation Loc, Expr *&From,
return true;
// Record usage of conversion in an implicit cast.
From = ImplicitCastExpr::Create(SemaRef.Context, Result.get()->getType(),
- CK_UserDefinedConversion, Result.get(), 0,
- Result.get()->getValueKind());
+ CK_UserDefinedConversion, Result.get(),
+ nullptr, Result.get()->getValueKind());
return false;
}
@@ -5257,14 +5299,14 @@ ExprResult Sema::PerformContextualImplicitConversion(
SourceLocation Loc, Expr *From, ContextualImplicitConverter &Converter) {
// We can't perform any more checking for type-dependent expressions.
if (From->isTypeDependent())
- return Owned(From);
+ return From;
// Process placeholders immediately.
if (From->hasPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(From);
if (result.isInvalid())
return result;
- From = result.take();
+ From = result.get();
}
// If the expression already has a matching type, we're golden.
@@ -5280,7 +5322,7 @@ ExprResult Sema::PerformContextualImplicitConversion(
if (!RecordTy || !getLangOpts().CPlusPlus) {
if (!Converter.Suppress)
Converter.diagnoseNoMatch(*this, Loc, T) << From->getSourceRange();
- return Owned(From);
+ return From;
}
// We must have a complete class type.
@@ -5291,13 +5333,13 @@ ExprResult Sema::PerformContextualImplicitConversion(
TypeDiagnoserPartialDiag(ContextualImplicitConverter &Converter, Expr *From)
: TypeDiagnoser(Converter.Suppress), Converter(Converter), From(From) {}
- virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
+ void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
Converter.diagnoseIncomplete(S, Loc, T) << From->getSourceRange();
}
} IncompleteDiagnoser(Converter, From);
if (RequireCompleteType(Loc, T, IncompleteDiagnoser))
- return Owned(From);
+ return From;
// Look for a conversion to an integral or enumeration type.
UnresolvedSet<4>
@@ -5381,7 +5423,7 @@ ExprResult Sema::PerformContextualImplicitConversion(
// If one unique T is found:
// First, build a candidate set from the previously recorded
// potentially viable conversions.
- OverloadCandidateSet CandidateSet(Loc);
+ OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
collectViableConversionCandidates(*this, From, ToType, ViableConversions,
CandidateSet);
@@ -5438,6 +5480,45 @@ ExprResult Sema::PerformContextualImplicitConversion(
return finishContextualImplicitConversion(*this, Loc, From, Converter);
}
+/// IsAcceptableNonMemberOperatorCandidate - Determine whether Fn is
+/// an acceptable non-member overloaded operator for a call whose
+/// arguments have types T1 (and, if non-empty, T2). This routine
+/// implements the check in C++ [over.match.oper]p3b2 concerning
+/// enumeration types.
+static bool IsAcceptableNonMemberOperatorCandidate(ASTContext &Context,
+ FunctionDecl *Fn,
+ ArrayRef<Expr *> Args) {
+ QualType T1 = Args[0]->getType();
+ QualType T2 = Args.size() > 1 ? Args[1]->getType() : QualType();
+
+ if (T1->isDependentType() || (!T2.isNull() && T2->isDependentType()))
+ return true;
+
+ if (T1->isRecordType() || (!T2.isNull() && T2->isRecordType()))
+ return true;
+
+ const FunctionProtoType *Proto = Fn->getType()->getAs<FunctionProtoType>();
+ if (Proto->getNumParams() < 1)
+ return false;
+
+ if (T1->isEnumeralType()) {
+ QualType ArgType = Proto->getParamType(0).getNonReferenceType();
+ if (Context.hasSameUnqualifiedType(T1, ArgType))
+ return true;
+ }
+
+ if (Proto->getNumParams() < 2)
+ return false;
+
+ if (!T2.isNull() && T2->isEnumeralType()) {
+ QualType ArgType = Proto->getParamType(1).getNonReferenceType();
+ if (Context.hasSameUnqualifiedType(T2, ArgType))
+ return true;
+ }
+
+ return false;
+}
+
/// AddOverloadCandidate - Adds the given function to the set of
/// candidate functions, using the given function call arguments. If
/// @p SuppressUserConversions, then don't allow user-defined
@@ -5450,11 +5531,11 @@ void
Sema::AddOverloadCandidate(FunctionDecl *Function,
DeclAccessPair FoundDecl,
ArrayRef<Expr *> Args,
- OverloadCandidateSet& CandidateSet,
+ OverloadCandidateSet &CandidateSet,
bool SuppressUserConversions,
bool PartialOverloading,
bool AllowExplicit) {
- const FunctionProtoType* Proto
+ const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>());
assert(Proto && "Functions without a prototype cannot be overloaded");
assert(!Function->getDescribedFunctionTemplate() &&
@@ -5481,6 +5562,17 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
if (!CandidateSet.isNewCandidate(Function))
return;
+ // C++ [over.match.oper]p3:
+ // if no operand has a class type, only those non-member functions in the
+ // lookup set that have a first parameter of type T1 or "reference to
+ // (possibly cv-qualified) T1", when T1 is an enumeration type, or (if there
+ // is a right operand) a second parameter of type T2 or "reference to
+ // (possibly cv-qualified) T2", when T2 is an enumeration type, are
+ // candidate functions.
+ if (CandidateSet.getKind() == OverloadCandidateSet::CSK_Operator &&
+ !IsAcceptableNonMemberOperatorCandidate(Context, Function, Args))
+ return;
+
// C++11 [class.copy]p11: [DR1402]
// A defaulted move constructor that is defined as deleted is ignored by
// overload resolution.
@@ -5513,12 +5605,12 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
Candidate.IgnoreObjectArgument = false;
Candidate.ExplicitCallArguments = Args.size();
- unsigned NumArgsInProto = Proto->getNumArgs();
+ unsigned NumParams = Proto->getNumParams();
// (C++ 13.3.2p2): A candidate function having fewer than m
// parameters is viable only if it has an ellipsis in its parameter
// list (8.3.5).
- if ((Args.size() + (PartialOverloading && Args.size())) > NumArgsInProto &&
+ if ((Args.size() + (PartialOverloading && Args.size())) > NumParams &&
!Proto->isVariadic()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_too_many_arguments;
@@ -5550,12 +5642,12 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
// Determine the implicit conversion sequences for each of the
// arguments.
for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) {
- if (ArgIdx < NumArgsInProto) {
+ if (ArgIdx < NumParams) {
// (C++ 13.3.2p3): for F to be a viable function, there shall
// exist for each argument an implicit conversion sequence
// (13.3.3.1) that converts that argument to the corresponding
// parameter of F.
- QualType ParamType = Proto->getArgType(ArgIdx);
+ QualType ParamType = Proto->getParamType(ArgIdx);
Candidate.Conversions[ArgIdx]
= TryCopyInitialization(*this, Args[ArgIdx], ParamType,
SuppressUserConversions,
@@ -5566,7 +5658,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
if (Candidate.Conversions[ArgIdx].isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
- break;
+ return;
}
} else {
// (C++ 13.3.2p2): For the purposes of overload resolution, any
@@ -5575,6 +5667,78 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
Candidate.Conversions[ArgIdx].setEllipsis();
}
}
+
+ if (EnableIfAttr *FailedAttr = CheckEnableIf(Function, Args)) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_enable_if;
+ Candidate.DeductionFailure.Data = FailedAttr;
+ return;
+ }
+}
+
+static bool IsNotEnableIfAttr(Attr *A) { return !isa<EnableIfAttr>(A); }
+
+EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
+ bool MissingImplicitThis) {
+ // FIXME: specific_attr_iterator<EnableIfAttr> iterates in reverse order, but
+ // we need to find the first failing one.
+ if (!Function->hasAttrs())
+ return nullptr;
+ AttrVec Attrs = Function->getAttrs();
+ AttrVec::iterator E = std::remove_if(Attrs.begin(), Attrs.end(),
+ IsNotEnableIfAttr);
+ if (Attrs.begin() == E)
+ return nullptr;
+ std::reverse(Attrs.begin(), E);
+
+ SFINAETrap Trap(*this);
+
+ // Convert the arguments.
+ SmallVector<Expr *, 16> ConvertedArgs;
+ bool InitializationFailed = false;
+ for (unsigned i = 0, e = Args.size(); i != e; ++i) {
+ if (i == 0 && !MissingImplicitThis && isa<CXXMethodDecl>(Function) &&
+ !cast<CXXMethodDecl>(Function)->isStatic() &&
+ !isa<CXXConstructorDecl>(Function)) {
+ CXXMethodDecl *Method = cast<CXXMethodDecl>(Function);
+ ExprResult R =
+ PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/nullptr,
+ Method, Method);
+ if (R.isInvalid()) {
+ InitializationFailed = true;
+ break;
+ }
+ ConvertedArgs.push_back(R.get());
+ } else {
+ ExprResult R =
+ PerformCopyInitialization(InitializedEntity::InitializeParameter(
+ Context,
+ Function->getParamDecl(i)),
+ SourceLocation(),
+ Args[i]);
+ if (R.isInvalid()) {
+ InitializationFailed = true;
+ break;
+ }
+ ConvertedArgs.push_back(R.get());
+ }
+ }
+
+ if (InitializationFailed || Trap.hasErrorOccurred())
+ return cast<EnableIfAttr>(Attrs[0]);
+
+ for (AttrVec::iterator I = Attrs.begin(); I != E; ++I) {
+ APValue Result;
+ EnableIfAttr *EIA = cast<EnableIfAttr>(*I);
+ if (!EIA->getCond()->EvaluateWithSubstitution(
+ Result, Context, Function,
+ ArrayRef<const Expr*>(ConvertedArgs.data(),
+ ConvertedArgs.size())) ||
+ !Result.isInt() || !Result.getInt().getBoolValue()) {
+ return EIA;
+ }
+ }
+ return nullptr;
}
/// \brief Add all of the function declarations in the given function set to
@@ -5632,7 +5796,7 @@ void Sema::AddMethodCandidate(DeclAccessPair FoundDecl,
assert(isa<CXXMethodDecl>(TD->getTemplatedDecl()) &&
"Expected a member function template");
AddMethodTemplateCandidate(TD, FoundDecl, ActingContext,
- /*ExplicitArgs*/ 0,
+ /*ExplicitArgs*/ nullptr,
ObjectType, ObjectClassification,
Args, CandidateSet,
SuppressUserConversions);
@@ -5656,9 +5820,9 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext, QualType ObjectType,
Expr::Classification ObjectClassification,
ArrayRef<Expr *> Args,
- OverloadCandidateSet& CandidateSet,
+ OverloadCandidateSet &CandidateSet,
bool SuppressUserConversions) {
- const FunctionProtoType* Proto
+ const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(Method->getType()->getAs<FunctionType>());
assert(Proto && "Methods without a prototype cannot be overloaded");
assert(!isa<CXXConstructorDecl>(Method) &&
@@ -5685,12 +5849,12 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
Candidate.IgnoreObjectArgument = false;
Candidate.ExplicitCallArguments = Args.size();
- unsigned NumArgsInProto = Proto->getNumArgs();
+ unsigned NumParams = Proto->getNumParams();
// (C++ 13.3.2p2): A candidate function having fewer than m
// parameters is viable only if it has an ellipsis in its parameter
// list (8.3.5).
- if (Args.size() > NumArgsInProto && !Proto->isVariadic()) {
+ if (Args.size() > NumParams && !Proto->isVariadic()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_too_many_arguments;
return;
@@ -5730,12 +5894,12 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
// Determine the implicit conversion sequences for each of the
// arguments.
for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) {
- if (ArgIdx < NumArgsInProto) {
+ if (ArgIdx < NumParams) {
// (C++ 13.3.2p3): for F to be a viable function, there shall
// exist for each argument an implicit conversion sequence
// (13.3.3.1) that converts that argument to the corresponding
// parameter of F.
- QualType ParamType = Proto->getArgType(ArgIdx);
+ QualType ParamType = Proto->getParamType(ArgIdx);
Candidate.Conversions[ArgIdx + 1]
= TryCopyInitialization(*this, Args[ArgIdx], ParamType,
SuppressUserConversions,
@@ -5745,15 +5909,22 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
if (Candidate.Conversions[ArgIdx + 1].isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
- break;
+ return;
}
} else {
// (C++ 13.3.2p2): For the purposes of overload resolution, any
// argument for which there is no corresponding parameter is
- // considered to ""match the ellipsis" (C+ 13.3.3.1.3).
+ // considered to "match the ellipsis" (C+ 13.3.3.1.3).
Candidate.Conversions[ArgIdx + 1].setEllipsis();
}
}
+
+ if (EnableIfAttr *FailedAttr = CheckEnableIf(Method, Args, true)) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_enable_if;
+ Candidate.DeductionFailure.Data = FailedAttr;
+ return;
+ }
}
/// \brief Add a C++ member function template as a candidate to the candidate
@@ -5782,7 +5953,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
// function template are combined with the set of non-template candidate
// functions.
TemplateDeductionInfo Info(CandidateSet.getLocation());
- FunctionDecl *Specialization = 0;
+ FunctionDecl *Specialization = nullptr;
if (TemplateDeductionResult Result
= DeduceTemplateArguments(MethodTmpl, ExplicitTemplateArgs, Args,
Specialization, Info)) {
@@ -5832,7 +6003,7 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
// function template are combined with the set of non-template candidate
// functions.
TemplateDeductionInfo Info(CandidateSet.getLocation());
- FunctionDecl *Specialization = 0;
+ FunctionDecl *Specialization = nullptr;
if (TemplateDeductionResult Result
= DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, Args,
Specialization, Info)) {
@@ -5969,7 +6140,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
return;
}
- // We won't go through a user-define type conversion function to convert a
+ // We won't go through a user-defined type conversion function to convert a
// derived to base as such conversions are given Conversion Rank. They only
// go through a copy constructor. 13.3.3.1.2-p4 [over.ics.user]
QualType FromCanon
@@ -6029,6 +6200,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
GetConversionRank(ICS.Standard.Second) != ICR_Exact_Match) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_final_conversion_not_exact;
+ return;
}
// C++0x [dcl.init.ref]p5:
@@ -6040,18 +6212,26 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
ICS.Standard.First == ICK_Lvalue_To_Rvalue) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_final_conversion;
+ return;
}
break;
case ImplicitConversionSequence::BadConversion:
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_final_conversion;
- break;
+ return;
default:
llvm_unreachable(
"Can only end up with a standard conversion sequence or failure");
}
+
+ if (EnableIfAttr *FailedAttr = CheckEnableIf(Conversion, ArrayRef<Expr*>())) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_enable_if;
+ Candidate.DeductionFailure.Data = FailedAttr;
+ return;
+ }
}
/// \brief Adds a conversion function template specialization
@@ -6073,7 +6253,7 @@ Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
return;
TemplateDeductionInfo Info(CandidateSet.getLocation());
- CXXConversionDecl *Specialization = 0;
+ CXXConversionDecl *Specialization = nullptr;
if (TemplateDeductionResult Result
= DeduceTemplateArguments(FunctionTemplate, ToType,
Specialization, Info)) {
@@ -6117,7 +6297,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size() + 1);
Candidate.FoundDecl = FoundDecl;
- Candidate.Function = 0;
+ Candidate.Function = nullptr;
Candidate.Surrogate = Conversion;
Candidate.Viable = true;
Candidate.IsSurrogate = true;
@@ -6151,12 +6331,12 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
Candidate.Conversions[0].UserDefined.After.setAsIdentityConversion();
// Find the
- unsigned NumArgsInProto = Proto->getNumArgs();
+ unsigned NumParams = Proto->getNumParams();
// (C++ 13.3.2p2): A candidate function having fewer than m
// parameters is viable only if it has an ellipsis in its parameter
// list (8.3.5).
- if (Args.size() > NumArgsInProto && !Proto->isVariadic()) {
+ if (Args.size() > NumParams && !Proto->isVariadic()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_too_many_arguments;
return;
@@ -6164,7 +6344,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
// Function types don't have any default arguments, so just check if
// we have enough arguments.
- if (Args.size() < NumArgsInProto) {
+ if (Args.size() < NumParams) {
// Not enough arguments.
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_too_few_arguments;
@@ -6174,12 +6354,12 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
// Determine the implicit conversion sequences for each of the
// arguments.
for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) {
- if (ArgIdx < NumArgsInProto) {
+ if (ArgIdx < NumParams) {
// (C++ 13.3.2p3): for F to be a viable function, there shall
// exist for each argument an implicit conversion sequence
// (13.3.3.1) that converts that argument to the corresponding
// parameter of F.
- QualType ParamType = Proto->getArgType(ArgIdx);
+ QualType ParamType = Proto->getParamType(ArgIdx);
Candidate.Conversions[ArgIdx + 1]
= TryCopyInitialization(*this, Args[ArgIdx], ParamType,
/*SuppressUserConversions=*/false,
@@ -6189,7 +6369,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
if (Candidate.Conversions[ArgIdx + 1].isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
- break;
+ return;
}
} else {
// (C++ 13.3.2p2): For the purposes of overload resolution, any
@@ -6198,6 +6378,13 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
Candidate.Conversions[ArgIdx + 1].setEllipsis();
}
}
+
+ if (EnableIfAttr *FailedAttr = CheckEnableIf(Conversion, ArrayRef<Expr*>())) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_enable_if;
+ Candidate.DeductionFailure.Data = FailedAttr;
+ return;
+ }
}
/// \brief Add overload candidates for overloaded operators that are
@@ -6270,8 +6457,8 @@ void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys,
// Add this candidate
OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size());
- Candidate.FoundDecl = DeclAccessPair::make(0, AS_none);
- Candidate.Function = 0;
+ Candidate.FoundDecl = DeclAccessPair::make(nullptr, AS_none);
+ Candidate.Function = nullptr;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
Candidate.BuiltinTypes.ResultTy = ResultTy;
@@ -7951,7 +8138,7 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
/// candidate set (C++ [basic.lookup.argdep]).
void
Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
- bool Operator, SourceLocation Loc,
+ SourceLocation Loc,
ArrayRef<Expr *> Args,
TemplateArgumentListInfo *ExplicitTemplateArgs,
OverloadCandidateSet& CandidateSet,
@@ -7966,7 +8153,7 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
// we supposed to consider on ADL candidates, anyway?
// FIXME: Pass in the explicit template arguments?
- ArgumentDependentLookup(Name, Operator, Loc, Args, Fns);
+ ArgumentDependentLookup(Name, Loc, Args, Fns);
// Erase all of the candidates we already knew about.
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
@@ -8051,18 +8238,48 @@ isBetterOverloadCandidate(Sema &S,
if (HasBetterConversion)
return true;
- // - F1 is a non-template function and F2 is a function template
+ // -- the context is an initialization by user-defined conversion
+ // (see 8.5, 13.3.1.5) and the standard conversion sequence
+ // from the return type of F1 to the destination type (i.e.,
+ // the type of the entity being initialized) is a better
+ // conversion sequence than the standard conversion sequence
+ // from the return type of F2 to the destination type.
+ if (UserDefinedConversion && Cand1.Function && Cand2.Function &&
+ isa<CXXConversionDecl>(Cand1.Function) &&
+ isa<CXXConversionDecl>(Cand2.Function)) {
+ // First check whether we prefer one of the conversion functions over the
+ // other. This only distinguishes the results in non-standard, extension
+ // cases such as the conversion from a lambda closure type to a function
+ // pointer or block.
+ ImplicitConversionSequence::CompareKind Result =
+ compareConversionFunctions(S, Cand1.Function, Cand2.Function);
+ if (Result == ImplicitConversionSequence::Indistinguishable)
+ Result = CompareStandardConversionSequences(S,
+ Cand1.FinalConversion,
+ Cand2.FinalConversion);
+
+ if (Result != ImplicitConversionSequence::Indistinguishable)
+ return Result == ImplicitConversionSequence::Better;
+
+ // FIXME: Compare kind of reference binding if conversion functions
+ // convert to a reference type used in direct reference binding, per
+ // C++14 [over.match.best]p1 section 2 bullet 3.
+ }
+
+ // -- F1 is a non-template function and F2 is a function template
// specialization, or, if not that,
- if ((!Cand1.Function || !Cand1.Function->getPrimaryTemplate()) &&
- Cand2.Function && Cand2.Function->getPrimaryTemplate())
- return true;
+ bool Cand1IsSpecialization = Cand1.Function &&
+ Cand1.Function->getPrimaryTemplate();
+ bool Cand2IsSpecialization = Cand2.Function &&
+ Cand2.Function->getPrimaryTemplate();
+ if (Cand1IsSpecialization != Cand2IsSpecialization)
+ return Cand2IsSpecialization;
// -- F1 and F2 are function template specializations, and the function
// template for F1 is more specialized than the template for F2
// according to the partial ordering rules described in 14.5.5.2, or,
// if not that,
- if (Cand1.Function && Cand1.Function->getPrimaryTemplate() &&
- Cand2.Function && Cand2.Function->getPrimaryTemplate()) {
+ if (Cand1IsSpecialization && Cand2IsSpecialization) {
if (FunctionTemplateDecl *BetterTemplate
= S.getMoreSpecializedTemplate(Cand1.Function->getPrimaryTemplate(),
Cand2.Function->getPrimaryTemplate(),
@@ -8074,39 +8291,49 @@ isBetterOverloadCandidate(Sema &S,
return BetterTemplate == Cand1.Function->getPrimaryTemplate();
}
- // -- the context is an initialization by user-defined conversion
- // (see 8.5, 13.3.1.5) and the standard conversion sequence
- // from the return type of F1 to the destination type (i.e.,
- // the type of the entity being initialized) is a better
- // conversion sequence than the standard conversion sequence
- // from the return type of F2 to the destination type.
- if (UserDefinedConversion && Cand1.Function && Cand2.Function &&
- isa<CXXConversionDecl>(Cand1.Function) &&
- isa<CXXConversionDecl>(Cand2.Function)) {
- // First check whether we prefer one of the conversion functions over the
- // other. This only distinguishes the results in non-standard, extension
- // cases such as the conversion from a lambda closure type to a function
- // pointer or block.
- ImplicitConversionSequence::CompareKind FuncResult
- = compareConversionFunctions(S, Cand1.Function, Cand2.Function);
- if (FuncResult != ImplicitConversionSequence::Indistinguishable)
- return FuncResult;
-
- switch (CompareStandardConversionSequences(S,
- Cand1.FinalConversion,
- Cand2.FinalConversion)) {
- case ImplicitConversionSequence::Better:
- // Cand1 has a better conversion sequence.
- return true;
-
- case ImplicitConversionSequence::Worse:
- // Cand1 can't be better than Cand2.
+ // Check for enable_if value-based overload resolution.
+ if (Cand1.Function && Cand2.Function &&
+ (Cand1.Function->hasAttr<EnableIfAttr>() ||
+ Cand2.Function->hasAttr<EnableIfAttr>())) {
+ // FIXME: The next several lines are just
+ // specific_attr_iterator<EnableIfAttr> but going in declaration order,
+ // instead of reverse order which is how they're stored in the AST.
+ AttrVec Cand1Attrs;
+ if (Cand1.Function->hasAttrs()) {
+ Cand1Attrs = Cand1.Function->getAttrs();
+ Cand1Attrs.erase(std::remove_if(Cand1Attrs.begin(), Cand1Attrs.end(),
+ IsNotEnableIfAttr),
+ Cand1Attrs.end());
+ std::reverse(Cand1Attrs.begin(), Cand1Attrs.end());
+ }
+
+ AttrVec Cand2Attrs;
+ if (Cand2.Function->hasAttrs()) {
+ Cand2Attrs = Cand2.Function->getAttrs();
+ Cand2Attrs.erase(std::remove_if(Cand2Attrs.begin(), Cand2Attrs.end(),
+ IsNotEnableIfAttr),
+ Cand2Attrs.end());
+ std::reverse(Cand2Attrs.begin(), Cand2Attrs.end());
+ }
+
+ // Candidate 1 is better if it has strictly more attributes and
+ // the common sequence is identical.
+ if (Cand1Attrs.size() <= Cand2Attrs.size())
return false;
- case ImplicitConversionSequence::Indistinguishable:
- // Do nothing
- break;
+ auto Cand1I = Cand1Attrs.begin();
+ for (auto &Cand2A : Cand2Attrs) {
+ auto &Cand1A = *Cand1I++;
+ llvm::FoldingSetNodeID Cand1ID, Cand2ID;
+ cast<EnableIfAttr>(Cand1A)->getCond()->Profile(Cand1ID,
+ S.getASTContext(), true);
+ cast<EnableIfAttr>(Cand2A)->getCond()->Profile(Cand2ID,
+ S.getASTContext(), true);
+ if (Cand1ID != Cand2ID)
+ return false;
}
+
+ return true;
}
return false;
@@ -8557,18 +8784,18 @@ void DiagnoseArityMismatch(Sema &S, Decl *D, unsigned NumFormalArgs) {
// at least / at most / exactly
unsigned mode, modeCount;
if (NumFormalArgs < MinParams) {
- if (MinParams != FnTy->getNumArgs() ||
- FnTy->isVariadic() || FnTy->isTemplateVariadic())
+ if (MinParams != FnTy->getNumParams() || FnTy->isVariadic() ||
+ FnTy->isTemplateVariadic())
mode = 0; // "at least"
else
mode = 2; // "exactly"
modeCount = MinParams;
} else {
- if (MinParams != FnTy->getNumArgs())
+ if (MinParams != FnTy->getNumParams())
mode = 1; // "at most"
else
mode = 2; // "exactly"
- modeCount = FnTy->getNumArgs();
+ modeCount = FnTy->getNumParams();
}
std::string Description;
@@ -8576,12 +8803,12 @@ void DiagnoseArityMismatch(Sema &S, Decl *D, unsigned NumFormalArgs) {
if (modeCount == 1 && Fn->getParamDecl(0)->getDeclName())
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity_one)
- << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != 0) << mode
- << Fn->getParamDecl(0) << NumFormalArgs;
+ << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != nullptr)
+ << mode << Fn->getParamDecl(0) << NumFormalArgs;
else
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity)
- << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != 0) << mode
- << modeCount << NumFormalArgs;
+ << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != nullptr)
+ << mode << modeCount << NumFormalArgs;
MaybeEmitInheritedConstructorNote(S, Fn);
}
@@ -8817,6 +9044,15 @@ void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) {
<< (unsigned) FnKind << CalleeTarget << CallerTarget;
}
+void DiagnoseFailedEnableIfAttr(Sema &S, OverloadCandidate *Cand) {
+ FunctionDecl *Callee = Cand->Function;
+ EnableIfAttr *Attr = static_cast<EnableIfAttr*>(Cand->DeductionFailure.Data);
+
+ S.Diag(Callee->getLocation(),
+ diag::note_ovl_candidate_disabled_by_enable_if_attr)
+ << Attr->getCond()->getSourceRange() << Attr->getMessage();
+}
+
/// Generates a 'note' diagnostic for an overload candidate. We've
/// already generated a primary error at the call site.
///
@@ -8880,6 +9116,9 @@ void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
case ovl_fail_bad_target:
return DiagnoseBadTarget(S, Cand);
+
+ case ovl_fail_enable_if:
+ return DiagnoseFailedEnableIfAttr(S, Cand);
}
}
@@ -8991,7 +9230,10 @@ static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) {
struct CompareOverloadCandidatesForDisplay {
Sema &S;
- CompareOverloadCandidatesForDisplay(Sema &S) : S(S) {}
+ size_t NumArgs;
+
+ CompareOverloadCandidatesForDisplay(Sema &S, size_t nArgs)
+ : S(S), NumArgs(nArgs) {}
bool operator()(const OverloadCandidate *L,
const OverloadCandidate *R) {
@@ -9016,8 +9258,24 @@ struct CompareOverloadCandidatesForDisplay {
if (!L->Viable) {
// 1. Arity mismatches come after other candidates.
if (L->FailureKind == ovl_fail_too_many_arguments ||
- L->FailureKind == ovl_fail_too_few_arguments)
+ L->FailureKind == ovl_fail_too_few_arguments) {
+ if (R->FailureKind == ovl_fail_too_many_arguments ||
+ R->FailureKind == ovl_fail_too_few_arguments) {
+ int LDist = std::abs((int)L->getNumParams() - (int)NumArgs);
+ int RDist = std::abs((int)R->getNumParams() - (int)NumArgs);
+ if (LDist == RDist) {
+ if (L->FailureKind == R->FailureKind)
+ // Sort non-surrogates before surrogates.
+ return !L->IsSurrogate && R->IsSurrogate;
+ // Sort candidates requiring fewer parameters than there were
+ // arguments given after candidates requiring more parameters
+ // than there were arguments given.
+ return L->FailureKind == ovl_fail_too_many_arguments;
+ }
+ return LDist < RDist;
+ }
return false;
+ }
if (R->FailureKind == ovl_fail_too_many_arguments ||
R->FailureKind == ovl_fail_too_few_arguments)
return true;
@@ -9160,15 +9418,14 @@ void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
}
// Fill in the rest of the conversions.
- unsigned NumArgsInProto = Proto->getNumArgs();
+ unsigned NumParams = Proto->getNumParams();
for (; ConvIdx != ConvCount; ++ConvIdx, ++ArgIdx) {
- if (ArgIdx < NumArgsInProto) {
- Cand->Conversions[ConvIdx]
- = TryCopyInitialization(S, Args[ArgIdx], Proto->getArgType(ArgIdx),
- SuppressUserConversions,
- /*InOverloadResolution=*/true,
- /*AllowObjCWritebackConversion=*/
- S.getLangOpts().ObjCAutoRefCount);
+ if (ArgIdx < NumParams) {
+ Cand->Conversions[ConvIdx] = TryCopyInitialization(
+ S, Args[ArgIdx], Proto->getParamType(ArgIdx), SuppressUserConversions,
+ /*InOverloadResolution=*/true,
+ /*AllowObjCWritebackConversion=*/
+ S.getLangOpts().ObjCAutoRefCount);
// Store the FixIt in the candidate if it exists.
if (!Unfixable && Cand->Conversions[ConvIdx].isBad())
Unfixable = !Cand->TryToFixBadConversion(ConvIdx, S);
@@ -9205,7 +9462,7 @@ void OverloadCandidateSet::NoteCandidates(Sema &S,
}
std::sort(Cands.begin(), Cands.end(),
- CompareOverloadCandidatesForDisplay(S));
+ CompareOverloadCandidatesForDisplay(S, Args.size()));
bool ReportedAmbiguousConversions = false;
@@ -9320,7 +9577,7 @@ void TemplateSpecCandidateSet::NoteCandidates(Sema &S, SourceLocation Loc) {
for (iterator Cand = begin(), LastCand = end(); Cand != LastCand; ++Cand) {
if (Cand->Specialization)
Cands.push_back(Cand);
- // Otherwise, this is a non matching builtin candidate. We do not,
+ // Otherwise, this is a non-matching builtin candidate. We do not,
// in general, want to list every possible builtin candidate.
}
@@ -9486,7 +9743,7 @@ private:
// resulting template argument list is used to generate a single
// function template specialization, which is added to the set of
// overloaded functions considered.
- FunctionDecl *Specialization = 0;
+ FunctionDecl *Specialization = nullptr;
TemplateDeductionInfo Info(FailedCandidates.getLocation());
if (Sema::TemplateDeductionResult Result
= S.DeduceTemplateArguments(FunctionTemplate,
@@ -9531,7 +9788,7 @@ private:
// If any candidate has a placeholder return type, trigger its deduction
// now.
if (S.getLangOpts().CPlusPlus1y &&
- FunDecl->getResultType()->isUndeducedType() &&
+ FunDecl->getReturnType()->isUndeducedType() &&
S.DeduceReturnType(FunDecl, SourceExpr->getLocStart(), Complain))
return false;
@@ -9622,7 +9879,7 @@ private:
// [...] any function template specializations in the set are
// eliminated if the set also contains a non-template function, [...]
for (unsigned I = 0, N = Matches.size(); I != N; ) {
- if (Matches[I].second->getPrimaryTemplate() == 0)
+ if (Matches[I].second->getPrimaryTemplate() == nullptr)
++I;
else {
Matches[I] = Matches[--N];
@@ -9694,12 +9951,12 @@ public:
int getNumMatches() const { return Matches.size(); }
FunctionDecl* getMatchingFunctionDecl() const {
- if (Matches.size() != 1) return 0;
+ if (Matches.size() != 1) return nullptr;
return Matches[0].second;
}
const DeclAccessPair* getMatchingFunctionAccessPair() const {
- if (Matches.size() != 1) return 0;
+ if (Matches.size() != 1) return nullptr;
return &Matches[0].first;
}
};
@@ -9730,7 +9987,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr,
AddressOfFunctionResolver Resolver(*this, AddressOfExpr, TargetType,
Complain);
int NumMatches = Resolver.getNumMatches();
- FunctionDecl* Fn = 0;
+ FunctionDecl *Fn = nullptr;
if (NumMatches == 0 && Complain) {
if (Resolver.IsInvalidFormOfPointerToMemberFunction())
Resolver.ComplainIsInvalidFormOfPointerToMemberFunction();
@@ -9779,7 +10036,7 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
// If we didn't actually find any template-ids, we're done.
if (!ovl->hasExplicitTemplateArgs())
- return 0;
+ return nullptr;
TemplateArgumentListInfo ExplicitTemplateArgs;
ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
@@ -9787,7 +10044,7 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
// Look through all of the overloaded functions, searching for one
// whose type matches exactly.
- FunctionDecl *Matched = 0;
+ FunctionDecl *Matched = nullptr;
for (UnresolvedSetIterator I = ovl->decls_begin(),
E = ovl->decls_end(); I != E; ++I) {
// C++0x [temp.arg.explicit]p3:
@@ -9805,7 +10062,7 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
// resulting template argument list is used to generate a single
// function template specialization, which is added to the set of
// overloaded functions considered.
- FunctionDecl *Specialization = 0;
+ FunctionDecl *Specialization = nullptr;
TemplateDeductionInfo Info(FailedCandidates.getLocation());
if (TemplateDeductionResult Result
= DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs,
@@ -9828,7 +10085,7 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
<< ovl->getName();
NoteAllOverloadCandidates(ovl);
}
- return 0;
+ return nullptr;
}
Matched = Specialization;
@@ -9836,9 +10093,9 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
}
if (Matched && getLangOpts().CPlusPlus1y &&
- Matched->getResultType()->isUndeducedType() &&
+ Matched->getReturnType()->isUndeducedType() &&
DeduceReturnType(Matched, ovl->getExprLoc(), Complain))
- return 0;
+ return nullptr;
return Matched;
}
@@ -9896,12 +10153,12 @@ bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization(
// Fix the expression to refer to 'fn'.
SingleFunctionExpression =
- Owned(FixOverloadedFunctionReference(SrcExpr.take(), found, fn));
+ FixOverloadedFunctionReference(SrcExpr.get(), found, fn);
// If desired, do function-to-pointer decay.
if (doFunctionPointerConverion) {
SingleFunctionExpression =
- DefaultFunctionArrayLvalueConversion(SingleFunctionExpression.take());
+ DefaultFunctionArrayLvalueConversion(SingleFunctionExpression.get());
if (SingleFunctionExpression.isInvalid()) {
SrcExpr = ExprError();
return true;
@@ -9999,7 +10256,7 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
// It would be nice to avoid this copy.
TemplateArgumentListInfo TABuffer;
- TemplateArgumentListInfo *ExplicitTemplateArgs = 0;
+ TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr;
if (ULE->hasExplicitTemplateArgs()) {
ULE->copyTemplateArgumentsInto(TABuffer);
ExplicitTemplateArgs = &TABuffer;
@@ -10012,8 +10269,7 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
/*KnownValid*/ true);
if (ULE->requiresADL())
- AddArgumentDependentLookupCandidates(ULE->getName(), /*Operator*/ false,
- ULE->getExprLoc(),
+ AddArgumentDependentLookupCandidates(ULE->getName(), ULE->getExprLoc(),
Args, ExplicitTemplateArgs,
CandidateSet, PartialOverloading);
}
@@ -10040,6 +10296,7 @@ static bool canBeDeclaredInNamespace(const DeclarationName &Name) {
static bool
DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc,
const CXXScopeSpec &SS, LookupResult &R,
+ OverloadCandidateSet::CandidateSetKind CSK,
TemplateArgumentListInfo *ExplicitTemplateArgs,
ArrayRef<Expr *> Args) {
if (SemaRef.ActiveTemplateInstantiations.empty() || !SS.isEmpty())
@@ -10061,7 +10318,7 @@ DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc,
return false;
}
- OverloadCandidateSet Candidates(FnLoc);
+ OverloadCandidateSet Candidates(FnLoc, CSK);
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
AddOverloadedCallCandidate(SemaRef, I.getPair(),
ExplicitTemplateArgs, Args,
@@ -10145,7 +10402,8 @@ DiagnoseTwoPhaseOperatorLookup(Sema &SemaRef, OverloadedOperatorKind Op,
SemaRef.Context.DeclarationNames.getCXXOperatorName(Op);
LookupResult R(SemaRef, OpName, OpLoc, Sema::LookupOperatorName);
return DiagnoseTwoPhaseLookup(SemaRef, OpLoc, CXXScopeSpec(), R,
- /*ExplicitTemplateArgs=*/0, Args);
+ OverloadCandidateSet::CSK_Operator,
+ /*ExplicitTemplateArgs=*/nullptr, Args);
}
namespace {
@@ -10171,7 +10429,7 @@ static ExprResult
BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
UnresolvedLookupExpr *ULE,
SourceLocation LParenLoc,
- llvm::MutableArrayRef<Expr *> Args,
+ MutableArrayRef<Expr *> Args,
SourceLocation RParenLoc,
bool EmptyLookup, bool AllowTypoCorrection) {
// Do not try to recover if it is already building a recovery call.
@@ -10189,7 +10447,7 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
SourceLocation TemplateKWLoc = ULE->getTemplateKeywordLoc();
TemplateArgumentListInfo TABuffer;
- TemplateArgumentListInfo *ExplicitTemplateArgs = 0;
+ TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr;
if (ULE->hasExplicitTemplateArgs()) {
ULE->copyTemplateArgumentsInto(TABuffer);
ExplicitTemplateArgs = &TABuffer;
@@ -10198,12 +10456,14 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(),
Sema::LookupOrdinaryName);
FunctionCallFilterCCC Validator(SemaRef, Args.size(),
- ExplicitTemplateArgs != 0);
+ ExplicitTemplateArgs != nullptr,
+ dyn_cast<MemberExpr>(Fn));
NoTypoCorrectionCCC RejectAll;
CorrectionCandidateCallback *CCC = AllowTypoCorrection ?
(CorrectionCandidateCallback*)&Validator :
(CorrectionCandidateCallback*)&RejectAll;
if (!DiagnoseTwoPhaseLookup(SemaRef, Fn->getExprLoc(), SS, R,
+ OverloadCandidateSet::CSK_Normal,
ExplicitTemplateArgs, Args) &&
(!EmptyLookup ||
SemaRef.DiagnoseEmptyLookup(S, SS, R, *CCC,
@@ -10230,7 +10490,7 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
// This shouldn't cause an infinite loop because we're giving it
// an expression with viable lookup results, which should never
// end up here.
- return SemaRef.ActOnCallExpr(/*Scope*/ 0, NewFn.take(), LParenLoc,
+ return SemaRef.ActOnCallExpr(/*Scope*/ nullptr, NewFn.get(), LParenLoc,
MultiExprArg(Args.data(), Args.size()),
RParenLoc);
}
@@ -10280,13 +10540,13 @@ bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn,
// create a type dependent CallExpr. The goal is to postpone name lookup
// to instantiation time to be able to search into type dependent base
// classes.
- if (getLangOpts().MicrosoftMode && CurContext->isDependentContext() &&
+ if (getLangOpts().MSVCCompat && CurContext->isDependentContext() &&
(isa<FunctionDecl>(CurContext) || isa<CXXRecordDecl>(CurContext))) {
CallExpr *CE = new (Context) CallExpr(Context, Fn, Args,
Context.DependentTy, VK_RValue,
RParenLoc);
CE->setTypeDependent(true);
- *Result = Owned(CE);
+ *Result = CE;
return true;
}
return false;
@@ -10382,7 +10642,8 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn,
SourceLocation RParenLoc,
Expr *ExecConfig,
bool AllowTypoCorrection) {
- OverloadCandidateSet CandidateSet(Fn->getExprLoc());
+ OverloadCandidateSet CandidateSet(Fn->getExprLoc(),
+ OverloadCandidateSet::CSK_Normal);
ExprResult result;
if (buildOverloadedCallSet(S, Fn, ULE, Args, LParenLoc, &CandidateSet,
@@ -10435,7 +10696,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
if (checkPlaceholderForOverload(*this, Input))
return ExprError();
- Expr *Args[2] = { Input, 0 };
+ Expr *Args[2] = { Input, nullptr };
unsigned NumArgs = 1;
// For post-increment and post-decrement, add the implicit '0' as
@@ -10452,26 +10713,22 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
if (Input->isTypeDependent()) {
if (Fns.empty())
- return Owned(new (Context) UnaryOperator(Input,
- Opc,
- Context.DependentTy,
- VK_RValue, OK_Ordinary,
- OpLoc));
+ return new (Context) UnaryOperator(Input, Opc, Context.DependentTy,
+ VK_RValue, OK_Ordinary, OpLoc);
- CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
+ CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
UnresolvedLookupExpr *Fn
= UnresolvedLookupExpr::Create(Context, NamingClass,
NestedNameSpecifierLoc(), OpNameInfo,
/*ADL*/ true, IsOverloaded(Fns),
Fns.begin(), Fns.end());
- return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, ArgsArray,
- Context.DependentTy,
- VK_RValue,
- OpLoc, false));
+ return new (Context)
+ CXXOperatorCallExpr(Context, Op, Fn, ArgsArray, Context.DependentTy,
+ VK_RValue, OpLoc, false);
}
// Build an empty overload set.
- OverloadCandidateSet CandidateSet(OpLoc);
+ OverloadCandidateSet CandidateSet(OpLoc, OverloadCandidateSet::CSK_Operator);
// Add the candidates from the given function set.
AddFunctionCandidates(Fns, ArgsArray, CandidateSet, false);
@@ -10480,8 +10737,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
AddMemberOperatorCandidates(Op, OpLoc, ArgsArray, CandidateSet);
// Add candidates from ADL.
- AddArgumentDependentLookupCandidates(OpName, /*Operator*/ true, OpLoc,
- ArgsArray, /*ExplicitTemplateArgs*/ 0,
+ AddArgumentDependentLookupCandidates(OpName, OpLoc, ArgsArray,
+ /*ExplicitTemplateArgs*/nullptr,
CandidateSet);
// Add builtin operator candidates.
@@ -10502,14 +10759,14 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
// Convert the arguments.
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
- CheckMemberOperatorAccess(OpLoc, Args[0], 0, Best->FoundDecl);
+ CheckMemberOperatorAccess(OpLoc, Args[0], nullptr, Best->FoundDecl);
ExprResult InputRes =
- PerformObjectArgumentInitialization(Input, /*Qualifier=*/0,
+ PerformObjectArgumentInitialization(Input, /*Qualifier=*/nullptr,
Best->FoundDecl, Method);
if (InputRes.isInvalid())
return ExprError();
- Input = InputRes.take();
+ Input = InputRes.get();
} else {
// Convert the arguments.
ExprResult InputInit
@@ -10520,7 +10777,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
Input);
if (InputInit.isInvalid())
return ExprError();
- Input = InputInit.take();
+ Input = InputInit.get();
}
// Build the actual expression node.
@@ -10530,17 +10787,16 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
return ExprError();
// Determine the result type.
- QualType ResultTy = FnDecl->getResultType();
+ QualType ResultTy = FnDecl->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
Args[0] = Input;
CallExpr *TheCall =
- new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(), ArgsArray,
+ new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.get(), ArgsArray,
ResultTy, VK, OpLoc, false);
- if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall,
- FnDecl))
+ if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall, FnDecl))
return ExprError();
return MaybeBindToTemporary(TheCall);
@@ -10553,7 +10809,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
Best->Conversions[0], AA_Passing);
if (InputRes.isInvalid())
return ExprError();
- Input = InputRes.take();
+ Input = InputRes.get();
break;
}
}
@@ -10619,7 +10875,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
const UnresolvedSetImpl &Fns,
Expr *LHS, Expr *RHS) {
Expr *Args[2] = { LHS, RHS };
- LHS=RHS=0; //Please use only Args instead of LHS/RHS couple
+ LHS=RHS=nullptr; // Please use only Args instead of LHS/RHS couple
BinaryOperator::Opcode Opc = static_cast<BinaryOperator::Opcode>(OpcIn);
OverloadedOperatorKind Op = BinaryOperator::getOverloadedOperator(Opc);
@@ -10632,24 +10888,18 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// If there are no functions to store, just build a dependent
// BinaryOperator or CompoundAssignment.
if (Opc <= BO_Assign || Opc > BO_OrAssign)
- return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc,
- Context.DependentTy,
- VK_RValue, OK_Ordinary,
- OpLoc,
- FPFeatures.fp_contract));
-
- return Owned(new (Context) CompoundAssignOperator(Args[0], Args[1], Opc,
- Context.DependentTy,
- VK_LValue,
- OK_Ordinary,
- Context.DependentTy,
- Context.DependentTy,
- OpLoc,
- FPFeatures.fp_contract));
+ return new (Context) BinaryOperator(
+ Args[0], Args[1], Opc, Context.DependentTy, VK_RValue, OK_Ordinary,
+ OpLoc, FPFeatures.fp_contract);
+
+ return new (Context) CompoundAssignOperator(
+ Args[0], Args[1], Opc, Context.DependentTy, VK_LValue, OK_Ordinary,
+ Context.DependentTy, Context.DependentTy, OpLoc,
+ FPFeatures.fp_contract);
}
// FIXME: save results of ADL from here?
- CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
+ CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
// TODO: provide better source location info in DNLoc component.
DeclarationNameInfo OpNameInfo(OpName, OpLoc);
UnresolvedLookupExpr *Fn
@@ -10657,9 +10907,9 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
NestedNameSpecifierLoc(), OpNameInfo,
/*ADL*/ true, IsOverloaded(Fns),
Fns.begin(), Fns.end());
- return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, Args,
- Context.DependentTy, VK_RValue,
- OpLoc, FPFeatures.fp_contract));
+ return new (Context)
+ CXXOperatorCallExpr(Context, Op, Fn, Args, Context.DependentTy,
+ VK_RValue, OpLoc, FPFeatures.fp_contract);
}
// Always do placeholder-like conversions on the RHS.
@@ -10687,7 +10937,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
// Build an empty overload set.
- OverloadCandidateSet CandidateSet(OpLoc);
+ OverloadCandidateSet CandidateSet(OpLoc, OverloadCandidateSet::CSK_Operator);
// Add the candidates from the given function set.
AddFunctionCandidates(Fns, Args, CandidateSet, false);
@@ -10696,9 +10946,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
AddMemberOperatorCandidates(Op, OpLoc, Args, CandidateSet);
// Add candidates from ADL.
- AddArgumentDependentLookupCandidates(OpName, /*Operator*/ true,
- OpLoc, Args,
- /*ExplicitTemplateArgs*/ 0,
+ AddArgumentDependentLookupCandidates(OpName, OpLoc, Args,
+ /*ExplicitTemplateArgs*/ nullptr,
CandidateSet);
// Add builtin operator candidates.
@@ -10726,23 +10975,23 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
PerformCopyInitialization(
InitializedEntity::InitializeParameter(Context,
FnDecl->getParamDecl(0)),
- SourceLocation(), Owned(Args[1]));
+ SourceLocation(), Args[1]);
if (Arg1.isInvalid())
return ExprError();
ExprResult Arg0 =
- PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0,
+ PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/nullptr,
Best->FoundDecl, Method);
if (Arg0.isInvalid())
return ExprError();
- Args[0] = Arg0.takeAs<Expr>();
- Args[1] = RHS = Arg1.takeAs<Expr>();
+ Args[0] = Arg0.getAs<Expr>();
+ Args[1] = RHS = Arg1.getAs<Expr>();
} else {
// Convert the arguments.
ExprResult Arg0 = PerformCopyInitialization(
InitializedEntity::InitializeParameter(Context,
FnDecl->getParamDecl(0)),
- SourceLocation(), Owned(Args[0]));
+ SourceLocation(), Args[0]);
if (Arg0.isInvalid())
return ExprError();
@@ -10750,11 +10999,11 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
PerformCopyInitialization(
InitializedEntity::InitializeParameter(Context,
FnDecl->getParamDecl(1)),
- SourceLocation(), Owned(Args[1]));
+ SourceLocation(), Args[1]);
if (Arg1.isInvalid())
return ExprError();
- Args[0] = LHS = Arg0.takeAs<Expr>();
- Args[1] = RHS = Arg1.takeAs<Expr>();
+ Args[0] = LHS = Arg0.getAs<Expr>();
+ Args[1] = RHS = Arg1.getAs<Expr>();
}
// Build the actual expression node.
@@ -10765,16 +11014,16 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
return ExprError();
// Determine the result type.
- QualType ResultTy = FnDecl->getResultType();
+ QualType ResultTy = FnDecl->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
CXXOperatorCallExpr *TheCall =
- new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(),
+ new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.get(),
Args, ResultTy, VK, OpLoc,
FPFeatures.fp_contract);
- if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall,
+ if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall,
FnDecl))
return ExprError();
@@ -10795,14 +11044,14 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
Best->Conversions[0], AA_Passing);
if (ArgsRes0.isInvalid())
return ExprError();
- Args[0] = ArgsRes0.take();
+ Args[0] = ArgsRes0.get();
ExprResult ArgsRes1 =
PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1],
Best->Conversions[1], AA_Passing);
if (ArgsRes1.isInvalid())
return ExprError();
- Args[1] = ArgsRes1.take();
+ Args[1] = ArgsRes1.get();
break;
}
}
@@ -10897,7 +11146,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
// expression.
if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
- CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
+ CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
// CHECKME: no 'operator' keyword?
DeclarationNameInfo OpNameInfo(OpName, LLoc);
OpNameInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc));
@@ -10909,11 +11158,9 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
UnresolvedSetIterator());
// Can't add any actual overloads yet
- return Owned(new (Context) CXXOperatorCallExpr(Context, OO_Subscript, Fn,
- Args,
- Context.DependentTy,
- VK_RValue,
- RLoc, false));
+ return new (Context)
+ CXXOperatorCallExpr(Context, OO_Subscript, Fn, Args,
+ Context.DependentTy, VK_RValue, RLoc, false);
}
// Handle placeholders on both operands.
@@ -10923,7 +11170,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
return ExprError();
// Build an empty overload set.
- OverloadCandidateSet CandidateSet(LLoc);
+ OverloadCandidateSet CandidateSet(LLoc, OverloadCandidateSet::CSK_Operator);
// Subscript can only be overloaded as a member function.
@@ -10951,11 +11198,11 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
// Convert the arguments.
CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
ExprResult Arg0 =
- PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0,
+ PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/nullptr,
Best->FoundDecl, Method);
if (Arg0.isInvalid())
return ExprError();
- Args[0] = Arg0.take();
+ Args[0] = Arg0.get();
// Convert the arguments.
ExprResult InputInit
@@ -10963,11 +11210,11 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
Context,
FnDecl->getParamDecl(0)),
SourceLocation(),
- Owned(Args[1]));
+ Args[1]);
if (InputInit.isInvalid())
return ExprError();
- Args[1] = InputInit.takeAs<Expr>();
+ Args[1] = InputInit.getAs<Expr>();
// Build the actual expression node.
DeclarationNameInfo OpLocInfo(OpName, LLoc);
@@ -10981,18 +11228,17 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
return ExprError();
// Determine the result type
- QualType ResultTy = FnDecl->getResultType();
+ QualType ResultTy = FnDecl->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
CXXOperatorCallExpr *TheCall =
new (Context) CXXOperatorCallExpr(Context, OO_Subscript,
- FnExpr.take(), Args,
+ FnExpr.get(), Args,
ResultTy, VK, RLoc,
false);
- if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall,
- FnDecl))
+ if (CheckCallReturnType(FnDecl->getReturnType(), LLoc, TheCall, FnDecl))
return ExprError();
return MaybeBindToTemporary(TheCall);
@@ -11005,14 +11251,14 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
Best->Conversions[0], AA_Passing);
if (ArgsRes0.isInvalid())
return ExprError();
- Args[0] = ArgsRes0.take();
+ Args[0] = ArgsRes0.get();
ExprResult ArgsRes1 =
PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1],
Best->Conversions[1], AA_Passing);
if (ArgsRes1.isInvalid())
return ExprError();
- Args[1] = ArgsRes1.take();
+ Args[1] = ArgsRes1.get();
break;
}
@@ -11084,7 +11330,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
const FunctionProtoType *proto = fnType->castAs<FunctionProtoType>();
QualType resultType = proto->getCallResultType(Context);
- ExprValueKind valueKind = Expr::getValueKindForType(proto->getResultType());
+ ExprValueKind valueKind = Expr::getValueKindForType(proto->getReturnType());
// Check that the object type isn't more qualified than the
// member function we're calling.
@@ -11105,17 +11351,16 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
<< qualsString
<< (qualsString.find(' ') == std::string::npos ? 1 : 2);
}
-
+
CXXMemberCallExpr *call
= new (Context) CXXMemberCallExpr(Context, MemExprE, Args,
resultType, valueKind, RParenLoc);
- if (CheckCallReturnType(proto->getResultType(),
- op->getRHS()->getLocStart(),
- call, 0))
+ if (CheckCallReturnType(proto->getReturnType(), op->getRHS()->getLocStart(),
+ call, nullptr))
return ExprError();
- if (ConvertArgumentsForCall(call, op, 0, proto, Args, RParenLoc))
+ if (ConvertArgumentsForCall(call, op, nullptr, proto, Args, RParenLoc))
return ExprError();
if (CheckOtherCall(call, proto))
@@ -11129,9 +11374,9 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
return ExprError();
MemberExpr *MemExpr;
- CXXMethodDecl *Method = 0;
- DeclAccessPair FoundDecl = DeclAccessPair::make(0, AS_public);
- NestedNameSpecifier *Qualifier = 0;
+ CXXMethodDecl *Method = nullptr;
+ DeclAccessPair FoundDecl = DeclAccessPair::make(nullptr, AS_public);
+ NestedNameSpecifier *Qualifier = nullptr;
if (isa<MemberExpr>(NakedMemExpr)) {
MemExpr = cast<MemberExpr>(NakedMemExpr);
Method = cast<CXXMethodDecl>(MemExpr->getMemberDecl());
@@ -11148,10 +11393,11 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
: UnresExpr->getBase()->Classify(Context);
// Add overload candidates
- OverloadCandidateSet CandidateSet(UnresExpr->getMemberLoc());
+ OverloadCandidateSet CandidateSet(UnresExpr->getMemberLoc(),
+ OverloadCandidateSet::CSK_Normal);
// FIXME: avoid copy.
- TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0;
+ TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
if (UnresExpr->hasExplicitTemplateArgs()) {
UnresExpr->copyTemplateArgumentsInto(TemplateArgsBuffer);
TemplateArgs = &TemplateArgsBuffer;
@@ -11250,7 +11496,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
MemExpr = cast<MemberExpr>(MemExprE->IgnoreParens());
}
- QualType ResultType = Method->getResultType();
+ QualType ResultType = Method->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultType);
ResultType = ResultType.getNonLValueExprType(Context);
@@ -11260,7 +11506,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
ResultType, VK, RParenLoc);
// Check for a valid return type.
- if (CheckCallReturnType(Method->getResultType(), MemExpr->getMemberLoc(),
+ if (CheckCallReturnType(Method->getReturnType(), MemExpr->getMemberLoc(),
TheCall, Method))
return ExprError();
@@ -11273,7 +11519,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
FoundDecl, Method);
if (ObjectArg.isInvalid())
return ExprError();
- MemExpr->setBase(ObjectArg.take());
+ MemExpr->setBase(ObjectArg.get());
}
// Convert the rest of the arguments
@@ -11316,7 +11562,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
SourceLocation RParenLoc) {
if (checkPlaceholderForOverload(*this, Obj))
return ExprError();
- ExprResult Object = Owned(Obj);
+ ExprResult Object = Obj;
UnbridgedCastsSet UnbridgedCasts;
if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts))
@@ -11332,7 +11578,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
// operators of T. The function call operators of T are obtained by
// ordinary lookup of the name operator() in the context of
// (E).operator().
- OverloadCandidateSet CandidateSet(LParenLoc);
+ OverloadCandidateSet CandidateSet(LParenLoc,
+ OverloadCandidateSet::CSK_Operator);
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call);
if (RequireCompleteType(LParenLoc, Object.get()->getType(),
@@ -11445,14 +11692,15 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
UnbridgedCasts.restore();
- if (Best->Function == 0) {
+ if (Best->Function == nullptr) {
// Since there is no function declaration, this is one of the
// surrogate candidates. Dig out the conversion function.
CXXConversionDecl *Conv
= cast<CXXConversionDecl>(
Best->Conversions[0].UserDefined.ConversionFunction);
- CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl);
+ CheckMemberOperatorAccess(LParenLoc, Object.get(), nullptr,
+ Best->FoundDecl);
if (DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc))
return ExprError();
assert(Conv == Best->FoundDecl.getDecl() &&
@@ -11468,14 +11716,14 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
if (Call.isInvalid())
return ExprError();
// Record usage of conversion in an implicit cast.
- Call = Owned(ImplicitCastExpr::Create(Context, Call.get()->getType(),
- CK_UserDefinedConversion,
- Call.get(), 0, VK_RValue));
+ Call = ImplicitCastExpr::Create(Context, Call.get()->getType(),
+ CK_UserDefinedConversion, Call.get(),
+ nullptr, VK_RValue);
return ActOnCallExpr(S, Call.get(), LParenLoc, Args, RParenLoc);
}
- CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl);
+ CheckMemberOperatorAccess(LParenLoc, Object.get(), nullptr, Best->FoundDecl);
// We found an overloaded operator(). Build a CXXOperatorCallExpr
// that calls this method, using Object for the implicit object
@@ -11489,7 +11737,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
const FunctionProtoType *Proto =
Method->getType()->getAs<FunctionProtoType>();
- unsigned NumArgsInProto = Proto->getNumArgs();
+ unsigned NumParams = Proto->getNumParams();
DeclarationNameInfo OpLocInfo(
Context.DeclarationNames.getCXXOperatorName(OO_Call), LParenLoc);
@@ -11503,45 +11751,44 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
// Build the full argument list for the method call (the implicit object
// parameter is placed at the beginning of the list).
- llvm::OwningArrayPtr<Expr *> MethodArgs(new Expr*[Args.size() + 1]);
+ std::unique_ptr<Expr * []> MethodArgs(new Expr *[Args.size() + 1]);
MethodArgs[0] = Object.get();
std::copy(Args.begin(), Args.end(), &MethodArgs[1]);
// Once we've built TheCall, all of the expressions are properly
// owned.
- QualType ResultTy = Method->getResultType();
+ QualType ResultTy = Method->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
CXXOperatorCallExpr *TheCall = new (Context)
- CXXOperatorCallExpr(Context, OO_Call, NewFn.take(),
+ CXXOperatorCallExpr(Context, OO_Call, NewFn.get(),
llvm::makeArrayRef(MethodArgs.get(), Args.size() + 1),
ResultTy, VK, RParenLoc, false);
MethodArgs.reset();
- if (CheckCallReturnType(Method->getResultType(), LParenLoc, TheCall,
- Method))
+ if (CheckCallReturnType(Method->getReturnType(), LParenLoc, TheCall, Method))
return true;
// We may have default arguments. If so, we need to allocate more
// slots in the call for them.
- if (Args.size() < NumArgsInProto)
- TheCall->setNumArgs(Context, NumArgsInProto + 1);
+ if (Args.size() < NumParams)
+ TheCall->setNumArgs(Context, NumParams + 1);
bool IsError = false;
// Initialize the implicit object parameter.
ExprResult ObjRes =
- PerformObjectArgumentInitialization(Object.get(), /*Qualifier=*/0,
+ PerformObjectArgumentInitialization(Object.get(), /*Qualifier=*/nullptr,
Best->FoundDecl, Method);
if (ObjRes.isInvalid())
IsError = true;
else
Object = ObjRes;
- TheCall->setArg(0, Object.take());
+ TheCall->setArg(0, Object.get());
// Check the argument types.
- for (unsigned i = 0; i != NumArgsInProto; i++) {
+ for (unsigned i = 0; i != NumParams; i++) {
Expr *Arg;
if (i < Args.size()) {
Arg = Args[i];
@@ -11555,7 +11802,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
SourceLocation(), Arg);
IsError |= InputInit.isInvalid();
- Arg = InputInit.takeAs<Expr>();
+ Arg = InputInit.getAs<Expr>();
} else {
ExprResult DefArg
= BuildCXXDefaultArgExpr(LParenLoc, Method, Method->getParamDecl(i));
@@ -11564,7 +11811,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
break;
}
- Arg = DefArg.takeAs<Expr>();
+ Arg = DefArg.getAs<Expr>();
}
TheCall->setArg(i + 1, Arg);
@@ -11573,10 +11820,11 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
// If this is a variadic call, handle args passed through "...".
if (Proto->isVariadic()) {
// Promote the arguments (C99 6.5.2.2p7).
- for (unsigned i = NumArgsInProto, e = Args.size(); i < e; i++) {
- ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0);
+ for (unsigned i = NumParams, e = Args.size(); i < e; i++) {
+ ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod,
+ nullptr);
IsError |= Arg.isInvalid();
- TheCall->setArg(i + 1, Arg.take());
+ TheCall->setArg(i + 1, Arg.get());
}
}
@@ -11612,7 +11860,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
// overload resolution mechanism (13.3).
DeclarationName OpName =
Context.DeclarationNames.getCXXOperatorName(OO_Arrow);
- OverloadCandidateSet CandidateSet(Loc);
+ OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Operator);
const RecordType *BaseRecord = Base->getType()->getAs<RecordType>();
if (RequireCompleteType(Loc, Base->getType(),
@@ -11675,16 +11923,16 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
return ExprError();
}
- CheckMemberOperatorAccess(OpLoc, Base, 0, Best->FoundDecl);
+ CheckMemberOperatorAccess(OpLoc, Base, nullptr, Best->FoundDecl);
// Convert the object parameter.
CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function);
ExprResult BaseResult =
- PerformObjectArgumentInitialization(Base, /*Qualifier=*/0,
+ PerformObjectArgumentInitialization(Base, /*Qualifier=*/nullptr,
Best->FoundDecl, Method);
if (BaseResult.isInvalid())
return ExprError();
- Base = BaseResult.take();
+ Base = BaseResult.get();
// Build the operator call.
ExprResult FnExpr = CreateFunctionRefExpr(*this, Method, Best->FoundDecl,
@@ -11692,15 +11940,14 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
if (FnExpr.isInvalid())
return ExprError();
- QualType ResultTy = Method->getResultType();
+ QualType ResultTy = Method->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
CXXOperatorCallExpr *TheCall =
- new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr.take(),
+ new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr.get(),
Base, ResultTy, VK, OpLoc, false);
- if (CheckCallReturnType(Method->getResultType(), OpLoc, TheCall,
- Method))
+ if (CheckCallReturnType(Method->getReturnType(), OpLoc, TheCall, Method))
return ExprError();
return MaybeBindToTemporary(TheCall);
@@ -11715,7 +11962,8 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R,
TemplateArgumentListInfo *TemplateArgs) {
SourceLocation UDSuffixLoc = SuffixInfo.getCXXLiteralOperatorNameLoc();
- OverloadCandidateSet CandidateSet(UDSuffixLoc);
+ OverloadCandidateSet CandidateSet(UDSuffixLoc,
+ OverloadCandidateSet::CSK_Normal);
AddFunctionCandidates(R.asUnresolvedSet(), Args, CandidateSet, true,
TemplateArgs);
@@ -11758,22 +12006,22 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R,
SourceLocation(), Args[ArgIdx]);
if (InputInit.isInvalid())
return true;
- ConvArgs[ArgIdx] = InputInit.take();
+ ConvArgs[ArgIdx] = InputInit.get();
}
- QualType ResultTy = FD->getResultType();
+ QualType ResultTy = FD->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
UserDefinedLiteral *UDL =
- new (Context) UserDefinedLiteral(Context, Fn.take(),
+ new (Context) UserDefinedLiteral(Context, Fn.get(),
llvm::makeArrayRef(ConvArgs, Args.size()),
ResultTy, VK, LitEndLoc, UDSuffixLoc);
- if (CheckCallReturnType(FD->getResultType(), UDSuffixLoc, UDL, FD))
+ if (CheckCallReturnType(FD->getReturnType(), UDSuffixLoc, UDL, FD))
return ExprError();
- if (CheckFunctionCall(FD, UDL, NULL))
+ if (CheckFunctionCall(FD, UDL, nullptr))
return ExprError();
return MaybeBindToTemporary(UDL);
@@ -11800,16 +12048,16 @@ Sema::BuildForRangeBeginEndCall(Scope *S, SourceLocation Loc,
BuildMemberReferenceExpr(Range, Range->getType(), Loc,
/*IsPtr=*/false, CXXScopeSpec(),
/*TemplateKWLoc=*/SourceLocation(),
- /*FirstQualifierInScope=*/0,
+ /*FirstQualifierInScope=*/nullptr,
MemberLookup,
- /*TemplateArgs=*/0);
+ /*TemplateArgs=*/nullptr);
if (MemberRef.isInvalid()) {
*CallExpr = ExprError();
Diag(Range->getLocStart(), diag::note_in_for_range)
<< RangeLoc << BEF << Range->getType();
return FRS_DiagnosticIssued;
}
- *CallExpr = ActOnCallExpr(S, MemberRef.get(), Loc, None, Loc, 0);
+ *CallExpr = ActOnCallExpr(S, MemberRef.get(), Loc, None, Loc, nullptr);
if (CallExpr->isInvalid()) {
*CallExpr = ExprError();
Diag(Range->getLocStart(), diag::note_in_for_range)
@@ -11819,7 +12067,7 @@ Sema::BuildForRangeBeginEndCall(Scope *S, SourceLocation Loc,
} else {
UnresolvedSet<0> FoundNames;
UnresolvedLookupExpr *Fn =
- UnresolvedLookupExpr::Create(Context, /*NamingClass=*/0,
+ UnresolvedLookupExpr::Create(Context, /*NamingClass=*/nullptr,
NestedNameSpecifierLoc(), NameInfo,
/*NeedsADL=*/true, /*Overloaded=*/false,
FoundNames.begin(), FoundNames.end());
@@ -11839,7 +12087,7 @@ Sema::BuildForRangeBeginEndCall(Scope *S, SourceLocation Loc,
return FRS_NoViableFunction;
}
*CallExpr = FinishOverloadedCallExpr(*this, S, Fn, Fn, Loc, Range,
- Loc, 0, CandidateSet, &Best,
+ Loc, nullptr, CandidateSet, &Best,
OverloadResult,
/*AllowTypoCorrection=*/false);
if (CallExpr->isInvalid() || OverloadResult != OR_Success) {
@@ -11881,7 +12129,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
return ImplicitCastExpr::Create(Context, ICE->getType(),
ICE->getCastKind(),
- SubExpr, 0,
+ SubExpr, nullptr,
ICE->getValueKind());
}
@@ -11893,7 +12141,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
// Do nothing: static member functions aren't any different
// from non-member functions.
} else {
- // Fix the sub expression, which really has to be an
+ // Fix the subexpression, which really has to be an
// UnresolvedLookupExpr holding an overloaded member function
// or template.
Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
@@ -11932,7 +12180,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
// FIXME: avoid copy.
- TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0;
+ TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
if (ULE->hasExplicitTemplateArgs()) {
ULE->copyTemplateArgumentsInto(TemplateArgsBuffer);
TemplateArgs = &TemplateArgsBuffer;
@@ -11955,7 +12203,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
if (UnresolvedMemberExpr *MemExpr = dyn_cast<UnresolvedMemberExpr>(E)) {
// FIXME: avoid copy.
- TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0;
+ TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
if (MemExpr->hasExplicitTemplateArgs()) {
MemExpr->copyTemplateArgumentsInto(TemplateArgsBuffer);
TemplateArgs = &TemplateArgsBuffer;
@@ -12022,7 +12270,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
ExprResult Sema::FixOverloadedFunctionReference(ExprResult E,
DeclAccessPair Found,
FunctionDecl *Fn) {
- return Owned(FixOverloadedFunctionReference((Expr *)E.get(), Found, Fn));
+ return FixOverloadedFunctionReference(E.get(), Found, Fn);
}
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp
index af74f0d..aa3e89e 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp
@@ -31,6 +31,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Lex/Preprocessor.h"
@@ -235,7 +236,10 @@ namespace {
}
/// Return true if assignments have a non-void result.
- bool CanCaptureValueOfType(QualType ty) {
+ bool CanCaptureValue(Expr *exp) {
+ if (exp->isGLValue())
+ return true;
+ QualType ty = exp->getType();
assert(!ty->isIncompleteType());
assert(!ty->isDependentType());
@@ -264,7 +268,8 @@ namespace {
public:
ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) :
PseudoOpBuilder(S, refExpr->getLocation()), RefExpr(refExpr),
- SyntacticRefExpr(0), InstanceReceiver(0), Getter(0), Setter(0) {
+ SyntacticRefExpr(nullptr), InstanceReceiver(nullptr), Getter(nullptr),
+ Setter(nullptr) {
}
ExprResult buildRValueOperation(Expr *op);
@@ -279,11 +284,12 @@ namespace {
bool tryBuildGetOfReference(Expr *op, ExprResult &result);
bool findSetter(bool warn=true);
bool findGetter();
+ void DiagnoseUnsupportedPropertyUse();
- Expr *rebuildAndCaptureObject(Expr *syntacticBase);
- ExprResult buildGet();
- ExprResult buildSet(Expr *op, SourceLocation, bool);
- ExprResult complete(Expr *SyntacticForm);
+ Expr *rebuildAndCaptureObject(Expr *syntacticBase) override;
+ ExprResult buildGet() override;
+ ExprResult buildSet(Expr *op, SourceLocation, bool) override;
+ ExprResult complete(Expr *SyntacticForm) override;
bool isWeakProperty() const;
};
@@ -303,21 +309,21 @@ namespace {
ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr) :
PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
RefExpr(refExpr),
- InstanceBase(0), InstanceKey(0),
- AtIndexGetter(0), AtIndexSetter(0) { }
-
+ InstanceBase(nullptr), InstanceKey(nullptr),
+ AtIndexGetter(nullptr), AtIndexSetter(nullptr) {}
+
ExprResult buildRValueOperation(Expr *op);
ExprResult buildAssignmentOperation(Scope *Sc,
SourceLocation opLoc,
BinaryOperatorKind opcode,
Expr *LHS, Expr *RHS);
- Expr *rebuildAndCaptureObject(Expr *syntacticBase);
-
+ Expr *rebuildAndCaptureObject(Expr *syntacticBase) override;
+
bool findAtIndexGetter();
bool findAtIndexSetter();
-
- ExprResult buildGet();
- ExprResult buildSet(Expr *op, SourceLocation, bool);
+
+ ExprResult buildGet() override;
+ ExprResult buildSet(Expr *op, SourceLocation, bool) override;
};
class MSPropertyOpBuilder : public PseudoOpBuilder {
@@ -328,9 +334,9 @@ namespace {
PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
RefExpr(refExpr) {}
- Expr *rebuildAndCaptureObject(Expr *);
- ExprResult buildGet();
- ExprResult buildSet(Expr *op, SourceLocation, bool);
+ Expr *rebuildAndCaptureObject(Expr *) override;
+ ExprResult buildGet() override;
+ ExprResult buildSet(Expr *op, SourceLocation, bool) override;
};
}
@@ -388,7 +394,7 @@ ExprResult PseudoOpBuilder::buildRValueOperation(Expr *op) {
ExprResult getExpr = buildGet();
if (getExpr.isInvalid()) return ExprError();
- addResultSemanticExpr(getExpr.take());
+ addResultSemanticExpr(getExpr.get());
return complete(syntacticBase);
}
@@ -421,7 +427,7 @@ PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,
BinaryOperatorKind nonCompound =
BinaryOperator::getOpForCompoundAssignment(opcode);
result = S.BuildBinOp(Sc, opcLoc, nonCompound,
- opLHS.take(), capturedRHS);
+ opLHS.get(), capturedRHS);
if (result.isInvalid()) return ExprError();
syntactic =
@@ -436,9 +442,9 @@ PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,
// The result of the assignment, if not void, is the value set into
// the l-value.
- result = buildSet(result.take(), opcLoc, /*captureSetValueAsResult*/ true);
+ result = buildSet(result.get(), opcLoc, /*captureSetValueAsResult*/ true);
if (result.isInvalid()) return ExprError();
- addSemanticExpr(result.take());
+ addSemanticExpr(result.get());
return complete(syntactic);
}
@@ -461,8 +467,8 @@ PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
// That's the postfix result.
if (UnaryOperator::isPostfix(opcode) &&
- (result.get()->isTypeDependent() || CanCaptureValueOfType(resultType))) {
- result = capture(result.take());
+ (result.get()->isTypeDependent() || CanCaptureValue(result.get()))) {
+ result = capture(result.get());
setResultToLastSemantic();
}
@@ -472,17 +478,17 @@ PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
GenericLoc);
if (UnaryOperator::isIncrementOp(opcode)) {
- result = S.BuildBinOp(Sc, opcLoc, BO_Add, result.take(), one);
+ result = S.BuildBinOp(Sc, opcLoc, BO_Add, result.get(), one);
} else {
- result = S.BuildBinOp(Sc, opcLoc, BO_Sub, result.take(), one);
+ result = S.BuildBinOp(Sc, opcLoc, BO_Sub, result.get(), one);
}
if (result.isInvalid()) return ExprError();
// Store that back into the result. The value stored is the result
// of a prefix operation.
- result = buildSet(result.take(), opcLoc, UnaryOperator::isPrefix(opcode));
+ result = buildSet(result.get(), opcLoc, UnaryOperator::isPrefix(opcode));
if (result.isInvalid()) return ExprError();
- addSemanticExpr(result.take());
+ addSemanticExpr(result.get());
UnaryOperator *syntactic =
new (S.Context) UnaryOperator(syntacticOp, opcode, resultType,
@@ -536,11 +542,11 @@ bool ObjCPropertyOpBuilder::isWeakProperty() const {
if (RefExpr->isExplicitProperty()) {
const ObjCPropertyDecl *Prop = RefExpr->getExplicitProperty();
if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak)
- return true;
+ return !Prop->hasAttr<IBOutletAttr>();
T = Prop->getType();
} else if (Getter) {
- T = Getter->getResultType();
+ T = Getter->getReturnType();
} else {
return false;
}
@@ -563,19 +569,17 @@ bool ObjCPropertyOpBuilder::findGetter() {
assert(setter && "both setter and getter are null - cannot happen");
IdentifierInfo *setterName =
setter->getSelector().getIdentifierInfoForSlot(0);
- const char *compStr = setterName->getNameStart();
- compStr += 3;
- IdentifierInfo *getterName = &S.Context.Idents.get(compStr);
+ IdentifierInfo *getterName =
+ &S.Context.Idents.get(setterName->getName().substr(3));
GetterSelector =
S.PP.getSelectorTable().getNullarySelector(getterName);
return false;
-
}
}
ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
Getter = LookupMethodInReceiverType(S, prop->getGetterName(), RefExpr);
- return (Getter != 0);
+ return (Getter != nullptr);
}
/// Try to find the most accurate setter declaration for the property
@@ -621,7 +625,7 @@ bool ObjCPropertyOpBuilder::findSetter(bool warn) {
if (ObjCPropertyDecl *prop1 = IFace->FindPropertyDeclaration(AltMember))
if (prop != prop1 && (prop1->getSetterMethodDecl() == setter)) {
S.Diag(RefExpr->getExprLoc(), diag::error_property_setter_ambiguous_use)
- << prop->getName() << prop1->getName() << setter->getSelector();
+ << prop << prop1 << setter->getSelector();
S.Diag(prop->getLocation(), diag::note_property_declare);
S.Diag(prop1->getLocation(), diag::note_property_declare);
}
@@ -638,9 +642,21 @@ bool ObjCPropertyOpBuilder::findSetter(bool warn) {
return false;
}
+void ObjCPropertyOpBuilder::DiagnoseUnsupportedPropertyUse() {
+ if (S.getCurLexicalContext()->isObjCContainer() &&
+ S.getCurLexicalContext()->getDeclKind() != Decl::ObjCCategoryImpl &&
+ S.getCurLexicalContext()->getDeclKind() != Decl::ObjCImplementation) {
+ if (ObjCPropertyDecl *prop = RefExpr->getExplicitProperty()) {
+ S.Diag(RefExpr->getLocation(),
+ diag::err_property_function_in_objc_container);
+ S.Diag(prop->getLocation(), diag::note_property_declare);
+ }
+ }
+}
+
/// Capture the base object of an Objective-C property expression.
Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
- assert(InstanceReceiver == 0);
+ assert(InstanceReceiver == nullptr);
// If we have a base, capture it in an OVE and rebuild the syntactic
// form to use the OVE as its base.
@@ -661,7 +677,10 @@ Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
/// Load from an Objective-C property reference.
ExprResult ObjCPropertyOpBuilder::buildGet() {
findGetter();
- assert(Getter);
+ if (!Getter) {
+ DiagnoseUnsupportedPropertyUse();
+ return ExprError();
+ }
if (SyntacticRefExpr)
SyntacticRefExpr->setIsMessagingGetter();
@@ -675,10 +694,12 @@ ExprResult ObjCPropertyOpBuilder::buildGet() {
assert(InstanceReceiver);
receiverType = InstanceReceiver->getType();
}
-
+ if (!Getter->isImplicit())
+ S.DiagnoseUseOfDecl(Getter, GenericLoc, nullptr, true);
// Build a message-send.
ExprResult msg;
- if (Getter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
+ if ((Getter->isInstanceMethod() && !RefExpr->isClassReceiver()) ||
+ RefExpr->isObjectReceiver()) {
assert(InstanceReceiver || RefExpr->isSuperReceiver());
msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
GenericLoc, Getter->getSelector(),
@@ -697,8 +718,10 @@ ExprResult ObjCPropertyOpBuilder::buildGet() {
/// value being set as the value of the property operation.
ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
bool captureSetValueAsResult) {
- bool hasSetter = findSetter(false);
- assert(hasSetter); (void) hasSetter;
+ if (!findSetter(false)) {
+ DiagnoseUnsupportedPropertyUse();
+ return ExprError();
+ }
if (SyntacticRefExpr)
SyntacticRefExpr->setIsMessagingSetter();
@@ -727,7 +750,7 @@ ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
Sema::AA_Assigning))
return ExprError();
- op = opResult.take();
+ op = opResult.get();
assert(op && "successful assignment left argument invalid?");
}
else if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(op)) {
@@ -747,7 +770,10 @@ ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
// Build a message-send.
ExprResult msg;
- if (Setter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
+ if (!Setter->isImplicit())
+ S.DiagnoseUseOfDecl(Setter, GenericLoc, nullptr, true);
+ if ((Setter->isInstanceMethod() && !RefExpr->isClassReceiver()) ||
+ RefExpr->isObjectReceiver()) {
msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
GenericLoc, SetterSelector, Setter,
MultiExprArg(args, 1));
@@ -762,7 +788,7 @@ ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
ObjCMessageExpr *msgExpr =
cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
Expr *arg = msgExpr->getArg(0);
- if (CanCaptureValueOfType(arg->getType()))
+ if (CanCaptureValue(arg))
msgExpr->setArg(0, captureValueAsResult(arg));
}
@@ -788,13 +814,20 @@ ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) {
// As a special case, if the method returns 'id', try to get
// a better type from the property.
- if (RefExpr->isExplicitProperty() && result.get()->isRValue() &&
- result.get()->getType()->isObjCIdType()) {
+ if (RefExpr->isExplicitProperty() && result.get()->isRValue()) {
QualType propType = RefExpr->getExplicitProperty()->getType();
- if (const ObjCObjectPointerType *ptr
- = propType->getAs<ObjCObjectPointerType>()) {
- if (!ptr->isObjCIdType())
- result = S.ImpCastExprToType(result.get(), propType, CK_BitCast);
+ if (result.get()->getType()->isObjCIdType()) {
+ if (const ObjCObjectPointerType *ptr
+ = propType->getAs<ObjCObjectPointerType>()) {
+ if (!ptr->isObjCIdType())
+ result = S.ImpCastExprToType(result.get(), propType, CK_BitCast);
+ }
+ }
+ if (S.getLangOpts().ObjCAutoRefCount) {
+ Qualifiers::ObjCLifetime LT = propType.getObjCLifetime();
+ if (LT == Qualifiers::OCL_Weak)
+ if (!S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, RefExpr->getLocation()))
+ S.getCurFunction()->markSafeWeakUse(RefExpr);
}
}
@@ -810,10 +843,15 @@ bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op,
if (!S.getLangOpts().CPlusPlus) return false;
findGetter();
- assert(Getter && "property has no setter and no getter!");
+ if (!Getter) {
+ // The property has no setter and no getter! This can happen if the type is
+ // invalid. Error have already been reported.
+ result = ExprError();
+ return true;
+ }
// Only do this if the getter returns an l-value reference type.
- QualType resultType = Getter->getResultType();
+ QualType resultType = Getter->getReturnType();
if (!resultType->isLValueReferenceType()) return false;
result = buildRValueOperation(op);
@@ -834,7 +872,7 @@ ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc,
ExprResult result;
if (tryBuildGetOfReference(LHS, result)) {
if (result.isInvalid()) return ExprError();
- return S.BuildBinOp(Sc, opcLoc, opcode, result.take(), RHS);
+ return S.BuildBinOp(Sc, opcLoc, opcode, result.get(), RHS);
}
// Otherwise, it's an error.
@@ -878,7 +916,7 @@ ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
ExprResult result;
if (tryBuildGetOfReference(op, result)) {
if (result.isInvalid()) return ExprError();
- return S.BuildUnaryOp(Sc, opcLoc, opcode, result.take());
+ return S.BuildUnaryOp(Sc, opcLoc, opcode, result.get());
}
// Otherwise, it's an error.
@@ -906,14 +944,11 @@ ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
}
ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) {
- if (S.getLangOpts().ObjCAutoRefCount && isWeakProperty()) {
- DiagnosticsEngine::Level Level =
- S.Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
- SyntacticForm->getLocStart());
- if (Level != DiagnosticsEngine::Ignored)
+ if (S.getLangOpts().ObjCAutoRefCount && isWeakProperty() &&
+ !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak,
+ SyntacticForm->getLocStart()))
S.recordUseOfEvaluatedWeak(SyntacticRefExpr,
SyntacticRefExpr->isMessagingGetter());
- }
return PseudoOpBuilder::complete(SyntacticForm);
}
@@ -961,8 +996,8 @@ ObjCSubscriptOpBuilder::buildAssignmentOperation(Scope *Sc,
/// Capture the base object of an Objective-C Index'ed expression.
Expr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
- assert(InstanceBase == 0);
-
+ assert(InstanceBase == nullptr);
+
// Capture base expression in an OVE and rebuild the syntactic
// form to use the OVE as its base expression.
InstanceBase = capture(RefExpr->getBaseExpr());
@@ -1011,8 +1046,6 @@ Sema::ObjCSubscriptKind
// Look for a conversion to an integral, enumeration type, or
// objective-C pointer type.
- UnresolvedSet<4> ViableConversions;
- UnresolvedSet<4> ExplicitConversions;
std::pair<CXXRecordDecl::conversion_iterator,
CXXRecordDecl::conversion_iterator> Conversions
= cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions();
@@ -1069,7 +1102,7 @@ static void CheckKeyForObjCARCConversion(Sema &S, QualType ContainerT,
true /*instance*/);
if (!Getter)
return;
- QualType T = Getter->param_begin()[0]->getType();
+ QualType T = Getter->parameters()[0]->getType();
S.CheckObjCARCConversion(Key->getSourceRange(),
T, Key, Sema::CCK_ImplicitConversion);
}
@@ -1130,7 +1163,7 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
AtIndexGetter = ObjCMethodDecl::Create(S.Context, SourceLocation(),
SourceLocation(), AtIndexGetterSelector,
S.Context.getObjCIdType() /*ReturnType*/,
- 0 /*TypeSourceInfo */,
+ nullptr /*TypeSourceInfo */,
S.Context.getTranslationUnitDecl(),
true /*Instance*/, false/*isVariadic*/,
/*isPropertyAccessor=*/false,
@@ -1143,9 +1176,9 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
: &S.Context.Idents.get("key"),
arrayRef ? S.Context.UnsignedLongTy
: S.Context.getObjCIdType(),
- /*TInfo=*/0,
+ /*TInfo=*/nullptr,
SC_None,
- 0);
+ nullptr);
AtIndexGetter->setMethodParams(S.Context, Argument, None);
}
@@ -1162,17 +1195,17 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
}
if (AtIndexGetter) {
- QualType T = AtIndexGetter->param_begin()[0]->getType();
+ QualType T = AtIndexGetter->parameters()[0]->getType();
if ((arrayRef && !T->isIntegralOrEnumerationType()) ||
(!arrayRef && !T->isObjCObjectPointerType())) {
S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
arrayRef ? diag::err_objc_subscript_index_type
: diag::err_objc_subscript_key_type) << T;
- S.Diag(AtIndexGetter->param_begin()[0]->getLocation(),
+ S.Diag(AtIndexGetter->parameters()[0]->getLocation(),
diag::note_parameter_type) << T;
return false;
}
- QualType R = AtIndexGetter->getResultType();
+ QualType R = AtIndexGetter->getReturnType();
if (!R->isObjCObjectPointerType()) {
S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
diag::err_objc_indexing_method_result_type) << R << arrayRef;
@@ -1239,26 +1272,23 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
BaseT->isObjCQualifiedIdType());
if (!AtIndexSetter && S.getLangOpts().DebuggerObjCLiteral) {
- TypeSourceInfo *ResultTInfo = 0;
+ TypeSourceInfo *ReturnTInfo = nullptr;
QualType ReturnType = S.Context.VoidTy;
- AtIndexSetter = ObjCMethodDecl::Create(S.Context, SourceLocation(),
- SourceLocation(), AtIndexSetterSelector,
- ReturnType,
- ResultTInfo,
- S.Context.getTranslationUnitDecl(),
- true /*Instance*/, false/*isVariadic*/,
- /*isPropertyAccessor=*/false,
- /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
- ObjCMethodDecl::Required,
- false);
+ AtIndexSetter = ObjCMethodDecl::Create(
+ S.Context, SourceLocation(), SourceLocation(), AtIndexSetterSelector,
+ ReturnType, ReturnTInfo, S.Context.getTranslationUnitDecl(),
+ true /*Instance*/, false /*isVariadic*/,
+ /*isPropertyAccessor=*/false,
+ /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
+ ObjCMethodDecl::Required, false);
SmallVector<ParmVarDecl *, 2> Params;
ParmVarDecl *object = ParmVarDecl::Create(S.Context, AtIndexSetter,
SourceLocation(), SourceLocation(),
&S.Context.Idents.get("object"),
S.Context.getObjCIdType(),
- /*TInfo=*/0,
+ /*TInfo=*/nullptr,
SC_None,
- 0);
+ nullptr);
Params.push_back(object);
ParmVarDecl *key = ParmVarDecl::Create(S.Context, AtIndexSetter,
SourceLocation(), SourceLocation(),
@@ -1266,9 +1296,9 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
: &S.Context.Idents.get("key"),
arrayRef ? S.Context.UnsignedLongTy
: S.Context.getObjCIdType(),
- /*TInfo=*/0,
+ /*TInfo=*/nullptr,
SC_None,
- 0);
+ nullptr);
Params.push_back(key);
AtIndexSetter->setMethodParams(S.Context, Params, None);
}
@@ -1288,26 +1318,26 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
bool err = false;
if (AtIndexSetter && arrayRef) {
- QualType T = AtIndexSetter->param_begin()[1]->getType();
+ QualType T = AtIndexSetter->parameters()[1]->getType();
if (!T->isIntegralOrEnumerationType()) {
S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
diag::err_objc_subscript_index_type) << T;
- S.Diag(AtIndexSetter->param_begin()[1]->getLocation(),
+ S.Diag(AtIndexSetter->parameters()[1]->getLocation(),
diag::note_parameter_type) << T;
err = true;
}
- T = AtIndexSetter->param_begin()[0]->getType();
+ T = AtIndexSetter->parameters()[0]->getType();
if (!T->isObjCObjectPointerType()) {
S.Diag(RefExpr->getBaseExpr()->getExprLoc(),
diag::err_objc_subscript_object_type) << T << arrayRef;
- S.Diag(AtIndexSetter->param_begin()[0]->getLocation(),
+ S.Diag(AtIndexSetter->parameters()[0]->getLocation(),
diag::note_parameter_type) << T;
err = true;
}
}
else if (AtIndexSetter && !arrayRef)
for (unsigned i=0; i <2; i++) {
- QualType T = AtIndexSetter->param_begin()[i]->getType();
+ QualType T = AtIndexSetter->parameters()[i]->getType();
if (!T->isObjCObjectPointerType()) {
if (i == 1)
S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
@@ -1315,7 +1345,7 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
else
S.Diag(RefExpr->getBaseExpr()->getExprLoc(),
diag::err_objc_subscript_dic_object_type) << T;
- S.Diag(AtIndexSetter->param_begin()[i]->getLocation(),
+ S.Diag(AtIndexSetter->parameters()[i]->getLocation(),
diag::note_parameter_type) << T;
err = true;
}
@@ -1339,6 +1369,8 @@ ExprResult ObjCSubscriptOpBuilder::buildGet() {
// Arguments.
Expr *args[] = { Index };
assert(InstanceBase);
+ if (AtIndexGetter)
+ S.DiagnoseUseOfDecl(AtIndexGetter, GenericLoc);
msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType,
GenericLoc,
AtIndexGetterSelector, AtIndexGetter,
@@ -1355,7 +1387,8 @@ ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
bool captureSetValueAsResult) {
if (!findAtIndexSetter())
return ExprError();
-
+ if (AtIndexSetter)
+ S.DiagnoseUseOfDecl(AtIndexSetter, GenericLoc);
QualType receiverType = InstanceBase->getType();
Expr *Index = InstanceKey;
@@ -1373,7 +1406,7 @@ ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
ObjCMessageExpr *msgExpr =
cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
Expr *arg = msgExpr->getArg(0);
- if (CanCaptureValueOfType(arg->getType()))
+ if (CanCaptureValue(arg))
msgExpr->setArg(0, captureValueAsResult(arg));
}
@@ -1395,8 +1428,8 @@ Expr *MSPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
ExprResult MSPropertyOpBuilder::buildGet() {
if (!RefExpr->getPropertyDecl()->hasGetter()) {
- S.Diag(RefExpr->getMemberLoc(), diag::err_no_getter_for_property)
- << RefExpr->getPropertyDecl()->getName();
+ S.Diag(RefExpr->getMemberLoc(), diag::err_no_accessor_for_property)
+ << 0 /* getter */ << RefExpr->getPropertyDecl();
return ExprError();
}
@@ -1408,15 +1441,16 @@ ExprResult MSPropertyOpBuilder::buildGet() {
ExprResult GetterExpr = S.ActOnMemberAccessExpr(
S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(),
RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(),
- GetterName, 0, true);
+ GetterName, nullptr, true);
if (GetterExpr.isInvalid()) {
- S.Diag(RefExpr->getMemberLoc(), diag::error_cannot_find_suitable_getter)
- << RefExpr->getPropertyDecl()->getName();
+ S.Diag(RefExpr->getMemberLoc(),
+ diag::error_cannot_find_suitable_accessor) << 0 /* getter */
+ << RefExpr->getPropertyDecl();
return ExprError();
}
MultiExprArg ArgExprs;
- return S.ActOnCallExpr(S.getCurScope(), GetterExpr.take(),
+ return S.ActOnCallExpr(S.getCurScope(), GetterExpr.get(),
RefExpr->getSourceRange().getBegin(), ArgExprs,
RefExpr->getSourceRange().getEnd());
}
@@ -1424,8 +1458,8 @@ ExprResult MSPropertyOpBuilder::buildGet() {
ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl,
bool captureSetValueAsResult) {
if (!RefExpr->getPropertyDecl()->hasSetter()) {
- S.Diag(RefExpr->getMemberLoc(), diag::err_no_setter_for_property)
- << RefExpr->getPropertyDecl()->getName();
+ S.Diag(RefExpr->getMemberLoc(), diag::err_no_accessor_for_property)
+ << 1 /* setter */ << RefExpr->getPropertyDecl();
return ExprError();
}
@@ -1437,16 +1471,17 @@ ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl,
ExprResult SetterExpr = S.ActOnMemberAccessExpr(
S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(),
RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(),
- SetterName, 0, true);
+ SetterName, nullptr, true);
if (SetterExpr.isInvalid()) {
- S.Diag(RefExpr->getMemberLoc(), diag::error_cannot_find_suitable_setter)
- << RefExpr->getPropertyDecl()->getName();
+ S.Diag(RefExpr->getMemberLoc(),
+ diag::error_cannot_find_suitable_accessor) << 1 /* setter */
+ << RefExpr->getPropertyDecl();
return ExprError();
}
SmallVector<Expr*, 1> ArgExprs;
ArgExprs.push_back(op);
- return S.ActOnCallExpr(S.getCurScope(), SetterExpr.take(),
+ return S.ActOnCallExpr(S.getCurScope(), SetterExpr.get(),
RefExpr->getSourceRange().getBegin(), ArgExprs,
op->getSourceRange().getEnd());
}
@@ -1513,7 +1548,7 @@ ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
if (RHS->getType()->isNonOverloadPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(RHS);
if (result.isInvalid()) return ExprError();
- RHS = result.take();
+ RHS = result.get();
}
Expr *opaqueRef = LHS->IgnoreParens();
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
index 9bd8678..278e6d6 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
@@ -49,7 +49,7 @@ StmtResult Sema::ActOnExprStmt(ExprResult FE) {
// operand, even incomplete types.
// Same thing in for stmt first clause (when expr) and third clause.
- return Owned(static_cast<Stmt*>(FE.take()));
+ return StmtResult(FE.getAs<Stmt>());
}
@@ -60,7 +60,7 @@ StmtResult Sema::ActOnExprStmtError() {
StmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc,
bool HasLeadingEmptyMacro) {
- return Owned(new (Context) NullStmt(SemiLoc, HasLeadingEmptyMacro));
+ return new (Context) NullStmt(SemiLoc, HasLeadingEmptyMacro);
}
StmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg, SourceLocation StartLoc,
@@ -70,7 +70,7 @@ StmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg, SourceLocation StartLoc,
// If we have an invalid decl, just return an error.
if (DG.isNull()) return StmtError();
- return Owned(new (Context) DeclStmt(DG, StartLoc, EndLoc));
+ return new (Context) DeclStmt(DG, StartLoc, EndLoc);
}
void Sema::ActOnForEachDeclStmt(DeclGroupPtrTy dg) {
@@ -95,7 +95,7 @@ void Sema::ActOnForEachDeclStmt(DeclGroupPtrTy dg) {
// foreach variables are never actually initialized in the way that
// the parser came up with.
- var->setInit(0);
+ var->setInit(nullptr);
// In ARC, we don't need to retain the iteration variable of a fast
// enumeration loop. Rather than actually trying to catch that
@@ -114,25 +114,38 @@ void Sema::ActOnForEachDeclStmt(DeclGroupPtrTy dg) {
}
}
-/// \brief Diagnose unused '==' and '!=' as likely typos for '=' or '|='.
+/// \brief 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
/// warning from firing.
static bool DiagnoseUnusedComparison(Sema &S, const Expr *E) {
SourceLocation Loc;
- bool IsNotEqual, CanAssign;
+ bool IsNotEqual, CanAssign, IsRelational;
if (const BinaryOperator *Op = dyn_cast<BinaryOperator>(E)) {
- if (Op->getOpcode() != BO_EQ && Op->getOpcode() != BO_NE)
+ if (!Op->isComparisonOp())
return false;
+ IsRelational = Op->isRelationalOp();
Loc = Op->getOperatorLoc();
IsNotEqual = Op->getOpcode() == BO_NE;
CanAssign = Op->getLHS()->IgnoreParenImpCasts()->isLValue();
} else if (const CXXOperatorCallExpr *Op = dyn_cast<CXXOperatorCallExpr>(E)) {
- if (Op->getOperator() != OO_EqualEqual &&
- Op->getOperator() != OO_ExclaimEqual)
+ switch (Op->getOperator()) {
+ default:
return false;
+ case OO_EqualEqual:
+ case OO_ExclaimEqual:
+ IsRelational = false;
+ break;
+ case OO_Less:
+ case OO_Greater:
+ case OO_GreaterEqual:
+ case OO_LessEqual:
+ IsRelational = true;
+ break;
+ }
Loc = Op->getOperatorLoc();
IsNotEqual = Op->getOperator() == OO_ExclaimEqual;
@@ -148,11 +161,11 @@ static bool DiagnoseUnusedComparison(Sema &S, const Expr *E) {
return false;
S.Diag(Loc, diag::warn_unused_comparison)
- << (unsigned)IsNotEqual << E->getSourceRange();
+ << (unsigned)IsRelational << (unsigned)IsNotEqual << E->getSourceRange();
// If the LHS is a plausible entity to assign to, provide a fixit hint to
// correct common typos.
- if (CanAssign) {
+ if (!IsRelational && CanAssign) {
if (IsNotEqual)
S.Diag(Loc, diag::note_inequality_comparison_to_or_assign)
<< FixItHint::CreateReplacement(Loc, "|=");
@@ -216,17 +229,17 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
// is written in a macro body, only warn if it has the warn_unused_result
// attribute.
if (const Decl *FD = CE->getCalleeDecl()) {
- if (FD->getAttr<WarnUnusedResultAttr>()) {
+ if (FD->hasAttr<WarnUnusedResultAttr>()) {
Diag(Loc, diag::warn_unused_result) << R1 << R2;
return;
}
if (ShouldSuppress)
return;
- if (FD->getAttr<PureAttr>()) {
+ if (FD->hasAttr<PureAttr>()) {
Diag(Loc, diag::warn_unused_call) << R1 << R2 << "pure";
return;
}
- if (FD->getAttr<ConstAttr>()) {
+ if (FD->hasAttr<ConstAttr>()) {
Diag(Loc, diag::warn_unused_call) << R1 << R2 << "const";
return;
}
@@ -240,9 +253,15 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
return;
}
const ObjCMethodDecl *MD = ME->getMethodDecl();
- if (MD && MD->getAttr<WarnUnusedResultAttr>()) {
- Diag(Loc, diag::warn_unused_result) << R1 << R2;
- return;
+ if (MD) {
+ if (MD->hasAttr<WarnUnusedResultAttr>()) {
+ Diag(Loc, diag::warn_unused_result) << R1 << R2;
+ return;
+ }
+ if (MD->isPropertyAccessor()) {
+ Diag(Loc, diag::warn_unused_property_expr);
+ return;
+ }
}
} else if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {
const Expr *Source = POE->getSyntacticForm();
@@ -276,7 +295,7 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
return;
}
- DiagRuntimeBehavior(Loc, 0, PDiag(DiagID) << R1 << R2);
+ DiagRuntimeBehavior(Loc, nullptr, PDiag(DiagID) << R1 << R2);
}
void Sema::ActOnStartOfCompoundStmt() {
@@ -331,14 +350,14 @@ StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
DiagnoseEmptyLoopBody(Elts[i], Elts[i + 1]);
}
- return Owned(new (Context) CompoundStmt(Context, Elts, L, R));
+ return new (Context) CompoundStmt(Context, Elts, L, R);
}
StmtResult
Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal,
SourceLocation DotDotDotLoc, Expr *RHSVal,
SourceLocation ColonLoc) {
- assert((LHSVal != 0) && "missing expression in case statement");
+ assert(LHSVal && "missing expression in case statement");
if (getCurFunction()->SwitchStack.empty()) {
Diag(CaseLoc, diag::err_case_not_in_switch);
@@ -349,7 +368,7 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal,
// 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).take();
+ LHSVal = VerifyIntegerConstantExpression(LHSVal).get();
if (!LHSVal)
return StmtError();
}
@@ -357,21 +376,21 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal,
// GCC extension: The expression shall be an integer constant.
if (RHSVal && !RHSVal->isTypeDependent() && !RHSVal->isValueDependent()) {
- RHSVal = VerifyIntegerConstantExpression(RHSVal).take();
+ RHSVal = VerifyIntegerConstantExpression(RHSVal).get();
// Recover from an error by just forgetting about it.
}
}
LHSVal = ActOnFinishFullExpr(LHSVal, LHSVal->getExprLoc(), false,
- getLangOpts().CPlusPlus11).take();
+ getLangOpts().CPlusPlus11).get();
if (RHSVal)
RHSVal = ActOnFinishFullExpr(RHSVal, RHSVal->getExprLoc(), false,
- getLangOpts().CPlusPlus11).take();
+ getLangOpts().CPlusPlus11).get();
CaseStmt *CS = new (Context) CaseStmt(LHSVal, RHSVal, CaseLoc, DotDotDotLoc,
ColonLoc);
getCurFunction()->SwitchStack.back()->addSwitchCase(CS);
- return Owned(CS);
+ return CS;
}
/// ActOnCaseStmtBody - This installs a statement as the body of a case.
@@ -389,12 +408,12 @@ Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc,
if (getCurFunction()->SwitchStack.empty()) {
Diag(DefaultLoc, diag::err_default_not_in_switch);
- return Owned(SubStmt);
+ return SubStmt;
}
DefaultStmt *DS = new (Context) DefaultStmt(DefaultLoc, ColonLoc, SubStmt);
getCurFunction()->SwitchStack.back()->addSwitchCase(DS);
- return Owned(DS);
+ return DS;
}
StmtResult
@@ -404,7 +423,7 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
if (TheDecl->getStmt()) {
Diag(IdentLoc, diag::err_redefinition_of_label) << TheDecl->getDeclName();
Diag(TheDecl->getLocation(), diag::note_previous_definition);
- return Owned(SubStmt);
+ return SubStmt;
}
// Otherwise, things are good. Fill in the declaration and return it.
@@ -414,7 +433,7 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
TheDecl->setLocStart(IdentLoc);
TheDecl->setLocation(IdentLoc);
}
- return Owned(LS);
+ return LS;
}
StmtResult Sema::ActOnAttributedStmt(SourceLocation AttrLoc,
@@ -422,7 +441,7 @@ StmtResult Sema::ActOnAttributedStmt(SourceLocation AttrLoc,
Stmt *SubStmt) {
// Fill in the declaration and return it.
AttributedStmt *LS = AttributedStmt::Create(Context, AttrLoc, Attrs, SubStmt);
- return Owned(LS);
+ return LS;
}
StmtResult
@@ -438,14 +457,14 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar,
ExprResult CondResult(CondVal.release());
- VarDecl *ConditionVar = 0;
+ VarDecl *ConditionVar = nullptr;
if (CondVar) {
ConditionVar = cast<VarDecl>(CondVar);
CondResult = CheckConditionVariable(ConditionVar, IfLoc, true);
if (CondResult.isInvalid())
return StmtError();
}
- Expr *ConditionExpr = CondResult.takeAs<Expr>();
+ Expr *ConditionExpr = CondResult.getAs<Expr>();
if (!ConditionExpr)
return StmtError();
@@ -458,8 +477,8 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar,
DiagnoseUnusedExprResult(elseStmt);
- return Owned(new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr,
- thenStmt, ElseLoc, elseStmt));
+ return new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr,
+ thenStmt, ElseLoc, elseStmt);
}
/// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have
@@ -499,7 +518,6 @@ void Sema::ConvertIntegerToTypeWarnOnOverflow(llvm::APSInt &Val,
// We don't diagnose this overflow, because it is implementation-defined
// behavior.
// FIXME: Introduce a second, default-ignored warning for this case?
- llvm::APSInt OldVal(Val);
Val.setIsSigned(NewSign);
}
}
@@ -568,14 +586,14 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond,
Decl *CondVar) {
ExprResult CondResult;
- VarDecl *ConditionVar = 0;
+ VarDecl *ConditionVar = nullptr;
if (CondVar) {
ConditionVar = cast<VarDecl>(CondVar);
CondResult = CheckConditionVariable(ConditionVar, SourceLocation(), false);
if (CondResult.isInvalid())
return StmtError();
- Cond = CondResult.release();
+ Cond = CondResult.get();
}
if (!Cond)
@@ -589,41 +607,41 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond,
: ICEConvertDiagnoser(/*AllowScopedEnumerations*/true, false, true),
Cond(Cond) {}
- virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
- QualType T) {
+ SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
+ QualType T) override {
return S.Diag(Loc, diag::err_typecheck_statement_requires_integer) << T;
}
- virtual SemaDiagnosticBuilder diagnoseIncomplete(
- Sema &S, SourceLocation Loc, QualType T) {
+ SemaDiagnosticBuilder diagnoseIncomplete(
+ Sema &S, SourceLocation Loc, QualType T) override {
return S.Diag(Loc, diag::err_switch_incomplete_class_type)
<< T << Cond->getSourceRange();
}
- virtual SemaDiagnosticBuilder diagnoseExplicitConv(
- Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
+ SemaDiagnosticBuilder diagnoseExplicitConv(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override {
return S.Diag(Loc, diag::err_switch_explicit_conversion) << T << ConvTy;
}
- virtual SemaDiagnosticBuilder noteExplicitConv(
- Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
+ SemaDiagnosticBuilder noteExplicitConv(
+ Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
return S.Diag(Conv->getLocation(), diag::note_switch_conversion)
<< ConvTy->isEnumeralType() << ConvTy;
}
- virtual SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
- QualType T) {
+ SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
+ QualType T) override {
return S.Diag(Loc, diag::err_switch_multiple_conversions) << T;
}
- virtual SemaDiagnosticBuilder noteAmbiguous(
- Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
+ SemaDiagnosticBuilder noteAmbiguous(
+ Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
return S.Diag(Conv->getLocation(), diag::note_switch_conversion)
<< ConvTy->isEnumeralType() << ConvTy;
}
- virtual SemaDiagnosticBuilder diagnoseConversion(
- Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
+ SemaDiagnosticBuilder diagnoseConversion(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override {
llvm_unreachable("conversion functions are permitted");
}
} SwitchDiagnoser(Cond);
@@ -631,25 +649,25 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond,
CondResult =
PerformContextualImplicitConversion(SwitchLoc, Cond, SwitchDiagnoser);
if (CondResult.isInvalid()) return StmtError();
- Cond = CondResult.take();
+ Cond = CondResult.get();
// C99 6.8.4.2p5 - Integer promotions are performed on the controlling expr.
CondResult = UsualUnaryConversions(Cond);
if (CondResult.isInvalid()) return StmtError();
- Cond = CondResult.take();
+ Cond = CondResult.get();
if (!CondVar) {
CondResult = ActOnFinishFullExpr(Cond, SwitchLoc);
if (CondResult.isInvalid())
return StmtError();
- Cond = CondResult.take();
+ Cond = CondResult.get();
}
getCurFunction()->setHasBranchIntoScope();
SwitchStmt *SS = new (Context) SwitchStmt(Context, ConditionVar, Cond);
getCurFunction()->SwitchStack.push_back(SS);
- return Owned(SS);
+ return SS;
}
static void AdjustAPSInt(llvm::APSInt &Val, unsigned BitWidth, bool IsSigned) {
@@ -660,6 +678,29 @@ static void AdjustAPSInt(llvm::APSInt &Val, unsigned BitWidth, bool IsSigned) {
Val.setIsSigned(IsSigned);
}
+/// Returns true if we should emit a diagnostic about this case expression not
+/// being a part of the enum used in the switch controlling expression.
+static bool ShouldDiagnoseSwitchCaseNotInEnum(const ASTContext &Ctx,
+ const EnumDecl *ED,
+ const Expr *CaseExpr) {
+ // Don't warn if the 'case' expression refers to a static const variable of
+ // the enum type.
+ CaseExpr = CaseExpr->IgnoreParenImpCasts();
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseExpr)) {
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
+ if (!VD->hasGlobalStorage())
+ return true;
+ QualType VarType = VD->getType();
+ if (!VarType.isConstQualified())
+ return true;
+ QualType EnumType = Ctx.getTypeDeclType(ED);
+ if (Ctx.hasSameUnqualifiedType(EnumType, VarType))
+ return false;
+ }
+ }
+ return true;
+}
+
StmtResult
Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
Stmt *BodyStmt) {
@@ -667,6 +708,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
assert(SS == getCurFunction()->SwitchStack.back() &&
"switch stack missing push/pop!");
+ if (!BodyStmt) return StmtError();
SS->setBody(BodyStmt, SwitchLoc);
getCurFunction()->SwitchStack.pop_back();
@@ -721,7 +763,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
typedef std::vector<std::pair<llvm::APSInt, CaseStmt*> > CaseRangesTy;
CaseRangesTy CaseRanges;
- DefaultStmt *TheDefaultStmt = 0;
+ DefaultStmt *TheDefaultStmt = nullptr;
bool CaseListIsErroneous = false;
@@ -762,7 +804,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
CaseListIsErroneous = true;
continue;
}
- Lo = ConvLo.take();
+ 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.
@@ -770,8 +812,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
// If the LHS is not the same type as the condition, insert an implicit
// cast.
- Lo = DefaultLvalueConversion(Lo).take();
- Lo = ImpCastExprToType(Lo, CondType, CK_IntegralCast).take();
+ Lo = DefaultLvalueConversion(Lo).get();
+ Lo = ImpCastExprToType(Lo, CondType, CK_IntegralCast).get();
}
// Convert the value to the same width/sign as the condition had prior to
@@ -883,14 +925,14 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
CaseListIsErroneous = true;
continue;
}
- Hi = ConvHi.take();
+ 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).take();
- Hi = ImpCastExprToType(Hi, CondType, CK_IntegralCast).take();
+ Hi = DefaultLvalueConversion(Hi).get();
+ Hi = ImpCastExprToType(Hi, CondType, CK_IntegralCast).get();
}
// Convert the value to the same width/sign as the condition.
@@ -928,7 +970,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
// Check to see whether the case range overlaps with any
// singleton cases.
- CaseStmt *OverlapStmt = 0;
+ CaseStmt *OverlapStmt = nullptr;
llvm::APSInt OverlapVal(32);
// Find the smallest value >= the lower bound. If I is in the
@@ -993,11 +1035,10 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
// Gather all enum values, set their type and sort them,
// allowing easier comparison with CaseVals.
- for (EnumDecl::enumerator_iterator EDI = ED->enumerator_begin();
- EDI != ED->enumerator_end(); ++EDI) {
+ for (auto *EDI : ED->enumerators()) {
llvm::APSInt Val = EDI->getInitVal();
AdjustAPSInt(Val, CondWidth, CondIsSigned);
- EnumVals.push_back(std::make_pair(Val, *EDI));
+ EnumVals.push_back(std::make_pair(Val, EDI));
}
std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals);
EnumValsTy::iterator EIend =
@@ -1009,9 +1050,12 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
CI != CaseVals.end(); CI++) {
while (EI != EIend && EI->first < CI->first)
EI++;
- if (EI == EIend || EI->first > CI->first)
- Diag(CI->second->getLHS()->getExprLoc(), diag::warn_not_in_enum)
- << CondTypeBeforePromotion;
+ if (EI == EIend || EI->first > CI->first) {
+ Expr *CaseExpr = CI->second->getLHS();
+ if (ShouldDiagnoseSwitchCaseNotInEnum(Context, ED, CaseExpr))
+ Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum)
+ << CondTypeBeforePromotion;
+ }
}
// See which of case ranges aren't in enum
EI = EnumVals.begin();
@@ -1021,8 +1065,10 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
EI++;
if (EI == EIend || EI->first != RI->first) {
- Diag(RI->second->getLHS()->getExprLoc(), diag::warn_not_in_enum)
- << CondTypeBeforePromotion;
+ Expr *CaseExpr = RI->second->getLHS();
+ if (ShouldDiagnoseSwitchCaseNotInEnum(Context, ED, CaseExpr))
+ Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum)
+ << CondTypeBeforePromotion;
}
llvm::APSInt Hi =
@@ -1030,9 +1076,12 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
AdjustAPSInt(Hi, CondWidth, CondIsSigned);
while (EI != EIend && EI->first < Hi)
EI++;
- if (EI == EIend || EI->first != Hi)
- Diag(RI->second->getRHS()->getExprLoc(), diag::warn_not_in_enum)
- << CondTypeBeforePromotion;
+ if (EI == EIend || EI->first != Hi) {
+ Expr *CaseExpr = RI->second->getRHS();
+ if (ShouldDiagnoseSwitchCaseNotInEnum(Context, ED, CaseExpr))
+ Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum)
+ << CondTypeBeforePromotion;
+ }
}
// Check which enum vals aren't in switch
@@ -1044,7 +1093,6 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
for (EI = EnumVals.begin(); EI != EIend; EI++){
// Drop unneeded case values
- llvm::APSInt CIVal;
while (CI != CaseVals.end() && CI->first < EI->first)
CI++;
@@ -1100,27 +1148,26 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
}
}
- DiagnoseEmptyStmtBody(CondExpr->getLocEnd(), BodyStmt,
- diag::warn_empty_switch_body);
+ if (BodyStmt)
+ DiagnoseEmptyStmtBody(CondExpr->getLocEnd(), BodyStmt,
+ diag::warn_empty_switch_body);
// FIXME: If the case list was broken is some way, we don't have a good system
// to patch it up. Instead, just return the whole substmt as broken.
if (CaseListIsErroneous)
return StmtError();
- return Owned(SS);
+ return SS;
}
void
Sema::DiagnoseAssignmentEnum(QualType DstType, QualType SrcType,
Expr *SrcExpr) {
- if (Diags.getDiagnosticLevel(diag::warn_not_in_enum_assignment,
- SrcExpr->getExprLoc()) ==
- DiagnosticsEngine::Ignored)
+ if (Diags.isIgnored(diag::warn_not_in_enum_assignment, SrcExpr->getExprLoc()))
return;
if (const EnumType *ET = DstType->getAs<EnumType>())
- if (!Context.hasSameType(SrcType, DstType) &&
+ if (!Context.hasSameUnqualifiedType(SrcType, DstType) &&
SrcType->isIntegerType()) {
if (!SrcExpr->isTypeDependent() && !SrcExpr->isValueDependent() &&
SrcExpr->isIntegerConstantExpr(Context)) {
@@ -1137,11 +1184,10 @@ Sema::DiagnoseAssignmentEnum(QualType DstType, QualType SrcType,
// Gather all enum values, set their type and sort them,
// allowing easier comparison with rhs constant.
- for (EnumDecl::enumerator_iterator EDI = ED->enumerator_begin();
- EDI != ED->enumerator_end(); ++EDI) {
+ for (auto *EDI : ED->enumerators()) {
llvm::APSInt Val = EDI->getInitVal();
AdjustAPSInt(Val, DstWidth, DstIsSigned);
- EnumVals.push_back(std::make_pair(Val, *EDI));
+ EnumVals.push_back(std::make_pair(Val, EDI));
}
if (EnumVals.empty())
return;
@@ -1155,7 +1201,7 @@ Sema::DiagnoseAssignmentEnum(QualType DstType, QualType SrcType,
EI++;
if (EI == EIend || EI->first != RhsVal) {
Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment)
- << DstType;
+ << DstType.getUnqualifiedType();
}
}
}
@@ -1166,24 +1212,25 @@ Sema::ActOnWhileStmt(SourceLocation WhileLoc, FullExprArg Cond,
Decl *CondVar, Stmt *Body) {
ExprResult CondResult(Cond.release());
- VarDecl *ConditionVar = 0;
+ VarDecl *ConditionVar = nullptr;
if (CondVar) {
ConditionVar = cast<VarDecl>(CondVar);
CondResult = CheckConditionVariable(ConditionVar, WhileLoc, true);
if (CondResult.isInvalid())
return StmtError();
}
- Expr *ConditionExpr = CondResult.take();
+ Expr *ConditionExpr = CondResult.get();
if (!ConditionExpr)
return StmtError();
+ CheckBreakContinueBinding(ConditionExpr);
DiagnoseUnusedExprResult(Body);
if (isa<NullStmt>(Body))
getCurCompoundScope().setHasEmptyLoopBodies();
- return Owned(new (Context) WhileStmt(Context, ConditionVar, ConditionExpr,
- Body, WhileLoc));
+ return new (Context)
+ WhileStmt(Context, ConditionVar, ConditionExpr, Body, WhileLoc);
}
StmtResult
@@ -1192,19 +1239,20 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body,
Expr *Cond, SourceLocation CondRParen) {
assert(Cond && "ActOnDoStmt(): missing expression");
+ CheckBreakContinueBinding(Cond);
ExprResult CondResult = CheckBooleanCondition(Cond, DoLoc);
if (CondResult.isInvalid())
return StmtError();
- Cond = CondResult.take();
+ Cond = CondResult.get();
CondResult = ActOnFinishFullExpr(Cond, DoLoc);
if (CondResult.isInvalid())
return StmtError();
- Cond = CondResult.take();
+ Cond = CondResult.get();
DiagnoseUnusedExprResult(Body);
- return Owned(new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen));
+ return new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen);
}
namespace {
@@ -1362,9 +1410,8 @@ namespace {
// Condition is empty
if (!Second) return;
- if (S.Diags.getDiagnosticLevel(diag::warn_variables_not_in_loop_body,
- Second->getLocStart())
- == DiagnosticsEngine::Ignored)
+ if (S.Diags.isIgnored(diag::warn_variables_not_in_loop_body,
+ Second->getLocStart()))
return;
PartialDiagnostic PDiag = S.PDiag(diag::warn_variables_not_in_loop_body);
@@ -1454,25 +1501,33 @@ namespace {
return false;
}
- // A visitor to determine if a continue statement is a subexpression.
- class ContinueFinder : public EvaluatedExprVisitor<ContinueFinder> {
- bool Found;
+ // A visitor to determine if a continue or break statement is a
+ // subexpression.
+ class BreakContinueFinder : public EvaluatedExprVisitor<BreakContinueFinder> {
+ SourceLocation BreakLoc;
+ SourceLocation ContinueLoc;
public:
- ContinueFinder(Sema &S, Stmt* Body) :
- Inherited(S.Context),
- Found(false) {
+ BreakContinueFinder(Sema &S, Stmt* Body) :
+ Inherited(S.Context) {
Visit(Body);
}
- typedef EvaluatedExprVisitor<ContinueFinder> Inherited;
+ typedef EvaluatedExprVisitor<BreakContinueFinder> Inherited;
void VisitContinueStmt(ContinueStmt* E) {
- Found = true;
+ ContinueLoc = E->getContinueLoc();
+ }
+
+ void VisitBreakStmt(BreakStmt* E) {
+ BreakLoc = E->getBreakLoc();
}
- bool ContinueFound() { return Found; }
+ bool ContinueFound() { return ContinueLoc.isValid(); }
+ bool BreakFound() { return BreakLoc.isValid(); }
+ SourceLocation GetContinueLoc() { return ContinueLoc; }
+ SourceLocation GetBreakLoc() { return BreakLoc; }
- }; // end class ContinueFinder
+ }; // end class BreakContinueFinder
// Emit a warning when a loop increment/decrement appears twice per loop
// iteration. The conditions which trigger this warning are:
@@ -1483,9 +1538,8 @@ namespace {
// Return when there is nothing to check.
if (!Body || !Third) return;
- if (S.Diags.getDiagnosticLevel(diag::warn_redundant_loop_iteration,
- Third->getLocStart())
- == DiagnosticsEngine::Ignored)
+ if (S.Diags.isIgnored(diag::warn_redundant_loop_iteration,
+ Third->getLocStart()))
return;
// Get the last statement from the loop body.
@@ -1501,11 +1555,11 @@ namespace {
if (!ProcessIterationStmt(S, LastStmt, LastIncrement, LastDRE)) return;
// Check that the two statements are both increments or both decrements
- // on the same varaible.
+ // on the same variable.
if (LoopIncrement != LastIncrement ||
LoopDRE->getDecl() != LastDRE->getDecl()) return;
- if (ContinueFinder(S, Body).ContinueFound()) return;
+ if (BreakContinueFinder(S, Body).ContinueFound()) return;
S.Diag(LastDRE->getLocation(), diag::warn_redundant_loop_iteration)
<< LastDRE->getDecl() << LastIncrement;
@@ -1515,6 +1569,25 @@ namespace {
} // end namespace
+
+void Sema::CheckBreakContinueBinding(Expr *E) {
+ if (!E || getLangOpts().CPlusPlus)
+ return;
+ BreakContinueFinder BCFinder(*this, E);
+ Scope *BreakParent = CurScope->getBreakParent();
+ if (BCFinder.BreakFound() && BreakParent) {
+ if (BreakParent->getFlags() & Scope::SwitchScope) {
+ Diag(BCFinder.GetBreakLoc(), diag::warn_break_binds_to_switch);
+ } else {
+ Diag(BCFinder.GetBreakLoc(), diag::warn_loop_ctrl_binds_to_inner)
+ << "break";
+ }
+ } else if (BCFinder.ContinueFound() && CurScope->getContinueParent()) {
+ Diag(BCFinder.GetContinueLoc(), diag::warn_loop_ctrl_binds_to_inner)
+ << "continue";
+ }
+}
+
StmtResult
Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
Stmt *First, FullExprArg second, Decl *secondVar,
@@ -1525,24 +1598,26 @@ Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
// C99 6.8.5p3: The declaration part of a 'for' statement shall only
// declare identifiers for objects having storage class 'auto' or
// 'register'.
- for (DeclStmt::decl_iterator DI=DS->decl_begin(), DE=DS->decl_end();
- DI!=DE; ++DI) {
- VarDecl *VD = dyn_cast<VarDecl>(*DI);
+ for (auto *DI : DS->decls()) {
+ VarDecl *VD = dyn_cast<VarDecl>(DI);
if (VD && VD->isLocalVarDecl() && !VD->hasLocalStorage())
- VD = 0;
- if (VD == 0) {
- Diag((*DI)->getLocation(), diag::err_non_local_variable_decl_in_for);
- (*DI)->setInvalidDecl();
+ VD = nullptr;
+ if (!VD) {
+ Diag(DI->getLocation(), diag::err_non_local_variable_decl_in_for);
+ DI->setInvalidDecl();
}
}
}
}
+ CheckBreakContinueBinding(second.get());
+ CheckBreakContinueBinding(third.get());
+
CheckForLoopConditionalStatement(*this, second.get(), third.get(), Body);
CheckForRedundantIteration(*this, third.get(), Body);
ExprResult SecondResult(second.release());
- VarDecl *ConditionVar = 0;
+ VarDecl *ConditionVar = nullptr;
if (secondVar) {
ConditionVar = cast<VarDecl>(secondVar);
SecondResult = CheckConditionVariable(ConditionVar, ForLoc, true);
@@ -1550,7 +1625,7 @@ Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
return StmtError();
}
- Expr *Third = third.release().takeAs<Expr>();
+ Expr *Third = third.release().getAs<Expr>();
DiagnoseUnusedExprResult(First);
DiagnoseUnusedExprResult(Third);
@@ -1559,10 +1634,8 @@ Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
if (isa<NullStmt>(Body))
getCurCompoundScope().setHasEmptyLoopBodies();
- return Owned(new (Context) ForStmt(Context, First,
- SecondResult.take(), ConditionVar,
- Third, Body, ForLoc, LParenLoc,
- RParenLoc));
+ return new (Context) ForStmt(Context, First, SecondResult.get(), ConditionVar,
+ Third, Body, ForLoc, LParenLoc, RParenLoc);
}
/// In an Objective C collection iteration statement:
@@ -1574,12 +1647,12 @@ StmtResult Sema::ActOnForEachLValueExpr(Expr *E) {
// use of pseudo-object l-values in this position.
ExprResult result = CheckPlaceholderExpr(E);
if (result.isInvalid()) return StmtError();
- E = result.take();
+ E = result.get();
ExprResult FullExpr = ActOnFinishFullExpr(E);
if (FullExpr.isInvalid())
return StmtError();
- return StmtResult(static_cast<Stmt*>(FullExpr.take()));
+ return StmtResult(static_cast<Stmt*>(FullExpr.get()));
}
ExprResult
@@ -1588,13 +1661,13 @@ Sema::CheckObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) {
return ExprError();
// Bail out early if we've got a type-dependent expression.
- if (collection->isTypeDependent()) return Owned(collection);
+ if (collection->isTypeDependent()) return collection;
// Perform normal l-value conversion.
ExprResult result = DefaultFunctionArrayLvalueConversion(collection);
if (result.isInvalid())
return ExprError();
- collection = result.take();
+ collection = result.get();
// The operand needs to have object-pointer type.
// TODO: should we do a contextual conversion?
@@ -1627,7 +1700,7 @@ Sema::CheckObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) {
};
Selector selector = Context.Selectors.getSelector(3, &selectorIdents[0]);
- ObjCMethodDecl *method = 0;
+ ObjCMethodDecl *method = nullptr;
// If there's an interface, look in both the public and private APIs.
if (iface) {
@@ -1650,7 +1723,7 @@ Sema::CheckObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) {
}
// Wrap up any cleanups in the expression.
- return Owned(collection);
+ return collection;
}
StmtResult
@@ -1725,13 +1798,12 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
if (CollectionExprResult.isInvalid())
return StmtError();
- CollectionExprResult = ActOnFinishFullExpr(CollectionExprResult.take());
+ CollectionExprResult = ActOnFinishFullExpr(CollectionExprResult.get());
if (CollectionExprResult.isInvalid())
return StmtError();
- return Owned(new (Context) ObjCForCollectionStmt(First,
- CollectionExprResult.take(), 0,
- ForLoc, RParenLoc));
+ return new (Context) ObjCForCollectionStmt(First, CollectionExprResult.get(),
+ nullptr, ForLoc, RParenLoc);
}
/// Finish building a variable declaration for a for-range statement.
@@ -1809,7 +1881,7 @@ VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc,
static bool ObjCEnumerationCollection(Expr *Collection) {
return !Collection->isTypeDependent()
- && Collection->getType()->getAs<ObjCObjectPointerType>() != 0;
+ && Collection->getType()->getAs<ObjCObjectPointerType>() != nullptr;
}
/// ActOnCXXForRangeStmt - Check and build a C++11 for-range statement.
@@ -1868,7 +1940,7 @@ Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc,
// Claim the type doesn't contain auto: we've already done the checking.
DeclGroupPtrTy RangeGroup =
- BuildDeclaratorGroup(llvm::MutableArrayRef<Decl *>((Decl **)&RangeVar, 1),
+ BuildDeclaratorGroup(MutableArrayRef<Decl *>((Decl **)&RangeVar, 1),
/*TypeMayContainAuto=*/ false);
StmtResult RangeDecl = ActOnDeclStmt(RangeGroup, RangeLoc, RangeLoc);
if (RangeDecl.isInvalid()) {
@@ -1877,8 +1949,8 @@ Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc,
}
return BuildCXXForRangeStmt(ForLoc, ColonLoc, RangeDecl.get(),
- /*BeginEndDecl=*/0, /*Cond=*/0, /*Inc=*/0, DS,
- RParenLoc, Kind);
+ /*BeginEndDecl=*/nullptr, /*Cond=*/nullptr,
+ /*Inc=*/nullptr, DS, RParenLoc, Kind);
}
/// \brief Create the initialization, compare, and increment steps for
@@ -2100,9 +2172,8 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
// Find the array bound.
ExprResult BoundExpr;
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(UnqAT))
- BoundExpr = Owned(IntegerLiteral::Create(Context, CAT->getSize(),
- Context.getPointerDiffType(),
- RangeLoc));
+ BoundExpr = IntegerLiteral::Create(
+ Context, CAT->getSize(), Context.getPointerDiffType(), RangeLoc);
else if (const VariableArrayType *VAT =
dyn_cast<VariableArrayType>(UnqAT))
BoundExpr = VAT->getSizeExpr();
@@ -2123,7 +2194,8 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
return StmtError();
}
} else {
- OverloadCandidateSet CandidateSet(RangeLoc);
+ OverloadCandidateSet CandidateSet(RangeLoc,
+ OverloadCandidateSet::CSK_Normal);
Sema::BeginEndFunction BEFFailure;
ForRangeStatus RangeStatus =
BuildNonArrayForRange(*this, S, BeginRangeRef.get(),
@@ -2185,7 +2257,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
Decl *BeginEndDecls[] = { BeginVar, EndVar };
// Claim the type doesn't contain auto: we've already done the checking.
DeclGroupPtrTy BeginEndGroup =
- BuildDeclaratorGroup(llvm::MutableArrayRef<Decl *>(BeginEndDecls, 2),
+ BuildDeclaratorGroup(MutableArrayRef<Decl *>(BeginEndDecls, 2),
/*TypeMayContainAuto=*/ false);
BeginEndDecl = ActOnDeclStmt(BeginEndGroup, ColonLoc, ColonLoc);
@@ -2258,11 +2330,9 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
if (Kind == BFRK_Check)
return StmtResult();
- return Owned(new (Context) CXXForRangeStmt(RangeDS,
- cast_or_null<DeclStmt>(BeginEndDecl.get()),
- NotEqExpr.take(), IncrExpr.take(),
- LoopVarDS, /*Body=*/0, ForLoc,
- ColonLoc, RParenLoc));
+ return new (Context) CXXForRangeStmt(
+ RangeDS, cast_or_null<DeclStmt>(BeginEndDecl.get()), NotEqExpr.get(),
+ IncrExpr.get(), LoopVarDS, /*Body=*/nullptr, ForLoc, ColonLoc, RParenLoc);
}
/// FinishObjCForCollectionStmt - Attach the body to a objective-C foreach
@@ -2301,7 +2371,7 @@ StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc,
LabelDecl *TheDecl) {
getCurFunction()->setHasBranchIntoScope();
TheDecl->markUsed(Context);
- return Owned(new (Context) GotoStmt(TheDecl, GotoLoc, LabelLoc));
+ return new (Context) GotoStmt(TheDecl, GotoLoc, LabelLoc);
}
StmtResult
@@ -2311,12 +2381,12 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc,
if (!E->isTypeDependent()) {
QualType ETy = E->getType();
QualType DestTy = Context.getPointerType(Context.VoidTy.withConst());
- ExprResult ExprRes = Owned(E);
+ ExprResult ExprRes = E;
AssignConvertType ConvTy =
CheckSingleAssignmentConstraints(DestTy, ExprRes);
if (ExprRes.isInvalid())
return StmtError();
- E = ExprRes.take();
+ E = ExprRes.get();
if (DiagnoseAssignmentResult(ConvTy, StarLoc, DestTy, ETy, E, AA_Passing))
return StmtError();
}
@@ -2324,11 +2394,11 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc,
ExprResult ExprRes = ActOnFinishFullExpr(E);
if (ExprRes.isInvalid())
return StmtError();
- E = ExprRes.take();
+ E = ExprRes.get();
getCurFunction()->setHasIndirectGoto();
- return Owned(new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E));
+ return new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E);
}
StmtResult
@@ -2339,7 +2409,7 @@ Sema::ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope) {
return StmtError(Diag(ContinueLoc, diag::err_continue_not_in_loop));
}
- return Owned(new (Context) ContinueStmt(ContinueLoc));
+ return new (Context) ContinueStmt(ContinueLoc);
}
StmtResult
@@ -2349,8 +2419,11 @@ Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) {
// C99 6.8.6.3p1: A break shall appear only in or as a switch/loop body.
return StmtError(Diag(BreakLoc, diag::err_break_not_in_loop_or_switch));
}
+ if (S->isOpenMPLoopScope())
+ return StmtError(Diag(BreakLoc, diag::err_omp_loop_cannot_use_stmt)
+ << "break");
- return Owned(new (Context) BreakStmt(BreakLoc));
+ return new (Context) BreakStmt(BreakLoc);
}
/// \brief Determine whether the given expression is a candidate for
@@ -2371,52 +2444,62 @@ 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.
-const VarDecl *Sema::getCopyElisionCandidate(QualType ReturnType,
- Expr *E,
- bool AllowFunctionParameter) {
- QualType ExprType = E->getType();
+VarDecl *Sema::getCopyElisionCandidate(QualType ReturnType,
+ Expr *E,
+ bool AllowFunctionParameter) {
+ if (!getLangOpts().CPlusPlus)
+ return nullptr;
+
+ // - 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());
+ if (!DR || DR->refersToEnclosingLocal())
+ return nullptr;
+ VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
+ if (!VD)
+ return nullptr;
+
+ if (isCopyElisionCandidate(ReturnType, VD, AllowFunctionParameter))
+ return VD;
+ return nullptr;
+}
+
+bool Sema::isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD,
+ bool AllowFunctionParameter) {
+ QualType VDType = VD->getType();
// - in a return statement in a function with ...
// ... a class return type ...
- if (!ReturnType.isNull()) {
+ if (!ReturnType.isNull() && !ReturnType->isDependentType()) {
if (!ReturnType->isRecordType())
- return 0;
+ return false;
// ... the same cv-unqualified type as the function return type ...
- if (!Context.hasSameUnqualifiedType(ReturnType, ExprType))
- return 0;
+ if (!VDType->isDependentType() &&
+ !Context.hasSameUnqualifiedType(ReturnType, VDType))
+ return false;
}
- // ... the expression is the name of a non-volatile automatic object
- // (other than a function or catch-clause parameter)) ...
- const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E->IgnoreParens());
- if (!DR || DR->refersToEnclosingLocal())
- return 0;
- const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
- if (!VD)
- return 0;
-
// ...object (other than a function or catch-clause parameter)...
if (VD->getKind() != Decl::Var &&
!(AllowFunctionParameter && VD->getKind() == Decl::ParmVar))
- return 0;
- if (VD->isExceptionVariable()) return 0;
+ return false;
+ if (VD->isExceptionVariable()) return false;
// ...automatic...
- if (!VD->hasLocalStorage()) return 0;
+ if (!VD->hasLocalStorage()) return false;
// ...non-volatile...
- if (VD->getType().isVolatileQualified()) return 0;
- if (VD->getType()->isReferenceType()) return 0;
+ if (VD->getType().isVolatileQualified()) return false;
// __block variables can't be allocated in a way that permits NRVO.
- if (VD->hasAttr<BlocksAttr>()) return 0;
+ if (VD->hasAttr<BlocksAttr>()) return false;
// Variables with higher required alignment than their type's ABI
// alignment cannot use NRVO.
- if (VD->hasAttr<AlignedAttr>() &&
+ if (!VD->getType()->isDependentType() && VD->hasAttr<AlignedAttr>() &&
Context.getDeclAlign(VD) > Context.getTypeAlignInChars(VD->getType()))
- return 0;
+ return false;
- return VD;
+ return true;
}
/// \brief Perform the initialization of a potentially-movable value, which
@@ -2476,7 +2559,7 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
// Promote "AsRvalue" to the heap, since we now need this
// expression node to persist.
Value = ImplicitCastExpr::Create(Context, Value->getType(),
- CK_NoOp, Value, 0, VK_XValue);
+ CK_NoOp, Value, nullptr, VK_XValue);
// Complete type-checking the initialization of the return type
// using the constructor we found.
@@ -2499,7 +2582,7 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
static bool hasDeducedReturnType(FunctionDecl *FD) {
const FunctionProtoType *FPT =
FD->getTypeSourceInfo()->getType()->castAs<FunctionProtoType>();
- return FPT->getResultType()->isUndeducedType();
+ return FPT->getReturnType()->isUndeducedType();
}
/// ActOnCapScopeReturnStmt - Utility routine to type-check return statements
@@ -2518,7 +2601,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// FIXME: Blocks might have a return type of 'auto' explicitly specified.
FunctionDecl *FD = CurLambda->CallOperator;
if (CurCap->ReturnType.isNull())
- CurCap->ReturnType = FD->getResultType();
+ CurCap->ReturnType = FD->getReturnType();
AutoType *AT = CurCap->ReturnType->getContainedAutoType();
assert(AT && "lost auto type from lambda return type");
@@ -2526,7 +2609,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
FD->setInvalidDecl();
return StmtError();
}
- CurCap->ReturnType = FnRetType = FD->getResultType();
+ CurCap->ReturnType = FnRetType = FD->getReturnType();
} else if (CurCap->HasImplicitReturnType) {
// For blocks/lambdas with implicit return types, we check each return
// statement individually, and deduce the common return type when the block
@@ -2536,7 +2619,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
ExprResult Result = DefaultFunctionArrayLvalueConversion(RetValExp);
if (Result.isInvalid())
return StmtError();
- RetValExp = Result.take();
+ RetValExp = Result.get();
if (!CurContext->isDependentContext())
FnRetType = RetValExp->getType();
@@ -2582,7 +2665,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// Otherwise, verify that this result type matches the previous one. We are
// pickier with blocks than for normal functions because we don't have GCC
// compatibility to worry about here.
- const VarDecl *NRVOCandidate = 0;
+ const VarDecl *NRVOCandidate = nullptr;
if (FnRetType->isDependentType()) {
// Delay processing for now. TODO: there are lots of dependent
// types we can conclusively prove aren't void.
@@ -2596,7 +2679,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
Diag(ReturnLoc, diag::ext_return_has_void_expr) << "literal" << 2;
else {
Diag(ReturnLoc, diag::err_return_block_has_expr);
- RetValExp = 0;
+ RetValExp = nullptr;
}
}
} else if (!RetValExp) {
@@ -2613,22 +2696,24 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false);
InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc,
FnRetType,
- NRVOCandidate != 0);
+ NRVOCandidate != nullptr);
ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate,
FnRetType, RetValExp);
if (Res.isInvalid()) {
// FIXME: Cleanup temporaries here, anyway?
return StmtError();
}
- RetValExp = Res.take();
- CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
+ RetValExp = Res.get();
+ CheckReturnValExpr(RetValExp, FnRetType, ReturnLoc);
+ } else {
+ NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false);
}
if (RetValExp) {
ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc);
if (ER.isInvalid())
return StmtError();
- RetValExp = ER.take();
+ RetValExp = ER.get();
}
ReturnStmt *Result = new (Context) ReturnStmt(ReturnLoc, RetValExp,
NRVOCandidate);
@@ -2636,12 +2721,10 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// If we need to check for the named return value optimization,
// or if we need to infer the return type,
// save the return statement in our scope for later processing.
- if (CurCap->HasImplicitReturnType ||
- (getLangOpts().CPlusPlus && FnRetType->isRecordType() &&
- !CurContext->isDependentContext()))
+ if (CurCap->HasImplicitReturnType || NRVOCandidate)
FunctionScopes.back()->Returns.push_back(Result);
- return Owned(Result);
+ return Result;
}
/// Deduce the return type for a function from a returned expression, per
@@ -2651,7 +2734,7 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
Expr *&RetExpr,
AutoType *AT) {
TypeLoc OrigResultType = FD->getTypeSourceInfo()->getTypeLoc().
- IgnoreParens().castAs<FunctionProtoTypeLoc>().getResultLoc();
+ IgnoreParens().castAs<FunctionProtoTypeLoc>().getReturnLoc();
QualType Deduced;
if (RetExpr && isa<InitListExpr>(RetExpr)) {
@@ -2735,7 +2818,24 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
}
StmtResult
-Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
+Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
+ Scope *CurScope) {
+ StmtResult R = BuildReturnStmt(ReturnLoc, RetValExp);
+ if (R.isInvalid()) {
+ return R;
+ }
+
+ if (VarDecl *VD =
+ const_cast<VarDecl*>(cast<ReturnStmt>(R.get())->getNRVOCandidate())) {
+ CurScope->addNRVOCandidate(VD);
+ } else {
+ CurScope->setNoNRVO();
+ }
+
+ return R;
+}
+
+StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// Check for unexpanded parameter packs.
if (RetValExp && DiagnoseUnexpandedParameterPack(RetValExp))
return StmtError();
@@ -2745,13 +2845,21 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
QualType FnRetType;
QualType RelatedRetType;
+ const AttrVec *Attrs = nullptr;
+ bool isObjCMethod = false;
+
if (const FunctionDecl *FD = getCurFunctionDecl()) {
- FnRetType = FD->getResultType();
+ FnRetType = FD->getReturnType();
+ if (FD->hasAttrs())
+ Attrs = &FD->getAttrs();
if (FD->isNoReturn())
Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr)
<< FD->getDeclName();
} else if (ObjCMethodDecl *MD = getCurMethodDecl()) {
- FnRetType = MD->getResultType();
+ FnRetType = MD->getReturnType();
+ isObjCMethod = true;
+ if (MD->hasAttrs())
+ Attrs = &MD->getAttrs();
if (MD->hasRelatedResultType() && MD->getClassInterface()) {
// In the implementation of a method with a related return type, the
// type used to type-check the validity of return statements within the
@@ -2771,14 +2879,14 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
FD->setInvalidDecl();
return StmtError();
} else {
- FnRetType = FD->getResultType();
+ FnRetType = FD->getReturnType();
}
}
}
bool HasDependentReturnType = FnRetType->isDependentType();
- ReturnStmt *Result = 0;
+ ReturnStmt *Result = nullptr;
if (FnRetType->isVoidType()) {
if (RetValExp) {
if (isa<InitListExpr>(RetValExp)) {
@@ -2799,24 +2907,36 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
<< RetValExp->getSourceRange();
// Drop the expression.
- RetValExp = 0;
+ RetValExp = nullptr;
} else if (!RetValExp->isTypeDependent()) {
// C99 6.8.6.4p1 (ext_ since GCC warns)
unsigned D = diag::ext_return_has_expr;
- if (RetValExp->getType()->isVoidType())
- D = diag::ext_return_has_void_expr;
+ if (RetValExp->getType()->isVoidType()) {
+ NamedDecl *CurDecl = getCurFunctionOrMethodDecl();
+ if (isa<CXXConstructorDecl>(CurDecl) ||
+ isa<CXXDestructorDecl>(CurDecl))
+ D = diag::err_ctor_dtor_returns_void;
+ else
+ D = diag::ext_return_has_void_expr;
+ }
else {
- ExprResult Result = Owned(RetValExp);
- Result = IgnoredValueConversions(Result.take());
+ ExprResult Result = RetValExp;
+ Result = IgnoredValueConversions(Result.get());
if (Result.isInvalid())
return StmtError();
- RetValExp = Result.take();
+ RetValExp = Result.get();
RetValExp = ImpCastExprToType(RetValExp,
- Context.VoidTy, CK_ToVoid).take();
+ Context.VoidTy, CK_ToVoid).get();
+ }
+ // return of void in constructor/destructor is illegal in C++.
+ if (D == diag::err_ctor_dtor_returns_void) {
+ NamedDecl *CurDecl = getCurFunctionOrMethodDecl();
+ Diag(ReturnLoc, D)
+ << CurDecl->getDeclName() << isa<CXXDestructorDecl>(CurDecl)
+ << RetValExp->getSourceRange();
}
-
// return (some void expression); is legal in C++.
- if (D != diag::ext_return_has_void_expr ||
+ else if (D != diag::ext_return_has_void_expr ||
!getLangOpts().CPlusPlus) {
NamedDecl *CurDecl = getCurFunctionOrMethodDecl();
@@ -2838,11 +2958,11 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc);
if (ER.isInvalid())
return StmtError();
- RetValExp = ER.take();
+ RetValExp = ER.get();
}
}
- Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, 0);
+ Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, nullptr);
} else if (!RetValExp && !HasDependentReturnType) {
unsigned DiagID = diag::warn_return_missing_expr; // C90 6.6.6.4p4
// C99 6.8.6.4p1 (ext_ since GCC warns)
@@ -2855,29 +2975,30 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
Result = new (Context) ReturnStmt(ReturnLoc);
} else {
assert(RetValExp || HasDependentReturnType);
- const VarDecl *NRVOCandidate = 0;
- if (!HasDependentReturnType && !RetValExp->isTypeDependent()) {
- // we have a non-void function with an expression, continue checking
+ const VarDecl *NRVOCandidate = nullptr;
- QualType RetType = (RelatedRetType.isNull() ? FnRetType : RelatedRetType);
+ QualType RetType = RelatedRetType.isNull() ? FnRetType : RelatedRetType;
- // C99 6.8.6.4p3(136): The return statement is not an assignment. The
- // overlap restriction of subclause 6.5.16.1 does not apply to the case of
- // function return.
+ // C99 6.8.6.4p3(136): The return statement is not an assignment. The
+ // overlap restriction of subclause 6.5.16.1 does not apply to the case of
+ // function return.
- // In C++ the return statement is handled via a copy initialization,
- // the C version of which boils down to CheckSingleAssignmentConstraints.
+ // 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);
+ if (!HasDependentReturnType && !RetValExp->isTypeDependent()) {
+ // we have a non-void function with an expression, continue checking
InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc,
RetType,
- NRVOCandidate != 0);
+ NRVOCandidate != nullptr);
ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate,
RetType, RetValExp);
if (Res.isInvalid()) {
// FIXME: Clean up temporaries here anyway?
return StmtError();
}
- RetValExp = Res.takeAs<Expr>();
+ RetValExp = Res.getAs<Expr>();
// If we have a related result type, we need to implicitly
// convert back to the formal result type. We can't pretend to
@@ -2891,28 +3012,28 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// FIXME: Clean up temporaries here anyway?
return StmtError();
}
- RetValExp = Res.takeAs<Expr>();
+ RetValExp = Res.getAs<Expr>();
}
- CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
+ CheckReturnValExpr(RetValExp, FnRetType, ReturnLoc, isObjCMethod, Attrs,
+ getCurFunctionDecl());
}
if (RetValExp) {
ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc);
if (ER.isInvalid())
return StmtError();
- RetValExp = ER.take();
+ RetValExp = ER.get();
}
Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, NRVOCandidate);
}
// If we need to check for the named return value optimization, save the
// return statement in our scope for later processing.
- if (getLangOpts().CPlusPlus && FnRetType->isRecordType() &&
- !CurContext->isDependentContext())
+ if (Result->getNRVOCandidate())
FunctionScopes.back()->Returns.push_back(Result);
- return Owned(Result);
+ return Result;
}
StmtResult
@@ -2923,12 +3044,12 @@ Sema::ActOnObjCAtCatchStmt(SourceLocation AtLoc,
if (Var && Var->isInvalidDecl())
return StmtError();
- return Owned(new (Context) ObjCAtCatchStmt(AtLoc, RParen, Var, Body));
+ return new (Context) ObjCAtCatchStmt(AtLoc, RParen, Var, Body);
}
StmtResult
Sema::ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body) {
- return Owned(new (Context) ObjCAtFinallyStmt(AtLoc, Body));
+ return new (Context) ObjCAtFinallyStmt(AtLoc, Body);
}
StmtResult
@@ -2939,10 +3060,8 @@ Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try,
getCurFunction()->setHasBranchProtectedScope();
unsigned NumCatchStmts = CatchStmts.size();
- return Owned(ObjCAtTryStmt::Create(Context, AtLoc, Try,
- CatchStmts.data(),
- NumCatchStmts,
- Finally));
+ return ObjCAtTryStmt::Create(Context, AtLoc, Try, CatchStmts.data(),
+ NumCatchStmts, Finally);
}
StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) {
@@ -2951,10 +3070,10 @@ StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) {
if (Result.isInvalid())
return StmtError();
- Result = ActOnFinishFullExpr(Result.take());
+ Result = ActOnFinishFullExpr(Result.get());
if (Result.isInvalid())
return StmtError();
- Throw = Result.take();
+ Throw = Result.get();
QualType ThrowType = Throw->getType();
// Make sure the expression type is an ObjC pointer or "void *".
@@ -2967,7 +3086,7 @@ StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) {
}
}
- return Owned(new (Context) ObjCAtThrowStmt(AtLoc, Throw));
+ return new (Context) ObjCAtThrowStmt(AtLoc, Throw);
}
StmtResult
@@ -2993,7 +3112,7 @@ Sema::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, Expr *operand) {
ExprResult result = DefaultLvalueConversion(operand);
if (result.isInvalid())
return ExprError();
- operand = result.take();
+ operand = result.get();
// Make sure the expression type is an ObjC pointer or "void *".
QualType type = operand->getType();
@@ -3014,7 +3133,7 @@ Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *SyncExpr,
Stmt *SyncBody) {
// We can't jump into or indirect-jump out of a @synchronized block.
getCurFunction()->setHasBranchProtectedScope();
- return Owned(new (Context) ObjCAtSynchronizedStmt(AtLoc, SyncExpr, SyncBody));
+ return new (Context) ObjCAtSynchronizedStmt(AtLoc, SyncExpr, SyncBody);
}
/// ActOnCXXCatchBlock - Takes an exception declaration and a handler block
@@ -3023,15 +3142,14 @@ StmtResult
Sema::ActOnCXXCatchBlock(SourceLocation CatchLoc, Decl *ExDecl,
Stmt *HandlerBlock) {
// There's nothing to test that ActOnExceptionDecl didn't already test.
- return Owned(new (Context) CXXCatchStmt(CatchLoc,
- cast_or_null<VarDecl>(ExDecl),
- HandlerBlock));
+ return new (Context)
+ CXXCatchStmt(CatchLoc, cast_or_null<VarDecl>(ExDecl), HandlerBlock);
}
StmtResult
Sema::ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body) {
getCurFunction()->setHasBranchProtectedScope();
- return Owned(new (Context) ObjCAutoreleasePoolStmt(AtLoc, Body));
+ return new (Context) ObjCAutoreleasePoolStmt(AtLoc, Body);
}
namespace {
@@ -3075,6 +3193,9 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
!getSourceManager().isInSystemHeader(TryLoc))
Diag(TryLoc, diag::err_exceptions_disabled) << "try";
+ if (getCurScope() && getCurScope()->isOpenMPSimdDirectiveScope())
+ Diag(TryLoc, diag::err_omp_simd_region_cannot_use_stmt) << "try";
+
const unsigned NumHandlers = Handlers.size();
assert(NumHandlers > 0 &&
"The parser shouldn't call this if there are no handlers.");
@@ -3125,19 +3246,18 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
// Neither of these are explicitly forbidden, but every compiler detects them
// and warns.
- return Owned(CXXTryStmt::Create(Context, TryLoc, TryBlock, Handlers));
+ return CXXTryStmt::Create(Context, TryLoc, TryBlock, Handlers);
}
-StmtResult
-Sema::ActOnSEHTryBlock(bool IsCXXTry,
- SourceLocation TryLoc,
- Stmt *TryBlock,
- Stmt *Handler) {
+StmtResult Sema::ActOnSEHTryBlock(bool IsCXXTry, SourceLocation TryLoc,
+ Stmt *TryBlock, Stmt *Handler,
+ int HandlerIndex, int HandlerParentIndex) {
assert(TryBlock && Handler);
getCurFunction()->setHasBranchProtectedScope();
- return Owned(SEHTryStmt::Create(Context,IsCXXTry,TryLoc,TryBlock,Handler));
+ return SEHTryStmt::Create(Context, IsCXXTry, TryLoc, TryBlock, Handler,
+ HandlerIndex, HandlerParentIndex);
}
StmtResult
@@ -3152,14 +3272,25 @@ Sema::ActOnSEHExceptBlock(SourceLocation Loc,
<< FilterExpr->getType());
}
- return Owned(SEHExceptStmt::Create(Context,Loc,FilterExpr,Block));
+ return SEHExceptStmt::Create(Context,Loc,FilterExpr,Block);
}
StmtResult
Sema::ActOnSEHFinallyBlock(SourceLocation Loc,
Stmt *Block) {
assert(Block);
- return Owned(SEHFinallyStmt::Create(Context,Loc,Block));
+ return SEHFinallyStmt::Create(Context,Loc,Block);
+}
+
+StmtResult
+Sema::ActOnSEHLeaveStmt(SourceLocation Loc, Scope *CurScope) {
+ Scope *SEHTryParent = CurScope;
+ while (SEHTryParent && !SEHTryParent->isSEHTryScope())
+ SEHTryParent = SEHTryParent->getParent();
+ if (!SEHTryParent)
+ return StmtError(Diag(Loc, diag::err_ms___leave_not_in___try));
+
+ return new (Context) SEHLeaveStmt(Loc);
}
StmtResult Sema::BuildMSDependentExistsStmt(SourceLocation KeywordLoc,
@@ -3192,30 +3323,20 @@ Sema::CreateCapturedStmtRecordDecl(CapturedDecl *&CD, SourceLocation Loc,
while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext()))
DC = DC->getParent();
- RecordDecl *RD = 0;
+ RecordDecl *RD = nullptr;
if (getLangOpts().CPlusPlus)
- RD = CXXRecordDecl::Create(Context, TTK_Struct, DC, Loc, Loc, /*Id=*/0);
+ RD = CXXRecordDecl::Create(Context, TTK_Struct, DC, Loc, Loc,
+ /*Id=*/nullptr);
else
- RD = RecordDecl::Create(Context, TTK_Struct, DC, Loc, Loc, /*Id=*/0);
+ RD = RecordDecl::Create(Context, TTK_Struct, DC, Loc, Loc, /*Id=*/nullptr);
DC->addDecl(RD);
RD->setImplicit();
RD->startDefinition();
+ assert(NumParams > 0 && "CapturedStmt requires context parameter");
CD = CapturedDecl::Create(Context, CurContext, NumParams);
DC->addDecl(CD);
-
- // Build the context parameter
- assert(NumParams > 0 && "CapturedStmt requires context parameter");
- DC = CapturedDecl::castToDeclContext(CD);
- IdentifierInfo *VarName = &Context.Idents.get("__context");
- QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD));
- ImplicitParamDecl *Param
- = ImplicitParamDecl::Create(Context, DC, Loc, VarName, ParamType);
- DC->addDecl(Param);
-
- CD->setContextParam(Param);
-
return RD;
}
@@ -3247,9 +3368,71 @@ static void buildCapturedStmtCaptureList(
void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
CapturedRegionKind Kind,
unsigned NumParams) {
- CapturedDecl *CD = 0;
+ CapturedDecl *CD = nullptr;
RecordDecl *RD = CreateCapturedStmtRecordDecl(CD, Loc, NumParams);
+ // Build the context parameter
+ DeclContext *DC = CapturedDecl::castToDeclContext(CD);
+ IdentifierInfo *ParamName = &Context.Idents.get("__context");
+ QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD));
+ ImplicitParamDecl *Param
+ = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType);
+ DC->addDecl(Param);
+
+ CD->setContextParam(0, Param);
+
+ // Enter the capturing scope for this captured region.
+ PushCapturedRegionScope(CurScope, CD, RD, Kind);
+
+ if (CurScope)
+ PushDeclContext(CurScope, CD);
+ else
+ CurContext = CD;
+
+ PushExpressionEvaluationContext(PotentiallyEvaluated);
+}
+
+void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
+ CapturedRegionKind Kind,
+ ArrayRef<CapturedParamNameType> Params) {
+ CapturedDecl *CD = nullptr;
+ RecordDecl *RD = CreateCapturedStmtRecordDecl(CD, Loc, Params.size());
+
+ // Build the context parameter
+ DeclContext *DC = CapturedDecl::castToDeclContext(CD);
+ bool ContextIsFound = false;
+ unsigned ParamNum = 0;
+ for (ArrayRef<CapturedParamNameType>::iterator I = Params.begin(),
+ E = Params.end();
+ I != E; ++I, ++ParamNum) {
+ if (I->second.isNull()) {
+ assert(!ContextIsFound &&
+ "null type has been found already for '__context' parameter");
+ IdentifierInfo *ParamName = &Context.Idents.get("__context");
+ QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD));
+ ImplicitParamDecl *Param
+ = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType);
+ DC->addDecl(Param);
+ CD->setContextParam(ParamNum, Param);
+ ContextIsFound = true;
+ } else {
+ IdentifierInfo *ParamName = &Context.Idents.get(I->first);
+ ImplicitParamDecl *Param
+ = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, I->second);
+ DC->addDecl(Param);
+ CD->setParam(ParamNum, Param);
+ }
+ }
+ assert(ContextIsFound && "no null type for '__context' parameter");
+ if (!ContextIsFound) {
+ // Add __context implicitly if it is not specified.
+ IdentifierInfo *ParamName = &Context.Idents.get("__context");
+ QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD));
+ ImplicitParamDecl *Param =
+ ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType);
+ DC->addDecl(Param);
+ CD->setContextParam(ParamNum, Param);
+ }
// Enter the capturing scope for this captured region.
PushCapturedRegionScope(CurScope, CD, RD, Kind);
@@ -3269,12 +3452,9 @@ void Sema::ActOnCapturedRegionError() {
RecordDecl *Record = RSI->TheRecordDecl;
Record->setInvalidDecl();
- SmallVector<Decl*, 4> Fields;
- for (RecordDecl::field_iterator I = Record->field_begin(),
- E = Record->field_end(); I != E; ++I)
- Fields.push_back(*I);
- ActOnFields(/*Scope=*/0, Record->getLocation(), Record, Fields,
- SourceLocation(), SourceLocation(), /*AttributeList=*/0);
+ SmallVector<Decl*, 4> Fields(Record->fields());
+ ActOnFields(/*Scope=*/nullptr, Record->getLocation(), Record, Fields,
+ SourceLocation(), SourceLocation(), /*AttributeList=*/nullptr);
PopDeclContext();
PopFunctionScopeInfo();
@@ -3303,5 +3483,5 @@ StmtResult Sema::ActOnCapturedRegionEnd(Stmt *S) {
PopDeclContext();
PopFunctionScopeInfo();
- return Owned(Res);
+ return Res;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
index 9169032..5d076ca 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
@@ -15,13 +15,13 @@
#include "clang/AST/RecordLayout.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
+#include "llvm/MC/MCParser/MCAsmParser.h"
using namespace clang;
using namespace sema;
@@ -152,6 +152,12 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
diag::err_asm_invalid_lvalue_in_input)
<< Info.getConstraintStr()
<< InputExpr->getSourceRange());
+ } else {
+ ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
+ if (Result.isInvalid())
+ return StmtError();
+
+ Exprs[i] = Result.get();
}
if (Info.allowsRegister()) {
@@ -163,11 +169,6 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
}
}
- ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
- if (Result.isInvalid())
- return StmtError();
-
- Exprs[i] = Result.take();
InputConstraintInfos.push_back(Info);
const Type *Ty = Exprs[i]->getType().getTypePtr();
@@ -352,7 +353,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
InputExpr->isEvaluatable(Context)) {
CastKind castKind =
(OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast);
- InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).take();
+ InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).get();
Exprs[InputOpNo] = InputExpr;
NS->setInputExpr(i, InputExpr);
continue;
@@ -365,13 +366,13 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
return StmtError();
}
- return Owned(NS);
+ return NS;
}
ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
UnqualifiedId &Id,
- InlineAsmIdentifierInfo &Info,
+ llvm::InlineAsmIdentifierInfo &Info,
bool IsUnevaluatedContext) {
Info.clear();
@@ -382,7 +383,7 @@ ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
ExprResult Result = ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Id,
/*trailing lparen*/ false,
/*is & operand*/ false,
- /*CorrectionCandidateCallback=*/0,
+ /*CorrectionCandidateCallback=*/nullptr,
/*IsInlineAsmIdentifier=*/ true);
if (IsUnevaluatedContext)
@@ -390,7 +391,7 @@ ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
if (!Result.isUsable()) return Result;
- Result = CheckPlaceholderExpr(Result.take());
+ Result = CheckPlaceholderExpr(Result.get());
if (!Result.isUsable()) return Result;
QualType T = Result.get()->getType();
@@ -438,12 +439,14 @@ bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member,
if (!BaseResult.isSingleResult())
return true;
- const RecordType *RT = 0;
+ const RecordType *RT = nullptr;
NamedDecl *FoundDecl = BaseResult.getFoundDecl();
if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl))
RT = VD->getType()->getAs<RecordType>();
- else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(FoundDecl))
+ else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(FoundDecl))
RT = TD->getUnderlyingType()->getAs<RecordType>();
+ else if (TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl))
+ RT = TD->getTypeForDecl()->getAs<RecordType>();
if (!RT)
return true;
@@ -483,5 +486,5 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
/*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs,
Constraints, Exprs, AsmString,
Clobbers, EndLoc);
- return Owned(NS);
+ return NS;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp
index eb0188a..a32e0fb 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp
@@ -12,12 +12,11 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "TargetAttributesSema.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Lex/Lexer.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Lookup.h"
+#include "clang/Sema/LoopHint.h"
#include "clang/Sema/ScopeInfo.h"
#include "llvm/ADT/StringExtras.h"
@@ -30,20 +29,164 @@ static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const AttributeList &A,
S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_wrong_target)
<< St->getLocStart();
if (isa<SwitchCase>(St)) {
- SourceLocation L = Lexer::getLocForEndOfToken(Range.getEnd(), 0,
- S.getSourceManager(), S.getLangOpts());
+ SourceLocation L = S.getLocForEndOfToken(Range.getEnd());
S.Diag(L, diag::note_fallthrough_insert_semi_fixit)
<< FixItHint::CreateInsertion(L, ";");
}
- return 0;
+ return nullptr;
}
if (S.getCurFunction()->SwitchStack.empty()) {
S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_outside_switch);
- return 0;
+ return nullptr;
}
- return ::new (S.Context) FallThroughAttr(A.getRange(), S.Context);
+ return ::new (S.Context) FallThroughAttr(A.getRange(), S.Context,
+ A.getAttributeSpellingListIndex());
}
+static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
+ SourceRange) {
+ IdentifierLoc *PragmaNameLoc = A.getArgAsIdent(0);
+ IdentifierLoc *OptionLoc = A.getArgAsIdent(1);
+ IdentifierInfo *OptionInfo = OptionLoc->Ident;
+ IdentifierLoc *ValueLoc = A.getArgAsIdent(2);
+ IdentifierInfo *ValueInfo = ValueLoc ? ValueLoc->Ident : nullptr;
+ Expr *ValueExpr = A.getArgAsExpr(3);
+
+ assert(OptionInfo && "Attribute must have valid option info.");
+
+ if (St->getStmtClass() != Stmt::DoStmtClass &&
+ St->getStmtClass() != Stmt::ForStmtClass &&
+ St->getStmtClass() != Stmt::CXXForRangeStmtClass &&
+ St->getStmtClass() != Stmt::WhileStmtClass) {
+ const char *Pragma = PragmaNameLoc->Ident->getName() == "unroll"
+ ? "#pragma unroll"
+ : "#pragma clang loop";
+ S.Diag(St->getLocStart(), diag::err_pragma_loop_precedes_nonloop) << Pragma;
+ return nullptr;
+ }
+
+ LoopHintAttr::OptionType Option;
+ LoopHintAttr::Spelling Spelling;
+ if (PragmaNameLoc->Ident->getName() == "unroll") {
+ Option = ValueLoc ? LoopHintAttr::UnrollCount : LoopHintAttr::Unroll;
+ Spelling = LoopHintAttr::Pragma_unroll;
+ } else {
+ Option = llvm::StringSwitch<LoopHintAttr::OptionType>(OptionInfo->getName())
+ .Case("vectorize", LoopHintAttr::Vectorize)
+ .Case("vectorize_width", LoopHintAttr::VectorizeWidth)
+ .Case("interleave", LoopHintAttr::Interleave)
+ .Case("interleave_count", LoopHintAttr::InterleaveCount)
+ .Case("unroll", LoopHintAttr::Unroll)
+ .Case("unroll_count", LoopHintAttr::UnrollCount)
+ .Default(LoopHintAttr::Vectorize);
+ Spelling = LoopHintAttr::Pragma_clang_loop;
+ }
+
+ int ValueInt;
+ if (Option == LoopHintAttr::Unroll &&
+ Spelling == LoopHintAttr::Pragma_unroll) {
+ ValueInt = 1;
+ } else if (Option == LoopHintAttr::Vectorize ||
+ Option == LoopHintAttr::Interleave ||
+ Option == LoopHintAttr::Unroll) {
+ if (!ValueInfo) {
+ S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_keyword);
+ return nullptr;
+ }
+ if (ValueInfo->isStr("disable"))
+ ValueInt = 0;
+ else if (ValueInfo->isStr("enable"))
+ ValueInt = 1;
+ else {
+ S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_keyword);
+ return nullptr;
+ }
+ } else if (Option == LoopHintAttr::VectorizeWidth ||
+ Option == LoopHintAttr::InterleaveCount ||
+ Option == LoopHintAttr::UnrollCount) {
+ // FIXME: We should support template parameters for the loop hint value.
+ // See bug report #19610.
+ llvm::APSInt ValueAPS;
+ if (!ValueExpr || !ValueExpr->isIntegerConstantExpr(ValueAPS, S.Context) ||
+ (ValueInt = ValueAPS.getSExtValue()) < 1) {
+ S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_value);
+ return nullptr;
+ }
+ } else
+ llvm_unreachable("Unknown loop hint option");
+
+ return LoopHintAttr::CreateImplicit(S.Context, Spelling, Option, ValueInt,
+ A.getRange());
+}
+
+static void CheckForIncompatibleAttributes(
+ Sema &S, const SmallVectorImpl<const Attr *> &Attrs) {
+ // There are 3 categories of loop hints: vectorize, interleave, and
+ // unroll. Each comes in two variants: an enable/disable form and a
+ // form which takes a numeric argument. For example:
+ // unroll(enable|disable) and unroll_count(N). The following array
+ // accumulate the hints encountered while iterating through the
+ // attributes to check for compatibility.
+ struct {
+ const LoopHintAttr *EnableAttr;
+ const LoopHintAttr *NumericAttr;
+ } HintAttrs[] = {{nullptr, nullptr}, {nullptr, nullptr}, {nullptr, nullptr}};
+
+ for (const auto *I : Attrs) {
+ const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(I);
+
+ // Skip non loop hint attributes
+ if (!LH)
+ continue;
+
+ int Option = LH->getOption();
+ int Category;
+ switch (Option) {
+ case LoopHintAttr::Vectorize:
+ case LoopHintAttr::VectorizeWidth:
+ Category = 0;
+ break;
+ case LoopHintAttr::Interleave:
+ case LoopHintAttr::InterleaveCount:
+ Category = 1;
+ break;
+ case LoopHintAttr::Unroll:
+ case LoopHintAttr::UnrollCount:
+ Category = 2;
+ break;
+ };
+
+ auto &CategoryState = HintAttrs[Category];
+ SourceLocation OptionLoc = LH->getRange().getBegin();
+ const LoopHintAttr *PrevAttr;
+ if (Option == LoopHintAttr::Vectorize ||
+ Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll) {
+ // Enable|disable hint. For example, vectorize(enable).
+ PrevAttr = CategoryState.EnableAttr;
+ CategoryState.EnableAttr = LH;
+ } else {
+ // Numeric hint. For example, vectorize_width(8).
+ PrevAttr = CategoryState.NumericAttr;
+ CategoryState.NumericAttr = LH;
+ }
+
+ if (PrevAttr)
+ // Cannot specify same type of attribute twice.
+ S.Diag(OptionLoc, diag::err_pragma_loop_compatibility)
+ << /*Duplicate=*/true << PrevAttr->getDiagnosticName()
+ << LH->getDiagnosticName();
+
+ if (CategoryState.EnableAttr && !CategoryState.EnableAttr->getValue() &&
+ CategoryState.NumericAttr) {
+ // Disable hints are not compatible with numeric hints of the
+ // same category.
+ S.Diag(OptionLoc, diag::err_pragma_loop_compatibility)
+ << /*Duplicate=*/false
+ << CategoryState.EnableAttr->getDiagnosticName()
+ << CategoryState.NumericAttr->getDiagnosticName();
+ }
+ }
+}
static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A,
SourceRange Range) {
@@ -52,15 +195,17 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A,
S.Diag(A.getLoc(), A.isDeclspecAttribute() ?
diag::warn_unhandled_ms_attribute_ignored :
diag::warn_unknown_attribute_ignored) << A.getName();
- return 0;
+ return nullptr;
case AttributeList::AT_FallThrough:
return handleFallThroughAttr(S, St, A, Range);
+ case AttributeList::AT_LoopHint:
+ return handleLoopHintAttr(S, St, A, Range);
default:
// if we're here, then we parsed a known attribute, but didn't recognize
// it as a statement attribute => it is declaration attribute
S.Diag(A.getRange().getBegin(), diag::err_attribute_invalid_on_stmt)
<< A.getName() << St->getLocStart();
- return 0;
+ return nullptr;
}
}
@@ -72,6 +217,8 @@ StmtResult Sema::ProcessStmtAttributes(Stmt *S, AttributeList *AttrList,
Attrs.push_back(a);
}
+ CheckForIncompatibleAttributes(*this, Attrs);
+
if (Attrs.empty())
return S;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
index 28603da..63581a4 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
@@ -10,8 +10,8 @@
//===----------------------------------------------------------------------===/
#include "TreeTransform.h"
-#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
@@ -20,6 +20,7 @@
#include "clang/AST/TypeVisitor.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ParsedTemplate.h"
@@ -51,8 +52,8 @@ static NamedDecl *isAcceptableTemplateName(ASTContext &Context,
if (isa<TemplateDecl>(D)) {
if (!AllowFunctionTemplates && isa<FunctionTemplateDecl>(D))
- return 0;
-
+ return nullptr;
+
return Orig;
}
@@ -78,10 +79,10 @@ static NamedDecl *isAcceptableTemplateName(ASTContext &Context,
return Spec->getSpecializedTemplate();
}
- return 0;
+ return nullptr;
}
- return 0;
+ return nullptr;
}
void Sema::FilterAcceptableTemplateNames(LookupResult &R,
@@ -193,8 +194,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
TemplateDecl *TD = cast<TemplateDecl>((*R.begin())->getUnderlyingDecl());
if (SS.isSet() && !SS.isInvalid()) {
- NestedNameSpecifier *Qualifier
- = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ NestedNameSpecifier *Qualifier = SS.getScopeRep();
Template = Context.getQualifiedTemplateName(Qualifier,
hasTemplateKeyword, TD);
} else {
@@ -250,7 +250,7 @@ void Sema::LookupTemplateName(LookupResult &Found,
bool &MemberOfUnknownSpecialization) {
// Determine where to perform name lookup
MemberOfUnknownSpecialization = false;
- DeclContext *LookupCtx = 0;
+ DeclContext *LookupCtx = nullptr;
bool isDependent = false;
if (!ObjectType.isNull()) {
// This nested-name-specifier occurs in a member access expression, e.g.,
@@ -325,7 +325,8 @@ void Sema::LookupTemplateName(LookupResult &Found,
FilterCCC.WantCXXNamedCasts = true;
if (TypoCorrection Corrected = CorrectTypo(Found.getLookupNameInfo(),
Found.getLookupKind(), S, &SS,
- FilterCCC, LookupCtx)) {
+ FilterCCC, CTK_ErrorRecovery,
+ LookupCtx)) {
Found.setLookupName(Corrected.getCorrection());
if (Corrected.getCorrectionDecl())
Found.addDecl(Corrected.getCorrectionDecl());
@@ -418,17 +419,12 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS,
// Since the 'this' expression is synthesized, we don't need to
// perform the double-lookup check.
- NamedDecl *FirstQualifierInScope = 0;
+ NamedDecl *FirstQualifierInScope = nullptr;
- return Owned(CXXDependentScopeMemberExpr::Create(Context,
- /*This*/ 0, ThisType,
- /*IsArrow*/ true,
- /*Op*/ SourceLocation(),
- SS.getWithLocInContext(Context),
- TemplateKWLoc,
- FirstQualifierInScope,
- NameInfo,
- TemplateArgs));
+ return CXXDependentScopeMemberExpr::Create(
+ Context, /*This*/ nullptr, ThisType, /*IsArrow*/ true,
+ /*Op*/ SourceLocation(), SS.getWithLocInContext(Context), TemplateKWLoc,
+ FirstQualifierInScope, NameInfo, TemplateArgs);
}
return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs);
@@ -439,11 +435,9 @@ Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
- return Owned(DependentScopeDeclRefExpr::Create(Context,
- SS.getWithLocInContext(Context),
- TemplateKWLoc,
- NameInfo,
- TemplateArgs));
+ return DependentScopeDeclRefExpr::Create(
+ Context, SS.getWithLocInContext(Context), TemplateKWLoc, NameInfo,
+ TemplateArgs);
}
/// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining
@@ -474,7 +468,7 @@ TemplateDecl *Sema::AdjustDeclIfTemplate(Decl *&D) {
D = Temp->getTemplatedDecl();
return Temp;
}
- return 0;
+ return nullptr;
}
ParsedTemplateArgument ParsedTemplateArgument::getTemplatePackExpansion(
@@ -550,7 +544,7 @@ static void maybeDiagnoseTemplateParameterShadow(Sema &SemaRef, Scope *S,
/// ParamNameLoc is the location of the parameter name (if any).
/// If the type parameter has a default argument, it will be added
/// later via ActOnTypeParameterDefault.
-Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
+Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename,
SourceLocation EllipsisLoc,
SourceLocation KeyLoc,
IdentifierInfo *ParamName,
@@ -566,10 +560,11 @@ Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
if (!ParamName)
Loc = KeyLoc;
+ bool IsParameterPack = EllipsisLoc.isValid();
TemplateTypeParmDecl *Param
= TemplateTypeParmDecl::Create(Context, Context.getTranslationUnitDecl(),
KeyLoc, Loc, Depth, Position, ParamName,
- Typename, Ellipsis);
+ Typename, IsParameterPack);
Param->setAccess(AS_public);
if (Invalid)
Param->setInvalidDecl();
@@ -585,7 +580,7 @@ Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
// C++0x [temp.param]p9:
// A default template-argument may be specified for any kind of
// template-parameter that is not a template parameter pack.
- if (DefaultArg && Ellipsis) {
+ if (DefaultArg && IsParameterPack) {
Diag(EqualLoc, diag::err_template_param_pack_default_arg);
DefaultArg = ParsedType();
}
@@ -715,7 +710,7 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
// template-parameter that is not a template parameter pack.
if (Default && IsParameterPack) {
Diag(EqualLoc, diag::err_template_param_pack_default_arg);
- Default = 0;
+ Default = nullptr;
}
// Check the well-formedness of the default template argument, if provided.
@@ -730,7 +725,7 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
Param->setInvalidDecl();
return Param;
}
- Default = DefaultRes.take();
+ Default = DefaultRes.get();
Param->setDefaultArgument(Default, false);
}
@@ -843,6 +838,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
AttributeList *Attr,
TemplateParameterList *TemplateParams,
AccessSpecifier AS, SourceLocation ModulePrivateLoc,
+ SourceLocation FriendLoc,
unsigned NumOuterTemplateParamLists,
TemplateParameterList** OuterTemplateParamLists) {
assert(TemplateParams && TemplateParams->size() > 0 &&
@@ -906,7 +902,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
if (Previous.isAmbiguous())
return true;
- NamedDecl *PrevDecl = 0;
+ NamedDecl *PrevDecl = nullptr;
if (Previous.begin() != Previous.end())
PrevDecl = (*Previous.begin())->getUnderlyingDecl();
@@ -949,7 +945,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// Declarations in outer scopes don't matter. However, the outermost
// context we computed is the semantic context for our new
// declaration.
- PrevDecl = PrevClassTemplate = 0;
+ PrevDecl = PrevClassTemplate = nullptr;
SemanticContext = OutermostContext;
// Check that the chosen semantic context doesn't already contain a
@@ -968,8 +964,9 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
PrevDecl = (*Previous.begin())->getUnderlyingDecl();
}
}
- } else if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S))
- PrevDecl = PrevClassTemplate = 0;
+ } else if (PrevDecl &&
+ !isDeclInScope(PrevDecl, SemanticContext, S, SS.isValid()))
+ PrevDecl = PrevClassTemplate = nullptr;
if (PrevClassTemplate) {
// Ensure that the template parameter lists are compatible. Skip this check
@@ -1011,7 +1008,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(NameLoc, PrevDecl);
// Just pretend that we didn't see the previous declaration.
- PrevDecl = 0;
+ PrevDecl = nullptr;
} else if (PrevDecl) {
// C++ [temp]p5:
// A class template shall not have the same name as any other
@@ -1030,7 +1027,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
if (!(TUK == TUK_Friend && CurContext->isDependentContext()) &&
CheckTemplateParameterList(
TemplateParams,
- PrevClassTemplate ? PrevClassTemplate->getTemplateParameters() : 0,
+ PrevClassTemplate ? PrevClassTemplate->getTemplateParameters()
+ : nullptr,
(SS.isSet() && SemanticContext && SemanticContext->isRecord() &&
SemanticContext->isDependentContext())
? TPC_ClassTemplateMember
@@ -1052,7 +1050,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
CXXRecordDecl *NewClass =
CXXRecordDecl::Create(Context, Kind, SemanticContext, KWLoc, NameLoc, Name,
PrevClassTemplate?
- PrevClassTemplate->getTemplatedDecl() : 0,
+ PrevClassTemplate->getTemplatedDecl() : nullptr,
/*DelayTypeCreation=*/true);
SetNestedNameSpecifier(NewClass, SS);
if (NumOuterTemplateParamLists > 0)
@@ -1126,10 +1124,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
/* AddToContext = */ false);
}
- FriendDecl *Friend = FriendDecl::Create(Context, CurContext,
- NewClass->getLocation(),
- NewTemplate,
- /*FIXME:*/NewClass->getLocation());
+ FriendDecl *Friend = FriendDecl::Create(
+ Context, CurContext, NewClass->getLocation(), NewTemplate, FriendLoc);
Friend->setAccess(AS_public);
CurContext->addDecl(Friend);
}
@@ -1299,7 +1295,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
// Merge default arguments for template type parameters.
TemplateTypeParmDecl *OldTypeParm
- = OldParams? cast<TemplateTypeParmDecl>(*OldParam) : 0;
+ = OldParams? cast<TemplateTypeParmDecl>(*OldParam) : nullptr;
if (NewTypeParm->isParameterPack()) {
assert(!NewTypeParm->hasDefaultArgument() &&
@@ -1344,7 +1340,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
// Merge default arguments for non-type template parameters
NonTypeTemplateParmDecl *OldNonTypeParm
- = OldParams? cast<NonTypeTemplateParmDecl>(*OldParam) : 0;
+ = OldParams? cast<NonTypeTemplateParmDecl>(*OldParam) : nullptr;
if (NewNonTypeParm->isParameterPack()) {
assert(!NewNonTypeParm->hasDefaultArgument() &&
"Parameter packs can't have a default argument!");
@@ -1391,7 +1387,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
// Merge default arguments for template template parameters
TemplateTemplateParmDecl *OldTemplateParm
- = OldParams? cast<TemplateTemplateParmDecl>(*OldParam) : 0;
+ = OldParams? cast<TemplateTemplateParmDecl>(*OldParam) : nullptr;
if (NewTemplateParm->isParameterPack()) {
assert(!NewTemplateParm->hasDefaultArgument() &&
"Parameter packs can't have a default argument!");
@@ -1487,6 +1483,9 @@ struct DependencyChecker : RecursiveASTVisitor<DependencyChecker> {
unsigned Depth;
bool Match;
+ SourceLocation MatchLoc;
+
+ DependencyChecker(unsigned Depth) : Depth(Depth), Match(false) {}
DependencyChecker(TemplateParameterList *Params) : Match(false) {
NamedDecl *ND = Params->getParam(0);
@@ -1500,14 +1499,19 @@ struct DependencyChecker : RecursiveASTVisitor<DependencyChecker> {
}
}
- bool Matches(unsigned ParmDepth) {
+ bool Matches(unsigned ParmDepth, SourceLocation Loc = SourceLocation()) {
if (ParmDepth >= Depth) {
Match = true;
+ MatchLoc = Loc;
return true;
}
return false;
}
+ bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
+ return !Matches(TL.getTypePtr()->getDepth(), TL.getNameLoc());
+ }
+
bool VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
return !Matches(T->getDepth());
}
@@ -1515,21 +1519,28 @@ struct DependencyChecker : RecursiveASTVisitor<DependencyChecker> {
bool TraverseTemplateName(TemplateName N) {
if (TemplateTemplateParmDecl *PD =
dyn_cast_or_null<TemplateTemplateParmDecl>(N.getAsTemplateDecl()))
- if (Matches(PD->getDepth())) return false;
+ if (Matches(PD->getDepth()))
+ return false;
return super::TraverseTemplateName(N);
}
bool VisitDeclRefExpr(DeclRefExpr *E) {
if (NonTypeTemplateParmDecl *PD =
- dyn_cast<NonTypeTemplateParmDecl>(E->getDecl())) {
- if (PD->getDepth() == Depth) {
- Match = true;
+ dyn_cast<NonTypeTemplateParmDecl>(E->getDecl()))
+ if (Matches(PD->getDepth(), E->getExprLoc()))
return false;
- }
- }
return super::VisitDeclRefExpr(E);
}
-
+
+ bool VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
+ return TraverseType(T->getReplacementType());
+ }
+
+ bool
+ VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) {
+ return TraverseTemplateArgument(T->getArgumentPack());
+ }
+
bool TraverseInjectedClassNameType(const InjectedClassNameType *T) {
return TraverseType(T->getInjectedSpecializationType());
}
@@ -1577,6 +1588,9 @@ static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context,
/// parameter lists. This scope specifier precedes a qualified name that is
/// being declared.
///
+/// \param TemplateId The template-id following the scope specifier, if there
+/// is one. Used to check for a missing 'template<>'.
+///
/// \param ParamLists the template parameter lists, from the outermost to the
/// innermost template parameter lists.
///
@@ -1595,6 +1609,7 @@ static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context,
/// itself a template).
TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
SourceLocation DeclStartLoc, SourceLocation DeclLoc, const CXXScopeSpec &SS,
+ TemplateIdAnnotation *TemplateId,
ArrayRef<TemplateParameterList *> ParamLists, bool IsFriend,
bool &IsExplicitSpecialization, bool &Invalid) {
IsExplicitSpecialization = false;
@@ -1701,6 +1716,37 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
// template<> for each enclosing class template that is
// explicitly specialized.
bool SawNonEmptyTemplateParameterList = false;
+
+ auto CheckExplicitSpecialization = [&](SourceRange Range, bool Recovery) {
+ if (SawNonEmptyTemplateParameterList) {
+ Diag(DeclLoc, diag::err_specialize_member_of_template)
+ << !Recovery << Range;
+ Invalid = true;
+ IsExplicitSpecialization = false;
+ return true;
+ }
+
+ return false;
+ };
+
+ auto DiagnoseMissingExplicitSpecialization = [&] (SourceRange Range) {
+ // Check that we can have an explicit specialization here.
+ if (CheckExplicitSpecialization(Range, true))
+ return true;
+
+ // We don't have a template header, but we should.
+ SourceLocation ExpectedTemplateLoc;
+ if (!ParamLists.empty())
+ ExpectedTemplateLoc = ParamLists[0]->getTemplateLoc();
+ else
+ ExpectedTemplateLoc = DeclStartLoc;
+
+ Diag(DeclLoc, diag::err_template_spec_needs_header)
+ << Range
+ << FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> ");
+ return false;
+ };
+
unsigned ParamIdx = 0;
for (unsigned TypeIdx = 0, NumTypes = NestedTypes.size(); TypeIdx != NumTypes;
++TypeIdx) {
@@ -1714,7 +1760,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
// For a dependent type, the set of template parameters that we
// expect to see.
- TemplateParameterList *ExpectedTemplateParams = 0;
+ TemplateParameterList *ExpectedTemplateParams = nullptr;
// C++0x [temp.expl.spec]p15:
// A member or a member template may be nested within many enclosing
@@ -1771,13 +1817,9 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
// are not explicitly specialized as well.
if (ParamIdx < ParamLists.size()) {
if (ParamLists[ParamIdx]->size() == 0) {
- if (SawNonEmptyTemplateParameterList) {
- Diag(DeclLoc, diag::err_specialize_member_of_template)
- << ParamLists[ParamIdx]->getSourceRange();
- Invalid = true;
- IsExplicitSpecialization = false;
- return 0;
- }
+ if (CheckExplicitSpecialization(ParamLists[ParamIdx]->getSourceRange(),
+ false))
+ return nullptr;
} else
SawNonEmptyTemplateParameterList = true;
}
@@ -1798,30 +1840,22 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
ParamLists[ParamIdx]->getRAngleLoc())
<< getRangeOfTypeInNestedNameSpecifier(Context, T, SS);
Invalid = true;
- return 0;
+ return nullptr;
}
-
+
// Consume this template header.
++ParamIdx;
continue;
- }
-
- if (!IsFriend) {
- // We don't have a template header, but we should.
- SourceLocation ExpectedTemplateLoc;
- if (!ParamLists.empty())
- ExpectedTemplateLoc = ParamLists[0]->getTemplateLoc();
- else
- ExpectedTemplateLoc = DeclStartLoc;
-
- Diag(DeclLoc, diag::err_template_spec_needs_header)
- << getRangeOfTypeInNestedNameSpecifier(Context, T, SS)
- << FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> ");
}
-
+
+ if (!IsFriend)
+ if (DiagnoseMissingExplicitSpecialization(
+ getRangeOfTypeInNestedNameSpecifier(Context, T, SS)))
+ return nullptr;
+
continue;
}
-
+
if (NeedNonemptyTemplateHeader) {
// In friend declarations we can have template-ids which don't
// depend on the corresponding template parameter lists. But
@@ -1830,7 +1864,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
if (IsFriend && T->isDependentType()) {
if (ParamIdx < ParamLists.size() &&
DependsOnTemplateParameters(T, ParamLists[ParamIdx]))
- ExpectedTemplateParams = 0;
+ ExpectedTemplateParams = nullptr;
else
continue;
}
@@ -1842,9 +1876,9 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
ExpectedTemplateParams,
true, TPL_TemplateMatch))
Invalid = true;
-
+
if (!Invalid &&
- CheckTemplateParameterList(ParamLists[ParamIdx], 0,
+ CheckTemplateParameterList(ParamLists[ParamIdx], nullptr,
TPC_ClassTemplateMember))
Invalid = true;
@@ -1859,12 +1893,26 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
continue;
}
}
-
+
// If there were at least as many template-ids as there were template
// parameter lists, then there are no template parameter lists remaining for
// the declaration itself.
- if (ParamIdx >= ParamLists.size())
- return 0;
+ if (ParamIdx >= ParamLists.size()) {
+ if (TemplateId && !IsFriend) {
+ // We don't have a template header for the declaration itself, but we
+ // should.
+ IsExplicitSpecialization = true;
+ DiagnoseMissingExplicitSpecialization(SourceRange(TemplateId->LAngleLoc,
+ TemplateId->RAngleLoc));
+
+ // Fabricate an empty template parameter list for the invented header.
+ return TemplateParameterList::Create(Context, SourceLocation(),
+ SourceLocation(), nullptr, 0,
+ SourceLocation());
+ }
+
+ return nullptr;
+ }
// If there were too many template parameter lists, complain about that now.
if (ParamIdx < ParamLists.size() - 1) {
@@ -1905,14 +1953,11 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
// unspecialized, except that the declaration shall not explicitly
// specialize a class member template if its en- closing class templates
// are not explicitly specialized as well.
- if (ParamLists.back()->size() == 0 && SawNonEmptyTemplateParameterList) {
- Diag(DeclLoc, diag::err_specialize_member_of_template)
- << ParamLists[ParamIdx]->getSourceRange();
- Invalid = true;
- IsExplicitSpecialization = false;
- return 0;
- }
-
+ if (ParamLists.back()->size() == 0 &&
+ CheckExplicitSpecialization(ParamLists[ParamIdx]->getSourceRange(),
+ false))
+ return nullptr;
+
// Return the last template parameter list, which corresponds to the
// entity being declared.
return ParamLists.back();
@@ -1959,7 +2004,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
TemplateArgs);
TemplateDecl *Template = Name.getAsTemplateDecl();
- if (!Template || isa<FunctionTemplateDecl>(Template)) {
+ if (!Template || isa<FunctionTemplateDecl>(Template) ||
+ isa<VarTemplateDecl>(Template)) {
// We might have a substituted template template parameter pack. If so,
// build a template specialization type for it.
if (Name.getAsSubstTemplateTemplateParmPack())
@@ -1974,17 +2020,15 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
// Check that the template argument list is well-formed for this
// template.
SmallVector<TemplateArgument, 4> Converted;
- bool ExpansionIntoFixedList = false;
if (CheckTemplateArgumentList(Template, TemplateLoc, TemplateArgs,
- false, Converted, &ExpansionIntoFixedList))
+ false, Converted))
return QualType();
QualType CanonType;
bool InstantiationDependent = false;
- TypeAliasTemplateDecl *AliasTemplate = 0;
- if (!ExpansionIntoFixedList &&
- (AliasTemplate = dyn_cast<TypeAliasTemplateDecl>(Template))) {
+ if (TypeAliasTemplateDecl *AliasTemplate =
+ dyn_cast<TypeAliasTemplateDecl>(Template)) {
// Find the canonical type for this type alias template specialization.
TypeAliasDecl *Pattern = AliasTemplate->getTemplatedDecl();
if (Pattern->isInvalidDecl())
@@ -2072,10 +2116,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
= dyn_cast<ClassTemplateDecl>(Template)) {
// Find the class template specialization declaration that
// corresponds to these arguments.
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
ClassTemplateSpecializationDecl *Decl
- = ClassTemplate->findSpecialization(Converted.data(), Converted.size(),
- InsertPos);
+ = ClassTemplate->findSpecialization(Converted, InsertPos);
if (!Decl) {
// This is the first time we have referenced this class template
// specialization. Create the canonical declaration and add it to
@@ -2087,7 +2130,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
ClassTemplate->getLocation(),
ClassTemplate,
Converted.data(),
- Converted.size(), 0);
+ Converted.size(), nullptr);
ClassTemplate->AddSpecialization(Decl, InsertPos);
if (ClassTemplate->isOutOfLine())
Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext());
@@ -2267,8 +2310,8 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
}
static bool CheckTemplatePartialSpecializationArgs(
- Sema &S, TemplateParameterList *TemplateParams,
- SmallVectorImpl<TemplateArgument> &TemplateArgs);
+ Sema &S, SourceLocation NameLoc, TemplateParameterList *TemplateParams,
+ unsigned ExplicitArgs, SmallVectorImpl<TemplateArgument> &TemplateArgs);
static bool CheckTemplateSpecializationScope(Sema &S, NamedDecl *Specialized,
NamedDecl *PrevDecl,
@@ -2340,25 +2383,49 @@ static bool isSameAsPrimaryTemplate(TemplateParameterList *Params,
return true;
}
-DeclResult Sema::ActOnVarTemplateSpecialization(
- Scope *S, VarTemplateDecl *VarTemplate, Declarator &D, TypeSourceInfo *DI,
- SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
- VarDecl::StorageClass SC, bool IsPartialSpecialization) {
- assert(VarTemplate && "A variable template id without template?");
+/// Convert the parser's template argument list representation into our form.
+static TemplateArgumentListInfo
+makeTemplateArgumentListInfo(Sema &S, TemplateIdAnnotation &TemplateId) {
+ TemplateArgumentListInfo TemplateArgs(TemplateId.LAngleLoc,
+ TemplateId.RAngleLoc);
+ ASTTemplateArgsPtr TemplateArgsPtr(TemplateId.getTemplateArgs(),
+ TemplateId.NumArgs);
+ S.translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
+ return TemplateArgs;
+}
+DeclResult Sema::ActOnVarTemplateSpecialization(
+ Scope *S, Declarator &D, TypeSourceInfo *DI, SourceLocation TemplateKWLoc,
+ TemplateParameterList *TemplateParams, VarDecl::StorageClass SC,
+ bool IsPartialSpecialization) {
// D must be variable template id.
assert(D.getName().getKind() == UnqualifiedId::IK_TemplateId &&
"Variable template specialization is declared with a template it.");
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
+ TemplateArgumentListInfo TemplateArgs =
+ makeTemplateArgumentListInfo(*this, *TemplateId);
SourceLocation TemplateNameLoc = D.getIdentifierLoc();
SourceLocation LAngleLoc = TemplateId->LAngleLoc;
SourceLocation RAngleLoc = TemplateId->RAngleLoc;
- ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
- TemplateId->NumArgs);
- TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
- translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
- TemplateName Name(VarTemplate);
+
+ TemplateName Name = TemplateId->Template.get();
+
+ // The template-id must name a variable template.
+ VarTemplateDecl *VarTemplate =
+ dyn_cast_or_null<VarTemplateDecl>(Name.getAsTemplateDecl());
+ if (!VarTemplate) {
+ NamedDecl *FnTemplate;
+ if (auto *OTS = Name.getAsOverloadedTemplate())
+ FnTemplate = *OTS->begin();
+ else
+ FnTemplate = dyn_cast_or_null<FunctionTemplateDecl>(Name.getAsTemplateDecl());
+ if (FnTemplate)
+ return Diag(D.getIdentifierLoc(), diag::err_var_spec_no_template_but_method)
+ << FnTemplate->getDeclName();
+ return Diag(D.getIdentifierLoc(), diag::err_var_spec_no_template)
+ << IsPartialSpecialization;
+ }
// Check for unexpanded parameter packs in any of the template arguments.
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
@@ -2396,7 +2463,8 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
// corresponds to these arguments.
if (IsPartialSpecialization) {
if (CheckTemplatePartialSpecializationArgs(
- *this, VarTemplate->getTemplateParameters(), Converted))
+ *this, TemplateNameLoc, VarTemplate->getTemplateParameters(),
+ TemplateArgs.size(), Converted))
return true;
bool InstantiationDependent;
@@ -2425,18 +2493,16 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
}
}
- void *InsertPos = 0;
- VarTemplateSpecializationDecl *PrevDecl = 0;
+ void *InsertPos = nullptr;
+ VarTemplateSpecializationDecl *PrevDecl = nullptr;
if (IsPartialSpecialization)
// FIXME: Template parameter list matters too
- PrevDecl = VarTemplate->findPartialSpecialization(
- Converted.data(), Converted.size(), InsertPos);
+ PrevDecl = VarTemplate->findPartialSpecialization(Converted, InsertPos);
else
- PrevDecl = VarTemplate->findSpecialization(Converted.data(),
- Converted.size(), InsertPos);
+ PrevDecl = VarTemplate->findSpecialization(Converted, InsertPos);
- VarTemplateSpecializationDecl *Specialization = 0;
+ VarTemplateSpecializationDecl *Specialization = nullptr;
// Check whether we can declare a variable template specialization in
// the current scope.
@@ -2452,7 +2518,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
// the list of outer template parameters to reflect our new declaration.
Specialization = PrevDecl;
Specialization->setLocation(TemplateNameLoc);
- PrevDecl = 0;
+ PrevDecl = nullptr;
} else if (IsPartialSpecialization) {
// Create a new class template partial specialization declaration node.
VarTemplatePartialSpecializationDecl *PrevPartial =
@@ -2494,7 +2560,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
<< Param->getDeclName();
else
Diag(Param->getLocation(), diag::note_partial_spec_unused_parameter)
- << "<anonymous>";
+ << "(anonymous)";
}
}
}
@@ -2589,18 +2655,17 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
// Check that the template argument list is well-formed for this template.
SmallVector<TemplateArgument, 4> Converted;
- bool ExpansionIntoFixedList = false;
if (CheckTemplateArgumentList(
Template, TemplateNameLoc,
const_cast<TemplateArgumentListInfo &>(TemplateArgs), false,
- Converted, &ExpansionIntoFixedList))
+ Converted))
return true;
// Find the variable template specialization declaration that
// corresponds to these arguments.
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (VarTemplateSpecializationDecl *Spec = Template->findSpecialization(
- Converted.data(), Converted.size(), InsertPos))
+ Converted, InsertPos))
// If we already have a variable template specialization, return it.
return Spec;
@@ -2652,11 +2717,6 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
}
}
- // 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.
- SmallVector<const NamedDecl *, 4> InstantiatedTemplateParameters;
-
if (Matched.size() >= 1) {
SmallVector<MatchResult, 4>::iterator Best = Matched.begin();
if (Matched.size() == 1) {
@@ -2756,7 +2816,7 @@ Sema::CheckVarTemplateId(const CXXScopeSpec &SS,
// Build an ordinary singleton decl ref.
return BuildDeclarationNameExpr(SS, NameInfo, Var,
- /*FoundD=*/0, TemplateArgs);
+ /*FoundD=*/nullptr, TemplateArgs);
}
ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
@@ -2779,10 +2839,13 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
assert(!R.isAmbiguous() && "ambiguous lookup when building templateid");
// In C++1y, check variable template ids.
- if (R.getAsSingle<VarTemplateDecl>()) {
- return Owned(CheckVarTemplateId(SS, R.getLookupNameInfo(),
- R.getAsSingle<VarTemplateDecl>(),
- TemplateKWLoc, TemplateArgs));
+ bool InstantiationDependent;
+ if (R.getAsSingle<VarTemplateDecl>() &&
+ !TemplateSpecializationType::anyDependentTemplateArguments(
+ *TemplateArgs, InstantiationDependent)) {
+ return CheckVarTemplateId(SS, R.getLookupNameInfo(),
+ R.getAsSingle<VarTemplateDecl>(),
+ TemplateKWLoc, TemplateArgs);
}
// We don't want lookup warnings at this point.
@@ -2796,7 +2859,7 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
RequiresADL, TemplateArgs,
R.begin(), R.end());
- return Owned(ULE);
+ return ULE;
}
// We actually only call this from template instantiation.
@@ -2815,7 +2878,7 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
bool MemberOfUnknownSpecialization;
LookupResult R(*this, NameInfo, LookupOrdinaryName);
- LookupTemplateName(R, (Scope*) 0, SS, QualType(), /*Entering*/ false,
+ LookupTemplateName(R, (Scope*)nullptr, SS, QualType(), /*Entering*/ false,
MemberOfUnknownSpecialization);
if (R.isAmbiguous())
@@ -2829,8 +2892,8 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
if (ClassTemplateDecl *Temp = R.getAsSingle<ClassTemplateDecl>()) {
Diag(NameInfo.getLoc(), diag::err_template_kw_refers_to_class_template)
- << (NestedNameSpecifier*) SS.getScopeRep()
- << NameInfo.getName() << SS.getRange();
+ << SS.getScopeRep()
+ << NameInfo.getName().getAsString() << SS.getRange();
Diag(Temp->getLocation(), diag::note_referenced_class_template);
return ExprError();
}
@@ -2859,7 +2922,7 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
diag::ext_template_outside_of_template)
<< FixItHint::CreateRemoval(TemplateKWLoc);
- DeclContext *LookupCtx = 0;
+ DeclContext *LookupCtx = nullptr;
if (SS.isSet())
LookupCtx = computeDeclContext(SS, EnteringContext);
if (!LookupCtx && ObjectType)
@@ -2903,8 +2966,7 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
}
}
- NestedNameSpecifier *Qualifier
- = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ NestedNameSpecifier *Qualifier = SS.getScopeRep();
switch (Name.getKind()) {
case UnqualifiedId::IK_Identifier:
@@ -2915,11 +2977,10 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
case UnqualifiedId::IK_OperatorFunctionId:
Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier,
Name.OperatorFunctionId.Operator));
- return TNK_Dependent_template_name;
+ return TNK_Function_template;
case UnqualifiedId::IK_LiteralOperatorId:
- llvm_unreachable(
- "We don't support these; Parse shouldn't have allowed propagation");
+ llvm_unreachable("literal operator id cannot have a dependent scope");
default:
break;
@@ -2934,9 +2995,11 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
}
bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
- const TemplateArgumentLoc &AL,
+ TemplateArgumentLoc &AL,
SmallVectorImpl<TemplateArgument> &Converted) {
const TemplateArgument &Arg = AL.getArgument();
+ QualType ArgType;
+ TypeSourceInfo *TSI = nullptr;
// Check template type parameter.
switch(Arg.getKind()) {
@@ -2944,6 +3007,8 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
// C++ [temp.arg.type]p1:
// A template-argument for a template-parameter which is a
// type shall be a type-id.
+ ArgType = Arg.getAsType();
+ TSI = AL.getTypeSourceInfo();
break;
case TemplateArgument::Template: {
// We have a template type parameter but the template argument
@@ -2978,18 +3043,38 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
}
}
- if (NameInfo.getName().isIdentifier()) {
+ if (auto *II = NameInfo.getName().getAsIdentifierInfo()) {
LookupResult Result(*this, NameInfo, LookupOrdinaryName);
LookupParsedName(Result, CurScope, &SS);
if (Result.getAsSingle<TypeDecl>() ||
Result.getResultKind() ==
- LookupResult::NotFoundInCurrentInstantiation) {
- // FIXME: Add a FixIt and fix up the template argument for recovery.
+ LookupResult::NotFoundInCurrentInstantiation) {
+ // Suggest that the user add 'typename' before the NNS.
SourceLocation Loc = AL.getSourceRange().getBegin();
- Diag(Loc, diag::err_template_arg_must_be_type_suggest);
+ Diag(Loc, getLangOpts().MSVCCompat
+ ? diag::ext_ms_template_type_arg_missing_typename
+ : diag::err_template_arg_must_be_type_suggest)
+ << FixItHint::CreateInsertion(Loc, "typename ");
Diag(Param->getLocation(), diag::note_template_param_here);
- return true;
+
+ // Recover by synthesizing a type using the location information that we
+ // already have.
+ ArgType =
+ Context.getDependentNameType(ETK_Typename, SS.getScopeRep(), II);
+ TypeLocBuilder TLB;
+ DependentNameTypeLoc TL = TLB.push<DependentNameTypeLoc>(ArgType);
+ TL.setElaboratedKeywordLoc(SourceLocation(/*synthesized*/));
+ TL.setQualifierLoc(SS.getWithLocInContext(Context));
+ TL.setNameLoc(NameInfo.getLoc());
+ TSI = TLB.getTypeSourceInfo(Context, ArgType);
+
+ // Overwrite our input TemplateArgumentLoc so that we can recover
+ // properly.
+ AL = TemplateArgumentLoc(TemplateArgument(ArgType),
+ TemplateArgumentLocInfo(TSI));
+
+ break;
}
}
// fallthrough
@@ -3005,11 +3090,11 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
}
}
- if (CheckTemplateArgument(Param, AL.getTypeSourceInfo()))
+ if (CheckTemplateArgument(Param, TSI))
return true;
// Add the converted template type argument.
- QualType ArgType = Context.getCanonicalType(Arg.getAsType());
+ ArgType = Context.getCanonicalType(ArgType);
// Objective-C ARC:
// If an explicitly-specified template argument type is a lifetime type
@@ -3063,7 +3148,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
Template, Converted,
SourceRange(TemplateLoc, RAngleLoc));
if (Inst.isInvalid())
- return 0;
+ return nullptr;
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
Converted.data(), Converted.size());
@@ -3239,7 +3324,7 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
if (Arg.isInvalid())
return TemplateArgumentLoc();
- Expr *ArgE = Arg.takeAs<Expr>();
+ Expr *ArgE = Arg.getAs<Expr>();
return TemplateArgumentLoc(TemplateArgument(ArgE), ArgE);
}
@@ -3291,7 +3376,7 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
///
/// \returns true on error, false otherwise.
bool Sema::CheckTemplateArgument(NamedDecl *Param,
- const TemplateArgumentLoc &Arg,
+ TemplateArgumentLoc &Arg,
NamedDecl *Template,
SourceLocation TemplateLoc,
SourceLocation RAngleLoc,
@@ -3381,21 +3466,20 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
// so it was provided with a template keyword. However, its source
// location is not stored in the template argument structure.
SourceLocation TemplateKWLoc;
- ExprResult E = Owned(DependentScopeDeclRefExpr::Create(Context,
- SS.getWithLocInContext(Context),
- TemplateKWLoc,
- NameInfo, 0));
+ ExprResult E = DependentScopeDeclRefExpr::Create(
+ Context, SS.getWithLocInContext(Context), TemplateKWLoc, NameInfo,
+ nullptr);
// If we parsed the template argument as a pack expansion, create a
// pack expansion expression.
if (Arg.getArgument().getKind() == TemplateArgument::TemplateExpansion){
- E = ActOnPackExpansion(E.take(), Arg.getTemplateEllipsisLoc());
+ E = ActOnPackExpansion(E.get(), Arg.getTemplateEllipsisLoc());
if (E.isInvalid())
return true;
}
TemplateArgument Result;
- E = CheckTemplateArgument(NTTP, NTTPType, E.take(), Result);
+ E = CheckTemplateArgument(NTTP, NTTPType, E.get(), Result);
if (E.isInvalid())
return true;
@@ -3555,11 +3639,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
SourceLocation TemplateLoc,
TemplateArgumentListInfo &TemplateArgs,
bool PartialTemplateArgs,
- SmallVectorImpl<TemplateArgument> &Converted,
- bool *ExpansionIntoFixedList) {
- if (ExpansionIntoFixedList)
- *ExpansionIntoFixedList = false;
-
+ SmallVectorImpl<TemplateArgument> &Converted) {
TemplateParameterList *Params = Template->getTemplateParameters();
SourceLocation RAngleLoc = TemplateArgs.getRAngleLoc();
@@ -3612,6 +3692,20 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
ArgumentPack.size(), Converted))
return true;
+ if (TemplateArgs[ArgIdx].getArgument().isPackExpansion() &&
+ isa<TypeAliasTemplateDecl>(Template) &&
+ !(Param + 1 == ParamEnd && (*Param)->isTemplateParameterPack() &&
+ !getExpandedPackSize(*Param))) {
+ // Core issue 1430: we have a pack expansion as an argument to an
+ // alias template, and it's not part of a final parameter pack. This
+ // can't be canonicalized, so reject it now.
+ Diag(TemplateArgs[ArgIdx].getLocation(),
+ diag::err_alias_template_expansion_into_fixed_list)
+ << TemplateArgs[ArgIdx].getSourceRange();
+ Diag((*Param)->getLocation(), diag::note_template_param_here);
+ return true;
+ }
+
// We're now done with this argument.
++ArgIdx;
@@ -3658,9 +3752,6 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
ArgumentPack.data(),
ArgumentPack.size()));
ArgumentPack.clear();
- } else if (ExpansionIntoFixedList) {
- // We have expanded a pack into a fixed list.
- *ExpansionIntoFixedList = true;
}
return false;
@@ -3738,7 +3829,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
if (E.isInvalid())
return true;
- Expr *Ex = E.takeAs<Expr>();
+ Expr *Ex = E.getAs<Expr>();
Arg = TemplateArgumentLoc(TemplateArgument(Ex), Ex);
} else {
TemplateTemplateParmDecl *TempParm
@@ -3785,6 +3876,17 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
++ArgIdx;
}
+ // If we're performing a partial argument substitution, allow any trailing
+ // pack expansions; they might be empty. This can happen even if
+ // PartialTemplateArgs is false (the list of arguments is complete but
+ // still dependent).
+ if (ArgIdx < NumArgs && CurrentInstantiationScope &&
+ CurrentInstantiationScope->getPartiallySubstitutedPack()) {
+ while (ArgIdx < NumArgs &&
+ TemplateArgs[ArgIdx].getArgument().isPackExpansion())
+ Converted.push_back(TemplateArgs[ArgIdx++].getArgument());
+ }
+
// If we have any leftover arguments, then there were too many arguments.
// Complain and fail.
if (ArgIdx < NumArgs)
@@ -3889,19 +3991,17 @@ bool UnnamedLocalNoLinkageFinder::VisitExtVectorType(const ExtVectorType* T) {
bool UnnamedLocalNoLinkageFinder::VisitFunctionProtoType(
const FunctionProtoType* T) {
- for (FunctionProtoType::arg_type_iterator A = T->arg_type_begin(),
- AEnd = T->arg_type_end();
- A != AEnd; ++A) {
- if (Visit(*A))
+ for (const auto &A : T->param_types()) {
+ if (Visit(A))
return true;
}
- return Visit(T->getResultType());
+ return Visit(T->getReturnType());
}
bool UnnamedLocalNoLinkageFinder::VisitFunctionNoProtoType(
const FunctionNoProtoType* T) {
- return Visit(T->getResultType());
+ return Visit(T->getReturnType());
}
bool UnnamedLocalNoLinkageFinder::VisitUnresolvedUsingType(
@@ -4057,12 +4157,17 @@ bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param,
//
// C++11 allows these, and even in C++03 we allow them as an extension with
// a warning.
- if (LangOpts.CPlusPlus11 ?
- Diags.getDiagnosticLevel(diag::warn_cxx98_compat_template_arg_unnamed_type,
- SR.getBegin()) != DiagnosticsEngine::Ignored ||
- Diags.getDiagnosticLevel(diag::warn_cxx98_compat_template_arg_local_type,
- SR.getBegin()) != DiagnosticsEngine::Ignored :
- Arg->hasUnnamedOrLocalType()) {
+ bool NeedsCheck;
+ if (LangOpts.CPlusPlus11)
+ NeedsCheck =
+ !Diags.isIgnored(diag::warn_cxx98_compat_template_arg_unnamed_type,
+ SR.getBegin()) ||
+ !Diags.isIgnored(diag::warn_cxx98_compat_template_arg_local_type,
+ SR.getBegin());
+ else
+ NeedsCheck = Arg->hasUnnamedOrLocalType();
+
+ if (NeedsCheck) {
UnnamedLocalNoLinkageFinder Finder(*this, SR);
(void)Finder.Visit(Context.getCanonicalType(Arg));
}
@@ -4091,7 +4196,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param,
ExprResult ArgRV = S.DefaultFunctionArrayConversion(Arg);
if (ArgRV.isInvalid())
return NPV_Error;
- Arg = ArgRV.take();
+ Arg = ArgRV.get();
Expr::EvalResult EvalResult;
SmallVector<PartialDiagnosticAt, 8> Notes;
@@ -4149,10 +4254,9 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param,
if (Arg->isNullPointerConstant(S.Context, Expr::NPC_NeverValueDependent)) {
std::string Code = "static_cast<" + ParamType.getAsString() + ">(";
S.Diag(Arg->getExprLoc(), diag::err_template_arg_untyped_null_constant)
- << ParamType
- << FixItHint::CreateInsertion(Arg->getLocStart(), Code)
- << FixItHint::CreateInsertion(S.PP.getLocForEndOfToken(Arg->getLocEnd()),
- ")");
+ << ParamType << FixItHint::CreateInsertion(Arg->getLocStart(), Code)
+ << FixItHint::CreateInsertion(S.getLocForEndOfToken(Arg->getLocEnd()),
+ ")");
S.Diag(Param->getLocation(), diag::note_template_param_here);
return NPV_NullPointer;
}
@@ -4232,22 +4336,6 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
Expr *Arg = ArgIn;
QualType ArgType = Arg->getType();
- // If our parameter has pointer type, check for a null template value.
- if (ParamType->isPointerType() || ParamType->isNullPtrType()) {
- switch (isNullPointerValueTemplateArgument(S, Param, ParamType, Arg)) {
- case NPV_NullPointer:
- S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
- Converted = TemplateArgument(ParamType, /*isNullPtr*/true);
- return false;
-
- case NPV_Error:
- return true;
-
- case NPV_NotNullPointer:
- break;
- }
- }
-
bool AddressTaken = false;
SourceLocation AddrOpLoc;
if (S.getLangOpts().MicrosoftExt) {
@@ -4335,6 +4423,33 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
Arg = subst->getReplacement()->IgnoreImpCasts();
}
+ DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg);
+ ValueDecl *Entity = DRE ? DRE->getDecl() : nullptr;
+
+ // If our parameter has pointer type, check for a null template value.
+ if (ParamType->isPointerType() || ParamType->isNullPtrType()) {
+ NullPointerValueKind NPV;
+ // dllimport'd entities aren't constant but are available inside of template
+ // arguments.
+ if (Entity && Entity->hasAttr<DLLImportAttr>())
+ NPV = NPV_NotNullPointer;
+ else
+ NPV = isNullPointerValueTemplateArgument(S, Param, ParamType, ArgIn);
+ switch (NPV) {
+ case NPV_NullPointer:
+ S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
+ Converted = TemplateArgument(S.Context.getCanonicalType(ParamType),
+ /*isNullPtr=*/true);
+ return false;
+
+ case NPV_Error:
+ return true;
+
+ case NPV_NotNullPointer:
+ break;
+ }
+ }
+
// Stop checking the precise nature of the argument if it is value dependent,
// it should be checked when instantiated.
if (Arg->isValueDependent()) {
@@ -4351,7 +4466,6 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
return false;
}
- DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg);
if (!DRE) {
S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref)
<< Arg->getSourceRange();
@@ -4359,8 +4473,6 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
return true;
}
- ValueDecl *Entity = DRE->getDecl();
-
// Cannot refer to non-static data members
if (isa<FieldDecl>(Entity) || isa<IndirectFieldDecl>(Entity)) {
S.Diag(Arg->getLocStart(), diag::err_template_arg_field)
@@ -4522,7 +4634,10 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
return true;
case NPV_NullPointer:
S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
- Converted = TemplateArgument(ParamType, /*isNullPtr*/true);
+ Converted = TemplateArgument(S.Context.getCanonicalType(ParamType),
+ /*isNullPtr*/true);
+ if (S.Context.getTargetInfo().getCXXABI().isMicrosoft())
+ S.RequireCompleteType(Arg->getExprLoc(), ParamType, 0);
return false;
case NPV_NotNullPointer:
break;
@@ -4533,7 +4648,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
ParamType.getNonReferenceType(),
false, ObjCLifetimeConversion)) {
Arg = S.ImpCastExprToType(Arg, ParamType, CK_NoOp,
- Arg->getValueKind()).take();
+ Arg->getValueKind()).get();
ResultArg = Arg;
} else if (!S.Context.hasSameUnqualifiedType(Arg->getType(),
ParamType.getNonReferenceType())) {
@@ -4554,7 +4669,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
// template-parameter shall be one of: [...]
//
// -- a pointer to member expressed as described in 5.3.1.
- DeclRefExpr *DRE = 0;
+ DeclRefExpr *DRE = nullptr;
// In C++98/03 mode, give an extension warning on any extra parentheses.
// See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#773
@@ -4581,7 +4696,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
if (UnOp->getOpcode() == UO_AddrOf) {
DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr());
if (DRE && !DRE->getQualifier())
- DRE = 0;
+ DRE = nullptr;
}
}
// A constant of pointer-to-member type.
@@ -4600,7 +4715,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
}
}
- DRE = 0;
+ DRE = nullptr;
}
if (!DRE)
@@ -4654,7 +4769,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (InstantiatedParamType->isDependentType() || Arg->isTypeDependent()) {
// FIXME: Produce a cloned, canonical expression?
Converted = TemplateArgument(Arg);
- return Owned(Arg);
+ return Arg;
}
// C++ [temp.arg.nontype]p5:
@@ -4698,7 +4813,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// we should be able to diagnose that prior to instantiation.
if (Arg->isValueDependent()) {
Converted = TemplateArgument(Arg);
- return Owned(Arg);
+ return Arg;
}
// C++ [temp.arg.nontype]p1:
@@ -4731,7 +4846,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
ExprResult ArgResult = DefaultLvalueConversion(Arg);
if (ArgResult.isInvalid())
return ExprError();
- Arg = ArgResult.take();
+ Arg = ArgResult.get();
QualType ArgType = Arg->getType();
@@ -4756,15 +4871,15 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
public:
TmplArgICEDiagnoser(QualType T) : T(T) { }
-
- virtual void diagnoseNotICE(Sema &S, SourceLocation Loc,
- SourceRange SR) {
+
+ void diagnoseNotICE(Sema &S, SourceLocation Loc,
+ SourceRange SR) override {
S.Diag(Loc, diag::err_template_arg_not_ice) << T << SR;
}
} Diagnoser(ArgType);
Arg = VerifyIntegerConstantExpression(Arg, &Value, Diagnoser,
- false).take();
+ false).get();
if (!Arg)
return ExprError();
}
@@ -4779,11 +4894,11 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// Okay: no conversion necessary
} else if (ParamType->isBooleanType()) {
// This is an integral-to-boolean conversion.
- Arg = ImpCastExprToType(Arg, ParamType, CK_IntegralToBoolean).take();
+ Arg = ImpCastExprToType(Arg, ParamType, CK_IntegralToBoolean).get();
} else if (IsIntegralPromotion(Arg, ArgType, ParamType) ||
!ParamType->isEnumeralType()) {
// This is an integral promotion or conversion.
- Arg = ImpCastExprToType(Arg, ParamType, CK_IntegralCast).take();
+ Arg = ImpCastExprToType(Arg, ParamType, CK_IntegralCast).get();
} else {
// We can't perform this conversion.
Diag(Arg->getLocStart(),
@@ -4800,7 +4915,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// The argument is value-dependent. Create a new
// TemplateArgument with the converted expression.
Converted = TemplateArgument(Arg);
- return Owned(Arg);
+ return Arg;
}
QualType IntegerType = Context.getCanonicalType(ParamType);
@@ -4854,7 +4969,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
ParamType->isEnumeralType()
? Context.getCanonicalType(ParamType)
: IntegerType);
- return Owned(Arg);
+ return Arg;
}
QualType ArgType = Arg->getType();
@@ -4902,13 +5017,13 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
ParamType,
Arg, Converted))
return ExprError();
- return Owned(Arg);
+ return Arg;
}
if (CheckTemplateArgumentPointerToMember(*this, Param, ParamType, Arg,
Converted))
return ExprError();
- return Owned(Arg);
+ return Arg;
}
if (ParamType->isPointerType()) {
@@ -4923,7 +5038,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
ParamType,
Arg, Converted))
return ExprError();
- return Owned(Arg);
+ return Arg;
}
if (const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>()) {
@@ -4954,14 +5069,14 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
ParamType,
Arg, Converted))
return ExprError();
- return Owned(Arg);
+ return Arg;
}
// Deal with parameters of type std::nullptr_t.
if (ParamType->isNullPtrType()) {
if (Arg->isTypeDependent() || Arg->isValueDependent()) {
Converted = TemplateArgument(Arg);
- return Owned(Arg);
+ return Arg;
}
switch (isNullPointerValueTemplateArgument(*this, Param, ParamType, Arg)) {
@@ -4976,8 +5091,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
case NPV_NullPointer:
Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
- Converted = TemplateArgument(ParamType, /*isNullPtr*/true);
- return Owned(Arg);
+ Converted = TemplateArgument(Context.getCanonicalType(ParamType),
+ /*isNullPtr*/true);
+ return Arg;
}
}
@@ -4988,7 +5104,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (CheckTemplateArgumentPointerToMember(*this, Param, ParamType, Arg,
Converted))
return ExprError();
- return Owned(Arg);
+ return Arg;
}
/// \brief Check a template argument against its corresponding
@@ -4997,7 +5113,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
/// 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,
- const TemplateArgumentLoc &Arg,
+ TemplateArgumentLoc &Arg,
unsigned ArgumentPackIndex) {
TemplateName Name = Arg.getArgument().getAsTemplateOrTemplatePattern();
TemplateDecl *Template = Name.getAsTemplateDecl();
@@ -5085,7 +5201,7 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
QualType ClassType
= Context.getTypeDeclType(cast<RecordDecl>(VD->getDeclContext()));
NestedNameSpecifier *Qualifier
- = NestedNameSpecifier::Create(Context, 0, false,
+ = NestedNameSpecifier::Create(Context, nullptr, false,
ClassType.getTypePtr());
CXXScopeSpec SS;
SS.MakeTrivial(Context, Qualifier, Loc);
@@ -5114,7 +5230,7 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
if (IsQualificationConversion(((Expr*) RefExpr.get())->getType(),
ParamType.getUnqualifiedType(), false,
ObjCLifetimeConversion))
- RefExpr = ImpCastExprToType(RefExpr.take(), ParamType.getUnqualifiedType(), CK_NoOp);
+ RefExpr = ImpCastExprToType(RefExpr.get(), ParamType.getUnqualifiedType(), CK_NoOp);
assert(!RefExpr.isInvalid() &&
Context.hasSameType(((Expr*) RefExpr.get())->getType(),
@@ -5134,7 +5250,7 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
if (T->isFunctionType() || T->isArrayType()) {
// Decay functions and arrays.
- RefExpr = DefaultFunctionArrayConversion(RefExpr.take());
+ RefExpr = DefaultFunctionArrayConversion(RefExpr.get());
if (RefExpr.isInvalid())
return ExprError();
@@ -5211,12 +5327,13 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
if (OrigT->isEnumeralType()) {
// FIXME: This is a hack. We need a better way to handle substituted
// non-type template parameters.
- E = CStyleCastExpr::Create(Context, OrigT, VK_RValue, CK_IntegralCast, E, 0,
+ E = CStyleCastExpr::Create(Context, OrigT, VK_RValue, CK_IntegralCast, E,
+ nullptr,
Context.getTrivialTypeSourceInfo(OrigT, Loc),
Loc, Loc);
}
- return Owned(E);
+ return E;
}
/// \brief Match two template parameters within template parameter lists.
@@ -5450,18 +5567,19 @@ Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) {
(S->getFlags() & Scope::TemplateParamScope) != 0)
S = S->getParent();
- // C++ [temp]p2:
- // A template-declaration can appear only as a namespace scope or
- // class scope declaration.
+ // C++ [temp]p4:
+ // A template [...] shall not have C linkage.
DeclContext *Ctx = S->getEntity();
- if (Ctx && isa<LinkageSpecDecl>(Ctx) &&
- cast<LinkageSpecDecl>(Ctx)->getLanguage() != LinkageSpecDecl::lang_cxx)
+ if (Ctx && Ctx->isExternCContext())
return Diag(TemplateParams->getTemplateLoc(), diag::err_template_linkage)
<< TemplateParams->getSourceRange();
while (Ctx && isa<LinkageSpecDecl>(Ctx))
Ctx = Ctx->getParent();
+ // C++ [temp]p2:
+ // A template-declaration can appear only as a namespace scope or
+ // class scope declaration.
if (Ctx) {
if (Ctx->isFileContext())
return false;
@@ -5598,13 +5716,37 @@ static bool CheckTemplateSpecializationScope(Sema &S,
// 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).
- bool ComplainedAboutScope = false;
- DeclContext *SpecializedContext
+ DeclContext *SpecializedContext
= Specialized->getDeclContext()->getEnclosingNamespaceContext();
DeclContext *DC = S.CurContext->getEnclosingNamespaceContext();
- if ((!PrevDecl ||
- getTemplateSpecializationKind(PrevDecl) == TSK_Undeclared ||
- getTemplateSpecializationKind(PrevDecl) == TSK_ImplicitInstantiation)){
+
+ // 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))) {
+ if (isa<TranslationUnitDecl>(SpecializedContext))
+ S.Diag(Loc, diag::err_template_spec_redecl_global_scope)
+ << EntityKind << Specialized;
+ else if (isa<NamespaceDecl>(SpecializedContext))
+ S.Diag(Loc, diag::err_template_spec_redecl_out_of_scope)
+ << EntityKind << Specialized
+ << cast<NamedDecl>(SpecializedContext);
+ else
+ llvm_unreachable("unexpected namespace context for specialization");
+
+ 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
@@ -5613,9 +5755,12 @@ static bool CheckTemplateSpecializationScope(Sema &S,
// static data member of a class template shall be declared in the
// namespace of which the class template is a member.
//
- // C++0x [temp.expl.spec]p2:
+ // 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)) {
@@ -5636,46 +5781,42 @@ static bool CheckTemplateSpecializationScope(Sema &S,
}
S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
- ComplainedAboutScope =
- !(IsCPlusPlus11Extension && S.getLangOpts().CPlusPlus11);
}
}
- // 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 (!ComplainedAboutScope && !DC->Encloses(SpecializedContext) &&
- !(isa<FunctionTemplateDecl>(Specialized) || isa<VarDecl>(Specialized) ||
- isa<FunctionDecl>(Specialized))) {
- if (isa<TranslationUnitDecl>(SpecializedContext))
- S.Diag(Loc, diag::err_template_spec_redecl_global_scope)
- << EntityKind << Specialized;
- else if (isa<NamespaceDecl>(SpecializedContext))
- S.Diag(Loc, diag::err_template_spec_redecl_out_of_scope)
- << EntityKind << Specialized
- << cast<NamedDecl>(SpecializedContext);
-
- S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
- }
+ return false;
+}
- // FIXME: check for specialization-after-instantiation errors and such.
+static SourceRange findTemplateParameter(unsigned Depth, Expr *E) {
+ if (!E->isInstantiationDependent())
+ return SourceLocation();
+ DependencyChecker Checker(Depth);
+ Checker.TraverseStmt(E);
+ if (Checker.Match && Checker.MatchLoc.isInvalid())
+ return E->getSourceRange();
+ return Checker.MatchLoc;
+}
- return false;
+static SourceRange findTemplateParameter(unsigned Depth, TypeLoc TL) {
+ if (!TL.getType()->isDependentType())
+ return SourceLocation();
+ DependencyChecker Checker(Depth);
+ Checker.TraverseTypeLoc(TL);
+ if (Checker.Match && Checker.MatchLoc.isInvalid())
+ return TL.getSourceRange();
+ return Checker.MatchLoc;
}
/// \brief Subroutine of Sema::CheckTemplatePartialSpecializationArgs
/// that checks non-type template partial specialization arguments.
static bool CheckNonTypeTemplatePartialSpecializationArgs(
- Sema &S, NonTypeTemplateParmDecl *Param, const TemplateArgument *Args,
- unsigned NumArgs) {
+ Sema &S, SourceLocation TemplateNameLoc, NonTypeTemplateParmDecl *Param,
+ const TemplateArgument *Args, unsigned NumArgs, bool IsDefaultArgument) {
for (unsigned I = 0; I != NumArgs; ++I) {
if (Args[I].getKind() == TemplateArgument::Pack) {
if (CheckNonTypeTemplatePartialSpecializationArgs(
- S, Param, Args[I].pack_begin(), Args[I].pack_size()))
+ S, TemplateNameLoc, Param, Args[I].pack_begin(),
+ Args[I].pack_size(), IsDefaultArgument))
return true;
continue;
@@ -5713,22 +5854,43 @@ static bool CheckNonTypeTemplatePartialSpecializationArgs(
// shall not involve a template parameter of the partial
// specialization except when the argument expression is a
// simple identifier.
- if (ArgExpr->isTypeDependent() || ArgExpr->isValueDependent()) {
- S.Diag(ArgExpr->getLocStart(),
- diag::err_dependent_non_type_arg_in_partial_spec)
- << ArgExpr->getSourceRange();
+ SourceRange ParamUseRange =
+ findTemplateParameter(Param->getDepth(), ArgExpr);
+ if (ParamUseRange.isValid()) {
+ if (IsDefaultArgument) {
+ S.Diag(TemplateNameLoc,
+ diag::err_dependent_non_type_arg_in_partial_spec);
+ S.Diag(ParamUseRange.getBegin(),
+ diag::note_dependent_non_type_default_arg_in_partial_spec)
+ << ParamUseRange;
+ } else {
+ S.Diag(ParamUseRange.getBegin(),
+ diag::err_dependent_non_type_arg_in_partial_spec)
+ << ParamUseRange;
+ }
return true;
}
// -- The type of a template parameter corresponding to a
// specialized non-type argument shall not be dependent on a
// parameter of the specialization.
- if (Param->getType()->isDependentType()) {
- S.Diag(ArgExpr->getLocStart(),
- diag::err_dependent_typed_non_type_arg_in_partial_spec)
- << Param->getType()
- << ArgExpr->getSourceRange();
- S.Diag(Param->getLocation(), diag::note_template_param_here);
+ //
+ // FIXME: We need to delay this check until instantiation in some cases:
+ //
+ // template<template<typename> class X> struct A {
+ // template<typename T, X<T> N> struct B;
+ // template<typename T> struct B<T, 0>;
+ // };
+ // template<typename> using X = int;
+ // A<X>::B<int, 0> b;
+ ParamUseRange = findTemplateParameter(
+ Param->getDepth(), Param->getTypeSourceInfo()->getTypeLoc());
+ if (ParamUseRange.isValid()) {
+ S.Diag(IsDefaultArgument ? TemplateNameLoc : ArgExpr->getLocStart(),
+ diag::err_dependent_typed_non_type_arg_in_partial_spec)
+ << Param->getType() << ParamUseRange;
+ S.Diag(Param->getLocation(), diag::note_template_param_here)
+ << (IsDefaultArgument ? ParamUseRange : SourceRange());
return true;
}
}
@@ -5739,15 +5901,17 @@ static bool CheckNonTypeTemplatePartialSpecializationArgs(
/// \brief 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.
/// \param TemplateParams the template parameters of the primary class
-/// template.
-///
+/// template.
+/// \param NumExplicit the number of explicitly-specified template arguments.
/// \param TemplateArgs the template arguments of the class template
-/// partial specialization.
+/// partial specialization.
///
-/// \returns true if there was an error, false otherwise.
+/// \returns \c true if there was an error, \c false otherwise.
static bool CheckTemplatePartialSpecializationArgs(
- Sema &S, TemplateParameterList *TemplateParams,
+ Sema &S, SourceLocation TemplateNameLoc,
+ TemplateParameterList *TemplateParams, unsigned NumExplicit,
SmallVectorImpl<TemplateArgument> &TemplateArgs) {
const TemplateArgument *ArgList = TemplateArgs.data();
@@ -5757,7 +5921,8 @@ static bool CheckTemplatePartialSpecializationArgs(
if (!Param)
continue;
- if (CheckNonTypeTemplatePartialSpecializationArgs(S, Param, &ArgList[I], 1))
+ if (CheckNonTypeTemplatePartialSpecializationArgs(
+ S, TemplateNameLoc, Param, &ArgList[I], 1, I >= NumExplicit))
return true;
}
@@ -5769,23 +5934,23 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
TagUseKind TUK,
SourceLocation KWLoc,
SourceLocation ModulePrivateLoc,
- CXXScopeSpec &SS,
- TemplateTy TemplateD,
- SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgsIn,
- SourceLocation RAngleLoc,
+ TemplateIdAnnotation &TemplateId,
AttributeList *Attr,
MultiTemplateParamsArg TemplateParameterLists) {
assert(TUK != TUK_Reference && "References are not specializations");
+ CXXScopeSpec &SS = TemplateId.SS;
+
// NOTE: KWLoc is the location of the tag keyword. This will instead
// store the location of the outermost template keyword in the declaration.
SourceLocation TemplateKWLoc = TemplateParameterLists.size() > 0
- ? TemplateParameterLists[0]->getTemplateLoc() : SourceLocation();
+ ? TemplateParameterLists[0]->getTemplateLoc() : KWLoc;
+ SourceLocation TemplateNameLoc = TemplateId.TemplateNameLoc;
+ SourceLocation LAngleLoc = TemplateId.LAngleLoc;
+ SourceLocation RAngleLoc = TemplateId.RAngleLoc;
// Find the class template we're specializing
- TemplateName Name = TemplateD.get();
+ TemplateName Name = TemplateId.Template.get();
ClassTemplateDecl *ClassTemplate
= dyn_cast_or_null<ClassTemplateDecl>(Name.getAsTemplateDecl());
@@ -5806,8 +5971,9 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
bool Invalid = false;
TemplateParameterList *TemplateParams =
MatchTemplateParametersToScopeSpecifier(
- TemplateNameLoc, TemplateNameLoc, SS, TemplateParameterLists,
- TUK == TUK_Friend, isExplicitSpecialization, Invalid);
+ KWLoc, TemplateNameLoc, SS, &TemplateId,
+ TemplateParameterLists, TUK == TUK_Friend, isExplicitSpecialization,
+ Invalid);
if (Invalid)
return true;
@@ -5858,11 +6024,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
<< SourceRange(LAngleLoc, RAngleLoc);
else
isExplicitSpecialization = true;
- } else if (TUK != TUK_Friend) {
- Diag(KWLoc, diag::err_template_spec_needs_header)
- << FixItHint::CreateInsertion(KWLoc, "template<> ");
- TemplateKWLoc = KWLoc;
- isExplicitSpecialization = true;
+ } else {
+ assert(TUK == TUK_Friend && "should have a 'template<>' for this decl");
}
// Check that the specialization uses the same tag kind as the
@@ -5882,10 +6045,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
}
// Translate the parser's template argument list in our AST format.
- TemplateArgumentListInfo TemplateArgs;
- TemplateArgs.setLAngleLoc(LAngleLoc);
- TemplateArgs.setRAngleLoc(RAngleLoc);
- translateTemplateArguments(TemplateArgsIn, TemplateArgs);
+ TemplateArgumentListInfo TemplateArgs =
+ makeTemplateArgumentListInfo(*this, TemplateId);
// Check for unexpanded parameter packs in any of the template arguments.
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
@@ -5904,7 +6065,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
// corresponds to these arguments.
if (isPartialSpecialization) {
if (CheckTemplatePartialSpecializationArgs(
- *this, ClassTemplate->getTemplateParameters(), Converted))
+ *this, TemplateNameLoc, ClassTemplate->getTemplateParameters(),
+ TemplateArgs.size(), Converted))
return true;
bool InstantiationDependent;
@@ -5919,21 +6081,16 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
}
}
- void *InsertPos = 0;
- ClassTemplateSpecializationDecl *PrevDecl = 0;
+ void *InsertPos = nullptr;
+ ClassTemplateSpecializationDecl *PrevDecl = nullptr;
if (isPartialSpecialization)
// FIXME: Template parameter list matters, too
- PrevDecl
- = ClassTemplate->findPartialSpecialization(Converted.data(),
- Converted.size(),
- InsertPos);
+ PrevDecl = ClassTemplate->findPartialSpecialization(Converted, InsertPos);
else
- PrevDecl
- = ClassTemplate->findSpecialization(Converted.data(),
- Converted.size(), InsertPos);
+ PrevDecl = ClassTemplate->findSpecialization(Converted, InsertPos);
- ClassTemplateSpecializationDecl *Specialization = 0;
+ ClassTemplateSpecializationDecl *Specialization = nullptr;
// Check whether we can declare a class template specialization in
// the current scope.
@@ -5945,24 +6102,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
// The canonical type
QualType CanonType;
- if (PrevDecl &&
- (PrevDecl->getSpecializationKind() == TSK_Undeclared ||
- TUK == TUK_Friend)) {
- // Since the only prior class template specialization with these
- // arguments was referenced but not declared, or we're only
- // referencing this specialization as a friend, reuse that
- // declaration node as our own, updating its source location and
- // the list of outer template parameters to reflect our new declaration.
- Specialization = PrevDecl;
- Specialization->setLocation(TemplateNameLoc);
- if (TemplateParameterLists.size() > 0) {
- Specialization->setTemplateParameterListsInfo(Context,
- TemplateParameterLists.size(),
- TemplateParameterLists.data());
- }
- PrevDecl = 0;
- CanonType = Context.getTypeDeclType(Specialization);
- } else if (isPartialSpecialization) {
+ if (isPartialSpecialization) {
// Build the canonical type that describes the converted template
// arguments of the class template partial specialization.
TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
@@ -5985,6 +6125,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
Attr,
TemplateParams,
AS_none, /*ModulePrivateLoc=*/SourceLocation(),
+ /*FriendLoc*/SourceLocation(),
TemplateParameterLists.size() - 1,
TemplateParameterLists.data());
}
@@ -6043,7 +6184,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
else
Diag(Param->getLocation(),
diag::note_partial_spec_unused_parameter)
- << "<anonymous>";
+ << "(anonymous)";
}
}
}
@@ -6187,7 +6328,7 @@ Decl *Sema::ActOnTemplateDeclarator(Scope *S,
Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
MultiTemplateParamsArg TemplateParameterLists,
Declarator &D) {
- assert(getCurFunctionDecl() == 0 && "Function parsing confused");
+ assert(getCurFunctionDecl() == nullptr && "Function parsing confused");
DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
if (FTI.hasPrototype) {
@@ -6210,10 +6351,8 @@ static void StripImplicitInstantiation(NamedDecl *D) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
FD->setInlineSpecified(false);
- for (FunctionDecl::param_iterator I = FD->param_begin(),
- E = FD->param_end();
- I != E; ++I)
- (*I)->dropAttrs();
+ for (auto I : FD->params())
+ I->dropAttrs();
}
}
@@ -6407,8 +6546,12 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
// For a given template and a given set of template-arguments,
// - an explicit instantiation definition shall appear at most once
// in a program,
- Diag(NewLoc, diag::err_explicit_instantiation_duplicate)
- << PrevDecl;
+
+ // MSVCCompat: MSVC silently ignores duplicate explicit instantiations.
+ Diag(NewLoc, (getLangOpts().MSVCCompat)
+ ? diag::ext_explicit_instantiation_duplicate
+ : diag::err_explicit_instantiation_duplicate)
+ << PrevDecl;
Diag(DiagLocForExplicitInstantiation(PrevDecl, PrevPointOfInstantiation),
diag::note_previous_explicit_instantiation);
HasNoEffect = true;
@@ -6509,8 +6652,8 @@ bool Sema::CheckFunctionTemplateSpecialization(
const FunctionProtoType *FPT = FT->castAs<FunctionProtoType>();
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.TypeQuals |= Qualifiers::Const;
- FT = Context.getFunctionType(FPT->getResultType(), FPT->getArgTypes(),
- EPI);
+ FT = Context.getFunctionType(FPT->getReturnType(),
+ FPT->getParamTypes(), EPI);
}
}
@@ -6522,7 +6665,7 @@ bool Sema::CheckFunctionTemplateSpecialization(
// specializing this template.
// FIXME: It is somewhat wasteful to build
TemplateDeductionInfo Info(FailedCandidates.getLocation());
- FunctionDecl *Specialization = 0;
+ FunctionDecl *Specialization = nullptr;
if (TemplateDeductionResult TDK = DeduceTemplateArguments(
cast<FunctionTemplateDecl>(FunTmpl->getFirstDecl()),
ExplicitTemplateArgs, FT, Specialization, Info)) {
@@ -6546,7 +6689,7 @@ bool Sema::CheckFunctionTemplateSpecialization(
FD->getLocation(),
PDiag(diag::err_function_template_spec_no_match) << FD->getDeclName(),
PDiag(diag::err_function_template_spec_ambiguous)
- << FD->getDeclName() << (ExplicitTemplateArgs != 0),
+ << FD->getDeclName() << (ExplicitTemplateArgs != nullptr),
PDiag(diag::note_function_template_spec_matched));
if (Result == Candidates.end())
@@ -6615,7 +6758,7 @@ bool Sema::CheckFunctionTemplateSpecialization(
const TemplateArgumentList* TemplArgs = new (Context)
TemplateArgumentList(Specialization->getTemplateSpecializationArgs());
FD->setFunctionTemplateSpecialization(Specialization->getPrimaryTemplate(),
- TemplArgs, /*InsertPos=*/0,
+ TemplArgs, /*InsertPos=*/nullptr,
SpecInfo->getTemplateSpecializationKind(),
ExplicitTemplateArgs);
@@ -6645,9 +6788,9 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
assert(!isa<TemplateDecl>(Member) && "Only for non-template members");
// Try to find the member we are instantiating.
- NamedDecl *Instantiation = 0;
- NamedDecl *InstantiatedFrom = 0;
- MemberSpecializationInfo *MSInfo = 0;
+ NamedDecl *Instantiation = nullptr;
+ NamedDecl *InstantiatedFrom = nullptr;
+ MemberSpecializationInfo *MSInfo = nullptr;
if (Previous.empty()) {
// Nowhere to look anyway.
@@ -6656,7 +6799,10 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
I != E; ++I) {
NamedDecl *D = (*I)->getUnderlyingDecl();
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
- if (Context.hasSameType(Function->getType(), Method->getType())) {
+ QualType Adjusted = Function->getType();
+ if (!hasExplicitCallingConv(Adjusted))
+ Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
+ if (Context.hasSameType(Adjusted, Method->getType())) {
Instantiation = Method;
InstantiatedFrom = Method->getInstantiatedFromMemberFunction();
MSInfo = Method->getMemberSpecializationInfo();
@@ -6877,8 +7023,8 @@ static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) {
// name shall be a simple-template-id.
//
// C++98 has the same restriction, just worded differently.
- for (NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
- NNS; NNS = NNS->getPrefix())
+ for (NestedNameSpecifier *NNS = SS.getScopeRep(); NNS;
+ NNS = NNS->getPrefix())
if (const Type *T = NNS->getAsType())
if (isa<TemplateSpecializationType>(T))
return true;
@@ -6951,10 +7097,9 @@ Sema::ActOnExplicitInstantiation(Scope *S,
// Find the class template specialization declaration that
// corresponds to these arguments.
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
ClassTemplateSpecializationDecl *PrevDecl
- = ClassTemplate->findSpecialization(Converted.data(),
- Converted.size(), InsertPos);
+ = ClassTemplate->findSpecialization(Converted, InsertPos);
TemplateSpecializationKind PrevDecl_TSK
= PrevDecl ? PrevDecl->getTemplateSpecializationKind() : TSK_Undeclared;
@@ -6968,7 +7113,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
SS.isSet()))
return true;
- ClassTemplateSpecializationDecl *Specialization = 0;
+ ClassTemplateSpecializationDecl *Specialization = nullptr;
bool HasNoEffect = false;
if (PrevDecl) {
@@ -6990,7 +7135,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
// (Other source locations will be updated later.)
Specialization = PrevDecl;
Specialization->setLocation(TemplateNameLoc);
- PrevDecl = 0;
+ PrevDecl = nullptr;
}
}
@@ -7074,6 +7219,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
// TSK_ExplicitInstantiationDefinition
if (Old_TSK == TSK_ExplicitInstantiationDeclaration &&
TSK == TSK_ExplicitInstantiationDefinition)
+ // FIXME: Need to notify the ASTMutationListener that we did this.
Def->setTemplateSpecializationKind(TSK);
InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
@@ -7102,7 +7248,8 @@ Sema::ActOnExplicitInstantiation(Scope *S,
KWLoc, SS, Name, NameLoc, Attr, AS_none,
/*ModulePrivateLoc=*/SourceLocation(),
MultiTemplateParamsArg(), Owned, IsDependent,
- SourceLocation(), false, TypeResult());
+ SourceLocation(), false, TypeResult(),
+ /*IsTypeSpecifier*/false);
assert(!IsDependent && "explicit instantiation of dependent name not yet handled");
if (!TagD)
@@ -7342,13 +7489,8 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
}
// Translate the parser's template argument list into our AST format.
- TemplateArgumentListInfo TemplateArgs;
- TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
- TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
- TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
- ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
- TemplateId->NumArgs);
- translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
+ TemplateArgumentListInfo TemplateArgs =
+ makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
DeclResult Res = CheckVarTemplateId(PrevTemplate, TemplateLoc,
D.getIdentifierLoc(), TemplateArgs);
@@ -7410,7 +7552,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
}
// FIXME: Create an ExplicitInstantiation node?
- return (Decl*) 0;
+ return (Decl*) nullptr;
}
// If the declarator is a template-id, translate the parser's template
@@ -7418,12 +7560,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
bool HasExplicitTemplateArgs = false;
TemplateArgumentListInfo TemplateArgs;
if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
- TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
- TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
- TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
- ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
- TemplateId->NumArgs);
- translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
+ TemplateArgs = makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
HasExplicitTemplateArgs = true;
}
@@ -7455,10 +7592,11 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
continue;
TemplateDeductionInfo Info(FailedCandidates.getLocation());
- FunctionDecl *Specialization = 0;
+ FunctionDecl *Specialization = nullptr;
if (TemplateDeductionResult TDK
= DeduceTemplateArguments(FunTmpl,
- (HasExplicitTemplateArgs ? &TemplateArgs : 0),
+ (HasExplicitTemplateArgs ? &TemplateArgs
+ : nullptr),
R, Specialization, Info)) {
// Keep track of almost-matches.
FailedCandidates.addCandidate()
@@ -7511,7 +7649,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
// FIXME: We may still want to build some representation of this
// explicit specialization.
if (HasNoEffect)
- return (Decl*) 0;
+ return (Decl*) nullptr;
}
Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
@@ -7519,7 +7657,11 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
if (Attr)
ProcessDeclAttributeList(S, Specialization, Attr);
- if (TSK == TSK_ExplicitInstantiationDefinition)
+ if (Specialization->isDefined()) {
+ // Let the ASTConsumer know that this function has been explicitly
+ // instantiated now, and its linkage might have changed.
+ Consumer.HandleTopLevelDecl(DeclGroupRef(Specialization));
+ } else if (TSK == TSK_ExplicitInstantiationDefinition)
InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization);
// C++0x [temp.explicit]p2:
@@ -7544,7 +7686,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
D.getCXXScopeSpec().isSet());
// FIXME: Create some kind of ExplicitInstantiationDecl here.
- return (Decl*) 0;
+ return (Decl*) nullptr;
}
TypeResult
@@ -7554,8 +7696,7 @@ Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// This has to hold, because SS is expected to be defined.
assert(Name && "Expected a name in a dependent tag");
- NestedNameSpecifier *NNS
- = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ NestedNameSpecifier *NNS = SS.getScopeRep();
if (!NNS)
return true;
@@ -7641,8 +7782,7 @@ Sema::ActOnTypenameType(Scope *S,
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
// Construct a dependent template specialization type.
assert(DTN && "dependent template has non-dependent name?");
- assert(DTN->getQualifier()
- == static_cast<NestedNameSpecifier*>(SS.getScopeRep()));
+ assert(DTN->getQualifier() == SS.getScopeRep());
QualType T = Context.getDependentTemplateSpecializationType(ETK_Typename,
DTN->getQualifier(),
DTN->getIdentifier(),
@@ -7758,7 +7898,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
LookupResult Result(*this, Name, IILoc, LookupOrdinaryName);
LookupQualifiedName(Result, Ctx);
unsigned DiagID = 0;
- Decl *Referenced = 0;
+ Decl *Referenced = nullptr;
switch (Result.getResultKind()) {
case LookupResult::NotFound: {
// If we're looking up 'type' within a template named 'enable_if', produce
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
index 8d66ff6..53a75d2 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -126,7 +126,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
unsigned TDF,
bool PartialOrdering = false,
SmallVectorImpl<RefParamPartialOrderingComparison> *
- RefParamComparisons = 0);
+ RefParamComparisons = nullptr);
static Sema::TemplateDeductionResult
DeduceTemplateArguments(Sema &S,
@@ -155,7 +155,7 @@ static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) {
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
return dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
- return 0;
+ return nullptr;
}
/// \brief Determine whether two declaration pointers refer to the same
@@ -297,6 +297,7 @@ checkDeducedTemplateArguments(ASTContext &Context,
XAEnd = X.pack_end(),
YA = Y.pack_begin();
XA != XAEnd; ++XA, ++YA) {
+ // FIXME: Do we need to merge the results together here?
if (checkDeducedTemplateArguments(Context,
DeducedTemplateArgument(*XA, X.wasDeducedFromArrayBound()),
DeducedTemplateArgument(*YA, Y.wasDeducedFromArrayBound()))
@@ -382,7 +383,7 @@ DeduceNonTypeTemplateArgument(Sema &S,
assert(NTTP->getDepth() == 0 &&
"Cannot deduce non-type template argument with depth > 0");
- D = D ? cast<ValueDecl>(D->getCanonicalDecl()) : 0;
+ D = D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
TemplateArgument New(D, NTTP->getType()->isReferenceType());
DeducedTemplateArgument NewDeduced(New);
DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
@@ -581,96 +582,181 @@ static TemplateParameter makeTemplateParameter(Decl *D) {
return TemplateParameter(cast<TemplateTemplateParmDecl>(D));
}
-typedef SmallVector<SmallVector<DeducedTemplateArgument, 4>, 2>
- NewlyDeducedPacksType;
+/// A pack that we're currently deducing.
+struct clang::DeducedPack {
+ DeducedPack(unsigned Index) : Index(Index), Outer(nullptr) {}
-/// \brief Prepare to perform template argument deduction for all of the
-/// arguments in a set of argument packs.
-static void
-PrepareArgumentPackDeduction(Sema &S,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced,
- ArrayRef<unsigned> PackIndices,
- SmallVectorImpl<DeducedTemplateArgument> &SavedPacks,
- NewlyDeducedPacksType &NewlyDeducedPacks) {
- // Save the deduced template arguments for each parameter pack expanded
- // by this pack expansion, then clear out the deduction.
- for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
- // Save the previously-deduced argument pack, then clear it out so that we
- // can deduce a new argument pack.
- SavedPacks[I] = Deduced[PackIndices[I]];
- Deduced[PackIndices[I]] = TemplateArgument();
-
- if (!S.CurrentInstantiationScope)
- continue;
+ // The index of the pack.
+ unsigned Index;
+
+ // The old value of the pack before we started deducing it.
+ DeducedTemplateArgument Saved;
+
+ // A deferred value of this pack from an inner deduction, that couldn't be
+ // deduced because this deduction hadn't happened yet.
+ DeducedTemplateArgument DeferredDeduction;
+
+ // The new value of the pack.
+ SmallVector<DeducedTemplateArgument, 4> New;
+
+ // The outer deduction for this pack, if any.
+ DeducedPack *Outer;
+};
+
+/// A scope in which we're performing pack deduction.
+class PackDeductionScope {
+public:
+ PackDeductionScope(Sema &S, TemplateParameterList *TemplateParams,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ TemplateDeductionInfo &Info, TemplateArgument Pattern)
+ : S(S), TemplateParams(TemplateParams), Deduced(Deduced), Info(Info) {
+ // Compute the set of template parameter indices that correspond to
+ // parameter packs expanded by the pack expansion.
+ {
+ llvm::SmallBitVector SawIndices(TemplateParams->size());
+ 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 == 0 && !SawIndices[Index]) {
+ SawIndices[Index] = true;
- // If the template argument pack was explicitly specified, add that to
- // the set of deduced arguments.
- const TemplateArgument *ExplicitArgs;
- unsigned NumExplicitArgs;
- if (NamedDecl *PartiallySubstitutedPack
- = S.CurrentInstantiationScope->getPartiallySubstitutedPack(
- &ExplicitArgs,
- &NumExplicitArgs)) {
- if (getDepthAndIndex(PartiallySubstitutedPack).second == PackIndices[I])
- NewlyDeducedPacks[I].append(ExplicitArgs,
- ExplicitArgs + NumExplicitArgs);
+ // 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);
+ }
+ }
}
- }
-}
+ assert(!Packs.empty() && "Pack expansion without unexpanded packs?");
-/// \brief Finish template argument deduction for a set of argument packs,
-/// producing the argument packs and checking for consistency with prior
-/// deductions.
-static Sema::TemplateDeductionResult
-FinishArgumentPackDeduction(Sema &S,
- TemplateParameterList *TemplateParams,
- bool HasAnyArguments,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced,
- ArrayRef<unsigned> PackIndices,
- SmallVectorImpl<DeducedTemplateArgument> &SavedPacks,
- NewlyDeducedPacksType &NewlyDeducedPacks,
- TemplateDeductionInfo &Info) {
- // Build argument packs for each of the parameter packs expanded by this
- // pack expansion.
- for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
- if (HasAnyArguments && NewlyDeducedPacks[I].empty()) {
- // We were not able to deduce anything for this parameter pack,
- // so just restore the saved argument pack.
- Deduced[PackIndices[I]] = SavedPacks[I];
- continue;
+ for (auto &Pack : Packs) {
+ if (Info.PendingDeducedPacks.size() > Pack.Index)
+ Pack.Outer = Info.PendingDeducedPacks[Pack.Index];
+ else
+ Info.PendingDeducedPacks.resize(Pack.Index + 1);
+ Info.PendingDeducedPacks[Pack.Index] = &Pack;
+
+ if (S.CurrentInstantiationScope) {
+ // If the template argument pack was explicitly specified, add that to
+ // the set of deduced arguments.
+ const TemplateArgument *ExplicitArgs;
+ unsigned NumExplicitArgs;
+ NamedDecl *PartiallySubstitutedPack =
+ S.CurrentInstantiationScope->getPartiallySubstitutedPack(
+ &ExplicitArgs, &NumExplicitArgs);
+ if (PartiallySubstitutedPack &&
+ getDepthAndIndex(PartiallySubstitutedPack).second == Pack.Index)
+ Pack.New.append(ExplicitArgs, ExplicitArgs + NumExplicitArgs);
+ }
}
+ }
+
+ ~PackDeductionScope() {
+ for (auto &Pack : Packs)
+ Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
+ }
- DeducedTemplateArgument NewPack;
-
- if (NewlyDeducedPacks[I].empty()) {
- // If we deduced an empty argument pack, create it now.
- NewPack = DeducedTemplateArgument(TemplateArgument::getEmptyPack());
- } else {
- TemplateArgument *ArgumentPack
- = new (S.Context) TemplateArgument [NewlyDeducedPacks[I].size()];
- std::copy(NewlyDeducedPacks[I].begin(), NewlyDeducedPacks[I].end(),
- ArgumentPack);
- NewPack
- = DeducedTemplateArgument(TemplateArgument(ArgumentPack,
- NewlyDeducedPacks[I].size()),
- NewlyDeducedPacks[I][0].wasDeducedFromArrayBound());
+ /// 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
+ // by this pack expansion, add them to the list of arguments we've deduced
+ // for that pack, then clear out the deduced argument.
+ for (auto &Pack : Packs) {
+ DeducedTemplateArgument &DeducedArg = Deduced[Pack.Index];
+ if (!DeducedArg.isNull()) {
+ Pack.New.push_back(DeducedArg);
+ DeducedArg = DeducedTemplateArgument();
+ }
}
+ }
- DeducedTemplateArgument Result
- = checkDeducedTemplateArguments(S.Context, SavedPacks[I], NewPack);
- if (Result.isNull()) {
- Info.Param
- = makeTemplateParameter(TemplateParams->getParam(PackIndices[I]));
- Info.FirstArg = SavedPacks[I];
- Info.SecondArg = NewPack;
- return Sema::TDK_Inconsistent;
+ /// \brief Finish template argument deduction for a set of argument packs,
+ /// producing the argument packs and checking for consistency with prior
+ /// deductions.
+ Sema::TemplateDeductionResult finish(bool HasAnyArguments) {
+ // 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;
+
+ // Build or find a new value for this pack.
+ DeducedTemplateArgument NewPack;
+ if (HasAnyArguments && Pack.New.empty()) {
+ if (Pack.DeferredDeduction.isNull()) {
+ // We were not able to deduce anything for this parameter pack
+ // (because it only appeared in non-deduced contexts), so just
+ // restore the saved argument pack.
+ continue;
+ }
+
+ NewPack = Pack.DeferredDeduction;
+ Pack.DeferredDeduction = TemplateArgument();
+ } else if (Pack.New.empty()) {
+ // If we deduced an empty argument pack, create it now.
+ NewPack = DeducedTemplateArgument(TemplateArgument::getEmptyPack());
+ } else {
+ TemplateArgument *ArgumentPack =
+ new (S.Context) TemplateArgument[Pack.New.size()];
+ std::copy(Pack.New.begin(), Pack.New.end(), ArgumentPack);
+ NewPack = DeducedTemplateArgument(
+ TemplateArgument(ArgumentPack, Pack.New.size()),
+ Pack.New[0].wasDeducedFromArrayBound());
+ }
+
+ // Pick where we're going to put the merged pack.
+ DeducedTemplateArgument *Loc;
+ if (Pack.Outer) {
+ if (Pack.Outer->DeferredDeduction.isNull()) {
+ // Defer checking this pack until we have a complete pack to compare
+ // it against.
+ Pack.Outer->DeferredDeduction = NewPack;
+ continue;
+ }
+ Loc = &Pack.Outer->DeferredDeduction;
+ } else {
+ Loc = &Deduced[Pack.Index];
+ }
+
+ // Check the new pack matches any previous value.
+ DeducedTemplateArgument OldPack = *Loc;
+ DeducedTemplateArgument Result =
+ checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
+
+ // If we deferred a deduction of this pack, check that one now too.
+ if (!Result.isNull() && !Pack.DeferredDeduction.isNull()) {
+ OldPack = Result;
+ NewPack = Pack.DeferredDeduction;
+ Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
+ }
+
+ if (Result.isNull()) {
+ Info.Param =
+ makeTemplateParameter(TemplateParams->getParam(Pack.Index));
+ Info.FirstArg = OldPack;
+ Info.SecondArg = NewPack;
+ return Sema::TDK_Inconsistent;
+ }
+
+ *Loc = Result;
}
- Deduced[PackIndices[I]] = Result;
+ return Sema::TDK_Success;
}
- return Sema::TDK_Success;
-}
+private:
+ Sema &S;
+ TemplateParameterList *TemplateParams;
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced;
+ TemplateDeductionInfo &Info;
+
+ SmallVector<DeducedPack, 2> Packs;
+};
/// \brief Deduce the template arguments by comparing the list of parameter
/// types to the list of argument types, as in the parameter-type-lists of
@@ -715,7 +801,7 @@ DeduceTemplateArguments(Sema &S,
unsigned TDF,
bool PartialOrdering = false,
SmallVectorImpl<RefParamPartialOrderingComparison> *
- RefParamComparisons = 0) {
+ RefParamComparisons = nullptr) {
// Fast-path check to see if we have too many/too few arguments.
if (NumParams != NumArgs &&
!(NumParams && isa<PackExpansionType>(Params[NumParams - 1])) &&
@@ -773,33 +859,8 @@ DeduceTemplateArguments(Sema &S,
// comparison deduces template arguments for subsequent positions in the
// template parameter packs expanded by the function parameter pack.
- // Compute the set of template parameter indices that correspond to
- // parameter packs expanded by the pack expansion.
- SmallVector<unsigned, 2> PackIndices;
QualType Pattern = Expansion->getPattern();
- {
- llvm::SmallBitVector SawIndices(TemplateParams->size());
- SmallVector<UnexpandedParameterPack, 2> Unexpanded;
- S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
- for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
- unsigned Depth, Index;
- llvm::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
- if (Depth == 0 && !SawIndices[Index]) {
- SawIndices[Index] = true;
- PackIndices.push_back(Index);
- }
- }
- }
- assert(!PackIndices.empty() && "Pack expansion without unexpanded packs?");
-
- // 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).
- NewlyDeducedPacksType NewlyDeducedPacks(PackIndices.size());
- SmallVector<DeducedTemplateArgument, 2>
- SavedPacks(PackIndices.size());
- PrepareArgumentPackDeduction(S, Deduced, PackIndices, SavedPacks,
- NewlyDeducedPacks);
+ PackDeductionScope PackScope(S, TemplateParams, Deduced, Info, Pattern);
bool HasAnyArguments = false;
for (; ArgIdx < NumArgs; ++ArgIdx) {
@@ -813,24 +874,12 @@ DeduceTemplateArguments(Sema &S,
RefParamComparisons))
return Result;
- // Capture the deduced template arguments for each parameter pack expanded
- // by this pack expansion, add them to the list of arguments we've deduced
- // for that pack, then clear out the deduced argument.
- for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
- DeducedTemplateArgument &DeducedArg = Deduced[PackIndices[I]];
- if (!DeducedArg.isNull()) {
- NewlyDeducedPacks[I].push_back(DeducedArg);
- DeducedArg = DeducedTemplateArgument();
- }
- }
+ PackScope.nextPackElement();
}
// Build argument packs for each of the parameter packs expanded by this
// pack expansion.
- if (Sema::TemplateDeductionResult Result
- = FinishArgumentPackDeduction(S, TemplateParams, HasAnyArguments,
- Deduced, PackIndices, SavedPacks,
- NewlyDeducedPacks, Info))
+ if (auto Result = PackScope.finish(HasAnyArguments))
return Result;
}
@@ -981,6 +1030,17 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
Comparison.Qualifiers = ParamMoreQualified;
else if (ArgQuals.isStrictSupersetOf(ParamQuals))
Comparison.Qualifiers = ArgMoreQualified;
+ else if (ArgQuals.getObjCLifetime() != ParamQuals.getObjCLifetime() &&
+ ArgQuals.withoutObjCLifetime()
+ == ParamQuals.withoutObjCLifetime()) {
+ // Prefer binding to non-__unsafe_autoretained parameters.
+ if (ArgQuals.getObjCLifetime() == Qualifiers::OCL_ExplicitNone &&
+ ParamQuals.getObjCLifetime())
+ Comparison.Qualifiers = ParamMoreQualified;
+ else if (ParamQuals.getObjCLifetime() == Qualifiers::OCL_ExplicitNone &&
+ ArgQuals.getObjCLifetime())
+ Comparison.Qualifiers = ArgMoreQualified;
+ }
RefParamComparisons->push_back(Comparison);
}
@@ -1364,19 +1424,17 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
return Sema::TDK_NonDeducedMismatch;
// Check return types.
- if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
- FunctionProtoParam->getResultType(),
- FunctionProtoArg->getResultType(),
- Info, Deduced, 0))
+ if (Sema::TemplateDeductionResult Result =
+ DeduceTemplateArgumentsByTypeMatch(
+ S, TemplateParams, FunctionProtoParam->getReturnType(),
+ FunctionProtoArg->getReturnType(), Info, Deduced, 0))
return Result;
- return DeduceTemplateArguments(S, TemplateParams,
- FunctionProtoParam->arg_type_begin(),
- FunctionProtoParam->getNumArgs(),
- FunctionProtoArg->arg_type_begin(),
- FunctionProtoArg->getNumArgs(),
- Info, Deduced, SubTDF);
+ return DeduceTemplateArguments(
+ S, TemplateParams, FunctionProtoParam->param_type_begin(),
+ FunctionProtoParam->getNumParams(),
+ FunctionProtoArg->param_type_begin(),
+ FunctionProtoArg->getNumParams(), Info, Deduced, SubTDF);
}
case Type::InjectedClassName: {
@@ -1463,12 +1521,10 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
// Visit base classes
CXXRecordDecl *Next = cast<CXXRecordDecl>(NextT->getDecl());
- for (CXXRecordDecl::base_class_iterator Base = Next->bases_begin(),
- BaseEnd = Next->bases_end();
- Base != BaseEnd; ++Base) {
- assert(Base->getType()->isRecordType() &&
+ for (const auto &Base : Next->bases()) {
+ assert(Base.getType()->isRecordType() &&
"Base class that isn't a record?");
- ToVisit.push_back(Base->getType()->getAs<RecordType>());
+ ToVisit.push_back(Base.getType()->getAs<RecordType>());
}
}
@@ -1845,41 +1901,18 @@ DeduceTemplateArguments(Sema &S,
// template parameter packs expanded by Pi.
TemplateArgument Pattern = Params[ParamIdx].getPackExpansionPattern();
- // Compute the set of template parameter indices that correspond to
- // parameter packs expanded by the pack expansion.
- SmallVector<unsigned, 2> PackIndices;
- {
- llvm::SmallBitVector SawIndices(TemplateParams->size());
- SmallVector<UnexpandedParameterPack, 2> Unexpanded;
- S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
- for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
- unsigned Depth, Index;
- llvm::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
- if (Depth == 0 && !SawIndices[Index]) {
- SawIndices[Index] = true;
- PackIndices.push_back(Index);
- }
- }
- }
- assert(!PackIndices.empty() && "Pack expansion without unexpanded packs?");
-
// 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.
- // Save the deduced template arguments for each parameter pack expanded
- // by this pack expansion, then clear out the deduction.
- SmallVector<DeducedTemplateArgument, 2>
- SavedPacks(PackIndices.size());
- NewlyDeducedPacksType NewlyDeducedPacks(PackIndices.size());
- PrepareArgumentPackDeduction(S, Deduced, PackIndices, SavedPacks,
- NewlyDeducedPacks);
+ // 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).
bool HasAnyArguments = false;
- while (hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs)) {
+ for (; hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs); ++ArgIdx) {
HasAnyArguments = true;
// Deduce template arguments from the pattern.
@@ -1888,26 +1921,12 @@ DeduceTemplateArguments(Sema &S,
Info, Deduced))
return Result;
- // Capture the deduced template arguments for each parameter pack expanded
- // by this pack expansion, add them to the list of arguments we've deduced
- // for that pack, then clear out the deduced argument.
- for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
- DeducedTemplateArgument &DeducedArg = Deduced[PackIndices[I]];
- if (!DeducedArg.isNull()) {
- NewlyDeducedPacks[I].push_back(DeducedArg);
- DeducedArg = DeducedTemplateArgument();
- }
- }
-
- ++ArgIdx;
+ PackScope.nextPackElement();
}
// Build argument packs for each of the parameter packs expanded by this
// pack expansion.
- if (Sema::TemplateDeductionResult Result
- = FinishArgumentPackDeduction(S, TemplateParams, HasAnyArguments,
- Deduced, PackIndices, SavedPacks,
- NewlyDeducedPacks, Info))
+ if (auto Result = PackScope.finish(HasAnyArguments))
return Result;
}
@@ -2013,21 +2032,21 @@ getTrivialTemplateArgumentLoc(Sema &S,
case TemplateArgument::Declaration: {
Expr *E
= S.BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc)
- .takeAs<Expr>();
+ .getAs<Expr>();
return TemplateArgumentLoc(TemplateArgument(E), E);
}
case TemplateArgument::NullPtr: {
Expr *E
= S.BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc)
- .takeAs<Expr>();
+ .getAs<Expr>();
return TemplateArgumentLoc(TemplateArgument(NTTPType, /*isNullPtr*/true),
E);
}
case TemplateArgument::Integral: {
Expr *E
- = S.BuildExpressionFromIntegralTemplateArgument(Arg, Loc).takeAs<Expr>();
+ = S.BuildExpressionFromIntegralTemplateArgument(Arg, Loc).getAs<Expr>();
return TemplateArgumentLoc(TemplateArgument(E), E);
}
@@ -2076,13 +2095,11 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
// This is a template argument pack, so check each of its arguments against
// the template parameter.
SmallVector<TemplateArgument, 2> PackedArgsBuilder;
- for (TemplateArgument::pack_iterator PA = Arg.pack_begin(),
- PAEnd = Arg.pack_end();
- PA != PAEnd; ++PA) {
+ for (const auto &P : Arg.pack_elements()) {
// When converting the deduced template argument, append it to the
// general output list. We need to do this so that the template argument
// checking logic has all of the prior template arguments available.
- DeducedTemplateArgument InnerArg(*PA);
+ DeducedTemplateArgument InnerArg(P);
InnerArg.setDeducedFromArrayBound(Arg.wasDeducedFromArrayBound());
if (ConvertDeducedTemplateArgument(S, Param, InnerArg, Template,
NTTPType, PackedArgsBuilder.size(),
@@ -2274,8 +2291,8 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
return Result;
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end());
- InstantiatingTemplate Inst(*this, Partial->getLocation(), Partial,
- DeducedArgs, Info);
+ InstantiatingTemplate Inst(*this, Info.getLocation(), Partial, DeducedArgs,
+ Info);
if (Inst.isInvalid())
return TDK_InstantiationDepth;
@@ -2438,8 +2455,8 @@ Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
return Result;
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end());
- InstantiatingTemplate Inst(*this, Partial->getLocation(), Partial,
- DeducedArgs, Info);
+ InstantiatingTemplate Inst(*this, Info.getLocation(), Partial, DeducedArgs,
+ Info);
if (Inst.isInvalid())
return TDK_InstantiationDepth;
@@ -2454,7 +2471,7 @@ Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
static bool isSimpleTemplateIdType(QualType T) {
if (const TemplateSpecializationType *Spec
= T->getAs<TemplateSpecializationType>())
- return Spec->getTemplateName().getAsTemplateDecl() != 0;
+ return Spec->getTemplateName().getAsTemplateDecl() != nullptr;
return false;
}
@@ -2498,11 +2515,8 @@ Sema::SubstituteExplicitTemplateArguments(
if (ExplicitTemplateArgs.size() == 0) {
// No arguments to substitute; just copy over the parameter types and
// fill in the function type.
- for (FunctionDecl::param_iterator P = Function->param_begin(),
- PEnd = Function->param_end();
- P != PEnd;
- ++P)
- ParamTypes.push_back((*P)->getType());
+ for (auto P : Function->params())
+ ParamTypes.push_back(P->getType());
if (FunctionType)
*FunctionType = Function->getType();
@@ -2524,8 +2538,8 @@ Sema::SubstituteExplicitTemplateArguments(
// explicitly-specified template arguments against this function template,
// and then substitute them into the function parameter types.
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end());
- InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
- FunctionTemplate, DeducedArgs,
+ InstantiatingTemplate Inst(*this, Info.getLocation(), FunctionTemplate,
+ DeducedArgs,
ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution,
Info);
if (Inst.isInvalid())
@@ -2596,7 +2610,7 @@ Sema::SubstituteExplicitTemplateArguments(
// and the end of the function-definition, member-declarator, or
// declarator.
unsigned ThisTypeQuals = 0;
- CXXRecordDecl *ThisContext = 0;
+ CXXRecordDecl *ThisContext = nullptr;
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) {
ThisContext = Method->getParent();
ThisTypeQuals = Method->getTypeQualifiers();
@@ -2604,11 +2618,11 @@ Sema::SubstituteExplicitTemplateArguments(
CXXThisScopeRAII ThisScope(*this, ThisContext, ThisTypeQuals,
getLangOpts().CPlusPlus11);
-
- ResultType = SubstType(Proto->getResultType(),
- MultiLevelTemplateArgumentList(*ExplicitArgumentList),
- Function->getTypeSpecStartLoc(),
- Function->getDeclName());
+
+ ResultType =
+ SubstType(Proto->getReturnType(),
+ MultiLevelTemplateArgumentList(*ExplicitArgumentList),
+ Function->getTypeSpecStartLoc(), Function->getDeclName());
if (ResultType.isNull() || Trap.hasErrorOccurred())
return TDK_SubstitutionFailure;
}
@@ -2778,8 +2792,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
// Enter a new template instantiation context while we instantiate the
// actual function declaration.
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end());
- InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
- FunctionTemplate, DeducedArgs,
+ InstantiatingTemplate Inst(*this, Info.getLocation(), FunctionTemplate,
+ DeducedArgs,
ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution,
Info);
if (Inst.isInvalid())
@@ -2800,9 +2814,19 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
// argument, because it was explicitly-specified. Just record the
// presence of this argument.
Builder.push_back(Deduced[I]);
+ // We may have had explicitly-specified template arguments for a
+ // template parameter pack (that may or may not have been extended
+ // via additional deduced arguments).
+ if (Param->isParameterPack() && CurrentInstantiationScope) {
+ if (CurrentInstantiationScope->getPartiallySubstitutedPack() ==
+ Param) {
+ // Forget the partially-substituted pack; its substitution is now
+ // complete.
+ CurrentInstantiationScope->ResetPartiallySubstitutedPack();
+ }
+ }
continue;
}
-
// We have deduced this argument, so it still needs to be
// checked and converted.
@@ -2976,8 +3000,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
static QualType GetTypeOfFunction(Sema &S, const OverloadExpr::FindResult &R,
FunctionDecl *Fn) {
// We may need to deduce the return type of the function now.
- if (S.getLangOpts().CPlusPlus1y && Fn->getResultType()->isUndeducedType() &&
- S.DeduceReturnType(Fn, R.Expression->getExprLoc(), /*Diagnose*/false))
+ if (S.getLangOpts().CPlusPlus1y && Fn->getReturnType()->isUndeducedType() &&
+ S.DeduceReturnType(Fn, R.Expression->getExprLoc(), /*Diagnose*/ false))
return QualType();
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn))
@@ -3048,7 +3072,7 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
return QualType();
// Otherwise, see if we can resolve a function type
- FunctionDecl *Specialization = 0;
+ FunctionDecl *Specialization = nullptr;
TemplateDeductionInfo Info(Ovl->getNameLoc());
if (S.DeduceTemplateArguments(FunTmpl, &ExplicitTemplateArgs,
Specialization, Info))
@@ -3140,7 +3164,7 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,
if (ArgType == S.Context.OverloadTy) {
ArgType = ResolveOverloadForDeduction(S, TemplateParams,
Arg, ParamType,
- ParamRefType != 0);
+ ParamRefType != nullptr);
if (ArgType.isNull())
return true;
}
@@ -3309,7 +3333,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
*ExplicitTemplateArgs,
Deduced,
ParamTypes,
- 0,
+ nullptr,
Info);
if (Result)
return Result;
@@ -3399,30 +3423,9 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
break;
QualType ParamPattern = ParamExpansion->getPattern();
- SmallVector<unsigned, 2> PackIndices;
- {
- llvm::SmallBitVector SawIndices(TemplateParams->size());
- SmallVector<UnexpandedParameterPack, 2> Unexpanded;
- collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
- for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
- unsigned Depth, Index;
- llvm::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
- if (Depth == 0 && !SawIndices[Index]) {
- SawIndices[Index] = true;
- PackIndices.push_back(Index);
- }
- }
- }
- assert(!PackIndices.empty() && "Pack expansion without unexpanded packs?");
+ PackDeductionScope PackScope(*this, TemplateParams, Deduced, Info,
+ ParamPattern);
- // 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).
- NewlyDeducedPacksType NewlyDeducedPacks(PackIndices.size());
- SmallVector<DeducedTemplateArgument, 2>
- SavedPacks(PackIndices.size());
- PrepareArgumentPackDeduction(*this, Deduced, PackIndices, SavedPacks,
- NewlyDeducedPacks);
bool HasAnyArguments = false;
for (; ArgIdx < Args.size(); ++ArgIdx) {
HasAnyArguments = true;
@@ -3431,7 +3434,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
ParamType = OrigParamType;
Expr *Arg = Args[ArgIdx];
QualType ArgType = Arg->getType();
-
+
unsigned TDF = 0;
if (AdjustFunctionParmAndArgTypesForDeduction(*this, TemplateParams,
ParamType, ArgType, Arg,
@@ -3472,24 +3475,12 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
return Result;
}
- // Capture the deduced template arguments for each parameter pack expanded
- // by this pack expansion, add them to the list of arguments we've deduced
- // for that pack, then clear out the deduced argument.
- for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
- DeducedTemplateArgument &DeducedArg = Deduced[PackIndices[I]];
- if (!DeducedArg.isNull()) {
- NewlyDeducedPacks[I].push_back(DeducedArg);
- DeducedArg = DeducedTemplateArgument();
- }
- }
+ PackScope.nextPackElement();
}
// Build argument packs for each of the parameter packs expanded by this
// pack expansion.
- if (Sema::TemplateDeductionResult Result
- = FinishArgumentPackDeduction(*this, TemplateParams, HasAnyArguments,
- Deduced, PackIndices, SavedPacks,
- NewlyDeducedPacks, Info))
+ if (auto Result = PackScope.finish(HasAnyArguments))
return Result;
// After we've matching against a parameter pack, we're done.
@@ -3589,7 +3580,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
// type so that we treat it as a non-deduced context in what follows.
bool HasDeducedReturnType = false;
if (getLangOpts().CPlusPlus1y && InOverloadResolution &&
- Function->getResultType()->getContainedAutoType()) {
+ Function->getReturnType()->getContainedAutoType()) {
FunctionType = SubstAutoType(FunctionType, Context.DependentTy);
HasDeducedReturnType = true;
}
@@ -3614,7 +3605,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
// If the function has a deduced return type, deduce it now, so we can check
// that the deduced function type matches the requested type.
if (HasDeducedReturnType &&
- Specialization->getResultType()->isUndeducedType() &&
+ Specialization->getReturnType()->isUndeducedType() &&
DeduceReturnType(Specialization, Info.getLocation(), false))
return TDK_MiscellaneousDeductionFailure;
@@ -3643,7 +3634,7 @@ static inline void
SubstAutoWithinFunctionReturnType(FunctionDecl *F,
QualType TypeToReplaceAutoWith, Sema &S) {
assert(!TypeToReplaceAutoWith->getContainedAutoType());
- QualType AutoResultType = F->getResultType();
+ QualType AutoResultType = F->getReturnType();
assert(AutoResultType->getContainedAutoType());
QualType DeducedResultType = S.SubstAutoType(AutoResultType,
TypeToReplaceAutoWith);
@@ -3668,14 +3659,14 @@ SpecializeCorrespondingLambdaCallOperatorAndInvoker(
assert(LambdaClass && LambdaClass->isGenericLambda());
CXXMethodDecl *CallOpGeneric = LambdaClass->getLambdaCallOperator();
- QualType CallOpResultType = CallOpGeneric->getResultType();
+ QualType CallOpResultType = CallOpGeneric->getReturnType();
const bool GenericLambdaCallOperatorHasDeducedReturnType =
CallOpResultType->getContainedAutoType();
FunctionTemplateDecl *CallOpTemplate =
CallOpGeneric->getDescribedFunctionTemplate();
- FunctionDecl *CallOpSpecialized = 0;
+ FunctionDecl *CallOpSpecialized = nullptr;
// Use the deduced arguments of the conversion function, to specialize our
// generic lambda's call operator.
if (Sema::TemplateDeductionResult Result
@@ -3685,15 +3676,15 @@ SpecializeCorrespondingLambdaCallOperatorAndInvoker(
return Result;
// If we need to deduce the return type, do so (instantiates the callop).
- if (GenericLambdaCallOperatorHasDeducedReturnType &&
- CallOpSpecialized->getResultType()->isUndeducedType())
+ if (GenericLambdaCallOperatorHasDeducedReturnType &&
+ CallOpSpecialized->getReturnType()->isUndeducedType())
S.DeduceReturnType(CallOpSpecialized,
CallOpSpecialized->getPointOfInstantiation(),
/*Diagnose*/ true);
// Check to see if the return type of the destination ptr-to-function
// matches the return type of the call operator.
- if (!S.Context.hasSameType(CallOpSpecialized->getResultType(),
+ if (!S.Context.hasSameType(CallOpSpecialized->getReturnType(),
ReturnTypeOfDestFunctionPtr))
return Sema::TDK_NonDeducedMismatch;
// Since we have succeeded in matching the source and destination
@@ -3701,7 +3692,7 @@ SpecializeCorrespondingLambdaCallOperatorAndInvoker(
// specialized our corresponding call operator, we are ready to
// specialize the static invoker with the deduced arguments of our
// ptr-to-function.
- FunctionDecl *InvokerSpecialized = 0;
+ FunctionDecl *InvokerSpecialized = nullptr;
FunctionTemplateDecl *InvokerTemplate = LambdaClass->
getLambdaStaticInvoker()->getDescribedFunctionTemplate();
@@ -3712,8 +3703,8 @@ SpecializeCorrespondingLambdaCallOperatorAndInvoker(
"If the call operator succeeded so should the invoker!");
// Set the result type to match the corresponding call operator
// specialization's result type.
- if (GenericLambdaCallOperatorHasDeducedReturnType &&
- InvokerSpecialized->getResultType()->isUndeducedType()) {
+ if (GenericLambdaCallOperatorHasDeducedReturnType &&
+ InvokerSpecialized->getReturnType()->isUndeducedType()) {
// Be sure to get the type to replace 'auto' with and not
// the full result type of the call op specialization
// to substitute into the 'auto' of the invoker and conversion
@@ -3722,9 +3713,9 @@ SpecializeCorrespondingLambdaCallOperatorAndInvoker(
// int* (*fp)(int*) = [](auto* a) -> auto* { return a; };
// We don't want to subst 'int*' into 'auto' to get int**.
- QualType TypeToReplaceAutoWith =
- CallOpSpecialized->getResultType()->
- getContainedAutoType()->getDeducedType();
+ QualType TypeToReplaceAutoWith = CallOpSpecialized->getReturnType()
+ ->getContainedAutoType()
+ ->getDeducedType();
SubstAutoWithinFunctionReturnType(InvokerSpecialized,
TypeToReplaceAutoWith, S);
SubstAutoWithinFunctionReturnType(ConversionSpecialized,
@@ -3740,7 +3731,7 @@ SpecializeCorrespondingLambdaCallOperatorAndInvoker(
FunctionProtoType::ExtProtoInfo EPI = InvokerFPT->getExtProtoInfo();
EPI.TypeQuals = 0;
InvokerSpecialized->setType(S.Context.getFunctionType(
- InvokerFPT->getResultType(), InvokerFPT->getArgTypes(),EPI));
+ InvokerFPT->getReturnType(), InvokerFPT->getParamTypes(), EPI));
return Sema::TDK_Success;
}
/// \brief Deduce template arguments for a templated conversion
@@ -3844,7 +3835,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
// Create an Instantiation Scope for finalizing the operator.
LocalInstantiationScope InstScope(*this);
// Finish template argument deduction.
- FunctionDecl *ConversionSpecialized = 0;
+ FunctionDecl *ConversionSpecialized = nullptr;
TemplateDeductionResult Result
= FinishTemplateArgumentDeduction(ConversionTemplate, Deduced, 0,
ConversionSpecialized, Info);
@@ -3863,8 +3854,8 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
"Can only convert from lambda to ptr-to-function");
const FunctionType *ToFunType =
A->getPointeeType().getTypePtr()->getAs<FunctionType>();
- const QualType DestFunctionPtrReturnType = ToFunType->getResultType();
-
+ const QualType DestFunctionPtrReturnType = ToFunType->getReturnType();
+
// Create the corresponding specializations of the call operator and
// the static-invoker; and if the return type is auto,
// deduce the return type and check if it matches the
@@ -3978,7 +3969,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
ExprResult NonPlaceholder = CheckPlaceholderExpr(Init);
if (NonPlaceholder.isInvalid())
return DAR_FailedAlreadyDiagnosed;
- Init = NonPlaceholder.take();
+ Init = NonPlaceholder.get();
}
if (Init->isTypeDependent() || Type.getType()->isDependentType()) {
@@ -4013,8 +4004,8 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
// Build template<class TemplParam> void Func(FuncParam);
TemplateTypeParmDecl *TemplParam =
- TemplateTypeParmDecl::Create(Context, 0, SourceLocation(), Loc, 0, 0, 0,
- false, false);
+ TemplateTypeParmDecl::Create(Context, nullptr, SourceLocation(), Loc, 0, 0,
+ nullptr, false, false);
QualType TemplArg = QualType(TemplParam->getTypeForDecl(), 0);
NamedDecl *TemplParamPtr = TemplParam;
FixedSizeTemplateParameterList<1> TemplateParams(Loc, Loc, &TemplParamPtr,
@@ -4109,12 +4100,12 @@ void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) {
bool Sema::DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
bool Diagnose) {
- assert(FD->getResultType()->isUndeducedType());
+ assert(FD->getReturnType()->isUndeducedType());
if (FD->getTemplateInstantiationPattern())
InstantiateFunctionDefinition(Loc, FD);
- bool StillUndeduced = FD->getResultType()->isUndeducedType();
+ bool StillUndeduced = FD->getReturnType()->isUndeducedType();
if (StillUndeduced && Diagnose && !FD->isInvalidDecl()) {
Diag(Loc, diag::err_auto_fn_used_before_defined) << FD;
Diag(FD->getLocation(), diag::note_callee_decl) << FD;
@@ -4195,35 +4186,25 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
// otherwise, the ordering rules for static functions against non-static
// functions don't make any sense.
//
- // C++98/03 doesn't have this provision, so instead we drop the
- // first argument of the free function, which seems to match
- // existing practice.
+ // C++98/03 doesn't have this provision but we've extended DR532 to cover
+ // it as wording was broken prior to it.
SmallVector<QualType, 4> Args1;
- unsigned Skip1 = 0, Skip2 = 0;
unsigned NumComparedArguments = NumCallArguments1;
if (!Method2 && Method1 && !Method1->isStatic()) {
- if (S.getLangOpts().CPlusPlus11) {
- // Compare 'this' from Method1 against first parameter from Method2.
- AddImplicitObjectParameterType(S.Context, Method1, Args1);
- ++NumComparedArguments;
- } else
- // Ignore first parameter from Method2.
- ++Skip2;
+ // Compare 'this' from Method1 against first parameter from Method2.
+ AddImplicitObjectParameterType(S.Context, Method1, Args1);
+ ++NumComparedArguments;
} else if (!Method1 && Method2 && !Method2->isStatic()) {
- if (S.getLangOpts().CPlusPlus11)
- // Compare 'this' from Method2 against first parameter from Method1.
- AddImplicitObjectParameterType(S.Context, Method2, Args2);
- else
- // Ignore first parameter from Method1.
- ++Skip1;
+ // Compare 'this' from Method2 against first parameter from Method1.
+ AddImplicitObjectParameterType(S.Context, Method2, Args2);
}
- Args1.insert(Args1.end(),
- Proto1->arg_type_begin() + Skip1, Proto1->arg_type_end());
- Args2.insert(Args2.end(),
- Proto2->arg_type_begin() + Skip2, Proto2->arg_type_end());
+ Args1.insert(Args1.end(), Proto1->param_type_begin(),
+ Proto1->param_type_end());
+ Args2.insert(Args2.end(), Proto2->param_type_begin(),
+ Proto2->param_type_end());
// C++ [temp.func.order]p5:
// The presence of unused ellipsis and default arguments has no effect on
@@ -4236,7 +4217,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
Args1.data(), Args1.size(), Info, Deduced,
TDF_None, /*PartialOrdering=*/true,
RefParamComparisons))
- return false;
+ return false;
break;
}
@@ -4244,12 +4225,10 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
case TPOC_Conversion:
// - In the context of a call to a conversion operator, the return types
// of the conversion function templates are used.
- if (DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
- Proto2->getResultType(),
- Proto1->getResultType(),
- Info, Deduced, TDF_None,
- /*PartialOrdering=*/true,
- RefParamComparisons))
+ if (DeduceTemplateArgumentsByTypeMatch(
+ S, TemplateParams, Proto2->getReturnType(), Proto1->getReturnType(),
+ Info, Deduced, TDF_None,
+ /*PartialOrdering=*/true, RefParamComparisons))
return false;
break;
@@ -4293,9 +4272,8 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
break;
case TPOC_Conversion:
- ::MarkUsedTemplateParameters(S.Context, Proto2->getResultType(), false,
- TemplateParams->getDepth(),
- UsedParameters);
+ ::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(), false,
+ TemplateParams->getDepth(), UsedParameters);
break;
case TPOC_Other:
@@ -4362,7 +4340,7 @@ Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
unsigned NumCallArguments2) {
SmallVector<RefParamPartialOrderingComparison, 4> RefParamComparisons;
bool Better1 = isAtLeastAsSpecializedAs(*this, Loc, FT1, FT2, TPOC,
- NumCallArguments1, 0);
+ NumCallArguments1, nullptr);
bool Better2 = isAtLeastAsSpecializedAs(*this, Loc, FT2, FT1, TPOC,
NumCallArguments2,
&RefParamComparisons);
@@ -4371,7 +4349,7 @@ Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
return Better1? FT1 : FT2;
if (!Better1 && !Better2) // Neither is better than the other
- return 0;
+ return nullptr;
// C++0x [temp.deduct.partial]p10:
// If for each type being considered a given template is at least as
@@ -4397,13 +4375,13 @@ Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
RefParamComparisons[I].ParamIsRvalueRef) {
Better2 = true;
if (Better1)
- return 0;
+ return nullptr;
continue;
} else if (!RefParamComparisons[I].ParamIsRvalueRef &&
RefParamComparisons[I].ArgIsRvalueRef) {
Better1 = true;
if (Better2)
- return 0;
+ return nullptr;
continue;
}
@@ -4418,13 +4396,13 @@ Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
case ParamMoreQualified:
Better1 = true;
if (Better2)
- return 0;
+ return nullptr;
continue;
case ArgMoreQualified:
Better2 = true;
if (Better1)
- return 0;
+ return nullptr;
continue;
}
@@ -4445,7 +4423,7 @@ Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
if (Variadic1 != Variadic2)
return Variadic1? FT2 : FT1;
- return 0;
+ return nullptr;
}
/// \brief Determine if the two templates are equivalent.
@@ -4610,11 +4588,10 @@ Sema::getMoreSpecializedPartialSpecialization(
PS2->getTemplateParameters(),
PT2, PT1, Info, Deduced, TDF_None,
/*PartialOrdering=*/true,
- /*RefParamComparisons=*/0);
+ /*RefParamComparisons=*/nullptr);
if (Better1) {
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),Deduced.end());
- InstantiatingTemplate Inst(*this, PS2->getLocation(), PS2, DeducedArgs,
- Info);
+ InstantiatingTemplate Inst(*this, Loc, PS2, DeducedArgs, Info);
Better1 = !::FinishTemplateArgumentDeduction(
*this, PS2, PS1->getTemplateArgs(), Deduced, Info);
}
@@ -4625,18 +4602,17 @@ Sema::getMoreSpecializedPartialSpecialization(
bool Better2 = !DeduceTemplateArgumentsByTypeMatch(
*this, PS1->getTemplateParameters(), PT1, PT2, Info, Deduced, TDF_None,
/*PartialOrdering=*/true,
- /*RefParamComparisons=*/0);
+ /*RefParamComparisons=*/nullptr);
if (Better2) {
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),
Deduced.end());
- InstantiatingTemplate Inst(*this, PS1->getLocation(), PS1, DeducedArgs,
- Info);
+ InstantiatingTemplate Inst(*this, Loc, PS1, DeducedArgs, Info);
Better2 = !::FinishTemplateArgumentDeduction(
*this, PS1, PS2->getTemplateArgs(), Deduced, Info);
}
if (Better1 == Better2)
- return 0;
+ return nullptr;
return Better1 ? PS1 : PS2;
}
@@ -4653,7 +4629,7 @@ Sema::getMoreSpecializedPartialSpecialization(
SmallVector<DeducedTemplateArgument, 4> Deduced;
TemplateDeductionInfo Info(Loc);
- assert(PS1->getSpecializedTemplate() == PS1->getSpecializedTemplate() &&
+ assert(PS1->getSpecializedTemplate() == PS2->getSpecializedTemplate() &&
"the partial specializations being compared should specialize"
" the same template.");
TemplateName Name(PS1->getSpecializedTemplate());
@@ -4670,12 +4646,11 @@ Sema::getMoreSpecializedPartialSpecialization(
bool Better1 = !DeduceTemplateArgumentsByTypeMatch(
*this, PS2->getTemplateParameters(), PT2, PT1, Info, Deduced, TDF_None,
/*PartialOrdering=*/true,
- /*RefParamComparisons=*/0);
+ /*RefParamComparisons=*/nullptr);
if (Better1) {
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),
Deduced.end());
- InstantiatingTemplate Inst(*this, PS2->getLocation(), PS2,
- DeducedArgs, Info);
+ InstantiatingTemplate Inst(*this, Loc, PS2, DeducedArgs, Info);
Better1 = !::FinishTemplateArgumentDeduction(*this, PS2,
PS1->getTemplateArgs(),
Deduced, Info);
@@ -4688,18 +4663,17 @@ Sema::getMoreSpecializedPartialSpecialization(
PS1->getTemplateParameters(),
PT1, PT2, Info, Deduced, TDF_None,
/*PartialOrdering=*/true,
- /*RefParamComparisons=*/0);
+ /*RefParamComparisons=*/nullptr);
if (Better2) {
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),Deduced.end());
- InstantiatingTemplate Inst(*this, PS1->getLocation(), PS1,
- DeducedArgs, Info);
+ InstantiatingTemplate Inst(*this, Loc, PS1, DeducedArgs, Info);
Better2 = !::FinishTemplateArgumentDeduction(*this, PS1,
PS2->getTemplateArgs(),
Deduced, Info);
}
if (Better1 == Better2)
- return 0;
+ return nullptr;
return Better1? PS1 : PS2;
}
@@ -4874,10 +4848,10 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
case Type::FunctionProto: {
const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
- MarkUsedTemplateParameters(Ctx, Proto->getResultType(), OnlyDeduced,
- Depth, Used);
- for (unsigned I = 0, N = Proto->getNumArgs(); I != N; ++I)
- MarkUsedTemplateParameters(Ctx, Proto->getArgType(I), OnlyDeduced,
+ 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);
break;
}
@@ -5061,10 +5035,8 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
break;
case TemplateArgument::Pack:
- for (TemplateArgument::pack_iterator P = TemplateArg.pack_begin(),
- PEnd = TemplateArg.pack_end();
- P != PEnd; ++P)
- MarkUsedTemplateParameters(Ctx, *P, OnlyDeduced, Depth, Used);
+ for (const auto &P : TemplateArg.pack_elements())
+ MarkUsedTemplateParameters(Ctx, P, OnlyDeduced, Depth, Used);
break;
}
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 8904f37..14c6405 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -76,8 +76,18 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
// If this variable template specialization was instantiated from a
// specialized member that is a variable template, we're done.
assert(Spec->getSpecializedTemplate() && "No variable template?");
- if (Spec->getSpecializedTemplate()->isMemberSpecialization())
- return Result;
+ llvm::PointerUnion<VarTemplateDecl*,
+ VarTemplatePartialSpecializationDecl*> Specialized
+ = Spec->getSpecializedTemplateOrPartial();
+ if (VarTemplatePartialSpecializationDecl *Partial =
+ Specialized.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
+ if (Partial->isMemberSpecialization())
+ return Result;
+ } else {
+ VarTemplateDecl *Tmpl = Specialized.get<VarTemplateDecl *>();
+ if (Tmpl->isMemberSpecialization())
+ return Result;
+ }
}
// If we have a template template parameter with translation unit context,
@@ -190,50 +200,49 @@ bool Sema::ActiveTemplateInstantiation::isInstantiationRecord() const {
llvm_unreachable("Invalid InstantiationKind!");
}
-Sema::InstantiatingTemplate::
-InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- Decl *Entity,
- SourceRange InstantiationRange)
- : SemaRef(SemaRef),
- SavedInNonInstantiationSFINAEContext(
- SemaRef.InNonInstantiationSFINAEContext)
-{
- Invalid = CheckInstantiationDepth(PointOfInstantiation,
- InstantiationRange);
+void Sema::InstantiatingTemplate::Initialize(
+ ActiveTemplateInstantiation::InstantiationKind Kind,
+ SourceLocation PointOfInstantiation, SourceRange InstantiationRange,
+ Decl *Entity, NamedDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
+ sema::TemplateDeductionInfo *DeductionInfo) {
+ SavedInNonInstantiationSFINAEContext =
+ SemaRef.InNonInstantiationSFINAEContext;
+ Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
if (!Invalid) {
ActiveTemplateInstantiation Inst;
- Inst.Kind = ActiveTemplateInstantiation::TemplateInstantiation;
+ Inst.Kind = Kind;
Inst.PointOfInstantiation = PointOfInstantiation;
Inst.Entity = Entity;
- Inst.TemplateArgs = 0;
- Inst.NumTemplateArgs = 0;
+ Inst.Template = Template;
+ Inst.TemplateArgs = TemplateArgs.data();
+ Inst.NumTemplateArgs = TemplateArgs.size();
+ Inst.DeductionInfo = DeductionInfo;
Inst.InstantiationRange = InstantiationRange;
SemaRef.InNonInstantiationSFINAEContext = false;
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+ if (!Inst.isInstantiationRecord())
+ ++SemaRef.NonInstantiationEntries;
}
}
Sema::InstantiatingTemplate::
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ Decl *Entity,
+ SourceRange InstantiationRange)
+ : SemaRef(SemaRef)
+{
+ Initialize(ActiveTemplateInstantiation::TemplateInstantiation,
+ PointOfInstantiation, InstantiationRange, Entity);
+}
+
+Sema::InstantiatingTemplate::
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
FunctionDecl *Entity, ExceptionSpecification,
SourceRange InstantiationRange)
- : SemaRef(SemaRef),
- SavedInNonInstantiationSFINAEContext(
- SemaRef.InNonInstantiationSFINAEContext)
+ : SemaRef(SemaRef)
{
- Invalid = CheckInstantiationDepth(PointOfInstantiation,
- InstantiationRange);
- if (!Invalid) {
- ActiveTemplateInstantiation Inst;
- Inst.Kind = ActiveTemplateInstantiation::ExceptionSpecInstantiation;
- Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Entity = Entity;
- Inst.TemplateArgs = 0;
- Inst.NumTemplateArgs = 0;
- Inst.InstantiationRange = InstantiationRange;
- SemaRef.InNonInstantiationSFINAEContext = false;
- SemaRef.ActiveTemplateInstantiations.push_back(Inst);
- }
+ Initialize(ActiveTemplateInstantiation::ExceptionSpecInstantiation,
+ PointOfInstantiation, InstantiationRange, Entity);
}
Sema::InstantiatingTemplate::
@@ -241,24 +250,11 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
TemplateDecl *Template,
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange)
- : SemaRef(SemaRef),
- SavedInNonInstantiationSFINAEContext(
- SemaRef.InNonInstantiationSFINAEContext)
+ : SemaRef(SemaRef)
{
- Invalid = CheckInstantiationDepth(PointOfInstantiation,
- InstantiationRange);
- if (!Invalid) {
- ActiveTemplateInstantiation Inst;
- Inst.Kind
- = ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation;
- Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Entity = Template;
- Inst.TemplateArgs = TemplateArgs.data();
- Inst.NumTemplateArgs = TemplateArgs.size();
- Inst.InstantiationRange = InstantiationRange;
- SemaRef.InNonInstantiationSFINAEContext = false;
- SemaRef.ActiveTemplateInstantiations.push_back(Inst);
- }
+ Initialize(ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation,
+ PointOfInstantiation, InstantiationRange,
+ Template, nullptr, TemplateArgs);
}
Sema::InstantiatingTemplate::
@@ -268,26 +264,10 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
ActiveTemplateInstantiation::InstantiationKind Kind,
sema::TemplateDeductionInfo &DeductionInfo,
SourceRange InstantiationRange)
- : SemaRef(SemaRef),
- SavedInNonInstantiationSFINAEContext(
- SemaRef.InNonInstantiationSFINAEContext)
+ : SemaRef(SemaRef)
{
- Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
- if (!Invalid) {
- ActiveTemplateInstantiation Inst;
- Inst.Kind = Kind;
- Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Entity = FunctionTemplate;
- Inst.TemplateArgs = TemplateArgs.data();
- Inst.NumTemplateArgs = TemplateArgs.size();
- Inst.DeductionInfo = &DeductionInfo;
- Inst.InstantiationRange = InstantiationRange;
- SemaRef.InNonInstantiationSFINAEContext = false;
- SemaRef.ActiveTemplateInstantiations.push_back(Inst);
-
- if (!Inst.isInstantiationRecord())
- ++SemaRef.NonInstantiationEntries;
- }
+ Initialize(Kind, PointOfInstantiation, InstantiationRange,
+ FunctionTemplate, nullptr, TemplateArgs, &DeductionInfo);
}
Sema::InstantiatingTemplate::
@@ -296,23 +276,11 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
ArrayRef<TemplateArgument> TemplateArgs,
sema::TemplateDeductionInfo &DeductionInfo,
SourceRange InstantiationRange)
- : SemaRef(SemaRef),
- SavedInNonInstantiationSFINAEContext(
- SemaRef.InNonInstantiationSFINAEContext)
+ : SemaRef(SemaRef)
{
- Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
- if (!Invalid) {
- ActiveTemplateInstantiation Inst;
- Inst.Kind = ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution;
- Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Entity = PartialSpec;
- Inst.TemplateArgs = TemplateArgs.data();
- Inst.NumTemplateArgs = TemplateArgs.size();
- Inst.DeductionInfo = &DeductionInfo;
- Inst.InstantiationRange = InstantiationRange;
- SemaRef.InNonInstantiationSFINAEContext = false;
- SemaRef.ActiveTemplateInstantiations.push_back(Inst);
- }
+ Initialize(ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution,
+ PointOfInstantiation, InstantiationRange,
+ PartialSpec, nullptr, TemplateArgs, &DeductionInfo);
}
Sema::InstantiatingTemplate::InstantiatingTemplate(
@@ -320,22 +288,11 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
VarTemplatePartialSpecializationDecl *PartialSpec,
ArrayRef<TemplateArgument> TemplateArgs,
sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
- : SemaRef(SemaRef), SavedInNonInstantiationSFINAEContext(
- SemaRef.InNonInstantiationSFINAEContext) {
- Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
- if (!Invalid) {
- ActiveTemplateInstantiation Inst;
- Inst.Kind =
- ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution;
- Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Entity = PartialSpec;
- Inst.TemplateArgs = TemplateArgs.data();
- Inst.NumTemplateArgs = TemplateArgs.size();
- Inst.DeductionInfo = &DeductionInfo;
- Inst.InstantiationRange = InstantiationRange;
- SemaRef.InNonInstantiationSFINAEContext = false;
- SemaRef.ActiveTemplateInstantiations.push_back(Inst);
- }
+ : SemaRef(SemaRef)
+{
+ Initialize(ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution,
+ PointOfInstantiation, InstantiationRange,
+ PartialSpec, nullptr, TemplateArgs, &DeductionInfo);
}
Sema::InstantiatingTemplate::
@@ -343,47 +300,24 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
ParmVarDecl *Param,
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange)
- : SemaRef(SemaRef),
- SavedInNonInstantiationSFINAEContext(
- SemaRef.InNonInstantiationSFINAEContext)
+ : SemaRef(SemaRef)
{
- Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
- if (!Invalid) {
- ActiveTemplateInstantiation Inst;
- Inst.Kind
- = ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation;
- Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Entity = Param;
- Inst.TemplateArgs = TemplateArgs.data();
- Inst.NumTemplateArgs = TemplateArgs.size();
- Inst.InstantiationRange = InstantiationRange;
- SemaRef.InNonInstantiationSFINAEContext = false;
- SemaRef.ActiveTemplateInstantiations.push_back(Inst);
- }
+ Initialize(ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation,
+ PointOfInstantiation, InstantiationRange,
+ Param, nullptr, TemplateArgs);
}
+
Sema::InstantiatingTemplate::
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
NamedDecl *Template, NonTypeTemplateParmDecl *Param,
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange)
- : SemaRef(SemaRef),
- SavedInNonInstantiationSFINAEContext(
- SemaRef.InNonInstantiationSFINAEContext)
+ : SemaRef(SemaRef)
{
- Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
- if (!Invalid) {
- ActiveTemplateInstantiation Inst;
- Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution;
- Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Template = Template;
- Inst.Entity = Param;
- Inst.TemplateArgs = TemplateArgs.data();
- Inst.NumTemplateArgs = TemplateArgs.size();
- Inst.InstantiationRange = InstantiationRange;
- SemaRef.InNonInstantiationSFINAEContext = false;
- SemaRef.ActiveTemplateInstantiations.push_back(Inst);
- }
+ Initialize(ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution,
+ PointOfInstantiation, InstantiationRange,
+ Param, Template, TemplateArgs);
}
Sema::InstantiatingTemplate::
@@ -391,23 +325,11 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
NamedDecl *Template, TemplateTemplateParmDecl *Param,
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange)
- : SemaRef(SemaRef),
- SavedInNonInstantiationSFINAEContext(
- SemaRef.InNonInstantiationSFINAEContext)
+ : SemaRef(SemaRef)
{
- Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
- if (!Invalid) {
- ActiveTemplateInstantiation Inst;
- Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution;
- Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Template = Template;
- Inst.Entity = Param;
- Inst.TemplateArgs = TemplateArgs.data();
- Inst.NumTemplateArgs = TemplateArgs.size();
- Inst.InstantiationRange = InstantiationRange;
- SemaRef.InNonInstantiationSFINAEContext = false;
- SemaRef.ActiveTemplateInstantiations.push_back(Inst);
- }
+ Initialize(ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution,
+ PointOfInstantiation, InstantiationRange,
+ Param, Template, TemplateArgs);
}
Sema::InstantiatingTemplate::
@@ -415,25 +337,11 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
TemplateDecl *Template, NamedDecl *Param,
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange)
- : SemaRef(SemaRef),
- SavedInNonInstantiationSFINAEContext(
- SemaRef.InNonInstantiationSFINAEContext)
+ : SemaRef(SemaRef)
{
- Invalid = false;
-
- ActiveTemplateInstantiation Inst;
- Inst.Kind = ActiveTemplateInstantiation::DefaultTemplateArgumentChecking;
- Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Template = Template;
- Inst.Entity = Param;
- Inst.TemplateArgs = TemplateArgs.data();
- Inst.NumTemplateArgs = TemplateArgs.size();
- Inst.InstantiationRange = InstantiationRange;
- SemaRef.InNonInstantiationSFINAEContext = false;
- SemaRef.ActiveTemplateInstantiations.push_back(Inst);
-
- assert(!Inst.isInstantiationRecord());
- ++SemaRef.NonInstantiationEntries;
+ Initialize(ActiveTemplateInstantiation::DefaultTemplateArgumentChecking,
+ PointOfInstantiation, InstantiationRange,
+ Param, Template, TemplateArgs);
}
void Sema::InstantiatingTemplate::Clear() {
@@ -624,8 +532,8 @@ void Sema::PrintInstantiationStack() {
std::string Name;
if (!Parm->getName().empty())
Name = std::string(" '") + Parm->getName().str() + "'";
-
- TemplateParameterList *TemplateParams = 0;
+
+ TemplateParameterList *TemplateParams = nullptr;
if (TemplateDecl *Template = dyn_cast<TemplateDecl>(Active->Template))
TemplateParams = Template->getTemplateParameters();
else
@@ -644,7 +552,7 @@ void Sema::PrintInstantiationStack() {
}
case ActiveTemplateInstantiation::DefaultTemplateArgumentChecking: {
- TemplateParameterList *TemplateParams = 0;
+ TemplateParameterList *TemplateParams = nullptr;
if (TemplateDecl *Template = dyn_cast<TemplateDecl>(Active->Template))
TemplateParams = Template->getTemplateParameters();
else
@@ -673,7 +581,7 @@ void Sema::PrintInstantiationStack() {
Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
if (InNonInstantiationSFINAEContext)
- return Optional<TemplateDeductionInfo *>(0);
+ return Optional<TemplateDeductionInfo *>(nullptr);
for (SmallVectorImpl<ActiveTemplateInstantiation>::const_reverse_iterator
Active = ActiveTemplateInstantiations.rbegin(),
@@ -789,7 +697,7 @@ namespace {
MultiLevelTemplateArgumentList &TemplateArgs
= const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
unsigned Depth, Index;
- llvm::tie(Depth, Index) = getDepthAndIndex(PartialPack);
+ std::tie(Depth, Index) = getDepthAndIndex(PartialPack);
if (TemplateArgs.hasTemplateArgument(Depth, Index)) {
Result = TemplateArgs(Depth, Index);
TemplateArgs.setArgument(Depth, Index, TemplateArgument());
@@ -808,7 +716,7 @@ namespace {
MultiLevelTemplateArgumentList &TemplateArgs
= const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
unsigned Depth, Index;
- llvm::tie(Depth, Index) = getDepthAndIndex(PartialPack);
+ std::tie(Depth, Index) = getDepthAndIndex(PartialPack);
TemplateArgs.setArgument(Depth, Index, Arg);
}
}
@@ -853,11 +761,11 @@ namespace {
NestedNameSpecifierLoc QualifierLoc,
QualType T);
- TemplateName TransformTemplateName(CXXScopeSpec &SS,
- TemplateName Name,
- SourceLocation NameLoc,
- QualType ObjectType = QualType(),
- NamedDecl *FirstQualifierInScope = 0);
+ TemplateName
+ TransformTemplateName(CXXScopeSpec &SS, TemplateName Name,
+ SourceLocation NameLoc,
+ QualType ObjectType = QualType(),
+ NamedDecl *FirstQualifierInScope = nullptr);
ExprResult TransformPredefinedExpr(PredefinedExpr *E);
ExprResult TransformDeclRefExpr(DeclRefExpr *E);
@@ -929,8 +837,6 @@ namespace {
OldCallOperator->getDescribedFunctionTemplate();
NewCallOperatorTemplate->setInstantiatedFromMemberTemplate(
OldCallOperatorTemplate);
- // Mark the NewCallOperatorTemplate a specialization.
- NewCallOperatorTemplate->setMemberSpecialization();
} else
// For a non-generic lambda we set the NewCallOperator to
// be an instantiation of the OldCallOperator.
@@ -940,7 +846,7 @@ namespace {
return inherited::TransformLambdaScope(E, NewCallOperator,
InitCaptureExprsAndTypes);
}
- TemplateParameterList *TransformTemplateParameterList(
+ TemplateParameterList *TransformTemplateParameterList(
TemplateParameterList *OrigTPL) {
if (!OrigTPL || !OrigTPL->size()) return OrigTPL;
@@ -979,7 +885,7 @@ getPackSubstitutedTemplateArgument(Sema &S, TemplateArgument Arg) {
Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
if (!D)
- return 0;
+ return nullptr;
if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) {
if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
@@ -1015,7 +921,7 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
Decl *TemplateInstantiator::TransformDefinition(SourceLocation Loc, Decl *D) {
Decl *Inst = getSema().SubstDecl(D, getSema().CurContext, TemplateArgs);
if (!Inst)
- return 0;
+ return nullptr;
getSema().CurrentInstantiationScope->InstantiatedLocal(D, Inst);
return Inst;
@@ -1039,8 +945,8 @@ TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D,
"Missing argument pack");
if (getSema().ArgumentPackSubstitutionIndex == -1)
- return 0;
-
+ return nullptr;
+
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
}
@@ -1053,7 +959,7 @@ TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D,
// The resulting type is not a tag; complain.
getSema().Diag(Loc, diag::err_nested_name_spec_non_tag) << T;
- return 0;
+ return nullptr;
}
}
@@ -1178,7 +1084,7 @@ TemplateName TemplateInstantiator::TransformTemplateName(CXXScopeSpec &SS,
ExprResult
TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) {
if (!E->isTypeDependent())
- return SemaRef.Owned(E);
+ return E;
return getSema().BuildPredefinedExpr(E->getLocation(), E->getIdentType());
}
@@ -1192,7 +1098,7 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
// arguments left unspecified.
if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(),
NTTP->getPosition()))
- return SemaRef.Owned(E);
+ return E;
TemplateArgument Arg = TemplateArgs(NTTP->getDepth(), NTTP->getPosition());
if (NTTP->isParameterPack()) {
@@ -1232,7 +1138,7 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
// case we just return that expression.
if (arg.getKind() == TemplateArgument::Expression) {
Expr *argExpr = arg.getAsExpr();
- result = SemaRef.Owned(argExpr);
+ result = argExpr;
type = argExpr->getType();
} else if (arg.getKind() == TemplateArgument::Declaration ||
@@ -1249,7 +1155,7 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
return ExprError();
} else {
// Propagate NULL template argument.
- VD = 0;
+ VD = nullptr;
}
// Derive the type we want the substituted decl to have. This had
@@ -1279,11 +1185,9 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
}
if (result.isInvalid()) return ExprError();
- Expr *resultExpr = result.take();
- return SemaRef.Owned(new (SemaRef.Context)
- SubstNonTypeTemplateParmExpr(type,
- resultExpr->getValueKind(),
- loc, parm, resultExpr));
+ Expr *resultExpr = result.get();
+ return new (SemaRef.Context) SubstNonTypeTemplateParmExpr(
+ type, resultExpr->getValueKind(), loc, parm, resultExpr);
}
ExprResult
@@ -1291,7 +1195,7 @@ TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
SubstNonTypeTemplateParmPackExpr *E) {
if (getSema().ArgumentPackSubstitutionIndex == -1) {
// We aren't expanding the parameter pack, so just return ourselves.
- return getSema().Owned(E);
+ return E;
}
TemplateArgument Arg = E->getArgumentPack();
@@ -1487,7 +1391,7 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
// the template parameter list of a member template inside the
// template we are instantiating). Create a new template type
// parameter with the template "level" reduced by one.
- TemplateTypeParmDecl *NewTTPDecl = 0;
+ TemplateTypeParmDecl *NewTTPDecl = nullptr;
if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
TransformDecl(TL.getNameLoc(), OldTTPDecl));
@@ -1580,7 +1484,7 @@ TypeSourceInfo *Sema::SubstType(TypeLoc TL,
"instantiation stack");
if (TL.getType().isNull())
- return 0;
+ return nullptr;
if (!TL.getType()->isInstantiationDependentType() &&
!TL.getType()->isVariablyModifiedType()) {
@@ -1596,7 +1500,7 @@ TypeSourceInfo *Sema::SubstType(TypeLoc TL,
TLB.reserve(TL.getFullDataSize());
QualType Result = Instantiator.TransformType(TLB, TL);
if (Result.isNull())
- return 0;
+ return nullptr;
return TLB.getTypeSourceInfo(Context, Result);
}
@@ -1628,8 +1532,8 @@ static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) {
return false;
FunctionProtoTypeLoc FP = TL.castAs<FunctionProtoTypeLoc>();
- for (unsigned I = 0, E = FP.getNumArgs(); I != E; ++I) {
- ParmVarDecl *P = FP.getArg(I);
+ for (unsigned I = 0, E = FP.getNumParams(); I != E; ++I) {
+ ParmVarDecl *P = FP.getParam(I);
// This must be synthesized from a typedef.
if (!P) continue;
@@ -1682,7 +1586,7 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
Result = Instantiator.TransformType(TLB, TL);
}
if (Result.isNull())
- return 0;
+ return nullptr;
return TLB.getTypeSourceInfo(Context, Result);
}
@@ -1693,8 +1597,8 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
Optional<unsigned> NumExpansions,
bool ExpectParameterPack) {
TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
- TypeSourceInfo *NewDI = 0;
-
+ TypeSourceInfo *NewDI = nullptr;
+
TypeLoc OldTL = OldDI->getTypeLoc();
if (PackExpansionTypeLoc ExpansionTL = OldTL.getAs<PackExpansionTypeLoc>()) {
@@ -1703,8 +1607,8 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
NewDI = SubstType(ExpansionTL.getPatternLoc(), TemplateArgs,
OldParm->getLocation(), OldParm->getDeclName());
if (!NewDI)
- return 0;
-
+ return nullptr;
+
if (NewDI->getType()->containsUnexpandedParameterPack()) {
// We still have unexpanded parameter packs, which means that
// our function parameter is still a function parameter pack.
@@ -1719,7 +1623,7 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
Diag(OldParm->getLocation(),
diag::err_function_parameter_pack_without_parameter_packs)
<< NewDI->getType();
- return 0;
+ return nullptr;
}
} else {
NewDI = SubstType(OldDI, TemplateArgs, OldParm->getLocation(),
@@ -1727,11 +1631,11 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
}
if (!NewDI)
- return 0;
+ return nullptr;
if (NewDI->getType()->isVoidType()) {
Diag(OldParm->getLocation(), diag::err_param_with_void_type);
- return 0;
+ return nullptr;
}
ParmVarDecl *NewParm = CheckParameter(Context.getTranslationUnitDecl(),
@@ -1741,8 +1645,8 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
NewDI->getType(), NewDI,
OldParm->getStorageClass());
if (!NewParm)
- return 0;
-
+ return nullptr;
+
// Mark the (new) default argument as uninstantiated (if any).
if (OldParm->hasUninstantiatedDefaultArg()) {
Expr *Arg = OldParm->getUninstantiatedDefaultArg();
@@ -1792,8 +1696,9 @@ bool Sema::SubstParmTypes(SourceLocation Loc,
TemplateInstantiator Instantiator(*this, TemplateArgs, Loc,
DeclarationName());
- return Instantiator.TransformFunctionTypeParams(Loc, Params, NumParams, 0,
- ParamTypes, OutParams);
+ return Instantiator.TransformFunctionTypeParams(Loc, Params, NumParams,
+ nullptr, ParamTypes,
+ OutParams);
}
/// \brief Perform substitution on the base class specifiers of the
@@ -1808,31 +1713,29 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
const MultiLevelTemplateArgumentList &TemplateArgs) {
bool Invalid = false;
SmallVector<CXXBaseSpecifier*, 4> InstantiatedBases;
- for (ClassTemplateSpecializationDecl::base_class_iterator
- Base = Pattern->bases_begin(), BaseEnd = Pattern->bases_end();
- Base != BaseEnd; ++Base) {
- if (!Base->getType()->isDependentType()) {
- if (const CXXRecordDecl *RD = Base->getType()->getAsCXXRecordDecl()) {
+ for (const auto Base : Pattern->bases()) {
+ if (!Base.getType()->isDependentType()) {
+ if (const CXXRecordDecl *RD = Base.getType()->getAsCXXRecordDecl()) {
if (RD->isInvalidDecl())
Instantiation->setInvalidDecl();
}
- InstantiatedBases.push_back(new (Context) CXXBaseSpecifier(*Base));
+ InstantiatedBases.push_back(new (Context) CXXBaseSpecifier(Base));
continue;
}
SourceLocation EllipsisLoc;
TypeSourceInfo *BaseTypeLoc;
- if (Base->isPackExpansion()) {
+ if (Base.isPackExpansion()) {
// This is a pack expansion. See whether we should expand it now, or
// wait until later.
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
- collectUnexpandedParameterPacks(Base->getTypeSourceInfo()->getTypeLoc(),
+ collectUnexpandedParameterPacks(Base.getTypeSourceInfo()->getTypeLoc(),
Unexpanded);
bool ShouldExpand = false;
bool RetainExpansion = false;
Optional<unsigned> NumExpansions;
- if (CheckParameterPacksForExpansion(Base->getEllipsisLoc(),
- Base->getSourceRange(),
+ if (CheckParameterPacksForExpansion(Base.getEllipsisLoc(),
+ Base.getSourceRange(),
Unexpanded,
TemplateArgs, ShouldExpand,
RetainExpansion,
@@ -1846,9 +1749,9 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
for (unsigned I = 0; I != *NumExpansions; ++I) {
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I);
- TypeSourceInfo *BaseTypeLoc = SubstType(Base->getTypeSourceInfo(),
+ TypeSourceInfo *BaseTypeLoc = SubstType(Base.getTypeSourceInfo(),
TemplateArgs,
- Base->getSourceRange().getBegin(),
+ Base.getSourceRange().getBegin(),
DeclarationName());
if (!BaseTypeLoc) {
Invalid = true;
@@ -1857,9 +1760,9 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
if (CXXBaseSpecifier *InstantiatedBase
= CheckBaseSpecifier(Instantiation,
- Base->getSourceRange(),
- Base->isVirtual(),
- Base->getAccessSpecifierAsWritten(),
+ Base.getSourceRange(),
+ Base.isVirtual(),
+ Base.getAccessSpecifierAsWritten(),
BaseTypeLoc,
SourceLocation()))
InstantiatedBases.push_back(InstantiatedBase);
@@ -1871,16 +1774,16 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
}
// The resulting base specifier will (still) be a pack expansion.
- EllipsisLoc = Base->getEllipsisLoc();
+ EllipsisLoc = Base.getEllipsisLoc();
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, -1);
- BaseTypeLoc = SubstType(Base->getTypeSourceInfo(),
+ BaseTypeLoc = SubstType(Base.getTypeSourceInfo(),
TemplateArgs,
- Base->getSourceRange().getBegin(),
+ Base.getSourceRange().getBegin(),
DeclarationName());
} else {
- BaseTypeLoc = SubstType(Base->getTypeSourceInfo(),
+ BaseTypeLoc = SubstType(Base.getTypeSourceInfo(),
TemplateArgs,
- Base->getSourceRange().getBegin(),
+ Base.getSourceRange().getBegin(),
DeclarationName());
}
@@ -1891,9 +1794,9 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
if (CXXBaseSpecifier *InstantiatedBase
= CheckBaseSpecifier(Instantiation,
- Base->getSourceRange(),
- Base->isVirtual(),
- Base->getAccessSpecifierAsWritten(),
+ Base.getSourceRange(),
+ Base.isVirtual(),
+ Base.getAccessSpecifierAsWritten(),
BaseTypeLoc,
EllipsisLoc))
InstantiatedBases.push_back(InstantiatedBase);
@@ -1945,7 +1848,7 @@ static bool DiagnoseUninstantiableTemplate(Sema &S,
S.Diag(PointOfInstantiation,
diag::err_implicit_instantiate_member_undefined)
<< S.Context.getTypeDeclType(Instantiation);
- S.Diag(Pattern->getLocation(), diag::note_member_of_template_here);
+ S.Diag(Pattern->getLocation(), diag::note_member_declared_at);
} else {
S.Diag(PointOfInstantiation, diag::err_template_instantiate_undefined)
<< (TSK != TSK_ImplicitInstantiation)
@@ -2008,7 +1911,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
Spec->setTemplateSpecializationKind(TSK);
Spec->setPointOfInstantiation(PointOfInstantiation);
}
-
+
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
if (Inst.isInvalid())
return true;
@@ -2030,7 +1933,12 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
// Start the definition of this instantiation.
Instantiation->startDefinition();
-
+
+ // The instantiation is visible here, even if it was first declared in an
+ // unimported module.
+ Instantiation->setHidden(false);
+
+ // FIXME: This loses the as-written tag kind for an explicit instantiation.
Instantiation->setTagKind(Pattern->getTagKind());
// Do substitution on the base class specifiers.
@@ -2045,9 +1953,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
LateInstantiatedAttrVec LateAttrs;
Instantiator.enableLateAttributeInstantiation(&LateAttrs);
- for (RecordDecl::decl_iterator Member = Pattern->decls_begin(),
- MemberEnd = Pattern->decls_end();
- Member != MemberEnd; ++Member) {
+ for (auto *Member : Pattern->decls()) {
// Don't instantiate members not belonging in this semantic context.
// e.g. for:
// @code
@@ -2057,19 +1963,19 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
// @endcode
// 'class B' has the template as lexical context but semantically it is
// introduced in namespace scope.
- if ((*Member)->getDeclContext() != Pattern)
+ if (Member->getDeclContext() != Pattern)
continue;
- if ((*Member)->isInvalidDecl()) {
+ if (Member->isInvalidDecl()) {
Instantiation->setInvalidDecl();
continue;
}
- Decl *NewMember = Instantiator.Visit(*Member);
+ Decl *NewMember = Instantiator.Visit(Member);
if (NewMember) {
if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember)) {
Fields.push_back(Field);
- FieldDecl *OldField = cast<FieldDecl>(*Member);
+ FieldDecl *OldField = cast<FieldDecl>(Member);
if (OldField->getInClassInitializer())
FieldsWithMemberInitializers.push_back(std::make_pair(OldField,
Field));
@@ -2105,8 +2011,8 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
}
// Finish checking fields.
- ActOnFields(0, Instantiation->getLocation(), Instantiation, Fields,
- SourceLocation(), SourceLocation(), 0);
+ ActOnFields(nullptr, Instantiation->getLocation(), Instantiation, Fields,
+ SourceLocation(), SourceLocation(), nullptr);
CheckCompletedCXXClass(Instantiation);
// Attach any in-class member initializers now the class is complete.
@@ -2124,16 +2030,14 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
FieldDecl *NewField = FieldsWithMemberInitializers[I].second;
Expr *OldInit = OldField->getInClassInitializer();
+ ActOnStartCXXInClassMemberInitializer();
ExprResult NewInit = SubstInitializer(OldInit, TemplateArgs,
/*CXXDirectInit=*/false);
- if (NewInit.isInvalid())
- NewField->setInvalidDecl();
- else {
- Expr *Init = NewInit.take();
- assert(Init && "no-argument initializer in class");
- assert(!isa<ParenListExpr>(Init) && "call-style init in class");
- ActOnCXXInClassMemberInitializer(NewField, Init->getLocStart(), Init);
- }
+ Expr *Init = NewInit.get();
+ assert((!Init || !isa<ParenListExpr>(Init)) &&
+ "call-style init in class");
+ ActOnFinishCXXInClassMemberInitializer(NewField,
+ Init ? Init->getLocStart() : SourceLocation(), Init);
}
}
// Instantiate late parsed attributes, and attach them to their decls.
@@ -2161,6 +2065,8 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
ActOnFinishDelayedMemberInitializers(Instantiation);
+ // FIXME: We should do something similar for explicit instantiations so they
+ // end up in the right module.
if (TSK == TSK_ImplicitInstantiation) {
Instantiation->setLocation(Pattern->getLocation());
Instantiation->setLocStart(Pattern->getInnerLocStart());
@@ -2250,6 +2156,10 @@ bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation,
if (Inst.isInvalid())
return true;
+ // The instantiation is visible here, even if it was first declared in an
+ // unimported module.
+ Instantiation->setHidden(false);
+
// Enter the scope of this instantiation. We don't use
// PushDeclContext because we don't have a scope.
ContextRAII SavedContext(*this, Instantiation);
@@ -2317,7 +2227,7 @@ bool Sema::InstantiateClassTemplateSpecialization(
return true;
ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
- CXXRecordDecl *Pattern = 0;
+ CXXRecordDecl *Pattern = nullptr;
// C++ [temp.class.spec.match]p1:
// When a class template is used in a context that requires an
@@ -2354,8 +2264,7 @@ bool Sema::InstantiateClassTemplateSpecialization(
// 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.
- SmallVector<const NamedDecl *, 4> InstantiatedTemplateParameters;
-
+
if (Matched.size() >= 1) {
SmallVectorImpl<MatchResult>::iterator Best = Matched.begin();
if (Matched.size() == 1) {
@@ -2459,16 +2368,17 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
CXXRecordDecl *Instantiation,
const MultiLevelTemplateArgumentList &TemplateArgs,
TemplateSpecializationKind TSK) {
+ // FIXME: We need to notify the ASTMutationListener that we did all of these
+ // things, in case we have an explicit instantiation definition in a PCM, a
+ // module, or preamble, and the declaration is in an imported AST.
assert(
(TSK == TSK_ExplicitInstantiationDefinition ||
TSK == TSK_ExplicitInstantiationDeclaration ||
(TSK == TSK_ImplicitInstantiation && Instantiation->isLocalClass())) &&
"Unexpected template specialization kind!");
- for (DeclContext::decl_iterator D = Instantiation->decls_begin(),
- DEnd = Instantiation->decls_end();
- D != DEnd; ++D) {
+ for (auto *D : Instantiation->decls()) {
bool SuppressNew = false;
- if (FunctionDecl *Function = dyn_cast<FunctionDecl>(*D)) {
+ if (auto *Function = dyn_cast<FunctionDecl>(D)) {
if (FunctionDecl *Pattern
= Function->getInstantiatedFromMemberFunction()) {
MemberSpecializationInfo *MSInfo
@@ -2485,31 +2395,30 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
SuppressNew) ||
SuppressNew)
continue;
-
- if (Function->isDefined())
+
+ // C++11 [temp.explicit]p8:
+ // An explicit instantiation definition that names a class template
+ // specialization explicitly instantiates the class template
+ // specialization and is only an explicit instantiation definition
+ // of members whose definition is visible at the point of
+ // instantiation.
+ if (TSK == TSK_ExplicitInstantiationDefinition && !Pattern->isDefined())
continue;
- if (TSK == TSK_ExplicitInstantiationDefinition) {
- // C++0x [temp.explicit]p8:
- // An explicit instantiation definition that names a class template
- // specialization explicitly instantiates the class template
- // specialization and is only an explicit instantiation definition
- // of members whose definition is visible at the point of
- // instantiation.
- if (!Pattern->isDefined())
- continue;
-
- Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);
-
+ Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+
+ if (Function->isDefined()) {
+ // Let the ASTConsumer know that this function has been explicitly
+ // instantiated now, and its linkage might have changed.
+ Consumer.HandleTopLevelDecl(DeclGroupRef(Function));
+ } else if (TSK == TSK_ExplicitInstantiationDefinition) {
InstantiateFunctionDefinition(PointOfInstantiation, Function);
- } else {
- Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);
- if (TSK == TSK_ImplicitInstantiation)
- PendingLocalImplicitInstantiations.push_back(
- std::make_pair(Function, PointOfInstantiation));
+ } else if (TSK == TSK_ImplicitInstantiation) {
+ PendingLocalImplicitInstantiations.push_back(
+ std::make_pair(Function, PointOfInstantiation));
}
}
- } else if (VarDecl *Var = dyn_cast<VarDecl>(*D)) {
+ } else if (auto *Var = dyn_cast<VarDecl>(D)) {
if (isa<VarTemplateSpecializationDecl>(Var))
continue;
@@ -2545,7 +2454,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
}
}
- } else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(*D)) {
+ } else if (auto *Record = dyn_cast<CXXRecordDecl>(D)) {
// Always skip the injected-class-name, along with any
// redeclarations of nested classes, since both would cause us
// to try to instantiate the members of a class twice.
@@ -2602,7 +2511,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
if (Pattern)
InstantiateClassMembers(PointOfInstantiation, Pattern, TemplateArgs,
TSK);
- } else if (EnumDecl *Enum = dyn_cast<EnumDecl>(*D)) {
+ } else if (auto *Enum = dyn_cast<EnumDecl>(D)) {
MemberSpecializationInfo *MSInfo = Enum->getMemberSpecializationInfo();
assert(MSInfo && "No member specialization information?");
@@ -2660,7 +2569,7 @@ Sema::InstantiateClassTemplateSpecializationMembers(
StmtResult
Sema::SubstStmt(Stmt *S, const MultiLevelTemplateArgumentList &TemplateArgs) {
if (!S)
- return Owned(S);
+ return S;
TemplateInstantiator Instantiator(*this, TemplateArgs,
SourceLocation(),
@@ -2671,7 +2580,7 @@ Sema::SubstStmt(Stmt *S, const MultiLevelTemplateArgumentList &TemplateArgs) {
ExprResult
Sema::SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) {
if (!E)
- return Owned(E);
+ return E;
TemplateInstantiator Instantiator(*this, TemplateArgs,
SourceLocation(),
@@ -2774,7 +2683,7 @@ LocalInstantiationScope::findInstantiationOf(const Decl *D) {
if (const TagDecl *Tag = dyn_cast<TagDecl>(CheckD))
CheckD = Tag->getPreviousDecl();
else
- CheckD = 0;
+ CheckD = nullptr;
} while (CheckD);
// If we aren't combined with our outer scope, we're done.
@@ -2786,13 +2695,13 @@ LocalInstantiationScope::findInstantiationOf(const Decl *D) {
// deduction, we may not have values for template parameters yet.
if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
isa<TemplateTemplateParmDecl>(D))
- return 0;
+ return nullptr;
// If we didn't find the decl, then we either have a sema bug, or we have a
// forward reference to a label declaration. Return null to indicate that
// we have an uninstantiated label.
assert(isa<LabelDecl>(D) && "declaration not instantiated in this scope");
- return 0;
+ return nullptr;
}
void LocalInstantiationScope::InstantiatedLocal(const Decl *D, Decl *Inst) {
@@ -2839,7 +2748,7 @@ NamedDecl *LocalInstantiationScope::getPartiallySubstitutedPack(
const TemplateArgument **ExplicitArgs,
unsigned *NumExplicitArgs) const {
if (ExplicitArgs)
- *ExplicitArgs = 0;
+ *ExplicitArgs = nullptr;
if (NumExplicitArgs)
*NumExplicitArgs = 0;
@@ -2857,6 +2766,6 @@ NamedDecl *LocalInstantiationScope::getPartiallySubstitutedPack(
if (!Current->CombineWithOuterScope)
break;
}
-
- return 0;
+
+ return nullptr;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 5c28e3b..accec95 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -12,13 +12,13 @@
#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/DependentDiagnostic.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/TypeLoc.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Template.h"
@@ -79,7 +79,7 @@ static void instantiateDependentAlignedAttr(
EnterExpressionEvaluationContext Unevaluated(S, Sema::ConstantEvaluated);
ExprResult Result = S.SubstExpr(Aligned->getAlignmentExpr(), TemplateArgs);
if (!Result.isInvalid())
- S.AddAlignedAttr(Aligned->getLocation(), New, Result.takeAs<Expr>(),
+ S.AddAlignedAttr(Aligned->getLocation(), New, Result.getAs<Expr>(),
Aligned->getSpellingListIndex(), IsPackExpansion);
} else {
TypeSourceInfo *Result = S.SubstType(Aligned->getAlignmentType(),
@@ -129,14 +129,46 @@ static void instantiateDependentAlignedAttr(
}
}
+static void instantiateDependentEnableIfAttr(
+ Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
+ const EnableIfAttr *A, const Decl *Tmpl, Decl *New) {
+ Expr *Cond = nullptr;
+ {
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated);
+ ExprResult Result = S.SubstExpr(A->getCond(), TemplateArgs);
+ if (Result.isInvalid())
+ return;
+ Cond = Result.getAs<Expr>();
+ }
+ if (A->getCond()->isTypeDependent() && !Cond->isTypeDependent()) {
+ ExprResult Converted = S.PerformContextuallyConvertToBool(Cond);
+ if (Converted.isInvalid())
+ return;
+ Cond = Converted.get();
+ }
+
+ SmallVector<PartialDiagnosticAt, 8> Diags;
+ if (A->getCond()->isValueDependent() && !Cond->isValueDependent() &&
+ !Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(Tmpl),
+ Diags)) {
+ S.Diag(A->getLocation(), diag::err_enable_if_never_constant_expr);
+ for (int I = 0, N = Diags.size(); I != N; ++I)
+ S.Diag(Diags[I].first, Diags[I].second);
+ return;
+ }
+
+ EnableIfAttr *EIA = new (S.getASTContext())
+ EnableIfAttr(A->getLocation(), S.getASTContext(), Cond,
+ A->getMessage(),
+ A->getSpellingListIndex());
+ New->addAttr(EIA);
+}
+
void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
const Decl *Tmpl, Decl *New,
LateInstantiatedAttrVec *LateAttrs,
LocalInstantiationScope *OuterMostScope) {
- for (AttrVec::const_iterator i = Tmpl->attr_begin(), e = Tmpl->attr_end();
- i != e; ++i) {
- const Attr *TmplAttr = *i;
-
+ for (const auto *TmplAttr : Tmpl->attrs()) {
// FIXME: This should be generalized to more than just the AlignedAttr.
const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr);
if (Aligned && Aligned->isAlignmentDependent()) {
@@ -144,11 +176,18 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
continue;
}
+ const EnableIfAttr *EnableIf = dyn_cast<EnableIfAttr>(TmplAttr);
+ if (EnableIf && EnableIf->getCond()->isValueDependent()) {
+ instantiateDependentEnableIfAttr(*this, TemplateArgs, EnableIf, Tmpl,
+ New);
+ continue;
+ }
+
assert(!TmplAttr->isPackExpansion());
if (TmplAttr->isLateParsed() && LateAttrs) {
// Late parsed attributes must be instantiated and attached after the
// enclosing class has been instantiated. See Sema::InstantiateClass.
- LocalInstantiationScope *Saved = 0;
+ LocalInstantiationScope *Saved = nullptr;
if (CurrentInstantiationScope)
Saved = CurrentInstantiationScope->cloneScopes(OuterMostScope);
LateAttrs->push_back(LateInstantiatedAttribute(TmplAttr, Saved, New));
@@ -258,7 +297,7 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D,
NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(D->getLocation(), Prev,
TemplateArgs);
if (!InstPrev)
- return 0;
+ return nullptr;
TypedefNameDecl *InstPrevTypedef = cast<TypedefNameDecl>(InstPrev);
@@ -296,11 +335,11 @@ TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
TemplateParameterList *TempParams = D->getTemplateParameters();
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
- return 0;
+ return nullptr;
TypeAliasDecl *Pattern = D->getTemplatedDecl();
- TypeAliasTemplateDecl *PrevAliasTemplate = 0;
+ TypeAliasTemplateDecl *PrevAliasTemplate = nullptr;
if (Pattern->getPreviousDecl()) {
DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName());
if (!Found.empty()) {
@@ -311,7 +350,7 @@ TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
TypeAliasDecl *AliasInst = cast_or_null<TypeAliasDecl>(
InstantiateTypedefNameDecl(Pattern, /*IsTypeAlias=*/true));
if (!AliasInst)
- return 0;
+ return nullptr;
TypeAliasTemplateDecl *Inst
= TypeAliasTemplateDecl::Create(SemaRef.Context, Owner, D->getLocation(),
@@ -341,7 +380,7 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
if (const RecordType *RecordTy = D->getType()->getAs<RecordType>())
if (RecordTy->getDecl()->isAnonymousStructOrUnion())
if (!VisitCXXRecordDecl(cast<CXXRecordDecl>(RecordTy->getDecl())))
- return 0;
+ return nullptr;
// Do substitution on the type of the declaration
TypeSourceInfo *DI = SemaRef.SubstType(D->getTypeSourceInfo(),
@@ -349,12 +388,12 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
D->getTypeSpecStartLoc(),
D->getDeclName());
if (!DI)
- return 0;
+ return nullptr;
if (DI->getType()->isFunctionType()) {
SemaRef.Diag(D->getLocation(), diag::err_variable_instantiates_to_function)
<< D->isStaticDataMember() << DI->getType();
- return 0;
+ return nullptr;
}
DeclContext *DC = Owner;
@@ -373,10 +412,19 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
// Substitute the nested name specifier, if any.
if (SubstQualifier(D, Var))
- return 0;
+ return nullptr;
SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs, Owner,
StartingScope, InstantiatingVarTemplate);
+
+ if (D->isNRVOVariable()) {
+ QualType ReturnType = cast<FunctionDecl>(DC)->getReturnType();
+ if (SemaRef.isCopyElisionCandidate(ReturnType, Var, false))
+ Var->setNRVOVariable(true);
+ }
+
+ Var->setImplicit(D->isImplicit());
+
return Var;
}
@@ -415,7 +463,7 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
Expr *BitWidth = D->getBitWidth();
if (Invalid)
- BitWidth = 0;
+ BitWidth = nullptr;
else if (BitWidth) {
// The bit-width expression is a constant expression.
EnterExpressionEvaluationContext Unevaluated(SemaRef,
@@ -425,9 +473,9 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
= SemaRef.SubstExpr(BitWidth, TemplateArgs);
if (InstantiatedBitWidth.isInvalid()) {
Invalid = true;
- BitWidth = 0;
+ BitWidth = nullptr;
} else
- BitWidth = InstantiatedBitWidth.takeAs<Expr>();
+ BitWidth = InstantiatedBitWidth.getAs<Expr>();
}
FieldDecl *Field = SemaRef.CheckFieldDecl(D->getDeclName(),
@@ -439,10 +487,10 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
D->getInClassInitStyle(),
D->getInnerLocStart(),
D->getAccess(),
- 0);
+ nullptr);
if (!Field) {
cast<Decl>(Owner)->setInvalidDecl();
- return 0;
+ return nullptr;
}
SemaRef.InstantiateAttrs(TemplateArgs, D, Field, LateAttrs, StartingScope);
@@ -476,7 +524,7 @@ Decl *TemplateDeclInstantiator::VisitMSPropertyDecl(MSPropertyDecl *D) {
if (DI->getType()->isVariablyModifiedType()) {
SemaRef.Diag(D->getLocation(), diag::err_property_is_variably_modified)
- << D->getName();
+ << D;
Invalid = true;
} else if (DI->getType()->isInstantiationDependentType()) {
DI = SemaRef.SubstType(DI, TemplateArgs,
@@ -499,11 +547,9 @@ Decl *TemplateDeclInstantiator::VisitMSPropertyDecl(MSPropertyDecl *D) {
SemaRef.MarkDeclarationsReferencedInType(D->getLocation(), DI->getType());
}
- MSPropertyDecl *Property = new (SemaRef.Context)
- MSPropertyDecl(Owner, D->getLocation(),
- D->getDeclName(), DI->getType(), DI,
- D->getLocStart(),
- D->getGetterId(), D->getSetterId());
+ MSPropertyDecl *Property = MSPropertyDecl::Create(
+ SemaRef.Context, Owner, D->getLocation(), D->getDeclName(), DI->getType(),
+ DI, D->getLocStart(), D->getGetterId(), D->getSetterId());
SemaRef.InstantiateAttrs(TemplateArgs, D, Property, LateAttrs,
StartingScope);
@@ -522,13 +568,11 @@ Decl *TemplateDeclInstantiator::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
new (SemaRef.Context)NamedDecl*[D->getChainingSize()];
int i = 0;
- for (IndirectFieldDecl::chain_iterator PI =
- D->chain_begin(), PE = D->chain_end();
- PI != PE; ++PI) {
- NamedDecl *Next = SemaRef.FindInstantiatedDecl(D->getLocation(), *PI,
+ for (auto *PI : D->chain()) {
+ NamedDecl *Next = SemaRef.FindInstantiatedDecl(D->getLocation(), PI,
TemplateArgs);
if (!Next)
- return 0;
+ return nullptr;
NamedChain[i++] = Next;
}
@@ -562,12 +606,12 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) {
D->getLocation(), DeclarationName());
}
if (!InstTy)
- return 0;
+ return nullptr;
FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getLocStart(),
D->getFriendLoc(), InstTy);
if (!FD)
- return 0;
+ return nullptr;
FD->setAccess(AS_public);
FD->setUnsupportedFriend(D->isUnsupportedFriend());
@@ -583,7 +627,7 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) {
// objects, with the most important detail being that the target
// decl should almost certainly not be placed in Owner.
Decl *NewND = Visit(ND);
- if (!NewND) return 0;
+ if (!NewND) return nullptr;
FriendDecl *FD =
FriendDecl::Create(SemaRef.Context, Owner, D->getLocation(),
@@ -604,7 +648,7 @@ Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) {
ExprResult InstantiatedAssertExpr
= SemaRef.SubstExpr(AssertExpr, TemplateArgs);
if (InstantiatedAssertExpr.isInvalid())
- return 0;
+ return nullptr;
return SemaRef.BuildStaticAssertDeclaration(D->getLocation(),
InstantiatedAssertExpr.get(),
@@ -614,12 +658,12 @@ Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) {
}
Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
- EnumDecl *PrevDecl = 0;
+ EnumDecl *PrevDecl = nullptr;
if (D->getPreviousDecl()) {
NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(),
D->getPreviousDecl(),
TemplateArgs);
- if (!Prev) return 0;
+ if (!Prev) return nullptr;
PrevDecl = cast<EnumDecl>(Prev);
}
@@ -650,7 +694,9 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
Enum->setInstantiationOfMemberEnum(D, TSK_ImplicitInstantiation);
Enum->setAccess(D->getAccess());
- if (SubstQualifier(D, Enum)) return 0;
+ // Forward the mangling number from the template to the instantiated decl.
+ SemaRef.Context.setManglingNumber(Enum, SemaRef.Context.getManglingNumber(D));
+ if (SubstQualifier(D, Enum)) return nullptr;
Owner->addDecl(Enum);
EnumDecl *Def = D->getDefinition();
@@ -692,12 +738,10 @@ void TemplateDeclInstantiator::InstantiateEnumDefinition(
SmallVector<Decl*, 4> Enumerators;
- EnumConstantDecl *LastEnumConst = 0;
- for (EnumDecl::enumerator_iterator EC = Pattern->enumerator_begin(),
- ECEnd = Pattern->enumerator_end();
- EC != ECEnd; ++EC) {
+ EnumConstantDecl *LastEnumConst = nullptr;
+ for (auto *EC : Pattern->enumerators()) {
// The specified value for the enumerator.
- ExprResult Value = SemaRef.Owned((Expr *)0);
+ ExprResult Value((Expr *)nullptr);
if (Expr *UninstValue = EC->getInitExpr()) {
// The enumerator's value expression is a constant expression.
EnterExpressionEvaluationContext Unevaluated(SemaRef,
@@ -709,7 +753,7 @@ void TemplateDeclInstantiator::InstantiateEnumDefinition(
// Drop the initial value and continue.
bool isInvalid = false;
if (Value.isInvalid()) {
- Value = SemaRef.Owned((Expr *)0);
+ Value = nullptr;
isInvalid = true;
}
@@ -725,7 +769,7 @@ void TemplateDeclInstantiator::InstantiateEnumDefinition(
}
if (EnumConst) {
- SemaRef.InstantiateAttrs(TemplateArgs, *EC, EnumConst);
+ SemaRef.InstantiateAttrs(TemplateArgs, EC, EnumConst);
EnumConst->setAccess(Enum->getAccess());
Enum->addDecl(EnumConst);
@@ -736,7 +780,7 @@ void TemplateDeclInstantiator::InstantiateEnumDefinition(
!Enum->isScoped()) {
// If the enumeration is within a function or method, record the enum
// constant as a local.
- SemaRef.CurrentInstantiationScope->InstantiatedLocal(*EC, EnumConst);
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(EC, EnumConst);
}
}
}
@@ -745,7 +789,7 @@ void TemplateDeclInstantiator::InstantiateEnumDefinition(
SemaRef.ActOnEnumBody(Enum->getLocation(), SourceLocation(),
Enum->getRBraceLoc(), Enum,
Enumerators,
- 0, 0);
+ nullptr, nullptr);
}
Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) {
@@ -761,7 +805,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
TemplateParameterList *TempParams = D->getTemplateParameters();
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
- return NULL;
+ return nullptr;
CXXRecordDecl *Pattern = D->getTemplatedDecl();
@@ -773,11 +817,11 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
TemplateArgs);
if (!QualifierLoc)
- return 0;
+ return nullptr;
}
- CXXRecordDecl *PrevDecl = 0;
- ClassTemplateDecl *PrevClassTemplate = 0;
+ CXXRecordDecl *PrevDecl = nullptr;
+ ClassTemplateDecl *PrevClassTemplate = nullptr;
if (!isFriend && Pattern->getPreviousDecl()) {
DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName());
@@ -798,7 +842,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
DC = SemaRef.computeDeclContext(SS);
- if (!DC) return 0;
+ if (!DC) return nullptr;
} else {
DC = SemaRef.FindInstantiatedContext(Pattern->getLocation(),
Pattern->getDeclContext(),
@@ -821,7 +865,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
SemaRef.Diag(Pattern->getLocation(), diag::err_not_tag_in_scope)
<< D->getTemplatedDecl()->getTagKind() << Pattern->getDeclName() << DC
<< QualifierLoc.getSourceRange();
- return 0;
+ return nullptr;
}
bool AdoptedPreviousTemplateParams = false;
@@ -843,11 +887,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
if (DCParent->isNamespace() &&
cast<NamespaceDecl>(DCParent)->getIdentifier() &&
cast<NamespaceDecl>(DCParent)->getIdentifier()->isStr("tr1")) {
- DeclContext *DCParent2 = DCParent->getParent();
- if (DCParent2->isNamespace() &&
- cast<NamespaceDecl>(DCParent2)->getIdentifier() &&
- cast<NamespaceDecl>(DCParent2)->getIdentifier()->isStr("std") &&
- DCParent2->getParent()->isTranslationUnit())
+ if (cast<Decl>(DCParent)->isInStdNamespace())
Complain = false;
}
}
@@ -860,7 +900,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
Complain,
Sema::TPL_TemplateMatch)) {
if (Complain)
- return 0;
+ return nullptr;
AdoptedPreviousTemplateParams = true;
InstParams = PrevParams;
@@ -871,7 +911,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
if (!AdoptedPreviousTemplateParams &&
SemaRef.CheckTemplateParameterList(InstParams, PrevParams,
Sema::TPC_ClassTemplate))
- return 0;
+ return nullptr;
}
}
@@ -948,12 +988,12 @@ TemplateDeclInstantiator::VisitClassTemplatePartialSpecializationDecl(
DeclContext::lookup_result Found
= Owner->lookup(ClassTemplate->getDeclName());
if (Found.empty())
- return 0;
+ return nullptr;
ClassTemplateDecl *InstClassTemplate
= dyn_cast<ClassTemplateDecl>(Found.front());
if (!InstClassTemplate)
- return 0;
+ return nullptr;
if (ClassTemplatePartialSpecializationDecl *Result
= InstClassTemplate->findPartialSpecInstantiatedFromMember(D))
@@ -972,10 +1012,10 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateDecl(VarTemplateDecl *D) {
TemplateParameterList *TempParams = D->getTemplateParameters();
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
- return NULL;
+ return nullptr;
VarDecl *Pattern = D->getTemplatedDecl();
- VarTemplateDecl *PrevVarTemplate = 0;
+ VarTemplateDecl *PrevVarTemplate = nullptr;
if (Pattern->getPreviousDecl()) {
DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName());
@@ -991,8 +1031,9 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateDecl(VarTemplateDecl *D) {
VarTemplateDecl *Inst = VarTemplateDecl::Create(
SemaRef.Context, DC, D->getLocation(), D->getIdentifier(), InstParams,
- VarInst, PrevVarTemplate);
+ VarInst);
VarInst->setDescribedVarTemplate(Inst);
+ Inst->setPreviousDecl(PrevVarTemplate);
Inst->setAccess(D->getAccess());
if (!PrevVarTemplate)
@@ -1052,9 +1093,9 @@ TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
TemplateParameterList *TempParams = D->getTemplateParameters();
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
- return NULL;
+ return nullptr;
- FunctionDecl *Instantiated = 0;
+ FunctionDecl *Instantiated = nullptr;
if (CXXMethodDecl *DMethod = dyn_cast<CXXMethodDecl>(D->getTemplatedDecl()))
Instantiated = cast_or_null<FunctionDecl>(VisitCXXMethodDecl(DMethod,
InstParams));
@@ -1064,7 +1105,7 @@ TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
InstParams));
if (!Instantiated)
- return 0;
+ return nullptr;
// Link the instantiated function template declaration to the function
// template from which it was instantiated.
@@ -1094,14 +1135,14 @@ TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
}
Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
- CXXRecordDecl *PrevDecl = 0;
+ CXXRecordDecl *PrevDecl = nullptr;
if (D->isInjectedClassName())
PrevDecl = cast<CXXRecordDecl>(Owner);
else if (D->getPreviousDecl()) {
NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(),
D->getPreviousDecl(),
TemplateArgs);
- if (!Prev) return 0;
+ if (!Prev) return nullptr;
PrevDecl = cast<CXXRecordDecl>(Prev);
}
@@ -1112,7 +1153,7 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
// Substitute the nested name specifier, if any.
if (SubstQualifier(D, Record))
- return 0;
+ return nullptr;
Record->setImplicit(D->isImplicit());
// FIXME: Check against AS_none is an ugly hack to work around the issue that
@@ -1135,19 +1176,20 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
if (D->isLocalClass())
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Record);
+ // Forward the mangling number from the template to the instantiated decl.
+ SemaRef.Context.setManglingNumber(Record,
+ SemaRef.Context.getManglingNumber(D));
+
Owner->addDecl(Record);
// DR1484 clarifies that the members of a local class are instantiated as part
// of the instantiation of their enclosing entity.
if (D->isCompleteDefinition() && D->isLocalClass()) {
- if (SemaRef.InstantiateClass(D->getLocation(), Record, D, TemplateArgs,
- TSK_ImplicitInstantiation,
- /*Complain=*/true)) {
- llvm_unreachable("InstantiateClass shouldn't fail here!");
- } else {
- SemaRef.InstantiateClassMembers(D->getLocation(), Record, TemplateArgs,
- TSK_ImplicitInstantiation);
- }
+ SemaRef.InstantiateClass(D->getLocation(), Record, D, TemplateArgs,
+ TSK_ImplicitInstantiation,
+ /*Complain=*/true);
+ SemaRef.InstantiateClassMembers(D->getLocation(), Record, TemplateArgs,
+ TSK_ImplicitInstantiation);
}
return Record;
}
@@ -1170,15 +1212,14 @@ static QualType adjustFunctionTypeForInstantiation(ASTContext &Context,
FunctionProtoType::ExtProtoInfo NewEPI = NewFunc->getExtProtoInfo();
NewEPI.ExtInfo = OrigFunc->getExtInfo();
- return Context.getFunctionType(NewFunc->getResultType(),
- NewFunc->getArgTypes(), NewEPI);
+ return Context.getFunctionType(NewFunc->getReturnType(),
+ NewFunc->getParamTypes(), NewEPI);
}
/// Normal class members are of more specific types and therefore
/// don't make it here. This function serves two purposes:
/// 1) instantiating function templates
/// 2) substituting friend declarations
-/// FIXME: preserve function definitions in case #2
Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
TemplateParameterList *TemplateParams) {
// Check whether there is already a function template specialization for
@@ -1187,10 +1228,9 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
if (FunctionTemplate && !TemplateParams) {
ArrayRef<TemplateArgument> Innermost = TemplateArgs.getInnermost();
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
FunctionDecl *SpecFunc
- = FunctionTemplate->findSpecialization(Innermost.begin(), Innermost.size(),
- InsertPos);
+ = FunctionTemplate->findSpecialization(Innermost, InsertPos);
// If we already have a function template specialization, return it.
if (SpecFunc)
@@ -1203,7 +1243,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
else
isFriend = (D->getFriendObjectKind() != Decl::FOK_None);
- bool MergeWithParentScope = (TemplateParams != 0) ||
+ bool MergeWithParentScope = (TemplateParams != nullptr) ||
Owner->isFunctionOrMethod() ||
!(isa<Decl>(Owner) &&
cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod());
@@ -1212,7 +1252,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
SmallVector<ParmVarDecl *, 4> Params;
TypeSourceInfo *TInfo = SubstFunctionType(D, Params);
if (!TInfo)
- return 0;
+ return nullptr;
QualType T = adjustFunctionTypeForInstantiation(SemaRef.Context, D, TInfo);
NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc();
@@ -1220,7 +1260,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
TemplateArgs);
if (!QualifierLoc)
- return 0;
+ return nullptr;
}
// If we're instantiating a local function declaration, put the result
@@ -1234,7 +1274,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
DC = SemaRef.computeDeclContext(SS);
- if (!DC) return 0;
+ if (!DC) return nullptr;
} else {
DC = SemaRef.FindInstantiatedContext(D->getLocation(), D->getDeclContext(),
TemplateArgs);
@@ -1308,7 +1348,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
TemplateArgumentList::CreateCopy(SemaRef.Context,
Innermost.begin(),
Innermost.size()),
- /*InsertPos=*/0);
+ /*InsertPos=*/nullptr);
} else if (isFriend) {
// Note, we need this connection even if the friend doesn't have a body.
// Its body may exist but not have been attached yet due to deferred
@@ -1342,14 +1382,14 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
Info->getRAngleLoc());
if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(),
ExplicitArgs, TemplateArgs))
- return 0;
+ return nullptr;
// Map the candidate templates to their instantiations.
for (unsigned I = 0, E = Info->getNumTemplates(); I != E; ++I) {
Decl *Temp = SemaRef.FindInstantiatedDecl(D->getLocation(),
Info->getTemplate(I),
TemplateArgs);
- if (!Temp) return 0;
+ if (!Temp) return nullptr;
Previous.addDecl(cast<FunctionTemplateDecl>(Temp));
}
@@ -1375,7 +1415,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
Previous.clear();
}
- SemaRef.CheckFunctionDeclaration(/*Scope*/ 0, Function, Previous,
+ SemaRef.CheckFunctionDeclaration(/*Scope*/ nullptr, Function, Previous,
isExplicitSpecialization);
NamedDecl *PrincipalDecl = (TemplateParams
@@ -1388,73 +1428,56 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
PrincipalDecl->setObjectOfFriendDecl();
DC->makeDeclVisibleInContext(PrincipalDecl);
- bool queuedInstantiation = false;
+ bool QueuedInstantiation = false;
- // C++98 [temp.friend]p5: When a function is defined in a friend function
- // declaration in a class template, the function is defined at each
- // instantiation of the class template. The function is defined even if it
- // is never used.
- // C++11 [temp.friend]p4: When a function is defined in a friend function
- // declaration in a class template, the function is instantiated when the
- // function is odr-used.
- //
- // If -Wc++98-compat is enabled, we go through the motions of checking for a
- // redefinition, but don't instantiate the function.
- if ((!SemaRef.getLangOpts().CPlusPlus11 ||
- SemaRef.Diags.getDiagnosticLevel(
- diag::warn_cxx98_compat_friend_redefinition,
- Function->getLocation())
- != DiagnosticsEngine::Ignored) &&
- D->isThisDeclarationADefinition()) {
+ // C++11 [temp.friend]p4 (DR329):
+ // When a function is defined in a friend function declaration in a class
+ // template, the function is instantiated when the function is odr-used.
+ // The same restrictions on multiple declarations and definitions that
+ // apply to non-template function declarations and definitions also apply
+ // to these implicit definitions.
+ if (D->isThisDeclarationADefinition()) {
// Check for a function body.
- const FunctionDecl *Definition = 0;
+ const FunctionDecl *Definition = nullptr;
if (Function->isDefined(Definition) &&
Definition->getTemplateSpecializationKind() == TSK_Undeclared) {
- SemaRef.Diag(Function->getLocation(),
- SemaRef.getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_friend_redefinition :
- diag::err_redefinition) << Function->getDeclName();
+ SemaRef.Diag(Function->getLocation(), diag::err_redefinition)
+ << Function->getDeclName();
SemaRef.Diag(Definition->getLocation(), diag::note_previous_definition);
- if (!SemaRef.getLangOpts().CPlusPlus11)
- Function->setInvalidDecl();
}
// Check for redefinitions due to other instantiations of this or
// a similar friend function.
- else for (FunctionDecl::redecl_iterator R = Function->redecls_begin(),
- REnd = Function->redecls_end();
- R != REnd; ++R) {
- if (*R == Function)
+ else for (auto R : Function->redecls()) {
+ if (R == Function)
continue;
- switch (R->getFriendObjectKind()) {
- case Decl::FOK_None:
- if (!SemaRef.getLangOpts().CPlusPlus11 &&
- !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 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;
}
}
- break;
- default:
- if (const FunctionDecl *RPattern
- = R->getTemplateInstantiationPattern())
+ }
+
+ // 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(),
- SemaRef.getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_friend_redefinition :
- diag::err_redefinition)
+ SemaRef.Diag(Function->getLocation(), diag::err_redefinition)
<< Function->getDeclName();
SemaRef.Diag(R->getLocation(), diag::note_previous_definition);
- if (!SemaRef.getLangOpts().CPlusPlus11)
- Function->setInvalidDecl();
break;
}
+ }
}
}
}
@@ -1482,11 +1505,9 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
// specialization for this particular set of template arguments.
ArrayRef<TemplateArgument> Innermost = TemplateArgs.getInnermost();
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
FunctionDecl *SpecFunc
- = FunctionTemplate->findSpecialization(Innermost.begin(),
- Innermost.size(),
- InsertPos);
+ = FunctionTemplate->findSpecialization(Innermost, InsertPos);
// If we already have a function template specialization, return it.
if (SpecFunc)
@@ -1499,7 +1520,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
else
isFriend = (D->getFriendObjectKind() != Decl::FOK_None);
- bool MergeWithParentScope = (TemplateParams != 0) ||
+ bool MergeWithParentScope = (TemplateParams != nullptr) ||
!(isa<Decl>(Owner) &&
cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod());
LocalInstantiationScope Scope(SemaRef, MergeWithParentScope);
@@ -1513,7 +1534,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
TemplateParameterList *TempParams = D->getTemplateParameterList(I);
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
- return NULL;
+ return nullptr;
TempParamLists[I] = InstParams;
}
}
@@ -1521,7 +1542,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
SmallVector<ParmVarDecl *, 4> Params;
TypeSourceInfo *TInfo = SubstFunctionType(D, Params);
if (!TInfo)
- return 0;
+ return nullptr;
QualType T = adjustFunctionTypeForInstantiation(SemaRef.Context, D, TInfo);
NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc();
@@ -1529,7 +1550,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
TemplateArgs);
if (!QualifierLoc)
- return 0;
+ return nullptr;
}
DeclContext *DC = Owner;
@@ -1540,18 +1561,18 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
DC = SemaRef.computeDeclContext(SS);
if (DC && SemaRef.RequireCompleteDeclContext(SS, DC))
- return 0;
+ return nullptr;
} else {
DC = SemaRef.FindInstantiatedContext(D->getLocation(),
D->getDeclContext(),
TemplateArgs);
}
- if (!DC) return 0;
+ if (!DC) return nullptr;
}
// Build the instantiated method declaration.
CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
- CXXMethodDecl *Method = 0;
+ CXXMethodDecl *Method = nullptr;
SourceLocation StartLoc = D->getInnerLocStart();
DeclarationNameInfo NameInfo
@@ -1577,7 +1598,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
Sema::InstantiatingTemplate Inst(SemaRef, Constructor->getLocation(),
Inh);
if (Inst.isInvalid())
- return 0;
+ return nullptr;
Sema::ContextRAII SavedContext(SemaRef, Inh->getDeclContext());
LocalInstantiationScope LocalScope(SemaRef);
@@ -1588,7 +1609,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
Inh = cast_or_null<CXXConstructorDecl>(
SemaRef.SubstDecl(Inh, Inh->getDeclContext(), InheritedArgs));
if (!Inh)
- return 0;
+ return nullptr;
}
cast<CXXConstructorDecl>(Method)->setInheritedConstructor(Inh);
}
@@ -1649,7 +1670,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
TemplateArgumentList::CreateCopy(SemaRef.Context,
Innermost.begin(),
Innermost.size()),
- /*InsertPos=*/0);
+ /*InsertPos=*/nullptr);
} else if (!isFriend) {
// Record that this is an instantiation of a member function.
Method->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
@@ -1692,7 +1713,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
}
if (!IsClassScopeSpecialization)
- SemaRef.CheckFunctionDeclaration(0, Method, Previous, false);
+ SemaRef.CheckFunctionDeclaration(nullptr, Method, Previous, false);
if (D->isPure())
SemaRef.CheckPureMethod(Method, SourceRange());
@@ -1810,13 +1831,13 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
D->getLocation(),
D->getDeclName());
if (!NewDI)
- return 0;
+ return nullptr;
ExpandedParameterPackTypesAsWritten.push_back(NewDI);
QualType NewT =SemaRef.CheckNonTypeTemplateParameterType(NewDI->getType(),
D->getLocation());
if (NewT.isNull())
- return 0;
+ return nullptr;
ExpandedParameterPackTypes.push_back(NewT);
}
@@ -1845,7 +1866,7 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
TemplateArgs,
Expand, RetainExpansion,
NumExpansions))
- return 0;
+ return nullptr;
if (Expand) {
for (unsigned I = 0; I != *NumExpansions; ++I) {
@@ -1854,14 +1875,14 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
D->getLocation(),
D->getDeclName());
if (!NewDI)
- return 0;
+ return nullptr;
ExpandedParameterPackTypesAsWritten.push_back(NewDI);
QualType NewT = SemaRef.CheckNonTypeTemplateParameterType(
NewDI->getType(),
D->getLocation());
if (NewT.isNull())
- return 0;
+ return nullptr;
ExpandedParameterPackTypes.push_back(NewT);
}
@@ -1879,12 +1900,12 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
D->getLocation(),
D->getDeclName());
if (!NewPattern)
- return 0;
+ return nullptr;
DI = SemaRef.CheckPackExpansion(NewPattern, Expansion.getEllipsisLoc(),
NumExpansions);
if (!DI)
- return 0;
+ return nullptr;
T = DI->getType();
}
@@ -1893,7 +1914,7 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
DI = SemaRef.SubstType(D->getTypeSourceInfo(), TemplateArgs,
D->getLocation(), D->getDeclName());
if (!DI)
- return 0;
+ return nullptr;
// Check that this type is acceptable for a non-type template parameter.
T = SemaRef.CheckNonTypeTemplateParameterType(DI->getType(),
@@ -1979,7 +2000,7 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
TemplateParameterList *Expansion =
SubstTemplateParams(D->getExpansionTemplateParameters(I));
if (!Expansion)
- return 0;
+ return nullptr;
ExpandedParams.push_back(Expansion);
}
@@ -2004,7 +2025,7 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
TemplateArgs,
Expand, RetainExpansion,
NumExpansions))
- return 0;
+ return nullptr;
if (Expand) {
for (unsigned I = 0; I != *NumExpansions; ++I) {
@@ -2012,7 +2033,7 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
LocalInstantiationScope Scope(SemaRef);
TemplateParameterList *Expansion = SubstTemplateParams(TempParams);
if (!Expansion)
- return 0;
+ return nullptr;
ExpandedParams.push_back(Expansion);
}
@@ -2029,7 +2050,7 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
LocalInstantiationScope Scope(SemaRef);
InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
- return 0;
+ return nullptr;
}
} else {
// Perform the actual substitution of template parameters within a new,
@@ -2037,7 +2058,7 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
LocalInstantiationScope Scope(SemaRef);
InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
- return 0;
+ return nullptr;
}
// Build the template template parameter.
@@ -2114,7 +2135,7 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
= SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(),
TemplateArgs);
if (!QualifierLoc)
- return 0;
+ return nullptr;
// The name info is non-dependent, so no transformation
// is required.
@@ -2149,7 +2170,7 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
}
if (!NewUD->isInvalidDecl() &&
- SemaRef.CheckUsingDeclQualifier(D->getUsingLoc(), SS,
+ SemaRef.CheckUsingDeclQualifier(D->getUsingLoc(), SS, NameInfo,
D->getLocation()))
NewUD->setInvalidDecl();
@@ -2162,24 +2183,21 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
return NewUD;
if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) {
- if (SemaRef.CheckInheritingConstructorUsingDecl(NewUD))
- NewUD->setInvalidDecl();
+ SemaRef.CheckInheritingConstructorUsingDecl(NewUD);
return NewUD;
}
bool isFunctionScope = Owner->isFunctionOrMethod();
// Process the shadow decls.
- for (UsingDecl::shadow_iterator I = D->shadow_begin(), E = D->shadow_end();
- I != E; ++I) {
- UsingShadowDecl *Shadow = *I;
+ for (auto *Shadow : D->shadows()) {
NamedDecl *InstTarget =
cast_or_null<NamedDecl>(SemaRef.FindInstantiatedDecl(
Shadow->getLocation(), Shadow->getTargetDecl(), TemplateArgs));
if (!InstTarget)
- return 0;
+ return nullptr;
- UsingShadowDecl *PrevDecl = 0;
+ UsingShadowDecl *PrevDecl = nullptr;
if (CheckRedeclaration) {
if (SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev, PrevDecl))
continue;
@@ -2189,7 +2207,8 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
}
UsingShadowDecl *InstShadow =
- SemaRef.BuildUsingShadowDecl(/*Scope*/0, NewUD, InstTarget, PrevDecl);
+ SemaRef.BuildUsingShadowDecl(/*Scope*/nullptr, NewUD, InstTarget,
+ PrevDecl);
SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow);
if (isFunctionScope)
@@ -2201,7 +2220,7 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) {
// Ignore these; we handle them in bulk when processing the UsingDecl.
- return 0;
+ return nullptr;
}
Decl * TemplateDeclInstantiator
@@ -2210,7 +2229,7 @@ Decl * TemplateDeclInstantiator
= SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(),
TemplateArgs);
if (!QualifierLoc)
- return 0;
+ return nullptr;
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
@@ -2219,8 +2238,8 @@ Decl * TemplateDeclInstantiator
// Hence, no transformation is required for it.
DeclarationNameInfo NameInfo(D->getDeclName(), D->getLocation());
NamedDecl *UD =
- SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
- D->getUsingLoc(), SS, NameInfo, 0,
+ SemaRef.BuildUsingDeclaration(/*Scope*/ nullptr, D->getAccess(),
+ D->getUsingLoc(), SS, NameInfo, nullptr,
/*instantiation*/ true,
/*typename*/ true, D->getTypenameLoc());
if (UD)
@@ -2234,7 +2253,7 @@ Decl * TemplateDeclInstantiator
NestedNameSpecifierLoc QualifierLoc
= SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(), TemplateArgs);
if (!QualifierLoc)
- return 0;
+ return nullptr;
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
@@ -2243,8 +2262,8 @@ Decl * TemplateDeclInstantiator
= SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs);
NamedDecl *UD =
- SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
- D->getUsingLoc(), SS, NameInfo, 0,
+ SemaRef.BuildUsingDeclaration(/*Scope*/ nullptr, D->getAccess(),
+ D->getUsingLoc(), SS, NameInfo, nullptr,
/*instantiation*/ true,
/*typename*/ false, SourceLocation());
if (UD)
@@ -2258,13 +2277,13 @@ Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl(
ClassScopeFunctionSpecializationDecl *Decl) {
CXXMethodDecl *OldFD = Decl->getSpecialization();
CXXMethodDecl *NewFD = cast<CXXMethodDecl>(VisitCXXMethodDecl(OldFD,
- 0, true));
+ nullptr, true));
LookupResult Previous(SemaRef, NewFD->getNameInfo(), Sema::LookupOrdinaryName,
Sema::ForRedeclaration);
TemplateArgumentListInfo TemplateArgs;
- TemplateArgumentListInfo* TemplateArgsPtr = 0;
+ TemplateArgumentListInfo *TemplateArgsPtr = nullptr;
if (Decl->hasExplicitTemplateArgs()) {
TemplateArgs = Decl->templateArgs();
TemplateArgsPtr = &TemplateArgs;
@@ -2288,10 +2307,8 @@ Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl(
Decl *TemplateDeclInstantiator::VisitOMPThreadPrivateDecl(
OMPThreadPrivateDecl *D) {
SmallVector<Expr *, 5> Vars;
- for (ArrayRef<Expr *>::iterator I = D->varlist_begin(),
- E = D->varlist_end();
- I != E; ++I) {
- Expr *Var = SemaRef.SubstExpr(*I, TemplateArgs).take();
+ for (auto *I : D->varlists()) {
+ Expr *Var = SemaRef.SubstExpr(I, TemplateArgs).get();
assert(isa<DeclRefExpr>(Var) && "threadprivate arg is not a DeclRefExpr");
Vars.push_back(Var);
}
@@ -2299,15 +2316,18 @@ Decl *TemplateDeclInstantiator::VisitOMPThreadPrivateDecl(
OMPThreadPrivateDecl *TD =
SemaRef.CheckOMPThreadPrivateDecl(D->getLocation(), Vars);
+ TD->setAccess(AS_public);
+ Owner->addDecl(TD);
+
return TD;
}
Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
- return VisitFunctionDecl(D, 0);
+ return VisitFunctionDecl(D, nullptr);
}
Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
- return VisitCXXMethodDecl(D, 0);
+ return VisitCXXMethodDecl(D, nullptr);
}
Decl *TemplateDeclInstantiator::VisitRecordDecl(RecordDecl *D) {
@@ -2330,11 +2350,11 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
DeclContext::lookup_result Found
= Owner->lookup(ClassTemplate->getDeclName());
if (Found.empty())
- return 0;
+ return nullptr;
ClassTemplateDecl *InstClassTemplate
= dyn_cast<ClassTemplateDecl>(Found.front());
if (!InstClassTemplate)
- return 0;
+ return nullptr;
// Substitute into the template arguments of the class template explicit
// specialization.
@@ -2347,7 +2367,7 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
ArgLocs.push_back(Loc.getArgLoc(I));
if (SemaRef.Subst(ArgLocs.data(), ArgLocs.size(),
InstTemplateArgs, TemplateArgs))
- return 0;
+ return nullptr;
// Check that the template argument list is well-formed for this
// class template.
@@ -2357,14 +2377,13 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
InstTemplateArgs,
false,
Converted))
- return 0;
+ return nullptr;
// Figure out where to insert this class template explicit specialization
// in the member template's set of class template explicit specializations.
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
ClassTemplateSpecializationDecl *PrevDecl =
- InstClassTemplate->findSpecialization(Converted.data(), Converted.size(),
- InsertPos);
+ InstClassTemplate->findSpecialization(Converted, InsertPos);
// Check whether we've already seen a conflicting instantiation of this
// declaration (for instance, if there was a prior implicit instantiation).
@@ -2376,7 +2395,7 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
PrevDecl->getSpecializationKind(),
PrevDecl->getPointOfInstantiation(),
Ignored))
- return 0;
+ return nullptr;
// If PrevDecl was a definition and D is also a definition, diagnose.
// This happens in cases like:
@@ -2395,7 +2414,7 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
SemaRef.Diag(D->getLocation(), diag::err_redefinition) << PrevDecl;
SemaRef.Diag(PrevDecl->getDefinition()->getLocation(),
diag::note_previous_definition);
- return 0;
+ return nullptr;
}
// Create the class template partial specialization declaration.
@@ -2417,7 +2436,7 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
// Substitute the nested name specifier, if any.
if (SubstQualifier(D, InstD))
- return 0;
+ return nullptr;
// Build the canonical type that describes the converted template
// arguments of the class template explicit specialization.
@@ -2452,7 +2471,7 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
SemaRef.InstantiateClass(D->getLocation(), InstD, D, TemplateArgs,
TSK_ImplicitInstantiation,
/*Complain=*/true))
- return 0;
+ return nullptr;
return InstD;
}
@@ -2472,22 +2491,21 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
if (SemaRef.Subst(TemplateArgsInfo.getArgumentArray(),
TemplateArgsInfo.size(), VarTemplateArgsInfo, TemplateArgs))
- return 0;
+ return nullptr;
// Check that the template argument list is well-formed for this template.
SmallVector<TemplateArgument, 4> Converted;
- bool ExpansionIntoFixedList = false;
if (SemaRef.CheckTemplateArgumentList(
VarTemplate, VarTemplate->getLocStart(),
const_cast<TemplateArgumentListInfo &>(VarTemplateArgsInfo), false,
- Converted, &ExpansionIntoFixedList))
- return 0;
+ Converted))
+ return nullptr;
// Find the variable template specialization declaration that
// corresponds to these arguments.
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (VarTemplateSpecializationDecl *VarSpec = VarTemplate->findSpecialization(
- Converted.data(), Converted.size(), InsertPos))
+ Converted, InsertPos))
// If we already have a variable template specialization, return it.
return VarSpec;
@@ -2498,26 +2516,26 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
VarTemplateDecl *VarTemplate, VarDecl *D, void *InsertPos,
const TemplateArgumentListInfo &TemplateArgsInfo,
- llvm::ArrayRef<TemplateArgument> Converted) {
+ ArrayRef<TemplateArgument> Converted) {
// If this is the variable for an anonymous struct or union,
// instantiate the anonymous struct/union type first.
if (const RecordType *RecordTy = D->getType()->getAs<RecordType>())
if (RecordTy->getDecl()->isAnonymousStructOrUnion())
if (!VisitCXXRecordDecl(cast<CXXRecordDecl>(RecordTy->getDecl())))
- return 0;
+ return nullptr;
// Do substitution on the type of the declaration
TypeSourceInfo *DI =
SemaRef.SubstType(D->getTypeSourceInfo(), TemplateArgs,
D->getTypeSpecStartLoc(), D->getDeclName());
if (!DI)
- return 0;
+ return nullptr;
if (DI->getType()->isFunctionType()) {
SemaRef.Diag(D->getLocation(), diag::err_variable_instantiates_to_function)
<< D->isStaticDataMember() << DI->getType();
- return 0;
+ return nullptr;
}
// Build the instantiated declaration
@@ -2531,7 +2549,7 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
// Substitute the nested name specifier, if any.
if (SubstQualifier(D, Var))
- return 0;
+ return nullptr;
SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs,
Owner, StartingScope);
@@ -2551,7 +2569,7 @@ Decl *TemplateDeclInstantiator::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
SemaRef.Diag(D->getLocation(), DiagID)
<< D->getDeclKindName();
- return 0;
+ return nullptr;
}
Decl *TemplateDeclInstantiator::VisitDecl(Decl *D) {
@@ -2562,7 +2580,7 @@ Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner,
const MultiLevelTemplateArgumentList &TemplateArgs) {
TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs);
if (D->isInvalidDecl())
- return 0;
+ return nullptr;
return Instantiator.Visit(D);
}
@@ -2591,7 +2609,7 @@ TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) {
// Clean up if we had an error.
if (Invalid)
- return NULL;
+ return nullptr;
TemplateParameterList *InstL
= TemplateParameterList::Create(SemaRef.Context, L->getTemplateLoc(),
@@ -2625,7 +2643,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
TemplateParameterList *TempParams = PartialSpec->getTemplateParameters();
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
- return 0;
+ return nullptr;
// Substitute into the template arguments of the class template partial
// specialization.
@@ -2636,7 +2654,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
if (SemaRef.Subst(TemplArgInfo->getTemplateArgs(),
TemplArgInfo->NumTemplateArgs,
InstTemplateArgs, TemplateArgs))
- return 0;
+ return nullptr;
// Check that the template argument list is well-formed for this
// class template.
@@ -2646,14 +2664,13 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
InstTemplateArgs,
false,
Converted))
- return 0;
+ return nullptr;
// Figure out where to insert this class template partial specialization
// in the member template's set of class template partial specializations.
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
ClassTemplateSpecializationDecl *PrevDecl
- = ClassTemplate->findPartialSpecialization(Converted.data(),
- Converted.size(), InsertPos);
+ = ClassTemplate->findPartialSpecialization(Converted, InsertPos);
// Build the canonical type that describes the converted template
// arguments of the class template partial specialization.
@@ -2696,7 +2713,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
<< WrittenTy->getType();
SemaRef.Diag(PrevDecl->getLocation(), diag::note_prev_partial_spec_here)
<< SemaRef.Context.getTypeDeclType(PrevDecl);
- return 0;
+ return nullptr;
}
@@ -2713,17 +2730,18 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
Converted.size(),
InstTemplateArgs,
CanonType,
- 0);
+ nullptr);
// Substitute the nested name specifier, if any.
if (SubstQualifier(PartialSpec, InstPartialSpec))
- return 0;
+ return nullptr;
InstPartialSpec->setInstantiatedFromMember(PartialSpec);
InstPartialSpec->setTypeAsWritten(WrittenTy);
// Add this partial specialization to the set of class template partial
// specializations.
- ClassTemplate->AddPartialSpecialization(InstPartialSpec, /*InsertPos=*/0);
+ ClassTemplate->AddPartialSpecialization(InstPartialSpec,
+ /*InsertPos=*/nullptr);
return InstPartialSpec;
}
@@ -2752,7 +2770,7 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization(
TemplateParameterList *TempParams = PartialSpec->getTemplateParameters();
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
- return 0;
+ return nullptr;
// Substitute into the template arguments of the variable template partial
// specialization.
@@ -2763,21 +2781,20 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization(
if (SemaRef.Subst(TemplArgInfo->getTemplateArgs(),
TemplArgInfo->NumTemplateArgs,
InstTemplateArgs, TemplateArgs))
- return 0;
+ return nullptr;
// Check that the template argument list is well-formed for this
// class template.
SmallVector<TemplateArgument, 4> Converted;
if (SemaRef.CheckTemplateArgumentList(VarTemplate, PartialSpec->getLocation(),
InstTemplateArgs, false, Converted))
- return 0;
+ return nullptr;
// Figure out where to insert this variable template partial specialization
// in the member template's set of variable template partial specializations.
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
VarTemplateSpecializationDecl *PrevDecl =
- VarTemplate->findPartialSpecialization(Converted.data(), Converted.size(),
- InsertPos);
+ VarTemplate->findPartialSpecialization(Converted, InsertPos);
// Build the canonical type that describes the converted template
// arguments of the variable template partial specialization.
@@ -2816,7 +2833,7 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization(
<< WrittenTy->getType();
SemaRef.Diag(PrevDecl->getLocation(),
diag::note_var_prev_partial_spec_here);
- return 0;
+ return nullptr;
}
// Do substitution on the type of the declaration
@@ -2824,13 +2841,13 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization(
PartialSpec->getTypeSourceInfo(), TemplateArgs,
PartialSpec->getTypeSpecStartLoc(), PartialSpec->getDeclName());
if (!DI)
- return 0;
+ return nullptr;
if (DI->getType()->isFunctionType()) {
SemaRef.Diag(PartialSpec->getLocation(),
diag::err_variable_instantiates_to_function)
<< PartialSpec->isStaticDataMember() << DI->getType();
- return 0;
+ return nullptr;
}
// Create the variable template partial specialization declaration.
@@ -2843,14 +2860,14 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization(
// Substitute the nested name specifier, if any.
if (SubstQualifier(PartialSpec, InstPartialSpec))
- return 0;
+ return nullptr;
InstPartialSpec->setInstantiatedFromMember(PartialSpec);
InstPartialSpec->setTypeAsWritten(WrittenTy);
// Add this partial specialization to the set of variable template partial
// specializations. The instantiation of the initializer is not necessary.
- VarTemplate->AddPartialSpecialization(InstPartialSpec, /*InsertPos=*/0);
+ VarTemplate->AddPartialSpecialization(InstPartialSpec, /*InsertPos=*/nullptr);
SemaRef.BuildVariableInstantiation(InstPartialSpec, PartialSpec, TemplateArgs,
LateAttrs, Owner, StartingScope);
@@ -2864,8 +2881,8 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
TypeSourceInfo *OldTInfo = D->getTypeSourceInfo();
assert(OldTInfo && "substituting function without type source info");
assert(Params.empty() && "parameter vector is non-empty at start");
-
- CXXRecordDecl *ThisContext = 0;
+
+ CXXRecordDecl *ThisContext = nullptr;
unsigned ThisTypeQuals = 0;
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
ThisContext = cast<CXXRecordDecl>(Owner);
@@ -2878,7 +2895,7 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
D->getDeclName(),
ThisContext, ThisTypeQuals);
if (!NewTInfo)
- return 0;
+ return nullptr;
TypeLoc OldTL = OldTInfo->getTypeLoc().IgnoreParens();
if (FunctionProtoTypeLoc OldProtoLoc = OldTL.getAs<FunctionProtoTypeLoc>()) {
@@ -2887,9 +2904,9 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
TypeLoc NewTL = NewTInfo->getTypeLoc().IgnoreParens();
FunctionProtoTypeLoc NewProtoLoc = NewTL.castAs<FunctionProtoTypeLoc>();
unsigned NewIdx = 0;
- for (unsigned OldIdx = 0, NumOldParams = OldProtoLoc.getNumArgs();
+ for (unsigned OldIdx = 0, NumOldParams = OldProtoLoc.getNumParams();
OldIdx != NumOldParams; ++OldIdx) {
- ParmVarDecl *OldParam = OldProtoLoc.getArg(OldIdx);
+ ParmVarDecl *OldParam = OldProtoLoc.getParam(OldIdx);
LocalInstantiationScope *Scope = SemaRef.CurrentInstantiationScope;
Optional<unsigned> NumArgumentsInExpansion;
@@ -2900,14 +2917,14 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
if (!NumArgumentsInExpansion) {
// Simple case: normal parameter, or a parameter pack that's
// instantiated to a (still-dependent) parameter pack.
- ParmVarDecl *NewParam = NewProtoLoc.getArg(NewIdx++);
+ ParmVarDecl *NewParam = NewProtoLoc.getParam(NewIdx++);
Params.push_back(NewParam);
Scope->InstantiatedLocal(OldParam, NewParam);
} else {
// Parameter pack expansion: make the instantiation an argument pack.
Scope->MakeInstantiatedLocalArgPack(OldParam);
for (unsigned I = 0; I != *NumArgumentsInExpansion; ++I) {
- ParmVarDecl *NewParam = NewProtoLoc.getArg(NewIdx++);
+ ParmVarDecl *NewParam = NewProtoLoc.getParam(NewIdx++);
Params.push_back(NewParam);
Scope->InstantiatedLocalPackArg(OldParam, NewParam);
}
@@ -2919,18 +2936,19 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
// the function parameters themselves.
const FunctionProtoType *OldProto =
cast<FunctionProtoType>(OldProtoLoc.getType());
- for (unsigned i = 0, i_end = OldProtoLoc.getNumArgs(); i != i_end; ++i) {
- ParmVarDecl *OldParam = OldProtoLoc.getArg(i);
+ for (unsigned i = 0, i_end = OldProtoLoc.getNumParams(); i != i_end;
+ ++i) {
+ ParmVarDecl *OldParam = OldProtoLoc.getParam(i);
if (!OldParam) {
Params.push_back(SemaRef.BuildParmVarDeclForTypedef(
- D, D->getLocation(), OldProto->getArgType(i)));
+ D, D->getLocation(), OldProto->getParamType(i)));
continue;
}
ParmVarDecl *Parm =
cast_or_null<ParmVarDecl>(VisitParmVarDecl(OldParam));
if (!Parm)
- return 0;
+ return nullptr;
Params.push_back(Parm);
}
}
@@ -2949,7 +2967,7 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
if (SemaRef.SubstParmTypes(D->getLocation(), D->param_begin(),
D->getNumParams(), TemplateArgs, ParamTypes,
&Params))
- return 0;
+ return nullptr;
}
return NewTInfo;
@@ -2969,6 +2987,14 @@ static void addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function,
// Simple case: not a parameter pack.
assert(FParamIdx < Function->getNumParams());
ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
+ // If the parameter's type is not dependent, update it to match the type
+ // in the pattern. They can differ in top-level cv-qualifiers, and we want
+ // the pattern's type here. If the type is dependent, they can't differ,
+ // per core issue 1668.
+ // FIXME: Updating the type to work around this is at best fragile.
+ if (!PatternDecl->getType()->isDependentType())
+ FunctionParam->setType(PatternParam->getType());
+
FunctionParam->setDeclName(PatternParam->getDeclName());
Scope.InstantiatedLocal(PatternParam, FunctionParam);
++FParamIdx;
@@ -2983,6 +3009,9 @@ static void addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function,
"should only be called when all template arguments are known");
for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg) {
ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
+ if (!PatternDecl->getType()->isDependentType())
+ FunctionParam->setType(PatternParam->getType());
+
FunctionParam->setDeclName(PatternParam->getDeclName());
Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam);
++FParamIdx;
@@ -3001,7 +3030,7 @@ static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New,
// "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
// and the end of the function-definition, member-declarator, or
// declarator.
- CXXRecordDecl *ThisContext = 0;
+ CXXRecordDecl *ThisContext = nullptr;
unsigned ThisTypeQuals = 0;
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(New)) {
ThisContext = Method->getParent();
@@ -3083,7 +3112,7 @@ static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New,
Exceptions.push_back(T);
}
- Expr *NoexceptExpr = 0;
+ Expr *NoexceptExpr = nullptr;
if (Expr *OldNoexceptExpr = Proto->getNoexceptExpr()) {
EnterExpressionEvaluationContext Unevaluated(SemaRef,
Sema::ConstantEvaluated);
@@ -3092,29 +3121,23 @@ static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New,
E = SemaRef.CheckBooleanCondition(E.get(), E.get()->getLocStart());
if (E.isUsable()) {
- NoexceptExpr = E.take();
+ NoexceptExpr = E.get();
if (!NoexceptExpr->isTypeDependent() &&
!NoexceptExpr->isValueDependent())
NoexceptExpr
= SemaRef.VerifyIntegerConstantExpression(NoexceptExpr,
- 0, diag::err_noexcept_needs_constant_expression,
- /*AllowFold*/ false).take();
+ nullptr, diag::err_noexcept_needs_constant_expression,
+ /*AllowFold*/ false).get();
}
}
- // Rebuild the function type
- const FunctionProtoType *NewProto
- = New->getType()->getAs<FunctionProtoType>();
- assert(NewProto && "Template instantiation without function prototype?");
-
- FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
+ FunctionProtoType::ExtProtoInfo EPI;
EPI.ExceptionSpecType = Proto->getExceptionSpecType();
EPI.NumExceptions = Exceptions.size();
EPI.Exceptions = Exceptions.data();
EPI.NoexceptExpr = NoexceptExpr;
- New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(),
- NewProto->getArgTypes(), EPI));
+ SemaRef.UpdateExceptionSpec(New, EPI);
}
void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
@@ -3128,10 +3151,9 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
if (Inst.isInvalid()) {
// We hit the instantiation depth limit. Clear the exception specification
// so that our callers don't have to cope with EST_Uninstantiated.
- FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
+ FunctionProtoType::ExtProtoInfo EPI;
EPI.ExceptionSpecType = EST_None;
- Decl->setType(Context.getFunctionType(Proto->getResultType(),
- Proto->getArgTypes(), EPI));
+ UpdateExceptionSpec(Decl, EPI);
return;
}
@@ -3141,7 +3163,7 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
LocalInstantiationScope Scope(*this);
MultiLevelTemplateArgumentList TemplateArgs =
- getTemplateInstantiationArgs(Decl, 0, /*RelativeToPrimary*/true);
+ getTemplateInstantiationArgs(Decl, nullptr, /*RelativeToPrimary*/true);
FunctionDecl *Template = Proto->getExceptionSpecTemplate();
addInstantiatedParametersToScope(*this, Decl, Template, Scope, TemplateArgs);
@@ -3161,6 +3183,10 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
if (Tmpl->isDeleted())
New->setDeletedAsWritten();
+ // Forward the mangling number from the template to the instantiated decl.
+ SemaRef.Context.setManglingNumber(New,
+ SemaRef.Context.getManglingNumber(Tmpl));
+
// If we are performing substituting explicitly-specified template arguments
// or deduced template arguments into a function template and we reach this
// point, we are now past the point where SFINAE applies and have committed
@@ -3211,7 +3237,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
EPI.ExceptionSpecDecl = New;
EPI.ExceptionSpecTemplate = ExceptionSpecTemplate;
New->setType(SemaRef.Context.getFunctionType(
- NewProto->getResultType(), NewProto->getArgTypes(), EPI));
+ NewProto->getReturnType(), NewProto->getParamTypes(), EPI));
} else {
::InstantiateExceptionSpec(SemaRef, New, Proto, TemplateArgs);
}
@@ -3339,14 +3365,22 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
// initializer or return value, and class template specializations, other
// explicit instantiation declarations have the effect of suppressing the
// implicit instantiation of the entity to which they refer.
- if (Function->getTemplateSpecializationKind()
- == TSK_ExplicitInstantiationDeclaration &&
+ if (Function->getTemplateSpecializationKind() ==
+ TSK_ExplicitInstantiationDeclaration &&
!PatternDecl->isInlined() &&
- !PatternDecl->getResultType()->getContainedAutoType())
+ !PatternDecl->getReturnType()->getContainedAutoType())
return;
- if (PatternDecl->isInlined())
- Function->setImplicitlyInline();
+ if (PatternDecl->isInlined()) {
+ // Function, and all later redeclarations of it (from imported modules,
+ // for instance), are now implicitly inline.
+ for (auto *D = Function->getMostRecentDecl(); /**/;
+ D = D->getPreviousDecl()) {
+ D->setImplicitlyInline();
+ if (D == Function)
+ break;
+ }
+ }
InstantiatingTemplate Inst(*this, PointOfInstantiation, Function);
if (Inst.isInvalid())
@@ -3383,14 +3417,14 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
if (PatternDecl->isDefaulted())
SetDeclDefaulted(Function, PatternDecl->getLocation());
else {
- ActOnStartOfFunctionDef(0, Function);
+ ActOnStartOfFunctionDef(nullptr, Function);
// Enter the scope of this instantiation. We don't use
// PushDeclContext because we don't have a scope.
Sema::ContextRAII savedContext(*this, Function);
MultiLevelTemplateArgumentList TemplateArgs =
- getTemplateInstantiationArgs(Function, 0, false, PatternDecl);
+ getTemplateInstantiationArgs(Function, nullptr, false, PatternDecl);
addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope,
TemplateArgs);
@@ -3413,6 +3447,9 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
PerformDependentDiagnostics(PatternDecl, TemplateArgs);
+ if (auto *Listener = getASTMutationListener())
+ Listener->FunctionDefinitionInstantiated(Function);
+
savedContext.pop();
}
@@ -3453,11 +3490,11 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
LateInstantiatedAttrVec *LateAttrs,
LocalInstantiationScope *StartingScope) {
if (FromVar->isInvalidDecl())
- return 0;
+ return nullptr;
InstantiatingTemplate Inst(*this, PointOfInstantiation, FromVar);
if (Inst.isInvalid())
- return 0;
+ return nullptr;
MultiLevelTemplateArgumentList TemplateArgLists;
TemplateArgLists.addOuterTemplateArguments(&TemplateArgList);
@@ -3467,7 +3504,18 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
// or may not be the declaration in the class; if it's in the class, we want
// to instantiate a member in the class (a declaration), and if it's outside,
// we want to instantiate a definition.
- FromVar = FromVar->getFirstDecl();
+ //
+ // If we're instantiating an explicitly-specialized member template or member
+ // partial specialization, don't do this. The member specialization completely
+ // replaces the original declaration in this case.
+ bool IsMemberSpec = false;
+ if (VarTemplatePartialSpecializationDecl *PartialSpec =
+ dyn_cast<VarTemplatePartialSpecializationDecl>(FromVar))
+ IsMemberSpec = PartialSpec->isMemberSpecialization();
+ else if (VarTemplateDecl *FromTemplate = FromVar->getDescribedVarTemplate())
+ IsMemberSpec = FromTemplate->isMemberSpecialization();
+ if (!IsMemberSpec)
+ FromVar = FromVar->getFirstDecl();
MultiLevelTemplateArgumentList MultiLevelList(TemplateArgList);
TemplateDeclInstantiator Instantiator(*this, FromVar->getDeclContext(),
@@ -3491,7 +3539,7 @@ VarTemplateSpecializationDecl *Sema::CompleteVarTemplateSpecializationDecl(
SubstType(PatternDecl->getTypeSourceInfo(), TemplateArgs,
PatternDecl->getTypeSpecStartLoc(), PatternDecl->getDeclName());
if (!DI)
- return 0;
+ return nullptr;
// Update the type of this variable template specialization.
VarSpec->setType(DI->getType());
@@ -3552,16 +3600,15 @@ void Sema::BuildVariableInstantiation(
InstantiateAttrs(TemplateArgs, OldVar, NewVar, LateAttrs, StartingScope);
- if (NewVar->hasAttrs())
- CheckAlignasUnderalignment(NewVar);
-
LookupResult Previous(
*this, NewVar->getDeclName(), NewVar->getLocation(),
NewVar->isLocalExternDecl() ? Sema::LookupRedeclarationWithLinkage
: Sema::LookupOrdinaryName,
Sema::ForRedeclaration);
- if (NewVar->isLocalExternDecl() && OldVar->getPreviousDecl()) {
+ if (NewVar->isLocalExternDecl() && OldVar->getPreviousDecl() &&
+ (!OldVar->getPreviousDecl()->getDeclContext()->isDependentContext() ||
+ OldVar->getPreviousDecl()->getDeclContext()==OldVar->getDeclContext())) {
// We have a previous declaration. Use that one, so we merge with the
// right type.
if (NamedDecl *NewPrev = FindInstantiatedDecl(
@@ -3589,9 +3636,16 @@ void Sema::BuildVariableInstantiation(
NewVar->setInstantiationOfStaticDataMember(OldVar,
TSK_ImplicitInstantiation);
+ // Forward the mangling number from the template to the instantiated decl.
+ Context.setManglingNumber(NewVar, Context.getManglingNumber(OldVar));
+ Context.setStaticLocalNumber(NewVar, Context.getStaticLocalNumber(OldVar));
+
// Delay instantiation of the initializer for variable templates until a
- // definition of the variable is needed.
- if (!isa<VarTemplateSpecializationDecl>(NewVar) && !InstantiatingVarTemplate)
+ // definition of the variable is needed. We need it right away if the type
+ // contains 'auto'.
+ if ((!isa<VarTemplateSpecializationDecl>(NewVar) &&
+ !InstantiatingVarTemplate) ||
+ NewVar->getType()->isUndeducedType())
InstantiateVariableInitializer(NewVar, OldVar, TemplateArgs);
// Diagnose unused local variables with dependent types, where the diagnostic
@@ -3623,9 +3677,15 @@ void Sema::InstantiateVariableInitializer(
OldVar->getInitStyle() == VarDecl::CallInit);
if (!Init.isInvalid()) {
bool TypeMayContainAuto = true;
- if (Init.get()) {
+ Expr *InitExpr = Init.get();
+
+ if (Var->hasAttr<DLLImportAttr>() &&
+ (!InitExpr ||
+ !InitExpr->isConstantInitializer(getASTContext(), false))) {
+ // Do not dynamically initialize dllimport variables.
+ } else if (InitExpr) {
bool DirectInit = OldVar->isDirectInit();
- AddInitializerToDecl(Var, Init.take(), DirectInit, TypeMayContainAuto);
+ AddInitializerToDecl(Var, InitExpr, DirectInit, TypeMayContainAuto);
} else
ActOnUninitializedDecl(Var, TypeMayContainAuto);
} else {
@@ -3673,7 +3733,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
VarTemplateSpecializationDecl *VarSpec =
dyn_cast<VarTemplateSpecializationDecl>(Var);
- VarDecl *PatternDecl = 0, *Def = 0;
+ VarDecl *PatternDecl = nullptr, *Def = nullptr;
MultiLevelTemplateArgumentList TemplateArgs =
getTemplateInstantiationArgs(Var);
@@ -3883,7 +3943,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
TemplateDeclInstantiator Instantiator(*this, Var->getDeclContext(),
TemplateArgs);
Var = cast_or_null<VarDecl>(Instantiator.VisitVarTemplateSpecializationDecl(
- VarSpec->getSpecializedTemplate(), Def, 0,
+ VarSpec->getSpecializedTemplate(), Def, nullptr,
VarSpec->getTemplateArgsInfo(), VarSpec->getTemplateArgs().asArray()));
if (Var) {
llvm::PointerUnion<VarTemplateDecl *,
@@ -3951,11 +4011,7 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
bool AnyErrors = Tmpl->isInvalidDecl();
// Instantiate all the initializers.
- for (CXXConstructorDecl::init_const_iterator Inits = Tmpl->init_begin(),
- InitsEnd = Tmpl->init_end();
- Inits != InitsEnd; ++Inits) {
- CXXCtorInitializer *Init = *Inits;
-
+ for (const auto *Init : Tmpl->inits()) {
// Only instantiate written initializers, let Sema re-construct implicit
// ones.
if (!Init->isWritten())
@@ -4008,7 +4064,7 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
// Build the initializer.
MemInitResult NewInit = BuildBaseInitializer(BaseTInfo->getType(),
- BaseTInfo, TempInit.take(),
+ BaseTInfo, TempInit.get(),
New->getParent(),
SourceLocation());
if (NewInit.isInvalid()) {
@@ -4043,10 +4099,10 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
}
if (Init->isBaseInitializer())
- NewInit = BuildBaseInitializer(TInfo->getType(), TInfo, TempInit.take(),
+ NewInit = BuildBaseInitializer(TInfo->getType(), TInfo, TempInit.get(),
New->getParent(), EllipsisLoc);
else
- NewInit = BuildDelegatingInitializer(TInfo, TempInit.take(),
+ NewInit = BuildDelegatingInitializer(TInfo, TempInit.get(),
cast<CXXRecordDecl>(CurContext->getParent()));
} else if (Init->isMemberInitializer()) {
FieldDecl *Member = cast_or_null<FieldDecl>(FindInstantiatedDecl(
@@ -4059,7 +4115,7 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
continue;
}
- NewInit = BuildMemberInitializer(Member, TempInit.take(),
+ NewInit = BuildMemberInitializer(Member, TempInit.get(),
Init->getSourceLocation());
} else if (Init->isIndirectMemberInitializer()) {
IndirectFieldDecl *IndirectMember =
@@ -4073,7 +4129,7 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
continue;
}
- NewInit = BuildMemberInitializer(IndirectMember, TempInit.take(),
+ NewInit = BuildMemberInitializer(IndirectMember, TempInit.get(),
Init->getSourceLocation());
}
@@ -4287,7 +4343,7 @@ static NamedDecl *findInstantiationOf(ASTContext &Ctx,
if (isInstantiationOf(Ctx, D, *first))
return cast<NamedDecl>(*first);
- return 0;
+ return nullptr;
}
/// \brief Finds the instantiation of the given declaration context
@@ -4339,7 +4395,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
// find an instantiated decl for (T y) when the ParentDC for y is
// the translation unit.
// e.g. template <class T> void Foo(auto (*p)(T y) -> decltype(y())) {}
- // float baz(float(*)()) { return 0.0; }
+ // float baz(float(*)()) { return 0.0; }
// Foo(baz);
// The better fix here is perhaps to ensure that a ParmVarDecl, by the time
// it gets here, always has a FunctionOrMethod as its ParentDC??
@@ -4377,7 +4433,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
return D;
if (D->isInvalidDecl())
- return 0;
+ return nullptr;
// If we didn't find the decl, then we must have a label decl that hasn't
// been found yet. Lazily instantiate it and return it now.
@@ -4461,7 +4517,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
ParentDC = FindInstantiatedContext(Loc, ParentDC, TemplateArgs);
if (!ParentDC)
- return 0;
+ return nullptr;
if (ParentDC != D->getDeclContext()) {
// We performed some kind of instantiation in the parent context,
@@ -4480,13 +4536,13 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
IsBeingInstantiated = true;
if (!Tag->isBeingDefined() &&
RequireCompleteType(Loc, T, diag::err_incomplete_type))
- return 0;
+ return nullptr;
ParentDC = Tag->getDecl();
}
}
- NamedDecl *Result = 0;
+ NamedDecl *Result = nullptr;
if (D->getDeclName()) {
DeclContext::lookup_result Found = ParentDC->lookup(D->getDeclName());
Result = findInstantiationOf(Context, D, Found.begin(), Found.end());
@@ -4550,14 +4606,6 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
/// \brief Performs template instantiation for all implicit template
/// instantiations we have seen until this point.
void Sema::PerformPendingInstantiations(bool LocalOnly) {
- // Load pending instantiations from the external source.
- if (!LocalOnly && ExternalSource) {
- SmallVector<PendingImplicitInstantiation, 4> Pending;
- ExternalSource->ReadPendingInstantiations(Pending);
- PendingInstantiations.insert(PendingInstantiations.begin(),
- Pending.begin(), Pending.end());
- }
-
while (!PendingLocalImplicitInstantiations.empty() ||
(!LocalOnly && !PendingInstantiations.empty())) {
PendingImplicitInstantiation Inst;
@@ -4624,10 +4672,7 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) {
void Sema::PerformDependentDiagnostics(const DeclContext *Pattern,
const MultiLevelTemplateArgumentList &TemplateArgs) {
- for (DeclContext::ddiag_iterator I = Pattern->ddiag_begin(),
- E = Pattern->ddiag_end(); I != E; ++I) {
- DependentDiagnostic *DD = *I;
-
+ for (auto DD : Pattern->ddiags()) {
switch (DD->getKind()) {
case DependentDiagnostic::Access:
HandleDependentAccessCheck(*DD, TemplateArgs);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
index 78aa7f8..8e4ce0d 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -10,6 +10,7 @@
//===----------------------------------------------------------------------===/
#include "clang/Sema/Sema.h"
+#include "TypeLocBuilder.h"
#include "clang/AST/Expr.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/TypeLoc.h"
@@ -18,7 +19,6 @@
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
-#include "TypeLocBuilder.h"
using namespace clang;
@@ -223,7 +223,7 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
llvm::SmallPtrSet<IdentifierInfo *, 4> NamesKnown;
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
- IdentifierInfo *Name = 0;
+ IdentifierInfo *Name = nullptr;
if (const TemplateTypeParmType *TTP
= Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>())
Name = TTP->getIdentifier();
@@ -463,7 +463,7 @@ Sema::CheckPackExpansion(TypeSourceInfo *Pattern, SourceLocation EllipsisLoc,
Pattern->getTypeLoc().getSourceRange(),
EllipsisLoc, NumExpansions);
if (Result.isNull())
- return 0;
+ return nullptr;
TypeLocBuilder TLB;
TLB.pushFullCopy(Pattern->getTypeLoc());
@@ -509,8 +509,8 @@ ExprResult Sema::CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
}
// Create the pack expansion expression and source-location information.
- return Owned(new (Context) PackExpansionExpr(Context.DependentTy, Pattern,
- EllipsisLoc, NumExpansions));
+ return new (Context)
+ PackExpansionExpr(Context.DependentTy, Pattern, EllipsisLoc, NumExpansions);
}
/// \brief Retrieve the depth and index of a parameter pack.
@@ -554,8 +554,8 @@ bool Sema::CheckParameterPacksForExpansion(
if (isa<ParmVarDecl>(ND))
IsFunctionParameterPack = true;
else
- llvm::tie(Depth, Index) = getDepthAndIndex(ND);
-
+ std::tie(Depth, Index) = getDepthAndIndex(ND);
+
Name = ND->getIdentifier();
}
@@ -599,7 +599,7 @@ bool Sema::CheckParameterPacksForExpansion(
if (NamedDecl *PartialPack
= CurrentInstantiationScope->getPartiallySubstitutedPack()){
unsigned PartialDepth, PartialIndex;
- llvm::tie(PartialDepth, PartialIndex) = getDepthAndIndex(PartialPack);
+ std::tie(PartialDepth, PartialIndex) = getDepthAndIndex(PartialPack);
if (PartialDepth == Depth && PartialIndex == Index)
RetainExpansion = true;
}
@@ -669,8 +669,8 @@ Optional<unsigned> Sema::getNumArgumentsInExpansion(QualType T,
Result = Size;
continue;
}
-
- llvm::tie(Depth, Index) = getDepthAndIndex(ND);
+
+ std::tie(Depth, Index) = getDepthAndIndex(ND);
}
if (Depth >= TemplateArgs.getNumLevels() ||
!TemplateArgs.hasTemplateArgument(Depth, Index))
@@ -730,14 +730,6 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
case TST_auto:
case TST_decltype_auto:
case TST_unknown_anytype:
- case TST_image1d_t:
- case TST_image1d_array_t:
- case TST_image1d_buffer_t:
- case TST_image2d_t:
- case TST_image2d_array_t:
- case TST_image3d_t:
- case TST_sampler_t:
- case TST_event_t:
case TST_error:
break;
}
@@ -775,7 +767,7 @@ namespace {
// Callback to only accept typo corrections that refer to parameter packs.
class ParameterPackValidatorCCC : public CorrectionCandidateCallback {
public:
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
NamedDecl *ND = candidate.getCorrectionDecl();
return ND && ND->isParameterPack();
}
@@ -806,8 +798,8 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S,
// The identifier in a sizeof... expression shall name a parameter pack.
LookupResult R(*this, &Name, NameLoc, LookupOrdinaryName);
LookupName(R, S);
-
- NamedDecl *ParameterPack = 0;
+
+ NamedDecl *ParameterPack = nullptr;
ParameterPackValidatorCCC Validator;
switch (R.getResultKind()) {
case LookupResult::Found:
@@ -817,8 +809,8 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S,
case LookupResult::NotFound:
case LookupResult::NotFoundInCurrentInstantiation:
if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(),
- R.getLookupKind(), S, 0,
- Validator)) {
+ R.getLookupKind(), S, nullptr,
+ Validator, CTK_ErrorRecovery)) {
diagnoseTypo(Corrected,
PDiag(diag::err_sizeof_pack_no_pack_name_suggest) << &Name,
PDiag(diag::note_parameter_pack_here));
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
index aa7459d..be1191c 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
+#include "TypeLocBuilder.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
@@ -21,10 +22,8 @@
#include "clang/AST/Expr.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeLocVisitor.h"
-#include "clang/Basic/OpenCL.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/DelayedDiagnostic.h"
@@ -34,7 +33,6 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
-#include "TypeLocBuilder.h"
using namespace clang;
@@ -81,7 +79,8 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
StringRef name = attr.getName()->getName();
// The GC attributes are usually written with macros; special-case them.
- IdentifierInfo *II = attr.isArgIdent(0) ? attr.getArgAsIdent(0)->Ident : 0;
+ IdentifierInfo *II = attr.isArgIdent(0) ? attr.getArgAsIdent(0)->Ident
+ : nullptr;
if (useExpansionLoc && loc.isMacroID() && II) {
if (II->isStr("strong")) {
if (S.findMacroSpelling(loc, "__strong")) name = "__strong";
@@ -225,14 +224,14 @@ namespace {
assert(hasSavedAttrs);
if (savedAttrs.empty()) {
- getMutableDeclSpec().getAttributes().set(0);
+ 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(0);
+ savedAttrs.back()->setNext(nullptr);
}
};
}
@@ -312,7 +311,7 @@ static DeclaratorChunk *maybeMovePastReturnType(Declarator &declarator,
unsigned i) {
assert(i <= declarator.getNumTypeObjects());
- DeclaratorChunk *result = 0;
+ DeclaratorChunk *result = nullptr;
// First, look inwards past parens for a function declarator.
for (; i != 0; --i) {
@@ -380,7 +379,7 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state,
case DeclaratorChunk::BlockPointer: {
// But don't move an ARC ownership attribute to the return type
// of a block.
- DeclaratorChunk *destChunk = 0;
+ DeclaratorChunk *destChunk = nullptr;
if (state.isProcessingDeclSpec() &&
attr.getKind() == AttributeList::AT_ObjCOwnership)
destChunk = maybeMovePastReturnType(declarator, i - 1);
@@ -664,7 +663,7 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
/*HasProto=*/true,
/*IsAmbiguous=*/false,
/*LParenLoc=*/NoLoc,
- /*ArgInfo=*/0,
+ /*ArgInfo=*/nullptr,
/*NumArgs=*/0,
/*EllipsisLoc=*/NoLoc,
/*RParenLoc=*/NoLoc,
@@ -676,10 +675,10 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
/*MutableLoc=*/NoLoc,
EST_None,
/*ESpecLoc=*/NoLoc,
- /*Exceptions=*/0,
- /*ExceptionRanges=*/0,
+ /*Exceptions=*/nullptr,
+ /*ExceptionRanges=*/nullptr,
/*NumExceptions=*/0,
- /*NoexceptExpr=*/0,
+ /*NoexceptExpr=*/nullptr,
loc, loc, declarator));
// For consistency, make sure the state still has us as processing
@@ -728,13 +727,15 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
Result = Context.WCharTy;
else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed) {
S.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
- << DS.getSpecifierName(DS.getTypeSpecType());
+ << DS.getSpecifierName(DS.getTypeSpecType(),
+ Context.getPrintingPolicy());
Result = Context.getSignedWCharType();
} else {
assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
"Unknown TSS value");
S.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
- << DS.getSpecifierName(DS.getTypeSpecType());
+ << DS.getSpecifierName(DS.getTypeSpecType(),
+ Context.getPrintingPolicy());
Result = Context.getUnsignedWCharType();
}
break;
@@ -851,7 +852,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
break;
}
case DeclSpec::TST_int128:
- if (!S.PP.getTargetInfo().hasInt128Type())
+ if (!S.Context.getTargetInfo().hasInt128Type())
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_int128_unsupported);
if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned)
Result = Context.UnsignedInt128Ty;
@@ -1058,38 +1059,6 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
}
break;
- case DeclSpec::TST_image1d_t:
- Result = Context.OCLImage1dTy;
- break;
-
- case DeclSpec::TST_image1d_array_t:
- Result = Context.OCLImage1dArrayTy;
- break;
-
- case DeclSpec::TST_image1d_buffer_t:
- Result = Context.OCLImage1dBufferTy;
- break;
-
- case DeclSpec::TST_image2d_t:
- Result = Context.OCLImage2dTy;
- break;
-
- case DeclSpec::TST_image2d_array_t:
- Result = Context.OCLImage2dArrayTy;
- break;
-
- case DeclSpec::TST_image3d_t:
- Result = Context.OCLImage3dTy;
- break;
-
- case DeclSpec::TST_sampler_t:
- Result = Context.OCLSamplerTy;
- break;
-
- case DeclSpec::TST_event_t:
- Result = Context.OCLEventTy;
- break;
-
case DeclSpec::TST_error:
Result = Context.IntTy;
declarator.setInvalidType(true);
@@ -1148,17 +1117,33 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
}
}
- // C++ [dcl.ref]p1:
+ // C++11 [dcl.ref]p1:
// Cv-qualified references are ill-formed except when the
- // cv-qualifiers are introduced through the use of a typedef
- // (7.1.3) or of a template type argument (14.3), in which
- // case the cv-qualifiers are ignored.
- // FIXME: Shouldn't we be checking SCS_typedef here?
+ // cv-qualifiers are introduced through the use of a typedef-name
+ // or decltype-specifier, in which case the cv-qualifiers are ignored.
+ //
+ // There don't appear to be any other contexts in which a cv-qualified
+ // reference type could be formed, so the 'ill-formed' clause here appears
+ // to never happen.
if (DS.getTypeSpecType() == DeclSpec::TST_typename &&
TypeQuals && Result->isReferenceType()) {
- TypeQuals &= ~DeclSpec::TQ_const;
- TypeQuals &= ~DeclSpec::TQ_volatile;
- TypeQuals &= ~DeclSpec::TQ_atomic;
+ // If this occurs outside a template instantiation, warn the user about
+ // it; they probably didn't mean to specify a redundant qualifier.
+ typedef std::pair<DeclSpec::TQ, SourceLocation> QualLoc;
+ QualLoc Quals[] = {
+ QualLoc(DeclSpec::TQ_const, DS.getConstSpecLoc()),
+ QualLoc(DeclSpec::TQ_volatile, DS.getVolatileSpecLoc()),
+ QualLoc(DeclSpec::TQ_atomic, DS.getAtomicSpecLoc())
+ };
+ for (unsigned I = 0, N = llvm::array_lengthof(Quals); I != N; ++I) {
+ if (S.ActiveTemplateInstantiations.empty()) {
+ if (TypeQuals & Quals[I].first)
+ S.Diag(Quals[I].second, diag::warn_typecheck_reference_qualifiers)
+ << DeclSpec::getSpecifierName(Quals[I].first) << Result
+ << FixItHint::CreateRemoval(Quals[I].second);
+ }
+ TypeQuals &= ~Quals[I].first;
+ }
}
// C90 6.5.3 constraints: "The same type qualifier shall not appear more
@@ -1327,6 +1312,59 @@ static QualType inferARCLifetimeForPointee(Sema &S, QualType type,
return S.Context.getQualifiedType(type, qs);
}
+static std::string getFunctionQualifiersAsString(const FunctionProtoType *FnTy){
+ std::string Quals =
+ Qualifiers::fromCVRMask(FnTy->getTypeQuals()).getAsString();
+
+ switch (FnTy->getRefQualifier()) {
+ case RQ_None:
+ break;
+
+ case RQ_LValue:
+ if (!Quals.empty())
+ Quals += ' ';
+ Quals += '&';
+ break;
+
+ case RQ_RValue:
+ if (!Quals.empty())
+ Quals += ' ';
+ Quals += "&&";
+ break;
+ }
+
+ return Quals;
+}
+
+namespace {
+/// Kinds of declarator that cannot contain a qualified function type.
+///
+/// C++98 [dcl.fct]p4 / C++11 [dcl.fct]p6:
+/// a function type with a cv-qualifier or a ref-qualifier can only appear
+/// at the topmost level of a type.
+///
+/// Parens and member pointers are permitted. We don't diagnose array and
+/// function declarators, because they don't allow function types at all.
+///
+/// The values of this enum are used in diagnostics.
+enum QualifiedFunctionKind { QFK_BlockPointer, QFK_Pointer, QFK_Reference };
+}
+
+/// Check whether the type T is a qualified function type, and if it is,
+/// diagnose that it cannot be contained within the given kind of declarator.
+static bool checkQualifiedFunction(Sema &S, QualType T, SourceLocation Loc,
+ QualifiedFunctionKind QFK) {
+ // Does T refer to a function type with a cv-qualifier or a ref-qualifier?
+ const FunctionProtoType *FPT = T->getAs<FunctionProtoType>();
+ if (!FPT || (FPT->getTypeQuals() == 0 && FPT->getRefQualifier() == RQ_None))
+ return false;
+
+ S.Diag(Loc, diag::err_compound_qualified_function_type)
+ << QFK << isa<FunctionType>(T.IgnoreParens()) << T
+ << getFunctionQualifiersAsString(FPT);
+ return true;
+}
+
/// \brief Build a pointer type.
///
/// \param T The type to which we'll be building a pointer.
@@ -1349,6 +1387,9 @@ QualType Sema::BuildPointerType(QualType T,
return QualType();
}
+ if (checkQualifiedFunction(*this, T, Loc, QFK_Pointer))
+ return QualType();
+
assert(!T->isObjCObjectType() && "Should build ObjCObjectPointerType");
// In ARC, it is forbidden to build pointers to unqualified pointers.
@@ -1408,6 +1449,9 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
return QualType();
}
+ if (checkQualifiedFunction(*this, T, Loc, QFK_Reference))
+ return QualType();
+
// In ARC, it is forbidden to build references to unqualified pointers.
if (getLangOpts().ObjCAutoRefCount)
T = inferARCLifetimeForPointee(*this, T, Loc, /*reference*/ true);
@@ -1427,10 +1471,10 @@ static bool isArraySizeVLA(Sema &S, Expr *ArraySize, llvm::APSInt &SizeVal) {
public:
VLADiagnoser() : Sema::VerifyICEDiagnoser(true) {}
- virtual void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) {
+ void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) override {
}
- virtual void diagnoseFold(Sema &S, SourceLocation Loc, SourceRange SR) {
+ void diagnoseFold(Sema &S, SourceLocation Loc, SourceRange SR) override {
S.Diag(Loc, diag::ext_vla_folded_to_constant) << SR;
}
} Diagnoser;
@@ -1487,6 +1531,13 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
diag::err_array_of_abstract_type))
return QualType();
+ // Mentioning a member pointer type for an array type causes us to lock in
+ // an inheritance model, even if it's inside an unused typedef.
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft())
+ if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>())
+ if (!MPTy->getClass()->isDependentType())
+ RequireCompleteType(Loc, T, 0);
+
} else {
// C99 6.7.5.2p1: If the element type is an incomplete or function type,
// reject it (e.g. void ary[7], struct foo ary[7], void ary[7]())
@@ -1515,7 +1566,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
if (ArraySize && ArraySize->hasPlaceholderType()) {
ExprResult Result = CheckPlaceholderExpr(ArraySize);
if (Result.isInvalid()) return QualType();
- ArraySize = Result.take();
+ ArraySize = Result.get();
}
// Do lvalue-to-rvalue conversions on the array size expression.
@@ -1524,7 +1575,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
if (Result.isInvalid())
return QualType();
- ArraySize = Result.take();
+ ArraySize = Result.get();
}
// C99 6.7.5.2p1: The size expression shall have integer type.
@@ -1540,7 +1591,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
llvm::APSInt ConstVal(Context.getTypeSize(Context.getSizeType()));
if (!ArraySize) {
if (ASM == ArrayType::Star)
- T = Context.getVariableArrayType(T, 0, ASM, Quals, Brackets);
+ T = Context.getVariableArrayType(T, nullptr, ASM, Quals, Brackets);
else
T = Context.getIncompleteArrayType(T, ASM, Quals);
} else if (ArraySize->isTypeDependent() || ArraySize->isValueDependent()) {
@@ -1614,6 +1665,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
// Prohibit the use of non-POD types in VLAs.
QualType BaseT = Context.getBaseElementType(T);
if (!T->isDependentType() &&
+ !RequireCompleteType(Loc, BaseT, 0) &&
!BaseT.isPODType(Context) &&
!BaseT->isObjCLifetimeType()) {
Diag(Loc, diag::err_vla_non_pod)
@@ -1711,7 +1763,7 @@ bool Sema::CheckFunctionReturnType(QualType T, SourceLocation Loc) {
}
QualType Sema::BuildFunctionType(QualType T,
- llvm::MutableArrayRef<QualType> ParamTypes,
+ MutableArrayRef<QualType> ParamTypes,
SourceLocation Loc, DeclarationName Entity,
const FunctionProtoType::ExtProtoInfo &EPI) {
bool Invalid = false;
@@ -1769,13 +1821,13 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
// with reference type, or "cv void."
if (T->isReferenceType()) {
Diag(Loc, diag::err_illegal_decl_mempointer_to_reference)
- << (Entity? Entity.getAsString() : "type name") << T;
+ << getPrintableNameForEntity(Entity) << T;
return QualType();
}
if (T->isVoidType()) {
Diag(Loc, diag::err_illegal_decl_mempointer_to_void)
- << (Entity? Entity.getAsString() : "type name");
+ << getPrintableNameForEntity(Entity);
return QualType();
}
@@ -1784,35 +1836,10 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
return QualType();
}
- // C++ allows the class type in a member pointer to be an incomplete type.
- // In the Microsoft ABI, the size of the member pointer can vary
- // according to the class type, which means that we really need a
- // complete type if possible, which means we need to instantiate templates.
- //
- // If template instantiation fails or the type is just incomplete, we have to
- // add an extra slot to the member pointer. Yes, this does cause problems
- // when passing pointers between TUs that disagree about the size.
- if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- CXXRecordDecl *RD = Class->getAsCXXRecordDecl();
- if (RD && !RD->hasAttr<MSInheritanceAttr>()) {
- // Lock in the inheritance model on the first use of a member pointer.
- // Otherwise we may disagree about the size at different points in the TU.
- // FIXME: MSVC picks a model on the first use that needs to know the size,
- // rather than on the first mention of the type, e.g. typedefs.
- if (RequireCompleteType(Loc, Class, 0) && !RD->isBeingDefined()) {
- // We know it doesn't have an attribute and it's incomplete, so use the
- // unspecified inheritance model. If we're in the record body, we can
- // figure out the inheritance model.
- for (CXXRecordDecl::redecl_iterator I = RD->redecls_begin(),
- E = RD->redecls_end(); I != E; ++I) {
- I->addAttr(::new (Context) UnspecifiedInheritanceAttr(
- RD->getSourceRange(), Context));
- }
- }
- }
- }
-
- // FIXME: Adjust member function pointer calling conventions.
+ // Adjust the default free function calling convention to the default method
+ // calling convention.
+ if (T->isFunctionType())
+ adjustMemberFunctionCC(T, /*IsStatic=*/false);
return Context.getMemberPointerType(T, Class.getTypePtr());
}
@@ -1836,17 +1863,20 @@ QualType Sema::BuildBlockPointerType(QualType T,
return QualType();
}
+ if (checkQualifiedFunction(*this, T, Loc, QFK_BlockPointer))
+ return QualType();
+
return Context.getBlockPointerType(T);
}
QualType Sema::GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo) {
QualType QT = Ty.get();
if (QT.isNull()) {
- if (TInfo) *TInfo = 0;
+ if (TInfo) *TInfo = nullptr;
return QualType();
}
- TypeSourceInfo *DI = 0;
+ TypeSourceInfo *DI = nullptr;
if (const LocInfoType *LIT = dyn_cast<LocInfoType>(QT)) {
QT = LIT->getType();
DI = LIT->getTypeSourceInfo();
@@ -1959,18 +1989,15 @@ static void inferARCWriteback(TypeProcessingState &state,
// TODO: mark whether we did this inference?
}
-static void diagnoseIgnoredQualifiers(
- Sema &S, unsigned Quals,
- SourceLocation FallbackLoc,
- SourceLocation ConstQualLoc = SourceLocation(),
- SourceLocation VolatileQualLoc = SourceLocation(),
- SourceLocation RestrictQualLoc = SourceLocation(),
- SourceLocation AtomicQualLoc = SourceLocation()) {
+void Sema::diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals,
+ SourceLocation FallbackLoc,
+ SourceLocation ConstQualLoc,
+ SourceLocation VolatileQualLoc,
+ SourceLocation RestrictQualLoc,
+ SourceLocation AtomicQualLoc) {
if (!Quals)
return;
- const SourceManager &SM = S.getSourceManager();
-
struct Qual {
unsigned Mask;
const char *Name;
@@ -1997,7 +2024,8 @@ static void diagnoseIgnoredQualifiers(
SourceLocation QualLoc = QualKinds[I].Loc;
if (!QualLoc.isInvalid()) {
FixIts[NumQuals] = FixItHint::CreateRemoval(QualLoc);
- if (Loc.isInvalid() || SM.isBeforeInTranslationUnit(QualLoc, Loc))
+ if (Loc.isInvalid() ||
+ getSourceManager().isBeforeInTranslationUnit(QualLoc, Loc))
Loc = QualLoc;
}
@@ -2005,19 +2033,20 @@ static void diagnoseIgnoredQualifiers(
}
}
- S.Diag(Loc.isInvalid() ? FallbackLoc : Loc, diag::warn_qual_return_type)
+ Diag(Loc.isInvalid() ? FallbackLoc : Loc, DiagID)
<< QualStr << NumQuals << FixIts[0] << FixIts[1] << FixIts[2] << FixIts[3];
}
// Diagnose pointless type qualifiers on the return type of a function.
-static void diagnoseIgnoredFunctionQualifiers(Sema &S, QualType RetTy,
- Declarator &D,
- unsigned FunctionChunkIndex) {
+static void diagnoseRedundantReturnTypeQualifiers(Sema &S, QualType RetTy,
+ Declarator &D,
+ unsigned FunctionChunkIndex) {
if (D.getTypeObject(FunctionChunkIndex).Fun.hasTrailingReturnType()) {
// FIXME: TypeSourceInfo doesn't preserve location information for
// qualifiers.
- diagnoseIgnoredQualifiers(S, RetTy.getLocalCVRQualifiers(),
- D.getIdentifierLoc());
+ S.diagnoseIgnoredQualifiers(diag::warn_qual_return_type,
+ RetTy.getLocalCVRQualifiers(),
+ D.getIdentifierLoc());
return;
}
@@ -2031,8 +2060,9 @@ static void diagnoseIgnoredFunctionQualifiers(Sema &S, QualType RetTy,
case DeclaratorChunk::Pointer: {
DeclaratorChunk::PointerTypeInfo &PTI = OuterChunk.Ptr;
- diagnoseIgnoredQualifiers(
- S, PTI.TypeQuals,
+ S.diagnoseIgnoredQualifiers(
+ diag::warn_qual_return_type,
+ PTI.TypeQuals,
SourceLocation(),
SourceLocation::getFromRawEncoding(PTI.ConstQualLoc),
SourceLocation::getFromRawEncoding(PTI.VolatileQualLoc),
@@ -2049,8 +2079,9 @@ static void diagnoseIgnoredFunctionQualifiers(Sema &S, QualType RetTy,
// FIXME: We can't currently provide an accurate source location and a
// fix-it hint for these.
unsigned AtomicQual = RetTy->isAtomicType() ? DeclSpec::TQ_atomic : 0;
- diagnoseIgnoredQualifiers(S, RetTy.getCVRQualifiers() | AtomicQual,
- D.getIdentifierLoc());
+ S.diagnoseIgnoredQualifiers(diag::warn_qual_return_type,
+ RetTy.getCVRQualifiers() | AtomicQual,
+ D.getIdentifierLoc());
return;
}
@@ -2065,12 +2096,13 @@ static void diagnoseIgnoredFunctionQualifiers(Sema &S, QualType RetTy,
// Just parens all the way out to the decl specifiers. Diagnose any qualifiers
// which are present there.
- diagnoseIgnoredQualifiers(S, D.getDeclSpec().getTypeQualifiers(),
- D.getIdentifierLoc(),
- D.getDeclSpec().getConstSpecLoc(),
- D.getDeclSpec().getVolatileSpecLoc(),
- D.getDeclSpec().getRestrictSpecLoc(),
- D.getDeclSpec().getAtomicSpecLoc());
+ S.diagnoseIgnoredQualifiers(diag::warn_qual_return_type,
+ D.getDeclSpec().getTypeQualifiers(),
+ D.getIdentifierLoc(),
+ D.getDeclSpec().getConstSpecLoc(),
+ D.getDeclSpec().getVolatileSpecLoc(),
+ D.getDeclSpec().getRestrictSpecLoc(),
+ D.getDeclSpec().getAtomicSpecLoc());
}
static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
@@ -2078,10 +2110,10 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
Sema &SemaRef = state.getSema();
Declarator &D = state.getDeclarator();
QualType T;
- ReturnTypeInfo = 0;
+ ReturnTypeInfo = nullptr;
// The TagDecl owned by the DeclSpec.
- TagDecl *OwnedTagDecl = 0;
+ TagDecl *OwnedTagDecl = nullptr;
bool ContainsPlaceholderType = false;
@@ -2303,67 +2335,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
return T;
}
-static std::string getFunctionQualifiersAsString(const FunctionProtoType *FnTy){
- std::string Quals =
- Qualifiers::fromCVRMask(FnTy->getTypeQuals()).getAsString();
-
- switch (FnTy->getRefQualifier()) {
- case RQ_None:
- break;
-
- case RQ_LValue:
- if (!Quals.empty())
- Quals += ' ';
- Quals += '&';
- break;
-
- case RQ_RValue:
- if (!Quals.empty())
- Quals += ' ';
- Quals += "&&";
- break;
- }
-
- return Quals;
-}
-
-/// Check that the function type T, which has a cv-qualifier or a ref-qualifier,
-/// can be contained within the declarator chunk DeclType, and produce an
-/// appropriate diagnostic if not.
-static void checkQualifiedFunction(Sema &S, QualType T,
- DeclaratorChunk &DeclType) {
- // C++98 [dcl.fct]p4 / C++11 [dcl.fct]p6: a function type with a
- // cv-qualifier or a ref-qualifier can only appear at the topmost level
- // of a type.
- int DiagKind = -1;
- switch (DeclType.Kind) {
- case DeclaratorChunk::Paren:
- case DeclaratorChunk::MemberPointer:
- // These cases are permitted.
- return;
- case DeclaratorChunk::Array:
- case DeclaratorChunk::Function:
- // These cases don't allow function types at all; no need to diagnose the
- // qualifiers separately.
- return;
- case DeclaratorChunk::BlockPointer:
- DiagKind = 0;
- break;
- case DeclaratorChunk::Pointer:
- DiagKind = 1;
- break;
- case DeclaratorChunk::Reference:
- DiagKind = 2;
- break;
- }
-
- assert(DiagKind != -1);
- S.Diag(DeclType.Loc, diag::err_compound_qualified_function_type)
- << DiagKind << isa<FunctionType>(T.IgnoreParens()) << T
- << getFunctionQualifiersAsString(T->castAs<FunctionProtoType>());
-}
-
-/// Produce an approprioate diagnostic for an ambiguity between a function
+/// Produce an appropriate diagnostic for an ambiguity between a function
/// declarator and a C++ direct-initializer.
static void warnAboutAmbiguousFunction(Sema &S, Declarator &D,
DeclaratorChunk &DeclType, QualType RT) {
@@ -2375,11 +2347,11 @@ static void warnAboutAmbiguousFunction(Sema &S, Declarator &D,
return;
// An initializer for a non-class type can have at most one argument.
- if (!RT->isRecordType() && FTI.NumArgs > 1)
+ if (!RT->isRecordType() && FTI.NumParams > 1)
return;
// An initializer for a reference must have exactly one argument.
- if (RT->isReferenceType() && FTI.NumArgs != 1)
+ if (RT->isReferenceType() && FTI.NumParams != 1)
return;
// Only warn if this declarator is declaring a function at block scope, and
@@ -2399,9 +2371,9 @@ static void warnAboutAmbiguousFunction(Sema &S, Declarator &D,
SourceRange ParenRange(DeclType.Loc, DeclType.EndLoc);
S.Diag(DeclType.Loc,
- FTI.NumArgs ? diag::warn_parens_disambiguated_as_function_declaration
- : diag::warn_empty_parens_are_function_decl)
- << ParenRange;
+ FTI.NumParams ? diag::warn_parens_disambiguated_as_function_declaration
+ : diag::warn_empty_parens_are_function_decl)
+ << ParenRange;
// If the declaration looks like:
// T var1,
@@ -2422,21 +2394,21 @@ static void warnAboutAmbiguousFunction(Sema &S, Declarator &D,
}
}
- if (FTI.NumArgs > 0) {
- // For a declaration with parameters, eg. "T var(T());", suggest adding parens
- // around the first parameter to turn the declaration into a variable
- // declaration.
- SourceRange Range = FTI.ArgInfo[0].Param->getSourceRange();
+ if (FTI.NumParams > 0) {
+ // For a declaration with parameters, eg. "T var(T());", suggest adding
+ // parens around the first parameter to turn the declaration into a
+ // variable declaration.
+ SourceRange Range = FTI.Params[0].Param->getSourceRange();
SourceLocation B = Range.getBegin();
- SourceLocation E = S.PP.getLocForEndOfToken(Range.getEnd());
+ SourceLocation E = S.getLocForEndOfToken(Range.getEnd());
// FIXME: Maybe we should suggest adding braces instead of parens
// in C++11 for classes that don't have an initializer_list constructor.
S.Diag(B, diag::note_additional_parens_for_variable_declaration)
<< FixItHint::CreateInsertion(B, "(")
<< FixItHint::CreateInsertion(E, ")");
} else {
- // For a declaration without parameters, eg. "T var();", suggest replacing the
- // parens with an initializer to turn the declaration into a variable
+ // For a declaration without parameters, eg. "T var();", suggest replacing
+ // the parens with an initializer to turn the declaration into a variable
// declaration.
const CXXRecordDecl *RD = RT->getAsCXXRecordDecl();
@@ -2579,10 +2551,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
unsigned chunkIndex = e - i - 1;
state.setCurrentChunkIndex(chunkIndex);
DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
- if (IsQualifiedFunction) {
- checkQualifiedFunction(S, T, DeclType);
- IsQualifiedFunction = DeclType.Kind == DeclaratorChunk::Paren;
- }
+ IsQualifiedFunction &= DeclType.Kind == DeclaratorChunk::Paren;
switch (DeclType.Kind) {
case DeclaratorChunk::Paren:
T = S.BuildParenType(T);
@@ -2625,7 +2594,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
T = S.BuildReferenceType(T, DeclType.Ref.LValueRef, DeclType.Loc, Name);
- Qualifiers Quals;
if (DeclType.Ref.HasRestrict)
T = S.BuildQualifiedType(T, DeclType.Loc, Qualifiers::Restrict);
break;
@@ -2727,11 +2695,13 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (!D.isInvalidType()) {
// trailing-return-type is only required if we're declaring a function,
// and not, for instance, a pointer to a function.
- if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
+ if (D.getDeclSpec().containsPlaceholderType() &&
!FTI.hasTrailingReturnType() && chunkIndex == 0 &&
!S.getLangOpts().CPlusPlus1y) {
S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
- diag::err_auto_missing_trailing_return);
+ D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto
+ ? diag::err_auto_missing_trailing_return
+ : diag::err_deduced_return_type);
T = Context.IntTy;
D.setInvalidType(true);
} else if (FTI.hasTrailingReturnType()) {
@@ -2794,10 +2764,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
SourceLocation DiagLoc, FixitLoc;
if (TInfo) {
DiagLoc = TInfo->getTypeLoc().getLocStart();
- FixitLoc = S.PP.getLocForEndOfToken(TInfo->getTypeLoc().getLocEnd());
+ FixitLoc = S.getLocForEndOfToken(TInfo->getTypeLoc().getLocEnd());
} else {
DiagLoc = D.getDeclSpec().getTypeSpecTypeLoc();
- FixitLoc = S.PP.getLocForEndOfToken(D.getDeclSpec().getLocEnd());
+ FixitLoc = S.getLocForEndOfToken(D.getDeclSpec().getLocEnd());
}
S.Diag(DiagLoc, diag::err_object_cannot_be_passed_returned_by_value)
<< 0 << T
@@ -2820,7 +2790,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if ((T.getCVRQualifiers() || T->isAtomicType()) &&
!(S.getLangOpts().CPlusPlus &&
(T->isDependentType() || T->isRecordType())))
- diagnoseIgnoredFunctionQualifiers(S, T, D, chunkIndex);
+ diagnoseRedundantReturnTypeQualifiers(S, T, D, chunkIndex);
// Objective-C ARC ownership qualifiers are ignored on the function
// return type (by type canonicalization). Complain if this attribute
@@ -2882,14 +2852,14 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
FunctionType::ExtInfo EI(getCCForDeclaratorChunk(S, D, FTI, chunkIndex));
- if (!FTI.NumArgs && !FTI.isVariadic && !LangOpts.CPlusPlus) {
+ if (!FTI.NumParams && !FTI.isVariadic && !LangOpts.CPlusPlus) {
// Simple void foo(), where the incoming T is the result type.
T = Context.getFunctionNoProtoType(T, EI);
} else {
// 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.NumArgs && FTI.isVariadic && !LangOpts.CPlusPlus) {
+ if (!FTI.NumParams && FTI.isVariadic && !LangOpts.CPlusPlus) {
bool Overloadable = false;
for (const AttributeList *Attrs = D.getAttributes();
Attrs; Attrs = Attrs->getNext()) {
@@ -2900,13 +2870,14 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
if (!Overloadable)
- S.Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_arg);
+ S.Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_param);
}
- if (FTI.NumArgs && FTI.ArgInfo[0].Param == 0) {
+ if (FTI.NumParams && FTI.Params[0].Param == nullptr) {
// C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function
// definition.
- S.Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration);
+ S.Diag(FTI.Params[0].IdentLoc,
+ diag::err_ident_list_in_fn_declaration);
D.setInvalidType(true);
// Recover by creating a K&R-style function type.
T = Context.getFunctionNoProtoType(T, EI);
@@ -2922,52 +2893,51 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
: FTI.RefQualifierIsLValueRef? RQ_LValue
: RQ_RValue;
- // Otherwise, we have a function with an argument list that is
+ // Otherwise, we have a function with a parameter list that is
// potentially variadic.
- SmallVector<QualType, 16> ArgTys;
- ArgTys.reserve(FTI.NumArgs);
+ SmallVector<QualType, 16> ParamTys;
+ ParamTys.reserve(FTI.NumParams);
- SmallVector<bool, 16> ConsumedArguments;
- ConsumedArguments.reserve(FTI.NumArgs);
- bool HasAnyConsumedArguments = false;
+ SmallVector<bool, 16> ConsumedParameters;
+ ConsumedParameters.reserve(FTI.NumParams);
+ bool HasAnyConsumedParameters = false;
- for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
- ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
- QualType ArgTy = Param->getType();
- assert(!ArgTy.isNull() && "Couldn't parse type?");
+ for (unsigned i = 0, e = FTI.NumParams; i != e; ++i) {
+ ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param);
+ QualType ParamTy = Param->getType();
+ assert(!ParamTy.isNull() && "Couldn't parse type?");
- // Look for 'void'. void is allowed only as a single argument to a
+ // Look for 'void'. void is allowed only as a single parameter to a
// function with no other parameters (C99 6.7.5.3p10). We record
- // int(void) as a FunctionProtoType with an empty argument list.
- if (ArgTy->isVoidType()) {
+ // int(void) as a FunctionProtoType with an empty parameter list.
+ if (ParamTy->isVoidType()) {
// If this is something like 'float(int, void)', reject it. 'void'
// is an incomplete type (C99 6.2.5p19) and function decls cannot
- // have arguments of incomplete type.
- if (FTI.NumArgs != 1 || FTI.isVariadic) {
+ // have parameters of incomplete type.
+ if (FTI.NumParams != 1 || FTI.isVariadic) {
S.Diag(DeclType.Loc, diag::err_void_only_param);
- ArgTy = Context.IntTy;
- Param->setType(ArgTy);
- } else if (FTI.ArgInfo[i].Ident) {
+ ParamTy = Context.IntTy;
+ Param->setType(ParamTy);
+ } else if (FTI.Params[i].Ident) {
// Reject, but continue to parse 'int(void abc)'.
- S.Diag(FTI.ArgInfo[i].IdentLoc,
- diag::err_param_with_void_type);
- ArgTy = Context.IntTy;
- Param->setType(ArgTy);
+ S.Diag(FTI.Params[i].IdentLoc, diag::err_param_with_void_type);
+ ParamTy = Context.IntTy;
+ Param->setType(ParamTy);
} else {
// Reject, but continue to parse 'float(const void)'.
- if (ArgTy.hasQualifiers())
+ if (ParamTy.hasQualifiers())
S.Diag(DeclType.Loc, diag::err_void_param_qualified);
- // Do not add 'void' to the ArgTys list.
+ // Do not add 'void' to the list.
break;
}
- } else if (ArgTy->isHalfType()) {
- // Disallow half FP arguments.
+ } else if (ParamTy->isHalfType()) {
+ // Disallow half FP parameters.
// FIXME: This really should be in BuildFunctionType.
if (S.getLangOpts().OpenCL) {
if (!S.getOpenCLOptions().cl_khr_fp16) {
S.Diag(Param->getLocation(),
- diag::err_opencl_half_argument) << ArgTy;
+ diag::err_opencl_half_param) << ParamTy;
D.setInvalidType();
Param->setInvalidDecl();
}
@@ -2977,12 +2947,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
D.setInvalidType();
}
} else if (!FTI.hasPrototype) {
- if (ArgTy->isPromotableIntegerType()) {
- ArgTy = Context.getPromotedIntegerType(ArgTy);
+ if (ParamTy->isPromotableIntegerType()) {
+ ParamTy = Context.getPromotedIntegerType(ParamTy);
Param->setKNRPromoted(true);
- } else if (const BuiltinType* BTy = ArgTy->getAs<BuiltinType>()) {
+ } else if (const BuiltinType* BTy = ParamTy->getAs<BuiltinType>()) {
if (BTy->getKind() == BuiltinType::Float) {
- ArgTy = Context.DoubleTy;
+ ParamTy = Context.DoubleTy;
Param->setKNRPromoted(true);
}
}
@@ -2990,20 +2960,20 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (LangOpts.ObjCAutoRefCount) {
bool Consumed = Param->hasAttr<NSConsumedAttr>();
- ConsumedArguments.push_back(Consumed);
- HasAnyConsumedArguments |= Consumed;
+ ConsumedParameters.push_back(Consumed);
+ HasAnyConsumedParameters |= Consumed;
}
- ArgTys.push_back(ArgTy);
+ ParamTys.push_back(ParamTy);
}
- if (HasAnyConsumedArguments)
- EPI.ConsumedArguments = ConsumedArguments.data();
+ if (HasAnyConsumedParameters)
+ EPI.ConsumedParameters = ConsumedParameters.data();
SmallVector<QualType, 4> Exceptions;
SmallVector<ParsedType, 2> DynamicExceptions;
SmallVector<SourceRange, 2> DynamicExceptionRanges;
- Expr *NoexceptExpr = 0;
+ Expr *NoexceptExpr = nullptr;
if (FTI.getExceptionSpecType() == EST_Dynamic) {
// FIXME: It's rather inefficient to have to split into two vectors
@@ -3026,7 +2996,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
Exceptions,
EPI);
- T = Context.getFunctionType(T, ArgTys, EPI);
+ T = Context.getFunctionType(T, ParamTys, EPI);
}
break;
@@ -3040,8 +3010,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
D.setInvalidType(true);
} else if (S.isDependentScopeSpecifier(SS) ||
dyn_cast_or_null<CXXRecordDecl>(S.computeDeclContext(SS))) {
- NestedNameSpecifier *NNS
- = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+ NestedNameSpecifier *NNS = SS.getScopeRep();
NestedNameSpecifier *NNSPrefix = NNS->getPrefix();
switch (NNS->getKind()) {
case NestedNameSpecifier::Identifier:
@@ -3126,6 +3095,13 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// alias-declaration,
// - the type-id in the default argument of a type-parameter, or
// - the type-id of a template-argument for a type-parameter
+ //
+ // FIXME: Checking this here is insufficient. We accept-invalid on:
+ //
+ // template<typename T> struct S { void f(T); };
+ // S<int() const> s;
+ //
+ // ... for instance.
if (IsQualifiedFunction &&
!(!FreeFunction &&
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) &&
@@ -3165,7 +3141,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
EPI.TypeQuals = 0;
EPI.RefQualifier = RQ_None;
- T = Context.getFunctionType(FnTy->getResultType(), FnTy->getArgTypes(),
+ T = Context.getFunctionType(FnTy->getReturnType(), FnTy->getParamTypes(),
EPI);
// Rebuild any parens around the identifier in the function type.
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
@@ -3283,7 +3259,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
TypeProcessingState state(*this, D);
- TypeSourceInfo *ReturnTypeInfo = 0;
+ TypeSourceInfo *ReturnTypeInfo = nullptr;
QualType T = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo);
if (T.isNull())
return Context.getNullTypeSourceInfo();
@@ -3318,7 +3294,7 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state,
if (attr->getKind() == AttributeList::AT_ObjCOwnership)
return;
- const char *attrStr = 0;
+ const char *attrStr = nullptr;
switch (ownership) {
case Qualifiers::OCL_None: llvm_unreachable("no ownership!");
case Qualifiers::OCL_ExplicitNone: attrStr = "none"; break;
@@ -3337,7 +3313,7 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state,
// so that we don't make an AttributedType for it).
AttributeList *attr = D.getAttributePool()
.create(&S.Context.Idents.get("objc_ownership"), SourceLocation(),
- /*scope*/ 0, SourceLocation(),
+ /*scope*/ nullptr, SourceLocation(),
/*args*/ &Args, 1, AttributeList::AS_GNU);
spliceAttrIntoList(*attr, chunk.getAttrListRef());
@@ -3398,7 +3374,7 @@ static void transferARCOwnership(TypeProcessingState &state,
TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) {
TypeProcessingState state(*this, D);
- TypeSourceInfo *ReturnTypeInfo = 0;
+ TypeSourceInfo *ReturnTypeInfo = nullptr;
QualType declSpecTy = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo);
if (declSpecTy.isNull())
return Context.getNullTypeSourceInfo();
@@ -3476,10 +3452,17 @@ static void fillAttributedTypeLoc(AttributedTypeLoc TL,
}
TL.setAttrNameLoc(attrs->getLoc());
- if (TL.hasAttrExprOperand() && attrs->isArgExpr(0))
+ if (TL.hasAttrExprOperand()) {
+ assert(attrs->isArgExpr(0) && "mismatched attribute operand kind");
TL.setAttrExprOperand(attrs->getArgAsExpr(0));
- else if (TL.hasAttrEnumOperand() && attrs->isArgIdent(0))
- TL.setAttrEnumOperandLoc(attrs->getArgAsIdent(0)->Loc);
+ } else if (TL.hasAttrEnumOperand()) {
+ assert((attrs->isArgIdent(0) || attrs->isArgExpr(0)) &&
+ "unexpected attribute operand kind");
+ if (attrs->isArgIdent(0))
+ TL.setAttrEnumOperandLoc(attrs->getArgAsIdent(0)->Loc);
+ else
+ TL.setAttrEnumOperandLoc(attrs->getArgAsExpr(0)->getExprLoc());
+ }
// FIXME: preserve this information to here.
if (TL.hasAttrOperand())
@@ -3541,7 +3524,7 @@ namespace {
Visit(TL.getPointeeLoc());
}
void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
// If we got no declarator info from previous Sema routines,
@@ -3573,7 +3556,7 @@ namespace {
TL.setTypeofLoc(DS.getTypeSpecTypeLoc());
TL.setParensRange(DS.getTypeofParensRange());
assert(DS.getRepAsType());
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
TL.setUnderlyingTInfo(TInfo);
}
@@ -3583,7 +3566,7 @@ namespace {
TL.setKWLoc(DS.getTypeSpecTypeLoc());
TL.setParensRange(DS.getTypeofParensRange());
assert(DS.getRepAsType());
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
TL.setUnderlyingTInfo(TInfo);
}
@@ -3606,7 +3589,7 @@ namespace {
ElaboratedTypeKeyword Keyword
= TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType());
if (DS.getTypeSpecType() == TST_typename) {
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
if (TInfo) {
TL.copy(TInfo->getTypeLoc().castAs<ElaboratedTypeLoc>());
@@ -3622,7 +3605,7 @@ namespace {
}
void VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
assert(DS.getTypeSpecType() == TST_typename);
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
assert(TInfo);
TL.copy(TInfo->getTypeLoc().castAs<DependentNameTypeLoc>());
@@ -3630,7 +3613,7 @@ namespace {
void VisitDependentTemplateSpecializationTypeLoc(
DependentTemplateSpecializationTypeLoc TL) {
assert(DS.getTypeSpecType() == TST_typename);
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
assert(TInfo);
TL.copy(
@@ -3646,7 +3629,7 @@ namespace {
TL.setKWLoc(DS.getTypeSpecTypeLoc());
TL.setParensRange(DS.getTypeofParensRange());
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
assert(TInfo);
TL.getValueLoc().initializeFullCopy(TInfo->getTypeLoc());
@@ -3682,6 +3665,9 @@ namespace {
void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
fillAttributedTypeLoc(TL, Chunk.getAttrs());
}
+ void VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
+ // nothing
+ }
void VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::BlockPointer);
TL.setCaretLoc(Chunk.Loc);
@@ -3763,9 +3749,9 @@ namespace {
const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun;
TL.setLParenLoc(FTI.getLParenLoc());
TL.setRParenLoc(FTI.getRParenLoc());
- for (unsigned i = 0, e = TL.getNumArgs(), tpi = 0; i != e; ++i) {
- ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
- TL.setArg(tpi++, Param);
+ for (unsigned i = 0, e = TL.getNumParams(), tpi = 0; i != e; ++i) {
+ ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param);
+ TL.setParam(tpi++, Param);
}
// FIXME: exception specs
}
@@ -3837,6 +3823,10 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
}
+ // FIXME: Ordering here?
+ while (AdjustedTypeLoc TL = CurrTL.getAs<AdjustedTypeLoc>())
+ CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
+
DeclaratorLocFiller(Context, D.getTypeObject(i)).Visit(CurrTL);
CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
}
@@ -3877,7 +3867,8 @@ void LocInfoType::getAsStringInternal(std::string &Str,
TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
// C99 6.7.6: Type names have no identifier. This is already validated by
// the parser.
- assert(D.getIdentifier() == 0 && "Type name should have no identifier!");
+ assert(D.getIdentifier() == nullptr &&
+ "Type name should have no identifier!");
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType T = TInfo->getType();
@@ -3936,44 +3927,60 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
return;
}
- // Check the attribute arguments.
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 1;
- Attr.setInvalid();
- return;
- }
- Expr *ASArgExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
- llvm::APSInt addrSpace(32);
- if (ASArgExpr->isTypeDependent() || ASArgExpr->isValueDependent() ||
- !ASArgExpr->isIntegerConstantExpr(addrSpace, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
- << Attr.getName() << AANT_ArgumentIntegerConstant
- << ASArgExpr->getSourceRange();
- Attr.setInvalid();
- return;
- }
-
- // Bounds checking.
- if (addrSpace.isSigned()) {
- if (addrSpace.isNegative()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_address_space_negative)
+ unsigned ASIdx;
+ if (Attr.getKind() == AttributeList::AT_AddressSpace) {
+ // Check the attribute arguments.
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr.getName() << 1;
+ Attr.setInvalid();
+ return;
+ }
+ Expr *ASArgExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
+ llvm::APSInt addrSpace(32);
+ if (ASArgExpr->isTypeDependent() || ASArgExpr->isValueDependent() ||
+ !ASArgExpr->isIntegerConstantExpr(addrSpace, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
+ << Attr.getName() << AANT_ArgumentIntegerConstant
<< ASArgExpr->getSourceRange();
Attr.setInvalid();
return;
}
- addrSpace.setIsSigned(false);
- }
- llvm::APSInt max(addrSpace.getBitWidth());
- max = Qualifiers::MaxAddressSpace;
- if (addrSpace > max) {
- S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high)
- << int(Qualifiers::MaxAddressSpace) << ASArgExpr->getSourceRange();
- Attr.setInvalid();
- return;
- }
- unsigned ASIdx = static_cast<unsigned>(addrSpace.getZExtValue());
+ // Bounds checking.
+ if (addrSpace.isSigned()) {
+ if (addrSpace.isNegative()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_address_space_negative)
+ << ASArgExpr->getSourceRange();
+ Attr.setInvalid();
+ return;
+ }
+ addrSpace.setIsSigned(false);
+ }
+ llvm::APSInt max(addrSpace.getBitWidth());
+ max = Qualifiers::MaxAddressSpace;
+ if (addrSpace > max) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high)
+ << int(Qualifiers::MaxAddressSpace) << ASArgExpr->getSourceRange();
+ Attr.setInvalid();
+ return;
+ }
+ ASIdx = static_cast<unsigned>(addrSpace.getZExtValue());
+ } else {
+ // The keyword-based type attributes imply which address space to use.
+ switch (Attr.getKind()) {
+ case AttributeList::AT_OpenCLGlobalAddressSpace:
+ ASIdx = LangAS::opencl_global; break;
+ case AttributeList::AT_OpenCLLocalAddressSpace:
+ ASIdx = LangAS::opencl_local; break;
+ case AttributeList::AT_OpenCLConstantAddressSpace:
+ ASIdx = LangAS::opencl_constant; break;
+ default:
+ assert(Attr.getKind() == AttributeList::AT_OpenCLPrivateAddressSpace);
+ ASIdx = 0; break;
+ }
+ }
+
Type = S.Context.getAddrSpaceQualType(Type, ASIdx);
}
@@ -4266,7 +4273,7 @@ namespace {
} else {
const Type *DTy = Ty->getUnqualifiedDesugaredType();
if (Ty == DTy) {
- Fn = 0;
+ Fn = nullptr;
return;
}
@@ -4276,7 +4283,7 @@ namespace {
}
}
- bool isFunctionType() const { return (Fn != 0); }
+ bool isFunctionType() const { return (Fn != nullptr); }
const FunctionType *get() const { return Fn; }
QualType wrap(Sema &S, const FunctionType *New) {
@@ -4586,73 +4593,38 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
return true;
}
+bool Sema::hasExplicitCallingConv(QualType &T) {
+ QualType R = T.IgnoreParens();
+ while (const AttributedType *AT = dyn_cast<AttributedType>(R)) {
+ if (AT->isCallingConv())
+ return true;
+ R = AT->getModifiedType().IgnoreParens();
+ }
+ return false;
+}
+
void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic) {
- const FunctionType *FT = T->castAs<FunctionType>();
+ FunctionTypeUnwrapper Unwrapped(*this, T);
+ const FunctionType *FT = Unwrapped.get();
bool IsVariadic = (isa<FunctionProtoType>(FT) &&
cast<FunctionProtoType>(FT)->isVariadic());
- CallingConv CC = FT->getCallConv();
// Only adjust types with the default convention. For example, on Windows we
// should adjust a __cdecl type to __thiscall for instance methods, and a
// __thiscall type to __cdecl for static methods.
- CallingConv DefaultCC =
+ CallingConv CurCC = FT->getCallConv();
+ CallingConv FromCC =
Context.getDefaultCallingConvention(IsVariadic, IsStatic);
- if (CC != DefaultCC)
+ CallingConv ToCC = Context.getDefaultCallingConvention(IsVariadic, !IsStatic);
+ if (CurCC != FromCC || FromCC == ToCC)
return;
- // Check if there was an explicit attribute, but only look through parens.
- // The intent is to look for an attribute on the current declarator, but not
- // one that came from a typedef.
- QualType R = T.IgnoreParens();
- while (const AttributedType *AT = dyn_cast<AttributedType>(R)) {
- if (AT->isCallingConv())
- return;
- R = AT->getModifiedType().IgnoreParens();
- }
-
- // FIXME: This loses sugar. This should probably be fixed with an implicit
- // AttributedType node that adjusts the convention.
- CC = Context.getDefaultCallingConvention(IsVariadic, !IsStatic);
- FT = Context.adjustFunctionType(FT, FT->getExtInfo().withCallingConv(CC));
- FunctionTypeUnwrapper Unwrapped(*this, T);
- T = Unwrapped.wrap(*this, FT);
-}
-
-/// Handle OpenCL image access qualifiers: read_only, write_only, read_write
-static void HandleOpenCLImageAccessAttribute(QualType& CurType,
- const AttributeList &Attr,
- Sema &S) {
- // Check the attribute arguments.
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 1;
- Attr.setInvalid();
- return;
- }
- Expr *sizeExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
- llvm::APSInt arg(32);
- if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() ||
- !sizeExpr->isIntegerConstantExpr(arg, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
- << Attr.getName() << AANT_ArgumentIntegerConstant
- << sizeExpr->getSourceRange();
- Attr.setInvalid();
+ if (hasExplicitCallingConv(T))
return;
- }
- unsigned iarg = static_cast<unsigned>(arg.getZExtValue());
- switch (iarg) {
- case CLIA_read_only:
- case CLIA_write_only:
- case CLIA_read_write:
- // Implemented in a separate patch
- break;
- default:
- // Implemented in a separate patch
- S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size)
- << sizeExpr->getSourceRange();
- Attr.setInvalid();
- break;
- }
+
+ FT = Context.adjustFunctionType(FT, FT->getExtInfo().withCallingConv(ToCC));
+ QualType Wrapped = Unwrapped.wrap(*this, FT);
+ T = Context.getAdjustedType(T, Wrapped);
}
/// HandleVectorSizeAttribute - this attribute is only applicable to integral
@@ -4757,17 +4729,25 @@ static void HandleExtVectorTypeAttr(QualType &CurType,
}
static bool isPermittedNeonBaseType(QualType &Ty,
- VectorType::VectorKind VecKind,
- bool IsAArch64) {
+ VectorType::VectorKind VecKind, Sema &S) {
const BuiltinType *BTy = Ty->getAs<BuiltinType>();
if (!BTy)
return false;
+ llvm::Triple Triple = S.Context.getTargetInfo().getTriple();
+
+ // Signed poly is mathematically wrong, but has been baked into some ABIs by
+ // now.
+ bool IsPolyUnsigned = Triple.getArch() == llvm::Triple::aarch64 ||
+ Triple.getArch() == llvm::Triple::aarch64_be ||
+ Triple.getArch() == llvm::Triple::arm64 ||
+ Triple.getArch() == llvm::Triple::arm64_be;
if (VecKind == VectorType::NeonPolyVector) {
- if (IsAArch64) {
+ if (IsPolyUnsigned) {
// AArch64 polynomial vectors are unsigned and support poly64.
return BTy->getKind() == BuiltinType::UChar ||
BTy->getKind() == BuiltinType::UShort ||
+ BTy->getKind() == BuiltinType::ULong ||
BTy->getKind() == BuiltinType::ULongLong;
} else {
// AArch32 polynomial vector are signed.
@@ -4778,7 +4758,12 @@ static bool isPermittedNeonBaseType(QualType &Ty,
// Non-polynomial vector types: the usual suspects are allowed, as well as
// float64_t on AArch64.
- if (IsAArch64 && BTy->getKind() == BuiltinType::Double)
+ bool Is64Bit = Triple.getArch() == llvm::Triple::aarch64 ||
+ Triple.getArch() == llvm::Triple::aarch64_be ||
+ Triple.getArch() == llvm::Triple::arm64 ||
+ Triple.getArch() == llvm::Triple::arm64_be;
+
+ if (Is64Bit && BTy->getKind() == BuiltinType::Double)
return true;
return BTy->getKind() == BuiltinType::SChar ||
@@ -4787,6 +4772,8 @@ static bool isPermittedNeonBaseType(QualType &Ty,
BTy->getKind() == BuiltinType::UShort ||
BTy->getKind() == BuiltinType::Int ||
BTy->getKind() == BuiltinType::UInt ||
+ BTy->getKind() == BuiltinType::Long ||
+ BTy->getKind() == BuiltinType::ULong ||
BTy->getKind() == BuiltinType::LongLong ||
BTy->getKind() == BuiltinType::ULongLong ||
BTy->getKind() == BuiltinType::Float ||
@@ -4828,10 +4815,7 @@ static void HandleNeonVectorTypeAttr(QualType& CurType,
return;
}
// Only certain element types are supported for Neon vectors.
- llvm::Triple::ArchType Arch =
- S.Context.getTargetInfo().getTriple().getArch();
- if (!isPermittedNeonBaseType(CurType, VecKind,
- Arch == llvm::Triple::aarch64)) {
+ if (!isPermittedNeonBaseType(CurType, VecKind, S)) {
S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
Attr.setInvalid();
return;
@@ -4911,6 +4895,10 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
// 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_AddressSpace:
HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
@@ -4939,13 +4927,11 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
attr.setUsedAsTypeAttr();
break;
case AttributeList::AT_OpenCLImageAccess:
- HandleOpenCLImageAccessAttribute(type, attr, state.getSema());
+ // FIXME: there should be some type checking happening here, I would
+ // imagine, but the original handler's checking was entirely superfluous.
attr.setUsedAsTypeAttr();
break;
- case AttributeList::AT_Win64:
- attr.setUsedAsTypeAttr();
- break;
MS_TYPE_ATTRS_CASELIST:
if (!handleMSPointerTypeQualifierAttr(state, attr, type))
attr.setUsedAsTypeAttr();
@@ -5058,7 +5044,7 @@ namespace {
TypeDiagnoserDiag(unsigned DiagID)
: Sema::TypeDiagnoser(DiagID == 0), DiagID(DiagID) {}
- virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
+ void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
if (Suppressed) return;
S.Diag(Loc, DiagID) << T;
}
@@ -5100,6 +5086,108 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
return false;
}
+/// \brief 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
+/// in order to provide a definition of this entity.
+static bool hasVisibleDefinition(Sema &S, NamedDecl *D, NamedDecl **Suggested) {
+ // Easy case: if we don't have modules, all declarations are visible.
+ if (!S.getLangOpts().Modules)
+ return true;
+
+ // If this definition was instantiated from a template, map back to the
+ // pattern from which it was instantiated.
+ //
+ // FIXME: There must be a better place for this to live.
+ if (auto *RD = dyn_cast<CXXRecordDecl>(D)) {
+ if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
+ auto From = TD->getInstantiatedFrom();
+ if (auto *CTD = From.dyn_cast<ClassTemplateDecl*>()) {
+ while (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate()) {
+ if (NewCTD->isMemberSpecialization())
+ break;
+ CTD = NewCTD;
+ }
+ RD = CTD->getTemplatedDecl();
+ } else if (auto *CTPSD = From.dyn_cast<
+ ClassTemplatePartialSpecializationDecl *>()) {
+ while (auto *NewCTPSD = CTPSD->getInstantiatedFromMember()) {
+ if (NewCTPSD->isMemberSpecialization())
+ break;
+ CTPSD = NewCTPSD;
+ }
+ RD = CTPSD;
+ }
+ } else if (isTemplateInstantiation(RD->getTemplateSpecializationKind())) {
+ while (auto *NewRD = RD->getInstantiatedFromMemberClass())
+ RD = NewRD;
+ }
+ D = RD->getDefinition();
+ } else if (auto *ED = dyn_cast<EnumDecl>(D)) {
+ while (auto *NewED = ED->getInstantiatedFromMemberEnum())
+ ED = NewED;
+ if (ED->isFixed()) {
+ // If the enum has a fixed underlying type, any declaration of it will do.
+ *Suggested = nullptr;
+ for (auto *Redecl : ED->redecls()) {
+ if (LookupResult::isVisible(S, Redecl))
+ return true;
+ if (Redecl->isThisDeclarationADefinition() ||
+ (Redecl->isCanonicalDecl() && !*Suggested))
+ *Suggested = Redecl;
+ }
+ return false;
+ }
+ D = ED->getDefinition();
+ }
+ assert(D && "missing definition for pattern of instantiated definition");
+
+ // FIXME: If we merged any other decl into D, and that declaration is visible,
+ // then we should consider a definition to be visible.
+ *Suggested = D;
+ return LookupResult::isVisible(S, D);
+}
+
+/// Locks in the inheritance model for the given class and all of its bases.
+static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) {
+ RD = RD->getMostRecentDecl();
+ if (!RD->hasAttr<MSInheritanceAttr>()) {
+ MSInheritanceAttr::Spelling IM;
+
+ switch (S.MSPointerToMemberRepresentationMethod) {
+ case LangOptions::PPTMK_BestCase:
+ IM = RD->calculateInheritanceModel();
+ break;
+ case LangOptions::PPTMK_FullGeneralitySingleInheritance:
+ IM = MSInheritanceAttr::Keyword_single_inheritance;
+ break;
+ case LangOptions::PPTMK_FullGeneralityMultipleInheritance:
+ IM = MSInheritanceAttr::Keyword_multiple_inheritance;
+ break;
+ case LangOptions::PPTMK_FullGeneralityVirtualInheritance:
+ IM = MSInheritanceAttr::Keyword_unspecified_inheritance;
+ break;
+ }
+
+ RD->addAttr(MSInheritanceAttr::CreateImplicit(
+ S.getASTContext(), IM,
+ /*BestCase=*/S.MSPointerToMemberRepresentationMethod ==
+ LangOptions::PPTMK_BestCase,
+ S.ImplicitMSInheritanceAttrLoc.isValid()
+ ? S.ImplicitMSInheritanceAttrLoc
+ : RD->getSourceRange()));
+ }
+
+ if (RD->hasDefinition()) {
+ // Assign inheritance models to all of the base classes, because now we can
+ // form pointers to members of base classes without calling
+ // RequireCompleteType on the pointer to member of the base class type.
+ for (const CXXBaseSpecifier &BS : RD->bases())
+ assignInheritanceModel(S, BS.getType()->getAsCXXRecordDecl());
+ }
+}
+
/// \brief The implementation of RequireCompleteType
bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
TypeDiagnoser &Diagnoser) {
@@ -5112,62 +5200,70 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
// "Can't ask whether a dependent type is complete");
// If we have a complete type, we're done.
- NamedDecl *Def = 0;
+ NamedDecl *Def = nullptr;
if (!T->isIncompleteType(&Def)) {
// If we know about the definition but it is not visible, complain.
- if (!Diagnoser.Suppressed && Def && !LookupResult::isVisible(*this, Def)) {
+ NamedDecl *SuggestedDef = nullptr;
+ if (!Diagnoser.Suppressed && Def &&
+ !hasVisibleDefinition(*this, Def, &SuggestedDef)) {
// Suppress this error outside of a SFINAE context if we've already
// emitted the error once for this type. There's no usefulness in
// repeating the diagnostic.
// FIXME: Add a Fix-It that imports the corresponding module or includes
// the header.
- Module *Owner = Def->getOwningModule();
+ Module *Owner = SuggestedDef->getOwningModule();
Diag(Loc, diag::err_module_private_definition)
<< T << Owner->getFullModuleName();
- Diag(Def->getLocation(), diag::note_previous_definition);
+ Diag(SuggestedDef->getLocation(), diag::note_previous_definition);
+
+ // Try to recover by implicitly importing this module.
+ createImplicitModuleImportForErrorRecovery(Loc, Owner);
+ }
- if (!isSFINAEContext()) {
- // Recover by implicitly importing this module.
- createImplicitModuleImport(Loc, Owner);
+ // 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()) {
+ RequireCompleteType(Loc, QualType(MPTy->getClass(), 0), 0);
+ assignInheritanceModel(*this, MPTy->getMostRecentCXXRecordDecl());
+ }
}
}
return false;
}
- // FIXME: If there's an unimported definition of this type in a module (for
+ const TagType *Tag = T->getAs<TagType>();
+ const ObjCInterfaceType *IFace = T->getAs<ObjCInterfaceType>();
+
+ // If there's an unimported definition of this type in a module (for
// instance, because we forward declared it, then imported the definition),
// import that definition now.
+ //
// FIXME: What about other cases where an import extends a redeclaration
// chain for a declaration that can be accessed through a mechanism other
// than name lookup (eg, referenced in a template, or a variable whose type
// could be completed by the module)?
+ if (Tag || IFace) {
+ NamedDecl *D =
+ Tag ? static_cast<NamedDecl *>(Tag->getDecl()) : IFace->getDecl();
- const TagType *Tag = T->getAs<TagType>();
- const ObjCInterfaceType *IFace = 0;
-
- if (Tag) {
// Avoid diagnosing invalid decls as incomplete.
- if (Tag->getDecl()->isInvalidDecl())
+ if (D->isInvalidDecl())
return true;
// Give the external AST source a chance to complete the type.
- if (Tag->getDecl()->hasExternalLexicalStorage()) {
- Context.getExternalSource()->CompleteType(Tag->getDecl());
- if (!Tag->isIncompleteType())
- return false;
- }
- }
- else if ((IFace = T->getAs<ObjCInterfaceType>())) {
- // Avoid diagnosing invalid decls as incomplete.
- if (IFace->getDecl()->isInvalidDecl())
- return true;
+ if (auto *Source = Context.getExternalSource()) {
+ if (Tag)
+ Source->CompleteType(Tag->getDecl());
+ else
+ Source->CompleteType(IFace->getDecl());
- // Give the external AST source a chance to complete the type.
- if (IFace->getDecl()->hasExternalLexicalStorage()) {
- Context.getExternalSource()->CompleteType(IFace->getDecl());
- if (!IFace->isIncompleteType())
- return false;
+ // If the external source completed the type, go through the motions
+ // again to ensure we're allowed to use the completed type.
+ if (!T->isIncompleteType())
+ return RequireCompleteTypeImpl(Loc, T, Diagnoser);
}
}
@@ -5310,29 +5406,26 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
if (RD->getNumVBases()) {
Diag(RD->getLocation(), diag::note_non_literal_virtual_base)
<< getLiteralDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases();
- for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
- E = RD->vbases_end(); I != E; ++I)
- Diag(I->getLocStart(),
- diag::note_constexpr_virtual_base_here) << I->getSourceRange();
+ for (const auto &I : RD->vbases())
+ Diag(I.getLocStart(), diag::note_constexpr_virtual_base_here)
+ << I.getSourceRange();
} else if (!RD->isAggregate() && !RD->hasConstexprNonCopyMoveConstructor() &&
!RD->hasTrivialDefaultConstructor()) {
Diag(RD->getLocation(), diag::note_non_literal_no_constexpr_ctors) << RD;
} else if (RD->hasNonLiteralTypeFieldsOrBases()) {
- for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
- E = RD->bases_end(); I != E; ++I) {
- if (!I->getType()->isLiteralType(Context)) {
- Diag(I->getLocStart(),
+ for (const auto &I : RD->bases()) {
+ if (!I.getType()->isLiteralType(Context)) {
+ Diag(I.getLocStart(),
diag::note_non_literal_base_class)
- << RD << I->getType() << I->getSourceRange();
+ << RD << I.getType() << I.getSourceRange();
return true;
}
}
- for (CXXRecordDecl::field_iterator I = RD->field_begin(),
- E = RD->field_end(); I != E; ++I) {
+ for (const auto *I : RD->fields()) {
if (!I->getType()->isLiteralType(Context) ||
I->getType().isVolatileQualified()) {
Diag(I->getLocation(), diag::note_non_literal_field)
- << RD << *I << I->getType()
+ << RD << I << I->getType()
<< I->getType().isVolatileQualified();
return true;
}
@@ -5368,11 +5461,11 @@ QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword,
return T;
NestedNameSpecifier *NNS;
if (SS.isValid())
- NNS = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ NNS = SS.getScopeRep();
else {
if (Keyword == ETK_None)
return T;
- NNS = 0;
+ NNS = nullptr;
}
return Context.getElaboratedType(Keyword, NNS, T);
}
@@ -5380,7 +5473,7 @@ QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword,
QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) {
ExprResult ER = CheckPlaceholderExpr(E);
if (ER.isInvalid()) return QualType();
- E = ER.take();
+ E = ER.get();
if (!E->isTypeDependent()) {
QualType T = E->getType();
@@ -5460,7 +5553,7 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) {
QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc) {
ExprResult ER = CheckPlaceholderExpr(E);
if (ER.isInvalid()) return QualType();
- E = ER.take();
+ E = ER.get();
return Context.getDecltypeType(E, getDecltypeForExpr(*this, E));
}
@@ -5476,12 +5569,23 @@ QualType Sema::BuildUnaryTransformType(QualType BaseType,
} else {
QualType Underlying = BaseType;
if (!BaseType->isDependentType()) {
+ // The enum could be incomplete if we're parsing its definition or
+ // recovering from an error.
+ NamedDecl *FwdDecl = nullptr;
+ if (BaseType->isIncompleteType(&FwdDecl)) {
+ Diag(Loc, diag::err_underlying_type_of_incomplete_enum) << BaseType;
+ Diag(FwdDecl->getLocation(), diag::note_forward_declaration) << FwdDecl;
+ return QualType();
+ }
+
EnumDecl *ED = BaseType->getAs<EnumType>()->getDecl();
assert(ED && "EnumType has no EnumDecl");
+
DiagnoseUseOfDecl(ED, Loc);
+
Underlying = ED->getIntegerType();
+ assert(!Underlying.isNull());
}
- assert(!Underlying.isNull());
return Context.getUnaryTransformType(BaseType, Underlying,
UnaryTransformType::EnumUnderlyingType);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp b/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp
deleted file mode 100644
index 45067de..0000000
--- a/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp
+++ /dev/null
@@ -1,353 +0,0 @@
-//===-- TargetAttributesSema.cpp - Encapsulate target attributes-*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains semantic analysis implementation for target-specific
-// attributes.
-//
-//===----------------------------------------------------------------------===//
-
-#include "TargetAttributesSema.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Sema/SemaInternal.h"
-#include "llvm/ADT/Triple.h"
-
-using namespace clang;
-
-TargetAttributesSema::~TargetAttributesSema() {}
-bool TargetAttributesSema::ProcessDeclAttribute(Scope *scope, Decl *D,
- const AttributeList &Attr, Sema &S) const {
- return false;
-}
-
-static void HandleARMInterruptAttr(Decl *d,
- const AttributeList &Attr, Sema &S) {
- // Check the attribute arguments.
- if (Attr.getNumArgs() > 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
- << 1;
- return;
- }
-
- StringRef Str;
- SourceLocation ArgLoc;
-
- if (Attr.getNumArgs() == 0)
- Str = "";
- else if (!S.checkStringLiteralArgumentAttr(Attr, 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;
- return;
- }
-
- unsigned Index = Attr.getAttributeSpellingListIndex();
- d->addAttr(::new (S.Context)
- ARMInterruptAttr(Attr.getLoc(), S.Context, Kind, Index));
-}
-
-namespace {
- class ARMAttributesSema : public TargetAttributesSema {
- public:
- ARMAttributesSema() { }
- bool ProcessDeclAttribute(Scope *scope, Decl *D,
- const AttributeList &Attr, Sema &S) const {
- if (Attr.getName()->getName() == "interrupt") {
- HandleARMInterruptAttr(D, Attr, S);
- return true;
- }
- return false;
- }
- };
-}
-
-static void HandleMSP430InterruptAttr(Decl *d,
- const AttributeList &Attr, Sema &S) {
- // Check the attribute arguments.
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 1;
- return;
- }
-
- // FIXME: Check for decl - it should be void ()(void).
-
- Expr *NumParamsExpr = static_cast<Expr *>(Attr.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
- << NumParamsExpr->getSourceRange();
- return;
- }
-
- unsigned Num = NumParams.getLimitedValue(255);
- if ((Num & 1) || Num > 30) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << "interrupt" << (int)NumParams.getSExtValue()
- << NumParamsExpr->getSourceRange();
- return;
- }
-
- d->addAttr(::new (S.Context) MSP430InterruptAttr(Attr.getLoc(), S.Context, Num));
- d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
- }
-
-namespace {
- class MSP430AttributesSema : public TargetAttributesSema {
- public:
- MSP430AttributesSema() { }
- bool ProcessDeclAttribute(Scope *scope, Decl *D,
- const AttributeList &Attr, Sema &S) const {
- if (Attr.getName()->getName() == "interrupt") {
- HandleMSP430InterruptAttr(D, Attr, S);
- return true;
- }
- return false;
- }
- };
-}
-
-static void HandleX86ForceAlignArgPointerAttr(Decl *D,
- const AttributeList& Attr,
- Sema &S) {
- // Check the attribute arguments.
- if (Attr.getNumArgs() != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 0;
- return;
- }
-
- // 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);
- if (VD && VD->getType()->isFunctionPointerType())
- return;
- // Also don't warn on function pointer typedefs.
- TypedefNameDecl *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;
- return;
- }
-
- D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr(Attr.getRange(),
- S.Context));
-}
-
-DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range,
- unsigned AttrSpellingListIndex) {
- if (D->hasAttr<DLLExportAttr>()) {
- Diag(Range.getBegin(), diag::warn_attribute_ignored) << "dllimport";
- return NULL;
- }
-
- if (D->hasAttr<DLLImportAttr>())
- return NULL;
-
- if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
- if (VD->hasDefinition()) {
- // dllimport cannot be applied to definitions.
- Diag(D->getLocation(), diag::warn_attribute_invalid_on_definition)
- << "dllimport";
- return NULL;
- }
- }
-
- return ::new (Context) DLLImportAttr(Range, Context,
- AttrSpellingListIndex);
-}
-
-static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
- // check the attribute arguments.
- if (Attr.getNumArgs() != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 0;
- return;
- }
-
- // Attribute can be applied only to functions or variables.
- FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
- if (!FD && !isa<VarDecl>(D)) {
- // Apparently Visual C++ thinks it is okay to not emit a warning
- // in this case, so only emit a warning when -fms-extensions is not
- // specified.
- if (!S.getLangOpts().MicrosoftExt)
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 2 /*variable and function*/;
- return;
- }
-
- // Currently, the dllimport attribute is ignored for inlined functions.
- // Warning is emitted.
- if (FD && FD->isInlineSpecified()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
- return;
- }
-
- unsigned Index = Attr.getAttributeSpellingListIndex();
- DLLImportAttr *NewAttr = S.mergeDLLImportAttr(D, Attr.getRange(), Index);
- if (NewAttr)
- D->addAttr(NewAttr);
-}
-
-DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range,
- unsigned AttrSpellingListIndex) {
- if (DLLImportAttr *Import = D->getAttr<DLLImportAttr>()) {
- Diag(Import->getLocation(), diag::warn_attribute_ignored) << "dllimport";
- D->dropAttr<DLLImportAttr>();
- }
-
- if (D->hasAttr<DLLExportAttr>())
- return NULL;
-
- return ::new (Context) DLLExportAttr(Range, Context,
- AttrSpellingListIndex);
-}
-
-static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
- // check the attribute arguments.
- if (Attr.getNumArgs() != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 0;
- return;
- }
-
- // Attribute can be applied only to functions or variables.
- FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
- if (!FD && !isa<VarDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 2 /*variable and function*/;
- return;
- }
-
- // Currently, the dllexport attribute is ignored for inlined functions, unless
- // the -fkeep-inline-functions flag has been used. Warning is emitted;
- if (FD && FD->isInlineSpecified()) {
- // FIXME: ... unless the -fkeep-inline-functions flag has been used.
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport";
- return;
- }
-
- unsigned Index = Attr.getAttributeSpellingListIndex();
- DLLExportAttr *NewAttr = S.mergeDLLExportAttr(D, Attr.getRange(), Index);
- if (NewAttr)
- D->addAttr(NewAttr);
-}
-
-namespace {
- class X86AttributesSema : public TargetAttributesSema {
- public:
- X86AttributesSema() { }
- bool ProcessDeclAttribute(Scope *scope, Decl *D,
- const AttributeList &Attr, Sema &S) const {
- const llvm::Triple &Triple(S.Context.getTargetInfo().getTriple());
- if (Triple.getOS() == llvm::Triple::Win32 ||
- Triple.getOS() == llvm::Triple::MinGW32) {
- switch (Attr.getKind()) {
- case AttributeList::AT_DLLImport: HandleDLLImportAttr(D, Attr, S);
- return true;
- case AttributeList::AT_DLLExport: HandleDLLExportAttr(D, Attr, S);
- return true;
- default: break;
- }
- }
- if (Triple.getArch() != llvm::Triple::x86_64 &&
- (Attr.getName()->getName() == "force_align_arg_pointer" ||
- Attr.getName()->getName() == "__force_align_arg_pointer__")) {
- HandleX86ForceAlignArgPointerAttr(D, Attr, S);
- return true;
- }
- return false;
- }
- };
-}
-
-static void HandleMips16Attr(Decl *D, const AttributeList &Attr, Sema &S) {
- // check the attribute arguments.
- if (Attr.getNumArgs()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 0;
- return;
- }
- // Attribute can only be applied to function types.
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << /* function */0;
- return;
- }
- D->addAttr(::new (S.Context) Mips16Attr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void HandleNoMips16Attr(Decl *D, const AttributeList &Attr, Sema &S) {
- // check the attribute arguments.
- if (Attr.getNumArgs()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 0;
- return;
- }
- // Attribute can only be applied to function types.
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << /* function */0;
- return;
- }
- D->addAttr(::new (S.Context)
- NoMips16Attr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-namespace {
- class MipsAttributesSema : public TargetAttributesSema {
- public:
- MipsAttributesSema() { }
- bool ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Attr,
- Sema &S) const {
- if (Attr.getName()->getName() == "mips16") {
- HandleMips16Attr(D, Attr, S);
- return true;
- } else if (Attr.getName()->getName() == "nomips16") {
- HandleNoMips16Attr(D, Attr, S);
- return true;
- }
- return false;
- }
- };
-}
-
-const TargetAttributesSema &Sema::getTargetAttributesSema() const {
- if (TheTargetAttributesSema)
- return *TheTargetAttributesSema;
-
- const llvm::Triple &Triple(Context.getTargetInfo().getTriple());
- switch (Triple.getArch()) {
- case llvm::Triple::arm:
- case llvm::Triple::thumb:
- return *(TheTargetAttributesSema = new ARMAttributesSema);
- case llvm::Triple::msp430:
- return *(TheTargetAttributesSema = new MSP430AttributesSema);
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- return *(TheTargetAttributesSema = new X86AttributesSema);
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- return *(TheTargetAttributesSema = new MipsAttributesSema);
- default:
- return *(TheTargetAttributesSema = new TargetAttributesSema);
- }
-}
diff --git a/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.h b/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.h
deleted file mode 100644
index 410c900..0000000
--- a/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.h
+++ /dev/null
@@ -1,27 +0,0 @@
-//===--- TargetAttributesSema.h - Semantic Analysis For Target Attributes -===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CLANG_SEMA_TARGETSEMA_H
-#define CLANG_SEMA_TARGETSEMA_H
-
-namespace clang {
- class Scope;
- class Decl;
- class AttributeList;
- class Sema;
-
- class TargetAttributesSema {
- public:
- virtual ~TargetAttributesSema();
- virtual bool ProcessDeclAttribute(Scope *scope, Decl *D,
- const AttributeList &Attr, Sema &S) const;
- };
-}
-
-#endif
diff --git a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
index f940da4..312811d 100644
--- a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
+++ b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
@@ -25,7 +25,6 @@
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtOpenMP.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Designator.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Ownership.h"
@@ -345,7 +344,7 @@ public:
/// TransformExpr or TransformExprs.
///
/// \returns the transformed initializer.
- ExprResult TransformInitializer(Expr *Init, bool CXXDirectInit);
+ ExprResult TransformInitializer(Expr *Init, bool NotCopyInit);
/// \brief Transform the given list of expressions.
///
@@ -372,7 +371,7 @@ public:
/// \returns true if an error occurred, false otherwise.
bool TransformExprs(Expr **Inputs, unsigned NumInputs, bool IsCall,
SmallVectorImpl<Expr *> &Outputs,
- bool *ArgChanged = 0);
+ bool *ArgChanged = nullptr);
/// \brief Transform the given declaration, which is referenced from a type
/// or expression.
@@ -434,10 +433,10 @@ public:
/// By default, transforms all of the types and declarations within the
/// nested-name-specifier. Subclasses may override this function to provide
/// alternate behavior.
- NestedNameSpecifierLoc TransformNestedNameSpecifierLoc(
- NestedNameSpecifierLoc NNS,
- QualType ObjectType = QualType(),
- NamedDecl *FirstQualifierInScope = 0);
+ NestedNameSpecifierLoc
+ TransformNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
+ QualType ObjectType = QualType(),
+ NamedDecl *FirstQualifierInScope = nullptr);
/// \brief Transform the given declaration name.
///
@@ -468,11 +467,11 @@ public:
/// By default, transforms the template name by transforming the declarations
/// and nested-name-specifiers that occur within the template name.
/// Subclasses may override this function to provide alternate behavior.
- TemplateName TransformTemplateName(CXXScopeSpec &SS,
- TemplateName Name,
- SourceLocation NameLoc,
- QualType ObjectType = QualType(),
- NamedDecl *FirstQualifierInScope = 0);
+ TemplateName
+ TransformTemplateName(CXXScopeSpec &SS, TemplateName Name,
+ SourceLocation NameLoc,
+ QualType ObjectType = QualType(),
+ NamedDecl *FirstQualifierInScope = nullptr);
/// \brief Transform the given template argument.
///
@@ -605,8 +604,16 @@ public:
}
ExprResult TransformAddressOfOperand(Expr *E);
+
ExprResult TransformDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E,
- bool IsAddressOfOperand);
+ bool IsAddressOfOperand,
+ TypeSourceInfo **RecoveryTSI);
+
+ ExprResult TransformParenDependentScopeDeclRefExpr(
+ ParenExpr *PE, DependentScopeDeclRefExpr *DRE, bool IsAddressOfOperand,
+ TypeSourceInfo **RecoveryTSI);
+
+ StmtResult TransformOMPExecutableDirective(OMPExecutableDirective *S);
// FIXME: We use LLVM_ATTRIBUTE_NOINLINE because inlining causes a ridiculous
// amount of stack usage with clang.
@@ -743,7 +750,7 @@ public:
/// By default, performs semantic analysis when building the function type.
/// Subclasses may override this routine to provide different behavior.
QualType RebuildFunctionProtoType(QualType T,
- llvm::MutableArrayRef<QualType> ParamTypes,
+ MutableArrayRef<QualType> ParamTypes,
const FunctionProtoType::ExtProtoInfo &EPI);
/// \brief Build a new unprototyped function type.
@@ -848,7 +855,8 @@ public:
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
TemplateName InstName
- = getDerived().RebuildTemplateName(SS, *Name, NameLoc, QualType(), 0);
+ = getDerived().RebuildTemplateName(SS, *Name, NameLoc, QualType(),
+ nullptr);
if (InstName.isNull())
return QualType();
@@ -866,7 +874,7 @@ public:
getDerived().RebuildTemplateSpecializationType(InstName, NameLoc, Args);
if (T.isNull()) return QualType();
- if (Keyword == ETK_None && QualifierLoc.getNestedNameSpecifier() == 0)
+ if (Keyword == ETK_None && QualifierLoc.getNestedNameSpecifier() == nullptr)
return T;
return SemaRef.Context.getElaboratedType(Keyword,
@@ -912,7 +920,7 @@ public:
if (SemaRef.RequireCompleteDeclContext(SS, DC))
return QualType();
- TagDecl *Tag = 0;
+ TagDecl *Tag = nullptr;
SemaRef.LookupQualifiedName(Result, DC);
switch (Result.getResultKind()) {
case LookupResult::NotFound:
@@ -951,9 +959,8 @@ public:
break;
}
default:
- // FIXME: Would be nice to highlight just the source range.
SemaRef.Diag(IdLoc, diag::err_not_tag_in_scope)
- << Kind << Id << DC;
+ << Kind << Id << DC << QualifierLoc.getSourceRange();
break;
}
return QualType();
@@ -1080,7 +1087,7 @@ public:
SourceLocation ColonLoc,
Stmt *SubStmt) {
return getSema().ActOnDefaultStmt(DefaultLoc, ColonLoc, SubStmt,
- /*CurScope=*/0);
+ /*CurScope=*/nullptr);
}
/// \brief Build a new label statement.
@@ -1187,14 +1194,14 @@ public:
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
StmtResult RebuildReturnStmt(SourceLocation ReturnLoc, Expr *Result) {
- return getSema().ActOnReturnStmt(ReturnLoc, Result);
+ return getSema().BuildReturnStmt(ReturnLoc, Result);
}
/// \brief Build a new declaration statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- StmtResult RebuildDeclStmt(llvm::MutableArrayRef<Decl *> Decls,
+ StmtResult RebuildDeclStmt(MutableArrayRef<Decl *> Decls,
SourceLocation StartLoc, SourceLocation EndLoc) {
Sema::DeclGroupPtrTy DG = getSema().BuildDeclaratorGroup(Decls);
return getSema().ActOnDeclStmt(DG, StartLoc, EndLoc);
@@ -1286,21 +1293,78 @@ public:
return getSema().BuildObjCAtThrowStmt(AtLoc, Operand);
}
- /// \brief Build a new OpenMP parallel directive.
+ /// \brief 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.
- StmtResult RebuildOMPParallelDirective(ArrayRef<OMPClause *> Clauses,
- Stmt *AStmt,
- SourceLocation StartLoc,
- SourceLocation EndLoc) {
- return getSema().ActOnOpenMPParallelDirective(Clauses, AStmt,
- StartLoc, EndLoc);
+ StmtResult RebuildOMPExecutableDirective(OpenMPDirectiveKind Kind,
+ DeclarationNameInfo DirName,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPExecutableDirective(Kind, DirName, Clauses,
+ AStmt, StartLoc, EndLoc);
+ }
+
+ /// \brief 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.
+ OMPClause *RebuildOMPIfClause(Expr *Condition,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPIfClause(Condition, StartLoc,
+ LParenLoc, EndLoc);
+ }
+
+ /// \brief 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.
+ OMPClause *RebuildOMPFinalClause(Expr *Condition, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPFinalClause(Condition, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
+ /// \brief 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.
+ OMPClause *RebuildOMPNumThreadsClause(Expr *NumThreads,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPNumThreadsClause(NumThreads, StartLoc,
+ LParenLoc, EndLoc);
+ }
+
+ /// \brief 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.
+ OMPClause *RebuildOMPSafelenClause(Expr *Len, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPSafelenClause(Len, StartLoc, LParenLoc, EndLoc);
+ }
+
+ /// \brief 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.
+ OMPClause *RebuildOMPCollapseClause(Expr *Num, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPCollapseClause(Num, StartLoc, LParenLoc,
+ EndLoc);
}
/// \brief Build a new OpenMP 'default' clause.
///
- /// By default, performs semantic analysis to build the new statement.
+ /// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
OMPClause *RebuildOMPDefaultClause(OpenMPDefaultClauseKind Kind,
SourceLocation KindKwLoc,
@@ -1311,9 +1375,37 @@ public:
StartLoc, LParenLoc, EndLoc);
}
+ /// \brief 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.
+ OMPClause *RebuildOMPProcBindClause(OpenMPProcBindClauseKind Kind,
+ SourceLocation KindKwLoc,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPProcBindClause(Kind, KindKwLoc,
+ StartLoc, LParenLoc, EndLoc);
+ }
+
+ /// \brief 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.
+ OMPClause *RebuildOMPScheduleClause(OpenMPScheduleClauseKind Kind,
+ Expr *ChunkSize,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation KindLoc,
+ SourceLocation CommaLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPScheduleClause(
+ Kind, ChunkSize, StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc);
+ }
+
/// \brief Build a new OpenMP 'private' clause.
///
- /// By default, performs semantic analysis to build the new statement.
+ /// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
OMPClause *RebuildOMPPrivateClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
@@ -1325,7 +1417,7 @@ public:
/// \brief Build a new OpenMP 'firstprivate' clause.
///
- /// By default, performs semantic analysis to build the new statement.
+ /// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
OMPClause *RebuildOMPFirstprivateClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
@@ -1335,6 +1427,22 @@ public:
EndLoc);
}
+ /// \brief 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.
+ OMPClause *RebuildOMPLastprivateClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPLastprivateClause(VarList, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
+ /// \brief 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.
OMPClause *RebuildOMPSharedClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
SourceLocation LParenLoc,
@@ -1343,6 +1451,84 @@ public:
EndLoc);
}
+ /// \brief 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.
+ OMPClause *RebuildOMPReductionClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation ColonLoc,
+ SourceLocation EndLoc,
+ CXXScopeSpec &ReductionIdScopeSpec,
+ const DeclarationNameInfo &ReductionId) {
+ return getSema().ActOnOpenMPReductionClause(
+ VarList, StartLoc, LParenLoc, ColonLoc, EndLoc, ReductionIdScopeSpec,
+ ReductionId);
+ }
+
+ /// \brief 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.
+ OMPClause *RebuildOMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation ColonLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPLinearClause(VarList, Step, StartLoc, LParenLoc,
+ ColonLoc, EndLoc);
+ }
+
+ /// \brief 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.
+ OMPClause *RebuildOMPAlignedClause(ArrayRef<Expr *> VarList, Expr *Alignment,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation ColonLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPAlignedClause(VarList, Alignment, StartLoc,
+ LParenLoc, ColonLoc, EndLoc);
+ }
+
+ /// \brief 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.
+ OMPClause *RebuildOMPCopyinClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
+ /// \brief 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.
+ OMPClause *RebuildOMPCopyprivateClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
+ /// \brief 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.
+ OMPClause *RebuildOMPFlushClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
/// \brief Rebuild the operand to an Objective-C \@synchronized statement.
///
/// By default, performs semantic analysis to build the new statement.
@@ -1386,7 +1572,7 @@ public:
if (ForEachStmt.isInvalid())
return StmtError();
- return getSema().FinishObjCForCollectionStmt(ForEachStmt.take(), Body);
+ return getSema().FinishObjCForCollectionStmt(ForEachStmt.get(), Body);
}
/// \brief Build a new C++ exception declaration.
@@ -1398,7 +1584,7 @@ public:
SourceLocation StartLoc,
SourceLocation IdLoc,
IdentifierInfo *Id) {
- VarDecl *Var = getSema().BuildExceptionDeclaration(0, Declarator,
+ VarDecl *Var = getSema().BuildExceptionDeclaration(nullptr, Declarator,
StartLoc, IdLoc, Id);
if (Var)
getSema().CurContext->addDecl(Var);
@@ -1479,8 +1665,10 @@ public:
}
StmtResult RebuildSEHTryStmt(bool IsCXXTry, SourceLocation TryLoc,
- Stmt *TryBlock, Stmt *Handler) {
- return getSema().ActOnSEHTryBlock(IsCXXTry, TryLoc, TryBlock, Handler);
+ Stmt *TryBlock, Stmt *Handler, int HandlerIndex,
+ int HandlerParentIndex) {
+ return getSema().ActOnSEHTryBlock(IsCXXTry, TryLoc, TryBlock, Handler,
+ HandlerIndex, HandlerParentIndex);
}
StmtResult RebuildSEHExceptStmt(SourceLocation Loc, Expr *FilterExpr,
@@ -1548,7 +1736,7 @@ public:
ExprResult RebuildUnaryOperator(SourceLocation OpLoc,
UnaryOperatorKind Opc,
Expr *SubExpr) {
- return getSema().BuildUnaryOp(/*Scope=*/0, OpLoc, Opc, SubExpr);
+ return getSema().BuildUnaryOp(/*Scope=*/nullptr, OpLoc, Opc, SubExpr);
}
/// \brief Build a new builtin offsetof expression.
@@ -1600,7 +1788,7 @@ public:
SourceLocation LBracketLoc,
Expr *RHS,
SourceLocation RBracketLoc) {
- return getSema().ActOnArraySubscriptExpr(/*Scope=*/0, LHS,
+ return getSema().ActOnArraySubscriptExpr(/*Scope=*/nullptr, LHS,
LBracketLoc, RHS,
RBracketLoc);
}
@@ -1612,8 +1800,8 @@ public:
ExprResult RebuildCallExpr(Expr *Callee, SourceLocation LParenLoc,
MultiExprArg Args,
SourceLocation RParenLoc,
- Expr *ExecConfig = 0) {
- return getSema().ActOnCallExpr(/*Scope=*/0, Callee, LParenLoc,
+ Expr *ExecConfig = nullptr) {
+ return getSema().ActOnCallExpr(/*Scope=*/nullptr, Callee, LParenLoc,
Args, RParenLoc, ExecConfig);
}
@@ -1641,25 +1829,25 @@ public:
"unnamed member not of record type?");
BaseResult =
- getSema().PerformObjectMemberConversion(BaseResult.take(),
+ getSema().PerformObjectMemberConversion(BaseResult.get(),
QualifierLoc.getNestedNameSpecifier(),
FoundDecl, Member);
if (BaseResult.isInvalid())
return ExprError();
- Base = BaseResult.take();
+ Base = BaseResult.get();
ExprValueKind VK = isArrow ? VK_LValue : Base->getValueKind();
MemberExpr *ME =
new (getSema().Context) MemberExpr(Base, isArrow,
Member, MemberNameInfo,
cast<FieldDecl>(Member)->getType(),
VK, OK_Ordinary);
- return getSema().Owned(ME);
+ return ME;
}
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
- Base = BaseResult.take();
+ Base = BaseResult.get();
QualType BaseType = Base->getType();
// FIXME: this involves duplicating earlier analysis in a lot of
@@ -1681,7 +1869,7 @@ public:
ExprResult RebuildBinaryOperator(SourceLocation OpLoc,
BinaryOperatorKind Opc,
Expr *LHS, Expr *RHS) {
- return getSema().BuildBinOp(/*Scope=*/0, OpLoc, Opc, LHS, RHS);
+ return getSema().BuildBinOp(/*Scope=*/nullptr, OpLoc, Opc, LHS, RHS);
}
/// \brief Build a new conditional operator expression.
@@ -1735,9 +1923,9 @@ public:
return getSema().BuildMemberReferenceExpr(Base, Base->getType(),
OpLoc, /*IsArrow*/ false,
SS, SourceLocation(),
- /*FirstQualifierInScope*/ 0,
+ /*FirstQualifierInScope*/ nullptr,
NameInfo,
- /* TemplateArgs */ 0);
+ /* TemplateArgs */ nullptr);
}
/// \brief Build a new initializer list expression.
@@ -1784,7 +1972,7 @@ public:
/// any semantic analysis. Subclasses may override this routine to provide
/// different behavior.
ExprResult RebuildImplicitValueInitExpr(QualType T) {
- return SemaRef.Owned(new (SemaRef.Context) ImplicitValueInitExpr(T));
+ return new (SemaRef.Context) ImplicitValueInitExpr(T);
}
/// \brief Build a new \c va_arg expression.
@@ -2049,9 +2237,7 @@ public:
QualType ThisType,
bool isImplicit) {
getSema().CheckCXXThisCapture(ThisLoc);
- return getSema().Owned(
- new (getSema().Context) CXXThisExpr(ThisLoc, ThisType,
- isImplicit));
+ return new (getSema().Context) CXXThisExpr(ThisLoc, ThisType, isImplicit);
}
/// \brief Build a new C++ throw expression.
@@ -2070,8 +2256,7 @@ public:
/// provide different behavior.
ExprResult RebuildCXXDefaultArgExpr(SourceLocation Loc,
ParmVarDecl *Param) {
- return getSema().Owned(CXXDefaultArgExpr::Create(getSema().Context, Loc,
- Param));
+ return CXXDefaultArgExpr::Create(getSema().Context, Loc, Param);
}
/// \brief Build a new C++11 default-initialization expression.
@@ -2081,8 +2266,7 @@ public:
/// routine to provide different behavior.
ExprResult RebuildCXXDefaultInitExpr(SourceLocation Loc,
FieldDecl *Field) {
- return getSema().Owned(CXXDefaultInitExpr::Create(getSema().Context, Loc,
- Field));
+ return CXXDefaultInitExpr::Create(getSema().Context, Loc, Field);
}
/// \brief Build a new C++ zero-initialization expression.
@@ -2135,29 +2319,6 @@ public:
Operand);
}
- /// \brief Build a new unary type trait expression.
- ///
- /// By default, performs semantic analysis to build the new expression.
- /// Subclasses may override this routine to provide different behavior.
- ExprResult RebuildUnaryTypeTrait(UnaryTypeTrait Trait,
- SourceLocation StartLoc,
- TypeSourceInfo *T,
- SourceLocation RParenLoc) {
- return getSema().BuildUnaryTypeTrait(Trait, StartLoc, T, RParenLoc);
- }
-
- /// \brief Build a new binary type trait expression.
- ///
- /// By default, performs semantic analysis to build the new expression.
- /// Subclasses may override this routine to provide different behavior.
- ExprResult RebuildBinaryTypeTrait(BinaryTypeTrait Trait,
- SourceLocation StartLoc,
- TypeSourceInfo *LhsT,
- TypeSourceInfo *RhsT,
- SourceLocation RParenLoc) {
- return getSema().BuildBinaryTypeTrait(Trait, StartLoc, LhsT, RhsT, RParenLoc);
- }
-
/// \brief Build a new type trait expression.
///
/// By default, performs semantic analysis to build the new expression.
@@ -2202,16 +2363,17 @@ public:
SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs,
- bool IsAddressOfOperand) {
+ bool IsAddressOfOperand,
+ TypeSourceInfo **RecoveryTSI) {
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
if (TemplateArgs || TemplateKWLoc.isValid())
- return getSema().BuildQualifiedTemplateIdExpr(SS, TemplateKWLoc,
- NameInfo, TemplateArgs);
+ return getSema().BuildQualifiedTemplateIdExpr(SS, TemplateKWLoc, NameInfo,
+ TemplateArgs);
- return getSema().BuildQualifiedDeclarationNameExpr(SS, NameInfo,
- IsAddressOfOperand);
+ return getSema().BuildQualifiedDeclarationNameExpr(
+ SS, NameInfo, IsAddressOfOperand, RecoveryTSI);
}
/// \brief Build a new template-id expression.
@@ -2238,6 +2400,7 @@ public:
MultiExprArg Args,
bool HadMultipleCandidates,
bool ListInitialization,
+ bool StdInitListInitialization,
bool RequiresZeroInit,
CXXConstructExpr::ConstructionKind ConstructKind,
SourceRange ParenRange) {
@@ -2250,6 +2413,7 @@ public:
ConvertedArgs,
HadMultipleCandidates,
ListInitialization,
+ StdInitListInitialization,
RequiresZeroInit, ConstructKind,
ParenRange);
}
@@ -2394,8 +2558,7 @@ public:
ExprResult RebuildObjCEncodeExpr(SourceLocation AtLoc,
TypeSourceInfo *EncodeTypeInfo,
SourceLocation RParenLoc) {
- return SemaRef.Owned(SemaRef.BuildObjCEncodeExpression(AtLoc, EncodeTypeInfo,
- RParenLoc));
+ return SemaRef.BuildObjCEncodeExpression(AtLoc, EncodeTypeInfo, RParenLoc);
}
/// \brief Build a new Objective-C class message.
@@ -2437,25 +2600,13 @@ public:
bool IsArrow, bool IsFreeIvar) {
// FIXME: We lose track of the IsFreeIvar bit.
CXXScopeSpec SS;
- ExprResult Base = getSema().Owned(BaseArg);
- LookupResult R(getSema(), Ivar->getDeclName(), IvarLoc,
- Sema::LookupMemberName);
- ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
- /*FIME:*/IvarLoc,
- SS, 0,
- false);
- if (Result.isInvalid() || Base.isInvalid())
- return ExprError();
-
- if (Result.get())
- return Result;
-
- return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(),
+ DeclarationNameInfo NameInfo(Ivar->getDeclName(), IvarLoc);
+ return getSema().BuildMemberReferenceExpr(BaseArg, BaseArg->getType(),
/*FIXME:*/IvarLoc, IsArrow,
SS, SourceLocation(),
- /*FirstQualifierInScope=*/0,
- R,
- /*TemplateArgs=*/0);
+ /*FirstQualifierInScope=*/nullptr,
+ NameInfo,
+ /*TemplateArgs=*/nullptr);
}
/// \brief Build a new Objective-C property reference expression.
@@ -2466,25 +2617,14 @@ public:
ObjCPropertyDecl *Property,
SourceLocation PropertyLoc) {
CXXScopeSpec SS;
- ExprResult Base = getSema().Owned(BaseArg);
- LookupResult R(getSema(), Property->getDeclName(), PropertyLoc,
- Sema::LookupMemberName);
- bool IsArrow = false;
- ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
- /*FIME:*/PropertyLoc,
- SS, 0, false);
- if (Result.isInvalid() || Base.isInvalid())
- return ExprError();
-
- if (Result.get())
- return Result;
-
- return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(),
- /*FIXME:*/PropertyLoc, IsArrow,
+ DeclarationNameInfo NameInfo(Property->getDeclName(), PropertyLoc);
+ return getSema().BuildMemberReferenceExpr(BaseArg, BaseArg->getType(),
+ /*FIXME:*/PropertyLoc,
+ /*IsArrow=*/false,
SS, SourceLocation(),
- /*FirstQualifierInScope=*/0,
- R,
- /*TemplateArgs=*/0);
+ /*FirstQualifierInScope=*/nullptr,
+ NameInfo,
+ /*TemplateArgs=*/nullptr);
}
/// \brief Build a new Objective-C property reference expression.
@@ -2508,27 +2648,15 @@ public:
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildObjCIsaExpr(Expr *BaseArg, SourceLocation IsaLoc,
- SourceLocation OpLoc,
- bool IsArrow) {
+ SourceLocation OpLoc, bool IsArrow) {
CXXScopeSpec SS;
- ExprResult Base = getSema().Owned(BaseArg);
- LookupResult R(getSema(), &getSema().Context.Idents.get("isa"), IsaLoc,
- Sema::LookupMemberName);
- ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
- OpLoc,
- SS, 0, false);
- if (Result.isInvalid() || Base.isInvalid())
- return ExprError();
-
- if (Result.get())
- return Result;
-
- return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(),
+ DeclarationNameInfo NameInfo(&getSema().Context.Idents.get("isa"), IsaLoc);
+ return getSema().BuildMemberReferenceExpr(BaseArg, BaseArg->getType(),
OpLoc, IsArrow,
SS, SourceLocation(),
- /*FirstQualifierInScope=*/0,
- R,
- /*TemplateArgs=*/0);
+ /*FirstQualifierInScope=*/nullptr,
+ NameInfo,
+ /*TemplateArgs=*/nullptr);
}
/// \brief Build a new shuffle vector expression.
@@ -2552,17 +2680,15 @@ public:
VK_RValue, BuiltinLoc);
QualType CalleePtrTy = SemaRef.Context.getPointerType(Builtin->getType());
Callee = SemaRef.ImpCastExprToType(Callee, CalleePtrTy,
- CK_BuiltinFnToFnPtr).take();
+ CK_BuiltinFnToFnPtr).get();
// Build the CallExpr
- ExprResult TheCall = SemaRef.Owned(
- new (SemaRef.Context) CallExpr(SemaRef.Context, Callee, SubExprs,
- Builtin->getCallResultType(),
- Expr::getValueKindForType(Builtin->getResultType()),
- RParenLoc));
+ ExprResult TheCall = new (SemaRef.Context) CallExpr(
+ SemaRef.Context, Callee, SubExprs, Builtin->getCallResultType(),
+ Expr::getValueKindForType(Builtin->getReturnType()), RParenLoc);
// Type-check the __builtin_shufflevector expression.
- return SemaRef.SemaBuiltinShuffleVector(cast<CallExpr>(TheCall.take()));
+ return SemaRef.SemaBuiltinShuffleVector(cast<CallExpr>(TheCall.get()));
}
/// \brief Build a new convert vector expression.
@@ -2657,12 +2783,16 @@ private:
QualType ObjectType,
NamedDecl *FirstQualifierInScope,
CXXScopeSpec &SS);
+
+ TypeSourceInfo *TransformTSIInObjectScope(TypeLoc TL, QualType ObjectType,
+ NamedDecl *FirstQualifierInScope,
+ CXXScopeSpec &SS);
};
template<typename Derived>
StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) {
if (!S)
- return SemaRef.Owned(S);
+ return S;
switch (S->getStmtClass()) {
case Stmt::NoStmtClass: break;
@@ -2688,7 +2818,7 @@ StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) {
}
}
- return SemaRef.Owned(S);
+ return S;
}
template<typename Derived>
@@ -2712,7 +2842,7 @@ OMPClause *TreeTransform<Derived>::TransformOMPClause(OMPClause *S) {
template<typename Derived>
ExprResult TreeTransform<Derived>::TransformExpr(Expr *E) {
if (!E)
- return SemaRef.Owned(E);
+ return E;
switch (E->getStmtClass()) {
case Stmt::NoStmtClass: break;
@@ -2723,16 +2853,16 @@ ExprResult TreeTransform<Derived>::TransformExpr(Expr *E) {
#include "clang/AST/StmtNodes.inc"
}
- return SemaRef.Owned(E);
+ return E;
}
template<typename Derived>
ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init,
- bool CXXDirectInit) {
+ bool NotCopyInit) {
// Initializers are instantiated like expressions, except that various outer
// layers are stripped.
if (!Init)
- return SemaRef.Owned(Init);
+ return Init;
if (ExprWithCleanups *ExprTemp = dyn_cast<ExprWithCleanups>(Init))
Init = ExprTemp->getSubExpr();
@@ -2748,13 +2878,13 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init,
if (CXXStdInitializerListExpr *ILE =
dyn_cast<CXXStdInitializerListExpr>(Init))
- return TransformInitializer(ILE->getSubExpr(), CXXDirectInit);
+ return TransformInitializer(ILE->getSubExpr(), NotCopyInit);
- // If this is not a direct-initializer, we only need to reconstruct
+ // If this is copy-initialization, we only need to reconstruct
// InitListExprs. Other forms of copy-initialization will be a no-op if
// the initializer is already the right type.
CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init);
- if (!CXXDirectInit && !(Construct && Construct->isListInitialization()))
+ if (!NotCopyInit && !(Construct && Construct->isListInitialization()))
return getDerived().TransformExpr(Init);
// Revert value-initialization back to empty parens.
@@ -2774,10 +2904,15 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init,
if (!Construct || isa<CXXTemporaryObjectExpr>(Construct))
return getDerived().TransformExpr(Init);
+ // If the initialization implicitly converted an initializer list to a
+ // std::initializer_list object, unwrap the std::initializer_list too.
+ if (Construct && Construct->isStdInitListInitialization())
+ return TransformInitializer(Construct->getArg(0), NotCopyInit);
+
SmallVector<Expr*, 8> NewArgs;
bool ArgChanged = false;
if (getDerived().TransformExprs(Construct->getArgs(), Construct->getNumArgs(),
- /*IsCall*/true, NewArgs, &ArgChanged))
+ /*IsCall*/true, NewArgs, &ArgChanged))
return ExprError();
// If this was list initialization, revert to list form.
@@ -2788,6 +2923,13 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init,
// Build a ParenListExpr to represent anything else.
SourceRange Parens = Construct->getParenOrBraceRange();
+ if (Parens.isInvalid()) {
+ // This was a variable declaration's initialization for which no initializer
+ // was specified.
+ assert(NewArgs.empty() &&
+ "no parens or braces but have direct init with arguments?");
+ return ExprEmpty();
+ }
return getDerived().RebuildParenListExpr(Parens.getBegin(), NewArgs,
Parens.getEnd());
}
@@ -2860,9 +3002,11 @@ bool TreeTransform<Derived>::TransformExprs(Expr **Inputs,
if (Out.isInvalid())
return true;
+ // FIXME: Can this happen? We should not try to expand the pack
+ // in this case.
if (Out.get()->containsUnexpandedParameterPack()) {
- Out = RebuildPackExpansion(Out.get(), Expansion->getEllipsisLoc(),
- OrigNumExpansions);
+ Out = getDerived().RebuildPackExpansion(
+ Out.get(), Expansion->getEllipsisLoc(), OrigNumExpansions);
if (Out.isInvalid())
return true;
}
@@ -2870,6 +3014,23 @@ bool TreeTransform<Derived>::TransformExprs(Expr **Inputs,
Outputs.push_back(Out.get());
}
+ // If we're supposed to retain a pack expansion, do so by temporarily
+ // forgetting the partially-substituted parameter pack.
+ if (RetainExpansion) {
+ ForgetPartiallySubstitutedPackRAII Forget(getDerived());
+
+ ExprResult Out = getDerived().TransformExpr(Pattern);
+ if (Out.isInvalid())
+ return true;
+
+ Out = getDerived().RebuildPackExpansion(
+ Out.get(), Expansion->getEllipsisLoc(), OrigNumExpansions);
+ if (Out.isInvalid())
+ return true;
+
+ Outputs.push_back(Out.get());
+ }
+
continue;
}
@@ -2906,7 +3067,7 @@ TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
switch (QNNS->getKind()) {
case NestedNameSpecifier::Identifier:
- if (SemaRef.BuildCXXNestedNameSpecifier(/*Scope=*/0,
+ if (SemaRef.BuildCXXNestedNameSpecifier(/*Scope=*/nullptr,
*QNNS->getAsIdentifier(),
Q.getLocalBeginLoc(),
Q.getLocalEndLoc(),
@@ -2974,7 +3135,7 @@ TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
}
// The qualifier-in-scope and object type only apply to the leftmost entity.
- FirstQualifierInScope = 0;
+ FirstQualifierInScope = nullptr;
ObjectType = QualType();
}
@@ -3023,7 +3184,7 @@ TreeTransform<Derived>
NewCanTy = SemaRef.Context.getCanonicalType(NewTInfo->getType());
}
else {
- NewTInfo = 0;
+ NewTInfo = nullptr;
TemporaryBase Rebase(*this, NameInfo.getLoc(), Name);
QualType NewT = getDerived().TransformType(Name.getCXXNameType());
if (NewT.isNull())
@@ -3074,7 +3235,7 @@ TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS,
if (SS.getScopeRep()) {
// These apply to the scope specifier, not the template.
ObjectType = QualType();
- FirstQualifierInScope = 0;
+ FirstQualifierInScope = nullptr;
}
if (!getDerived().AlwaysRebuild() &&
@@ -3193,7 +3354,7 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
case TemplateArgument::Type: {
TypeSourceInfo *DI = Input.getTypeSourceInfo();
- if (DI == NULL)
+ if (!DI)
DI = InventTypeSourceInfo(Input.getArgument().getAsType());
DI = getDerived().TransformType(DI);
@@ -3238,7 +3399,7 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
ExprResult E = getDerived().TransformExpr(InputExpr);
E = SemaRef.ActOnConstantExpression(E);
if (E.isInvalid()) return true;
- Output = TemplateArgumentLoc(TemplateArgument(E.take()), E.take());
+ Output = TemplateArgumentLoc(TemplateArgument(E.get()), E.get());
return false;
}
}
@@ -3463,7 +3624,7 @@ TypeSourceInfo *TreeTransform<Derived>::TransformType(TypeSourceInfo *DI) {
QualType Result = getDerived().TransformType(TLB, TL);
if (Result.isNull())
- return 0;
+ return nullptr;
return TLB.getTypeSourceInfo(SemaRef.Context, Result);
}
@@ -3564,52 +3725,14 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeLoc TL,
QualType ObjectType,
NamedDecl *UnqualLookup,
CXXScopeSpec &SS) {
- QualType T = TL.getType();
- if (getDerived().AlreadyTransformed(T))
+ if (getDerived().AlreadyTransformed(TL.getType()))
return TL;
- TypeLocBuilder TLB;
- QualType Result;
-
- if (isa<TemplateSpecializationType>(T)) {
- TemplateSpecializationTypeLoc SpecTL =
- TL.castAs<TemplateSpecializationTypeLoc>();
-
- TemplateName Template =
- getDerived().TransformTemplateName(SS,
- SpecTL.getTypePtr()->getTemplateName(),
- SpecTL.getTemplateNameLoc(),
- ObjectType, UnqualLookup);
- if (Template.isNull())
- return TypeLoc();
-
- Result = getDerived().TransformTemplateSpecializationType(TLB, SpecTL,
- Template);
- } else if (isa<DependentTemplateSpecializationType>(T)) {
- DependentTemplateSpecializationTypeLoc SpecTL =
- TL.castAs<DependentTemplateSpecializationTypeLoc>();
-
- TemplateName Template
- = getDerived().RebuildTemplateName(SS,
- *SpecTL.getTypePtr()->getIdentifier(),
- SpecTL.getTemplateNameLoc(),
- ObjectType, UnqualLookup);
- if (Template.isNull())
- return TypeLoc();
-
- Result = getDerived().TransformDependentTemplateSpecializationType(TLB,
- SpecTL,
- Template,
- SS);
- } else {
- // Nothing special needs to be done for these.
- Result = getDerived().TransformType(TLB, TL);
- }
-
- if (Result.isNull())
- return TypeLoc();
-
- return TLB.getTypeSourceInfo(SemaRef.Context, Result)->getTypeLoc();
+ TypeSourceInfo *TSI =
+ TransformTSIInObjectScope(TL, ObjectType, UnqualLookup, SS);
+ if (TSI)
+ return TSI->getTypeLoc();
+ return TypeLoc();
}
template<typename Derived>
@@ -3618,16 +3741,23 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSInfo,
QualType ObjectType,
NamedDecl *UnqualLookup,
CXXScopeSpec &SS) {
- // FIXME: Painfully copy-paste from the above!
-
- QualType T = TSInfo->getType();
- if (getDerived().AlreadyTransformed(T))
+ if (getDerived().AlreadyTransformed(TSInfo->getType()))
return TSInfo;
+ return TransformTSIInObjectScope(TSInfo->getTypeLoc(), ObjectType,
+ UnqualLookup, SS);
+}
+
+template <typename Derived>
+TypeSourceInfo *TreeTransform<Derived>::TransformTSIInObjectScope(
+ TypeLoc TL, QualType ObjectType, NamedDecl *UnqualLookup,
+ CXXScopeSpec &SS) {
+ QualType T = TL.getType();
+ assert(!getDerived().AlreadyTransformed(T));
+
TypeLocBuilder TLB;
QualType Result;
- TypeLoc TL = TSInfo->getTypeLoc();
if (isa<TemplateSpecializationType>(T)) {
TemplateSpecializationTypeLoc SpecTL =
TL.castAs<TemplateSpecializationTypeLoc>();
@@ -3638,7 +3768,7 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSInfo,
SpecTL.getTemplateNameLoc(),
ObjectType, UnqualLookup);
if (Template.isNull())
- return 0;
+ return nullptr;
Result = getDerived().TransformTemplateSpecializationType(TLB, SpecTL,
Template);
@@ -3652,7 +3782,7 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSInfo,
SpecTL.getTemplateNameLoc(),
ObjectType, UnqualLookup);
if (Template.isNull())
- return 0;
+ return nullptr;
Result = getDerived().TransformDependentTemplateSpecializationType(TLB,
SpecTL,
@@ -3664,7 +3794,7 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSInfo,
}
if (Result.isNull())
- return 0;
+ return nullptr;
return TLB.getTypeSourceInfo(SemaRef.Context, Result);
}
@@ -3693,6 +3823,13 @@ QualType TreeTransform<Derived>::TransformComplexType(TypeLocBuilder &TLB,
return TransformTypeSpecType(TLB, T);
}
+template <typename Derived>
+QualType TreeTransform<Derived>::TransformAdjustedType(TypeLocBuilder &TLB,
+ AdjustedTypeLoc TL) {
+ // Adjustments applied during transformation are handled elsewhere.
+ return getDerived().TransformType(TLB, TL.getOriginalLoc());
+}
+
template<typename Derived>
QualType TreeTransform<Derived>::TransformDecayedType(TypeLocBuilder &TLB,
DecayedTypeLoc TL) {
@@ -3833,7 +3970,7 @@ TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB,
return QualType();
TypeSourceInfo* OldClsTInfo = TL.getClassTInfo();
- TypeSourceInfo* NewClsTInfo = 0;
+ TypeSourceInfo *NewClsTInfo = nullptr;
if (OldClsTInfo) {
NewClsTInfo = getDerived().TransformType(OldClsTInfo);
if (!NewClsTInfo)
@@ -3861,6 +3998,14 @@ TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB,
return QualType();
}
+ // If we had to adjust the pointee type when building a member pointer, make
+ // sure to push TypeLoc info for it.
+ const MemberPointerType *MPT = Result->getAs<MemberPointerType>();
+ if (MPT && PointeeType != MPT->getPointeeType()) {
+ assert(isa<AdjustedType>(MPT->getPointeeType()));
+ TLB.push<AdjustedTypeLoc>(MPT->getPointeeType());
+ }
+
MemberPointerTypeLoc NewTL = TLB.push<MemberPointerTypeLoc>(Result);
NewTL.setSigilLoc(TL.getSigilLoc());
NewTL.setClassTInfo(NewClsTInfo);
@@ -3901,8 +4046,8 @@ TreeTransform<Derived>::TransformConstantArrayType(TypeLocBuilder &TLB,
if (Size) {
EnterExpressionEvaluationContext Unevaluated(SemaRef,
Sema::ConstantEvaluated);
- Size = getDerived().TransformExpr(Size).template takeAs<Expr>();
- Size = SemaRef.ActOnConstantExpression(Size).take();
+ Size = getDerived().TransformExpr(Size).template getAs<Expr>();
+ Size = SemaRef.ActOnConstantExpression(Size).get();
}
NewTL.setSizeExpr(Size);
@@ -3932,7 +4077,7 @@ QualType TreeTransform<Derived>::TransformIncompleteArrayType(
IncompleteArrayTypeLoc NewTL = TLB.push<IncompleteArrayTypeLoc>(Result);
NewTL.setLBracketLoc(TL.getLBracketLoc());
NewTL.setRBracketLoc(TL.getRBracketLoc());
- NewTL.setSizeExpr(0);
+ NewTL.setSizeExpr(nullptr);
return Result;
}
@@ -3951,7 +4096,7 @@ TreeTransform<Derived>::TransformVariableArrayType(TypeLocBuilder &TLB,
if (SizeResult.isInvalid())
return QualType();
- Expr *Size = SizeResult.take();
+ Expr *Size = SizeResult.get();
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() ||
@@ -4049,7 +4194,7 @@ QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
ElementType != T->getElementType() ||
Size.get() != T->getSizeExpr()) {
Result = getDerived().RebuildDependentSizedExtVectorType(ElementType,
- Size.take(),
+ Size.get(),
T->getAttributeLoc());
if (Result.isNull())
return QualType();
@@ -4120,7 +4265,7 @@ ParmVarDecl *TreeTransform<Derived>::TransformFunctionTypeParam(
ParmVarDecl *OldParm, int indexAdjustment, Optional<unsigned> NumExpansions,
bool ExpectParameterPack) {
TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
- TypeSourceInfo *NewDI = 0;
+ TypeSourceInfo *NewDI = nullptr;
if (NumExpansions && isa<PackExpansionType>(OldDI->getType())) {
// If we're substituting into a pack expansion type and we know the
@@ -4135,14 +4280,14 @@ ParmVarDecl *TreeTransform<Derived>::TransformFunctionTypeParam(
QualType Result = getDerived().TransformType(TLB,
OldExpansionTL.getPatternLoc());
if (Result.isNull())
- return 0;
+ return nullptr;
Result = RebuildPackExpansionType(Result,
OldExpansionTL.getPatternLoc().getSourceRange(),
OldExpansionTL.getEllipsisLoc(),
NumExpansions);
if (Result.isNull())
- return 0;
+ return nullptr;
PackExpansionTypeLoc NewExpansionTL
= TLB.push<PackExpansionTypeLoc>(Result);
@@ -4151,7 +4296,7 @@ ParmVarDecl *TreeTransform<Derived>::TransformFunctionTypeParam(
} else
NewDI = getDerived().TransformType(OldDI);
if (!NewDI)
- return 0;
+ return nullptr;
if (NewDI == OldDI && indexAdjustment == 0)
return OldParm;
@@ -4164,7 +4309,7 @@ ParmVarDecl *TreeTransform<Derived>::TransformFunctionTypeParam(
NewDI->getType(),
NewDI,
OldParm->getStorageClass(),
- /* DefArg */ NULL);
+ /* DefArg */ nullptr);
newParm->setScopeInfo(OldParm->getFunctionScopeDepth(),
OldParm->getFunctionScopeIndex() + indexAdjustment);
return newParm;
@@ -4184,7 +4329,7 @@ bool TreeTransform<Derived>::
assert(OldParm->getFunctionScopeIndex() == i);
Optional<unsigned> NumExpansions;
- ParmVarDecl *NewParm = 0;
+ ParmVarDecl *NewParm = nullptr;
if (OldParm->isParameterPack()) {
// We have a function parameter pack that may need to be expanded.
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
@@ -4313,7 +4458,7 @@ bool TreeTransform<Derived>::
OutParamTypes.push_back(NewType);
if (PVars)
- PVars->push_back(0);
+ PVars->push_back(nullptr);
}
// We're done with the pack expansion.
@@ -4330,7 +4475,7 @@ bool TreeTransform<Derived>::
OutParamTypes.push_back(NewType);
if (PVars)
- PVars->push_back(0);
+ PVars->push_back(nullptr);
}
// We'll substitute the parameter now without expanding the pack
@@ -4352,7 +4497,7 @@ bool TreeTransform<Derived>::
OutParamTypes.push_back(NewType);
if (PVars)
- PVars->push_back(0);
+ PVars->push_back(nullptr);
}
#ifndef NDEBUG
@@ -4370,7 +4515,7 @@ template<typename Derived>
QualType
TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL) {
- return getDerived().TransformFunctionProtoType(TLB, TL, 0, 0);
+ return getDerived().TransformFunctionProtoType(TLB, TL, nullptr, 0);
}
template<typename Derived>
@@ -4393,11 +4538,9 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
QualType ResultType;
if (T->hasTrailingReturn()) {
- if (getDerived().TransformFunctionTypeParams(TL.getBeginLoc(),
- TL.getParmArray(),
- TL.getNumArgs(),
- TL.getTypePtr()->arg_type_begin(),
- ParamTypes, &ParamDecls))
+ if (getDerived().TransformFunctionTypeParams(
+ TL.getBeginLoc(), TL.getParmArray(), TL.getNumParams(),
+ TL.getTypePtr()->param_type_begin(), ParamTypes, &ParamDecls))
return QualType();
{
@@ -4409,31 +4552,29 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
// declarator.
Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, ThisTypeQuals);
- ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
+ ResultType = getDerived().TransformType(TLB, TL.getReturnLoc());
if (ResultType.isNull())
return QualType();
}
}
else {
- ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
+ ResultType = getDerived().TransformType(TLB, TL.getReturnLoc());
if (ResultType.isNull())
return QualType();
- if (getDerived().TransformFunctionTypeParams(TL.getBeginLoc(),
- TL.getParmArray(),
- TL.getNumArgs(),
- TL.getTypePtr()->arg_type_begin(),
- ParamTypes, &ParamDecls))
+ if (getDerived().TransformFunctionTypeParams(
+ TL.getBeginLoc(), TL.getParmArray(), TL.getNumParams(),
+ TL.getTypePtr()->param_type_begin(), ParamTypes, &ParamDecls))
return QualType();
}
// FIXME: Need to transform the exception-specification too.
QualType Result = TL.getType();
- if (getDerived().AlwaysRebuild() ||
- ResultType != T->getResultType() ||
- T->getNumArgs() != ParamTypes.size() ||
- !std::equal(T->arg_type_begin(), T->arg_type_end(), ParamTypes.begin())) {
+ if (getDerived().AlwaysRebuild() || ResultType != T->getReturnType() ||
+ T->getNumParams() != ParamTypes.size() ||
+ !std::equal(T->param_type_begin(), T->param_type_end(),
+ ParamTypes.begin())) {
Result = getDerived().RebuildFunctionProtoType(ResultType, ParamTypes,
T->getExtProtoInfo());
if (Result.isNull())
@@ -4445,8 +4586,8 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
NewTL.setLParenLoc(TL.getLParenLoc());
NewTL.setRParenLoc(TL.getRParenLoc());
NewTL.setLocalRangeEnd(TL.getLocalRangeEnd());
- for (unsigned i = 0, e = NewTL.getNumArgs(); i != e; ++i)
- NewTL.setArg(i, ParamDecls[i]);
+ for (unsigned i = 0, e = NewTL.getNumParams(); i != e; ++i)
+ NewTL.setParam(i, ParamDecls[i]);
return Result;
}
@@ -4456,13 +4597,12 @@ QualType TreeTransform<Derived>::TransformFunctionNoProtoType(
TypeLocBuilder &TLB,
FunctionNoProtoTypeLoc TL) {
const FunctionNoProtoType *T = TL.getTypePtr();
- QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
+ QualType ResultType = getDerived().TransformType(TLB, TL.getReturnLoc());
if (ResultType.isNull())
return QualType();
QualType Result = TL.getType();
- if (getDerived().AlwaysRebuild() ||
- ResultType != T->getResultType())
+ if (getDerived().AlwaysRebuild() || ResultType != T->getReturnType())
Result = getDerived().RebuildFunctionNoProtoType(ResultType);
FunctionNoProtoTypeLoc NewTL = TLB.push<FunctionNoProtoTypeLoc>(Result);
@@ -4543,7 +4683,7 @@ QualType TreeTransform<Derived>::TransformTypeOfExprType(TypeLocBuilder &TLB,
if (Result.isNull())
return QualType();
}
- else E.take();
+ else E.get();
TypeOfExprTypeLoc NewTL = TLB.push<TypeOfExprTypeLoc>(Result);
NewTL.setTypeofLoc(TL.getTypeofLoc());
@@ -4583,14 +4723,14 @@ QualType TreeTransform<Derived>::TransformDecltypeType(TypeLocBuilder &TLB,
const DecltypeType *T = TL.getTypePtr();
// decltype expressions are not potentially evaluated contexts
- EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated, 0,
- /*IsDecltype=*/ true);
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated,
+ nullptr, /*IsDecltype=*/ true);
ExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
if (E.isInvalid())
return QualType();
- E = getSema().ActOnDecltypeExpression(E.take());
+ E = getSema().ActOnDecltypeExpression(E.get());
if (E.isInvalid())
return QualType();
@@ -4601,7 +4741,7 @@ QualType TreeTransform<Derived>::TransformDecltypeType(TypeLocBuilder &TLB,
if (Result.isNull())
return QualType();
}
- else E.take();
+ else E.get();
DecltypeTypeLoc NewTL = TLB.push<DecltypeTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
@@ -5268,7 +5408,7 @@ TreeTransform<Derived>::TransformObjCObjectPointerType(TypeLocBuilder &TLB,
template<typename Derived>
StmtResult
TreeTransform<Derived>::TransformNullStmt(NullStmt *S) {
- return SemaRef.Owned(S);
+ return S;
}
template<typename Derived>
@@ -5286,13 +5426,12 @@ TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S,
bool SubStmtInvalid = false;
bool SubStmtChanged = false;
SmallVector<Stmt*, 8> Statements;
- for (CompoundStmt::body_iterator B = S->body_begin(), BEnd = S->body_end();
- B != BEnd; ++B) {
- StmtResult Result = getDerived().TransformStmt(*B);
+ for (auto *B : S->body()) {
+ StmtResult Result = getDerived().TransformStmt(B);
if (Result.isInvalid()) {
// Immediately fail if this was a DeclStmt, since it's very
// likely that this will cause problems for future statements.
- if (isa<DeclStmt>(*B))
+ if (isa<DeclStmt>(B))
return StmtError();
// Otherwise, just keep processing substatements and fail later.
@@ -5300,8 +5439,8 @@ TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S,
continue;
}
- SubStmtChanged = SubStmtChanged || Result.get() != *B;
- Statements.push_back(Result.takeAs<Stmt>());
+ SubStmtChanged = SubStmtChanged || Result.get() != B;
+ Statements.push_back(Result.getAs<Stmt>());
}
if (SubStmtInvalid)
@@ -5309,7 +5448,7 @@ TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S,
if (!getDerived().AlwaysRebuild() &&
!SubStmtChanged)
- return SemaRef.Owned(S);
+ return S;
return getDerived().RebuildCompoundStmt(S->getLBracLoc(),
Statements,
@@ -5411,7 +5550,7 @@ StmtResult
TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
// Transform the condition
ExprResult Cond;
- VarDecl *ConditionVar = 0;
+ VarDecl *ConditionVar = nullptr;
if (S->getConditionVariable()) {
ConditionVar
= cast_or_null<VarDecl>(
@@ -5428,7 +5567,7 @@ TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
// Convert the condition to a boolean value.
if (S->getCond()) {
- ExprResult CondE = getSema().ActOnBooleanCondition(0, S->getIfLoc(),
+ ExprResult CondE = getSema().ActOnBooleanCondition(nullptr, S->getIfLoc(),
Cond.get());
if (CondE.isInvalid())
return StmtError();
@@ -5437,7 +5576,7 @@ TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
}
}
- Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.take()));
+ Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.get()));
if (!S->getConditionVariable() && S->getCond() && !FullCond.get())
return StmtError();
@@ -5456,7 +5595,7 @@ TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
ConditionVar == S->getConditionVariable() &&
Then.get() == S->getThen() &&
Else.get() == S->getElse())
- return SemaRef.Owned(S);
+ return S;
return getDerived().RebuildIfStmt(S->getIfLoc(), FullCond, ConditionVar,
Then.get(),
@@ -5468,7 +5607,7 @@ StmtResult
TreeTransform<Derived>::TransformSwitchStmt(SwitchStmt *S) {
// Transform the condition.
ExprResult Cond;
- VarDecl *ConditionVar = 0;
+ VarDecl *ConditionVar = nullptr;
if (S->getConditionVariable()) {
ConditionVar
= cast_or_null<VarDecl>(
@@ -5506,7 +5645,7 @@ StmtResult
TreeTransform<Derived>::TransformWhileStmt(WhileStmt *S) {
// Transform the condition
ExprResult Cond;
- VarDecl *ConditionVar = 0;
+ VarDecl *ConditionVar = nullptr;
if (S->getConditionVariable()) {
ConditionVar
= cast_or_null<VarDecl>(
@@ -5523,7 +5662,8 @@ TreeTransform<Derived>::TransformWhileStmt(WhileStmt *S) {
if (S->getCond()) {
// Convert the condition to a boolean value.
- ExprResult CondE = getSema().ActOnBooleanCondition(0, S->getWhileLoc(),
+ ExprResult CondE = getSema().ActOnBooleanCondition(nullptr,
+ S->getWhileLoc(),
Cond.get());
if (CondE.isInvalid())
return StmtError();
@@ -5531,7 +5671,7 @@ TreeTransform<Derived>::TransformWhileStmt(WhileStmt *S) {
}
}
- Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.take()));
+ Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.get()));
if (!S->getConditionVariable() && S->getCond() && !FullCond.get())
return StmtError();
@@ -5566,7 +5706,7 @@ TreeTransform<Derived>::TransformDoStmt(DoStmt *S) {
if (!getDerived().AlwaysRebuild() &&
Cond.get() == S->getCond() &&
Body.get() == S->getBody())
- return SemaRef.Owned(S);
+ return S;
return getDerived().RebuildDoStmt(S->getDoLoc(), Body.get(), S->getWhileLoc(),
/*FIXME:*/S->getWhileLoc(), Cond.get(),
@@ -5583,7 +5723,7 @@ TreeTransform<Derived>::TransformForStmt(ForStmt *S) {
// Transform the condition
ExprResult Cond;
- VarDecl *ConditionVar = 0;
+ VarDecl *ConditionVar = nullptr;
if (S->getConditionVariable()) {
ConditionVar
= cast_or_null<VarDecl>(
@@ -5600,7 +5740,8 @@ TreeTransform<Derived>::TransformForStmt(ForStmt *S) {
if (S->getCond()) {
// Convert the condition to a boolean value.
- ExprResult CondE = getSema().ActOnBooleanCondition(0, S->getForLoc(),
+ ExprResult CondE = getSema().ActOnBooleanCondition(nullptr,
+ S->getForLoc(),
Cond.get());
if (CondE.isInvalid())
return StmtError();
@@ -5609,7 +5750,7 @@ TreeTransform<Derived>::TransformForStmt(ForStmt *S) {
}
}
- Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.take()));
+ Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.get()));
if (!S->getConditionVariable() && S->getCond() && !FullCond.get())
return StmtError();
@@ -5632,7 +5773,7 @@ TreeTransform<Derived>::TransformForStmt(ForStmt *S) {
FullCond.get() == S->getCond() &&
Inc.get() == S->getInc() &&
Body.get() == S->getBody())
- return SemaRef.Owned(S);
+ return S;
return getDerived().RebuildForStmt(S->getForLoc(), S->getLParenLoc(),
Init.get(), FullCond, ConditionVar,
@@ -5658,11 +5799,11 @@ TreeTransform<Derived>::TransformIndirectGotoStmt(IndirectGotoStmt *S) {
ExprResult Target = getDerived().TransformExpr(S->getTarget());
if (Target.isInvalid())
return StmtError();
- Target = SemaRef.MaybeCreateExprWithCleanups(Target.take());
+ Target = SemaRef.MaybeCreateExprWithCleanups(Target.get());
if (!getDerived().AlwaysRebuild() &&
Target.get() == S->getTarget())
- return SemaRef.Owned(S);
+ return S;
return getDerived().RebuildIndirectGotoStmt(S->getGotoLoc(), S->getStarLoc(),
Target.get());
@@ -5671,13 +5812,13 @@ TreeTransform<Derived>::TransformIndirectGotoStmt(IndirectGotoStmt *S) {
template<typename Derived>
StmtResult
TreeTransform<Derived>::TransformContinueStmt(ContinueStmt *S) {
- return SemaRef.Owned(S);
+ return S;
}
template<typename Derived>
StmtResult
TreeTransform<Derived>::TransformBreakStmt(BreakStmt *S) {
- return SemaRef.Owned(S);
+ return S;
}
template<typename Derived>
@@ -5697,21 +5838,19 @@ StmtResult
TreeTransform<Derived>::TransformDeclStmt(DeclStmt *S) {
bool DeclChanged = false;
SmallVector<Decl *, 4> Decls;
- for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
- D != DEnd; ++D) {
- Decl *Transformed = getDerived().TransformDefinition((*D)->getLocation(),
- *D);
+ for (auto *D : S->decls()) {
+ Decl *Transformed = getDerived().TransformDefinition(D->getLocation(), D);
if (!Transformed)
return StmtError();
- if (Transformed != *D)
+ if (Transformed != D)
DeclChanged = true;
Decls.push_back(Transformed);
}
if (!getDerived().AlwaysRebuild() && !DeclChanged)
- return SemaRef.Owned(S);
+ return S;
return getDerived().RebuildDeclStmt(Decls, S->getStartLoc(), S->getEndLoc());
}
@@ -5766,14 +5905,14 @@ TreeTransform<Derived>::TransformGCCAsmStmt(GCCAsmStmt *S) {
}
if (!getDerived().AlwaysRebuild() && !ExprsChanged)
- return SemaRef.Owned(S);
+ return S;
// Go through the clobbers.
for (unsigned I = 0, E = S->getNumClobbers(); I != E; ++I)
Clobbers.push_back(S->getClobberStringLiteral(I));
// No need to transform the asm string literal.
- AsmString = SemaRef.Owned(S->getAsmString());
+ AsmString = S->getAsmString();
return getDerived().RebuildGCCAsmStmt(S->getAsmLoc(), S->isSimple(),
S->isVolatile(), S->getNumOutputs(),
S->getNumInputs(), Names.data(),
@@ -5798,7 +5937,7 @@ TreeTransform<Derived>::TransformMSAsmStmt(MSAsmStmt *S) {
HadError = true;
} else {
HadChange |= (Result.get() != SrcExprs[i]);
- TransformedExprs.push_back(Result.take());
+ TransformedExprs.push_back(Result.get());
}
}
@@ -5830,7 +5969,7 @@ TreeTransform<Derived>::TransformObjCAtTryStmt(ObjCAtTryStmt *S) {
return StmtError();
if (Catch.get() != S->getCatchStmt(I))
AnyCatchChanged = true;
- CatchStmts.push_back(Catch.release());
+ CatchStmts.push_back(Catch.get());
}
// Transform the @finally statement (if present).
@@ -5846,7 +5985,7 @@ TreeTransform<Derived>::TransformObjCAtTryStmt(ObjCAtTryStmt *S) {
TryBody.get() == S->getTryBody() &&
!AnyCatchChanged &&
Finally.get() == S->getFinallyStmt())
- return SemaRef.Owned(S);
+ return S;
// Build a new statement.
return getDerived().RebuildObjCAtTryStmt(S->getAtTryLoc(), TryBody.get(),
@@ -5857,9 +5996,9 @@ template<typename Derived>
StmtResult
TreeTransform<Derived>::TransformObjCAtCatchStmt(ObjCAtCatchStmt *S) {
// Transform the @catch parameter, if there is one.
- VarDecl *Var = 0;
+ VarDecl *Var = nullptr;
if (VarDecl *FromVar = S->getCatchParamDecl()) {
- TypeSourceInfo *TSInfo = 0;
+ TypeSourceInfo *TSInfo = nullptr;
if (FromVar->getTypeSourceInfo()) {
TSInfo = getDerived().TransformType(FromVar->getTypeSourceInfo());
if (!TSInfo)
@@ -5900,7 +6039,7 @@ TreeTransform<Derived>::TransformObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
// If nothing changed, just retain this statement.
if (!getDerived().AlwaysRebuild() &&
Body.get() == S->getFinallyBody())
- return SemaRef.Owned(S);
+ return S;
// Build a new statement.
return getDerived().RebuildObjCAtFinallyStmt(S->getAtFinallyLoc(),
@@ -5919,7 +6058,7 @@ TreeTransform<Derived>::TransformObjCAtThrowStmt(ObjCAtThrowStmt *S) {
if (!getDerived().AlwaysRebuild() &&
Operand.get() == S->getThrowExpr())
- return getSema().Owned(S);
+ return S;
return getDerived().RebuildObjCAtThrowStmt(S->getThrowLoc(), Operand.get());
}
@@ -5947,7 +6086,7 @@ TreeTransform<Derived>::TransformObjCAtSynchronizedStmt(
if (!getDerived().AlwaysRebuild() &&
Object.get() == S->getSynchExpr() &&
Body.get() == S->getSynchBody())
- return SemaRef.Owned(S);
+ return S;
// Build a new statement.
return getDerived().RebuildObjCAtSynchronizedStmt(S->getAtSynchronizedLoc(),
@@ -5966,7 +6105,7 @@ TreeTransform<Derived>::TransformObjCAutoreleasePoolStmt(
// If nothing changed, just retain this statement.
if (!getDerived().AlwaysRebuild() &&
Body.get() == S->getSubStmt())
- return SemaRef.Owned(S);
+ return S;
// Build a new statement.
return getDerived().RebuildObjCAutoreleasePoolStmt(
@@ -5997,7 +6136,7 @@ TreeTransform<Derived>::TransformObjCForCollectionStmt(
Element.get() == S->getElement() &&
Collection.get() == S->getCollection() &&
Body.get() == S->getBody())
- return SemaRef.Owned(S);
+ return S;
// Build a new statement.
return getDerived().RebuildObjCForCollectionStmt(S->getForLoc(),
@@ -6010,7 +6149,7 @@ TreeTransform<Derived>::TransformObjCForCollectionStmt(
template <typename Derived>
StmtResult TreeTransform<Derived>::TransformCXXCatchStmt(CXXCatchStmt *S) {
// Transform the exception declaration, if any.
- VarDecl *Var = 0;
+ VarDecl *Var = nullptr;
if (VarDecl *ExceptionDecl = S->getExceptionDecl()) {
TypeSourceInfo *T =
getDerived().TransformType(ExceptionDecl->getTypeSourceInfo());
@@ -6031,7 +6170,7 @@ StmtResult TreeTransform<Derived>::TransformCXXCatchStmt(CXXCatchStmt *S) {
if (!getDerived().AlwaysRebuild() && !Var &&
Handler.get() == S->getHandlerBlock())
- return SemaRef.Owned(S);
+ return S;
return getDerived().RebuildCXXCatchStmt(S->getCatchLoc(), Var, Handler.get());
}
@@ -6052,12 +6191,12 @@ StmtResult TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) {
return StmtError();
HandlerChanged = HandlerChanged || Handler.get() != S->getHandler(I);
- Handlers.push_back(Handler.takeAs<Stmt>());
+ Handlers.push_back(Handler.getAs<Stmt>());
}
if (!getDerived().AlwaysRebuild() && TryBlock.get() == S->getTryBlock() &&
!HandlerChanged)
- return SemaRef.Owned(S);
+ return S;
return getDerived().RebuildCXXTryStmt(S->getTryLoc(), TryBlock.get(),
Handlers);
@@ -6078,17 +6217,17 @@ TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) {
if (Cond.isInvalid())
return StmtError();
if (Cond.get())
- Cond = SemaRef.CheckBooleanCondition(Cond.take(), S->getColonLoc());
+ Cond = SemaRef.CheckBooleanCondition(Cond.get(), S->getColonLoc());
if (Cond.isInvalid())
return StmtError();
if (Cond.get())
- Cond = SemaRef.MaybeCreateExprWithCleanups(Cond.take());
+ Cond = SemaRef.MaybeCreateExprWithCleanups(Cond.get());
ExprResult Inc = getDerived().TransformExpr(S->getInc());
if (Inc.isInvalid())
return StmtError();
if (Inc.get())
- Inc = SemaRef.MaybeCreateExprWithCleanups(Inc.take());
+ Inc = SemaRef.MaybeCreateExprWithCleanups(Inc.get());
StmtResult LoopVar = getDerived().TransformStmt(S->getLoopVarStmt());
if (LoopVar.isInvalid())
@@ -6127,7 +6266,7 @@ TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) {
}
if (NewStmt.get() == S)
- return SemaRef.Owned(S);
+ return S;
return FinishCXXForRangeStmt(NewStmt.get(), Body.get());
}
@@ -6163,7 +6302,7 @@ TreeTransform<Derived>::TransformMSDependentExistsStmt(
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
bool Dependent = false;
- switch (getSema().CheckMicrosoftIfExistsSymbol(/*S=*/0, SS, NameInfo)) {
+ switch (getSema().CheckMicrosoftIfExistsSymbol(/*S=*/nullptr, SS, NameInfo)) {
case Sema::IER_Exists:
if (S->isIfExists())
break;
@@ -6239,10 +6378,11 @@ StmtResult TreeTransform<Derived>::TransformSEHTryStmt(SEHTryStmt *S) {
if (!getDerived().AlwaysRebuild() && TryBlock.get() == S->getTryBlock() &&
Handler.get() == S->getHandler())
- return SemaRef.Owned(S);
+ return S;
- return getDerived().RebuildSEHTryStmt(S->getIsCXXTry(), S->getTryLoc(),
- TryBlock.take(), Handler.take());
+ return getDerived().RebuildSEHTryStmt(
+ S->getIsCXXTry(), S->getTryLoc(), TryBlock.get(), Handler.get(),
+ S->getHandlerIndex(), S->getHandlerParentIndex());
}
template <typename Derived>
@@ -6251,7 +6391,7 @@ StmtResult TreeTransform<Derived>::TransformSEHFinallyStmt(SEHFinallyStmt *S) {
if (Block.isInvalid())
return StmtError();
- return getDerived().RebuildSEHFinallyStmt(S->getFinallyLoc(), Block.take());
+ return getDerived().RebuildSEHFinallyStmt(S->getFinallyLoc(), Block.get());
}
template <typename Derived>
@@ -6264,8 +6404,8 @@ StmtResult TreeTransform<Derived>::TransformSEHExceptStmt(SEHExceptStmt *S) {
if (Block.isInvalid())
return StmtError();
- return getDerived().RebuildSEHExceptStmt(S->getExceptLoc(), FilterExpr.take(),
- Block.take());
+ return getDerived().RebuildSEHExceptStmt(S->getExceptLoc(), FilterExpr.get(),
+ Block.get());
}
template <typename Derived>
@@ -6278,9 +6418,16 @@ StmtResult TreeTransform<Derived>::TransformSEHHandler(Stmt *Handler) {
template<typename Derived>
StmtResult
-TreeTransform<Derived>::TransformOMPParallelDirective(OMPParallelDirective *D) {
- DeclarationNameInfo DirName;
- getSema().StartOpenMPDSABlock(OMPD_parallel, DirName, 0);
+TreeTransform<Derived>::TransformSEHLeaveStmt(SEHLeaveStmt *S) {
+ return S;
+}
+
+//===----------------------------------------------------------------------===//
+// OpenMP directive transformation
+//===----------------------------------------------------------------------===//
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformOMPExecutableDirective(
+ OMPExecutableDirective *D) {
// Transform the clauses
llvm::SmallVector<OMPClause *, 16> TClauses;
@@ -6290,101 +6437,473 @@ TreeTransform<Derived>::TransformOMPParallelDirective(OMPParallelDirective *D) {
I != E; ++I) {
if (*I) {
OMPClause *Clause = getDerived().TransformOMPClause(*I);
- if (!Clause) {
- getSema().EndOpenMPDSABlock(0);
- return StmtError();
- }
- TClauses.push_back(Clause);
+ if (Clause)
+ TClauses.push_back(Clause);
+ } else {
+ TClauses.push_back(nullptr);
}
- else {
- TClauses.push_back(0);
+ }
+ StmtResult AssociatedStmt;
+ if (D->hasAssociatedStmt()) {
+ if (!D->getAssociatedStmt()) {
+ return StmtError();
+ }
+ AssociatedStmt = getDerived().TransformStmt(D->getAssociatedStmt());
+ if (AssociatedStmt.isInvalid()) {
+ return StmtError();
}
}
- if (!D->getAssociatedStmt()) {
- getSema().EndOpenMPDSABlock(0);
+ if (TClauses.size() != Clauses.size()) {
return StmtError();
}
- StmtResult AssociatedStmt =
- getDerived().TransformStmt(D->getAssociatedStmt());
- if (AssociatedStmt.isInvalid()) {
- getSema().EndOpenMPDSABlock(0);
- return StmtError();
+
+ // Transform directive name for 'omp critical' directive.
+ DeclarationNameInfo DirName;
+ if (D->getDirectiveKind() == OMPD_critical) {
+ DirName = cast<OMPCriticalDirective>(D)->getDirectiveName();
+ DirName = getDerived().TransformDeclarationNameInfo(DirName);
}
- StmtResult Res = getDerived().RebuildOMPParallelDirective(TClauses,
- AssociatedStmt.take(),
- D->getLocStart(),
- D->getLocEnd());
- getSema().EndOpenMPDSABlock(Res.get());
+ return getDerived().RebuildOMPExecutableDirective(
+ D->getDirectiveKind(), DirName, TClauses, AssociatedStmt.get(),
+ D->getLocStart(), D->getLocEnd());
+}
+
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPParallelDirective(OMPParallelDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
}
-template<typename Derived>
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPSimdDirective(OMPSimdDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_simd, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPForDirective(OMPForDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_for, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPSectionsDirective(OMPSectionsDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_sections, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPSectionDirective(OMPSectionDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_section, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPSingleDirective(OMPSingleDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_single, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPMasterDirective(OMPMasterDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_master, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPCriticalDirective(OMPCriticalDirective *D) {
+ getDerived().getSema().StartOpenMPDSABlock(
+ OMPD_critical, D->getDirectiveName(), nullptr, D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformOMPParallelForDirective(
+ OMPParallelForDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel_for, DirName,
+ nullptr, D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformOMPParallelSectionsDirective(
+ OMPParallelSectionsDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel_sections, DirName,
+ nullptr, D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPTaskDirective(OMPTaskDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_task, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformOMPTaskyieldDirective(
+ OMPTaskyieldDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_taskyield, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPBarrierDirective(OMPBarrierDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_barrier, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPTaskwaitDirective(OMPTaskwaitDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_taskwait, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPFlushDirective(OMPFlushDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_flush, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+//===----------------------------------------------------------------------===//
+// OpenMP clause transformation
+//===----------------------------------------------------------------------===//
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPIfClause(OMPIfClause *C) {
+ ExprResult Cond = getDerived().TransformExpr(C->getCondition());
+ if (Cond.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPIfClause(Cond.get(), C->getLocStart(),
+ C->getLParenLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPFinalClause(OMPFinalClause *C) {
+ ExprResult Cond = getDerived().TransformExpr(C->getCondition());
+ if (Cond.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPFinalClause(Cond.get(), C->getLocStart(),
+ C->getLParenLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPNumThreadsClause(OMPNumThreadsClause *C) {
+ ExprResult NumThreads = getDerived().TransformExpr(C->getNumThreads());
+ if (NumThreads.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPNumThreadsClause(
+ NumThreads.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPSafelenClause(OMPSafelenClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getSafelen());
+ if (E.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPSafelenClause(
+ E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPCollapseClause(OMPCollapseClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getNumForLoops());
+ if (E.isInvalid())
+ return 0;
+ return getDerived().RebuildOMPCollapseClause(
+ E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPDefaultClause(OMPDefaultClause *C) {
- return getDerived().RebuildOMPDefaultClause(C->getDefaultKind(),
- C->getDefaultKindKwLoc(),
- C->getLocStart(),
- C->getLParenLoc(),
- C->getLocEnd());
+ return getDerived().RebuildOMPDefaultClause(
+ C->getDefaultKind(), C->getDefaultKindKwLoc(), C->getLocStart(),
+ C->getLParenLoc(), C->getLocEnd());
}
-template<typename Derived>
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPProcBindClause(OMPProcBindClause *C) {
+ return getDerived().RebuildOMPProcBindClause(
+ C->getProcBindKind(), C->getProcBindKindKwLoc(), C->getLocStart(),
+ C->getLParenLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPScheduleClause(OMPScheduleClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getChunkSize());
+ if (E.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPScheduleClause(
+ C->getScheduleKind(), E.get(), C->getLocStart(), C->getLParenLoc(),
+ C->getScheduleKindLoc(), C->getCommaLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPOrderedClause(OMPOrderedClause *C) {
+ // No need to rebuild this clause, no template-dependent parameters.
+ return C;
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPNowaitClause(OMPNowaitClause *C) {
+ // No need to rebuild this clause, no template-dependent parameters.
+ return C;
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPUntiedClause(OMPUntiedClause *C) {
+ // No need to rebuild this clause, no template-dependent parameters.
+ return C;
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPMergeableClause(OMPMergeableClause *C) {
+ // No need to rebuild this clause, no template-dependent parameters.
+ return C;
+}
+
+template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPPrivateClause(OMPPrivateClause *C) {
llvm::SmallVector<Expr *, 16> Vars;
Vars.reserve(C->varlist_size());
- for (OMPPrivateClause::varlist_iterator I = C->varlist_begin(),
- E = C->varlist_end();
- I != E; ++I) {
- ExprResult EVar = getDerived().TransformExpr(cast<Expr>(*I));
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
if (EVar.isInvalid())
- return 0;
- Vars.push_back(EVar.take());
+ return nullptr;
+ Vars.push_back(EVar.get());
}
- return getDerived().RebuildOMPPrivateClause(Vars,
- C->getLocStart(),
- C->getLParenLoc(),
- C->getLocEnd());
+ return getDerived().RebuildOMPPrivateClause(
+ Vars, C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
}
-template<typename Derived>
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPFirstprivateClause(
+ OMPFirstprivateClause *C) {
+ llvm::SmallVector<Expr *, 16> Vars;
+ Vars.reserve(C->varlist_size());
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
+ if (EVar.isInvalid())
+ return nullptr;
+ Vars.push_back(EVar.get());
+ }
+ return getDerived().RebuildOMPFirstprivateClause(
+ Vars, C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
OMPClause *
-TreeTransform<Derived>::TransformOMPFirstprivateClause(
- OMPFirstprivateClause *C) {
+TreeTransform<Derived>::TransformOMPLastprivateClause(OMPLastprivateClause *C) {
llvm::SmallVector<Expr *, 16> Vars;
Vars.reserve(C->varlist_size());
- for (OMPFirstprivateClause::varlist_iterator I = C->varlist_begin(),
- E = C->varlist_end();
- I != E; ++I) {
- ExprResult EVar = getDerived().TransformExpr(cast<Expr>(*I));
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
if (EVar.isInvalid())
- return 0;
- Vars.push_back(EVar.take());
+ return nullptr;
+ Vars.push_back(EVar.get());
}
- return getDerived().RebuildOMPFirstprivateClause(Vars,
- C->getLocStart(),
- C->getLParenLoc(),
- C->getLocEnd());
+ return getDerived().RebuildOMPLastprivateClause(
+ Vars, C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
}
-template<typename Derived>
+template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPSharedClause(OMPSharedClause *C) {
llvm::SmallVector<Expr *, 16> Vars;
Vars.reserve(C->varlist_size());
- for (OMPSharedClause::varlist_iterator I = C->varlist_begin(),
- E = C->varlist_end();
- I != E; ++I) {
- ExprResult EVar = getDerived().TransformExpr(cast<Expr>(*I));
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
+ if (EVar.isInvalid())
+ return nullptr;
+ Vars.push_back(EVar.get());
+ }
+ return getDerived().RebuildOMPSharedClause(Vars, C->getLocStart(),
+ C->getLParenLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPReductionClause(OMPReductionClause *C) {
+ llvm::SmallVector<Expr *, 16> Vars;
+ Vars.reserve(C->varlist_size());
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
+ if (EVar.isInvalid())
+ return nullptr;
+ Vars.push_back(EVar.get());
+ }
+ CXXScopeSpec ReductionIdScopeSpec;
+ ReductionIdScopeSpec.Adopt(C->getQualifierLoc());
+
+ DeclarationNameInfo NameInfo = C->getNameInfo();
+ if (NameInfo.getName()) {
+ NameInfo = getDerived().TransformDeclarationNameInfo(NameInfo);
+ if (!NameInfo.getName())
+ return nullptr;
+ }
+ return getDerived().RebuildOMPReductionClause(
+ Vars, C->getLocStart(), C->getLParenLoc(), C->getColonLoc(),
+ C->getLocEnd(), ReductionIdScopeSpec, NameInfo);
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPLinearClause(OMPLinearClause *C) {
+ llvm::SmallVector<Expr *, 16> Vars;
+ Vars.reserve(C->varlist_size());
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
if (EVar.isInvalid())
- return 0;
- Vars.push_back(EVar.take());
+ return nullptr;
+ Vars.push_back(EVar.get());
}
- return getDerived().RebuildOMPSharedClause(Vars,
- C->getLocStart(),
+ ExprResult Step = getDerived().TransformExpr(C->getStep());
+ if (Step.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPLinearClause(Vars, Step.get(), C->getLocStart(),
C->getLParenLoc(),
- C->getLocEnd());
+ C->getColonLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPAlignedClause(OMPAlignedClause *C) {
+ llvm::SmallVector<Expr *, 16> Vars;
+ Vars.reserve(C->varlist_size());
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
+ if (EVar.isInvalid())
+ return nullptr;
+ Vars.push_back(EVar.get());
+ }
+ ExprResult Alignment = getDerived().TransformExpr(C->getAlignment());
+ if (Alignment.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPAlignedClause(
+ Vars, Alignment.get(), C->getLocStart(), C->getLParenLoc(),
+ C->getColonLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPCopyinClause(OMPCopyinClause *C) {
+ llvm::SmallVector<Expr *, 16> Vars;
+ Vars.reserve(C->varlist_size());
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
+ if (EVar.isInvalid())
+ return nullptr;
+ Vars.push_back(EVar.get());
+ }
+ return getDerived().RebuildOMPCopyinClause(Vars, C->getLocStart(),
+ C->getLParenLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPCopyprivateClause(OMPCopyprivateClause *C) {
+ llvm::SmallVector<Expr *, 16> Vars;
+ Vars.reserve(C->varlist_size());
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
+ if (EVar.isInvalid())
+ return nullptr;
+ Vars.push_back(EVar.get());
+ }
+ return getDerived().RebuildOMPCopyprivateClause(
+ Vars, C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPFlushClause(OMPFlushClause *C) {
+ llvm::SmallVector<Expr *, 16> Vars;
+ Vars.reserve(C->varlist_size());
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
+ if (EVar.isInvalid())
+ return nullptr;
+ Vars.push_back(EVar.get());
+ }
+ return getDerived().RebuildOMPFlushClause(Vars, C->getLocStart(),
+ C->getLParenLoc(), C->getLocEnd());
}
//===----------------------------------------------------------------------===//
@@ -6393,7 +6912,7 @@ TreeTransform<Derived>::TransformOMPSharedClause(OMPSharedClause *C) {
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E) {
- return SemaRef.Owned(E);
+ return E;
}
template<typename Derived>
@@ -6430,10 +6949,10 @@ TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E) {
// FIXME: this is a bit instantiation-specific.
SemaRef.MarkDeclRefReferenced(E);
- return SemaRef.Owned(E);
+ return E;
}
- TemplateArgumentListInfo TransArgs, *TemplateArgs = 0;
+ TemplateArgumentListInfo TransArgs, *TemplateArgs = nullptr;
if (E->hasExplicitTemplateArgs()) {
TemplateArgs = &TransArgs;
TransArgs.setLAngleLoc(E->getLAngleLoc());
@@ -6451,31 +6970,31 @@ TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E) {
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformIntegerLiteral(IntegerLiteral *E) {
- return SemaRef.Owned(E);
+ return E;
}
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformFloatingLiteral(FloatingLiteral *E) {
- return SemaRef.Owned(E);
+ return E;
}
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformImaginaryLiteral(ImaginaryLiteral *E) {
- return SemaRef.Owned(E);
+ return E;
}
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformStringLiteral(StringLiteral *E) {
- return SemaRef.Owned(E);
+ return E;
}
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformCharacterLiteral(CharacterLiteral *E) {
- return SemaRef.Owned(E);
+ return E;
}
template<typename Derived>
@@ -6504,19 +7023,19 @@ TreeTransform<Derived>::TransformGenericSelectionExpr(GenericSelectionExpr *E) {
return ExprError();
AssocTypes.push_back(AssocType);
} else {
- AssocTypes.push_back(0);
+ AssocTypes.push_back(nullptr);
}
ExprResult AssocExpr = getDerived().TransformExpr(E->getAssocExpr(i));
if (AssocExpr.isInvalid())
return ExprError();
- AssocExprs.push_back(AssocExpr.release());
+ AssocExprs.push_back(AssocExpr.get());
}
return getDerived().RebuildGenericSelectionExpr(E->getGenericLoc(),
E->getDefaultLoc(),
E->getRParenLoc(),
- ControllingExpr.release(),
+ ControllingExpr.get(),
AssocTypes,
AssocExprs);
}
@@ -6529,7 +7048,7 @@ TreeTransform<Derived>::TransformParenExpr(ParenExpr *E) {
return ExprError();
if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getSubExpr())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildParenExpr(SubExpr.get(), E->getLParen(),
E->getRParen());
@@ -6542,7 +7061,7 @@ template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformAddressOfOperand(Expr *E) {
if (DependentScopeDeclRefExpr *DRE = dyn_cast<DependentScopeDeclRefExpr>(E))
- return getDerived().TransformDependentScopeDeclRefExpr(DRE, true);
+ return getDerived().TransformDependentScopeDeclRefExpr(DRE, true, nullptr);
else
return getDerived().TransformExpr(E);
}
@@ -6559,7 +7078,7 @@ TreeTransform<Derived>::TransformUnaryOperator(UnaryOperator *E) {
return ExprError();
if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getSubExpr())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildUnaryOperator(E->getOperatorLoc(),
E->getOpcode(),
@@ -6624,7 +7143,7 @@ TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) {
if (!getDerived().AlwaysRebuild() &&
Type == E->getTypeSourceInfo() &&
!ExprChanged)
- return SemaRef.Owned(E);
+ return E;
// Build a new offsetof expression.
return getDerived().RebuildOffsetOfExpr(E->getOperatorLoc(), Type,
@@ -6637,7 +7156,7 @@ ExprResult
TreeTransform<Derived>::TransformOpaqueValueExpr(OpaqueValueExpr *E) {
assert(getDerived().AlreadyTransformed(E->getType()) &&
"opaque value expression requires transformation");
- return SemaRef.Owned(E);
+ return E;
}
template<typename Derived>
@@ -6657,7 +7176,7 @@ TreeTransform<Derived>::TransformPseudoObjectExpr(PseudoObjectExpr *E) {
// expression must have been an lvalue-to-rvalue conversion which we
// should reapply.
if (result.get()->hasPlaceholderType(BuiltinType::PseudoObject))
- result = SemaRef.checkPseudoObjectRValue(result.take());
+ result = SemaRef.checkPseudoObjectRValue(result.get());
return result;
}
@@ -6674,7 +7193,7 @@ TreeTransform<Derived>::TransformUnaryExprOrTypeTraitExpr(
return ExprError();
if (!getDerived().AlwaysRebuild() && OldT == NewT)
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildUnaryExprOrTypeTrait(NewT, E->getOperatorLoc(),
E->getKind(),
@@ -6687,12 +7206,26 @@ TreeTransform<Derived>::TransformUnaryExprOrTypeTraitExpr(
EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated,
Sema::ReuseLambdaContextDecl);
- ExprResult SubExpr = getDerived().TransformExpr(E->getArgumentExpr());
- if (SubExpr.isInvalid())
+ // Try to recover if we have something like sizeof(T::X) where X is a type.
+ // Notably, there must be *exactly* one set of parens if X is a type.
+ TypeSourceInfo *RecoveryTSI = nullptr;
+ ExprResult SubExpr;
+ auto *PE = dyn_cast<ParenExpr>(E->getArgumentExpr());
+ if (auto *DRE =
+ PE ? dyn_cast<DependentScopeDeclRefExpr>(PE->getSubExpr()) : nullptr)
+ SubExpr = getDerived().TransformParenDependentScopeDeclRefExpr(
+ PE, DRE, false, &RecoveryTSI);
+ else
+ SubExpr = getDerived().TransformExpr(E->getArgumentExpr());
+
+ if (RecoveryTSI) {
+ return getDerived().RebuildUnaryExprOrTypeTrait(
+ RecoveryTSI, E->getOperatorLoc(), E->getKind(), E->getSourceRange());
+ } else if (SubExpr.isInvalid())
return ExprError();
if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getArgumentExpr())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildUnaryExprOrTypeTrait(SubExpr.get(),
E->getOperatorLoc(),
@@ -6715,7 +7248,7 @@ TreeTransform<Derived>::TransformArraySubscriptExpr(ArraySubscriptExpr *E) {
if (!getDerived().AlwaysRebuild() &&
LHS.get() == E->getLHS() &&
RHS.get() == E->getRHS())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildArraySubscriptExpr(LHS.get(),
/*FIXME:*/E->getLHS()->getLocStart(),
@@ -6795,7 +7328,7 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
// FIXME: this is a bit instantiation-specific.
SemaRef.MarkMemberReferenced(E);
- return SemaRef.Owned(E);
+ return E;
}
TemplateArgumentListInfo TransArgs;
@@ -6809,14 +7342,14 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
}
// FIXME: Bogus source location for the operator
- SourceLocation FakeOperatorLoc
- = SemaRef.PP.getLocForEndOfToken(E->getBase()->getSourceRange().getEnd());
+ SourceLocation FakeOperatorLoc =
+ SemaRef.getLocForEndOfToken(E->getBase()->getSourceRange().getEnd());
// FIXME: to do this check properly, we will need to preserve the
// first-qualifier-in-scope here, just in case we had a dependent
// base (and therefore couldn't do the check) and a
// nested-name-qualifier (and therefore could do the lookup).
- NamedDecl *FirstQualifierInScope = 0;
+ NamedDecl *FirstQualifierInScope = nullptr;
return getDerived().RebuildMemberExpr(Base.get(), FakeOperatorLoc,
E->isArrow(),
@@ -6826,7 +7359,7 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
Member,
FoundDecl,
(E->hasExplicitTemplateArgs()
- ? &TransArgs : 0),
+ ? &TransArgs : nullptr),
FirstQualifierInScope);
}
@@ -6844,7 +7377,7 @@ TreeTransform<Derived>::TransformBinaryOperator(BinaryOperator *E) {
if (!getDerived().AlwaysRebuild() &&
LHS.get() == E->getLHS() &&
RHS.get() == E->getRHS())
- return SemaRef.Owned(E);
+ return E;
Sema::FPContractStateRAII FPContractState(getSema());
getSema().FPFeatures.fp_contract = E->isFPContractable();
@@ -6877,11 +7410,11 @@ TransformBinaryConditionalOperator(BinaryConditionalOperator *e) {
if (!getDerived().AlwaysRebuild() &&
commonExpr.get() == e->getCommon() &&
rhs.get() == e->getFalseExpr())
- return SemaRef.Owned(e);
+ return e;
- return getDerived().RebuildConditionalOperator(commonExpr.take(),
+ return getDerived().RebuildConditionalOperator(commonExpr.get(),
e->getQuestionLoc(),
- 0,
+ nullptr,
e->getColonLoc(),
rhs.get());
}
@@ -6905,7 +7438,7 @@ TreeTransform<Derived>::TransformConditionalOperator(ConditionalOperator *E) {
Cond.get() == E->getCond() &&
LHS.get() == E->getLHS() &&
RHS.get() == E->getRHS())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildConditionalOperator(Cond.get(),
E->getQuestionLoc(),
@@ -6937,7 +7470,7 @@ TreeTransform<Derived>::TransformCStyleCastExpr(CStyleCastExpr *E) {
if (!getDerived().AlwaysRebuild() &&
Type == E->getTypeInfoAsWritten() &&
SubExpr.get() == E->getSubExpr())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildCStyleCastExpr(E->getLParenLoc(),
Type,
@@ -6980,11 +7513,11 @@ TreeTransform<Derived>::TransformExtVectorElementExpr(ExtVectorElementExpr *E) {
if (!getDerived().AlwaysRebuild() &&
Base.get() == E->getBase())
- return SemaRef.Owned(E);
+ return E;
// FIXME: Bad source location
- SourceLocation FakeOperatorLoc
- = SemaRef.PP.getLocForEndOfToken(E->getBase()->getLocEnd());
+ SourceLocation FakeOperatorLoc =
+ SemaRef.getLocForEndOfToken(E->getBase()->getLocEnd());
return getDerived().RebuildExtVectorElementExpr(Base.get(), FakeOperatorLoc,
E->getAccessorLoc(),
E->getAccessor());
@@ -7001,7 +7534,7 @@ TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E) {
return ExprError();
if (!getDerived().AlwaysRebuild() && !InitChanged)
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildInitList(E->getLBraceLoc(), Inits,
E->getRBraceLoc(), E->getType());
@@ -7039,7 +7572,7 @@ TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E) {
D->getLBracketLoc()));
ExprChanged = ExprChanged || Init.get() != E->getArrayIndex(*D);
- ArrayExprs.push_back(Index.release());
+ ArrayExprs.push_back(Index.get());
continue;
}
@@ -7061,14 +7594,14 @@ TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E) {
ExprChanged = ExprChanged || Start.get() != E->getArrayRangeStart(*D) ||
End.get() != E->getArrayRangeEnd(*D);
- ArrayExprs.push_back(Start.release());
- ArrayExprs.push_back(End.release());
+ ArrayExprs.push_back(Start.get());
+ ArrayExprs.push_back(End.get());
}
if (!getDerived().AlwaysRebuild() &&
Init.get() == E->getInit() &&
!ExprChanged)
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildDesignatedInitExpr(Desig, ArrayExprs,
E->getEqualOrColonLoc(),
@@ -7089,7 +7622,7 @@ TreeTransform<Derived>::TransformImplicitValueInitExpr(
if (!getDerived().AlwaysRebuild() &&
T == E->getType())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildImplicitValueInitExpr(T);
}
@@ -7108,7 +7641,7 @@ TreeTransform<Derived>::TransformVAArgExpr(VAArgExpr *E) {
if (!getDerived().AlwaysRebuild() &&
TInfo == E->getWrittenTypeInfo() &&
SubExpr.get() == E->getSubExpr())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildVAArgExpr(E->getBuiltinLoc(), SubExpr.get(),
TInfo, E->getRParenLoc());
@@ -7187,7 +7720,7 @@ TreeTransform<Derived>::TransformChooseExpr(ChooseExpr *E) {
Cond.get() == E->getCond() &&
LHS.get() == E->getLHS() &&
RHS.get() == E->getRHS())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildChooseExpr(E->getBuiltinLoc(),
Cond.get(), LHS.get(), RHS.get(),
@@ -7197,7 +7730,7 @@ TreeTransform<Derived>::TransformChooseExpr(ChooseExpr *E) {
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformGNUNullExpr(GNUNullExpr *E) {
- return SemaRef.Owned(E);
+ return E;
}
template<typename Derived>
@@ -7220,9 +7753,8 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
return ExprError();
// FIXME: Poor location information
- SourceLocation FakeLParenLoc
- = SemaRef.PP.getLocForEndOfToken(
- static_cast<Expr *>(Object.get())->getLocEnd());
+ SourceLocation FakeLParenLoc = SemaRef.getLocForEndOfToken(
+ static_cast<Expr *>(Object.get())->getLocEnd());
// Transform the call arguments.
SmallVector<Expr*, 8> Args;
@@ -7340,7 +7872,7 @@ TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) {
if (!getDerived().AlwaysRebuild() &&
Type == E->getTypeInfoAsWritten() &&
SubExpr.get() == E->getSubExpr())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildCXXNamedCastExpr(E->getOperatorLoc(),
E->getStmtClass(),
E->getAngleBrackets().getBegin(),
@@ -7393,7 +7925,7 @@ TreeTransform<Derived>::TransformCXXFunctionalCastExpr(
if (!getDerived().AlwaysRebuild() &&
Type == E->getTypeInfoAsWritten() &&
SubExpr.get() == E->getSubExpr())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildCXXFunctionalCastExpr(Type,
E->getLParenLoc(),
@@ -7412,7 +7944,7 @@ TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) {
if (!getDerived().AlwaysRebuild() &&
TInfo == E->getTypeOperandSourceInfo())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildCXXTypeidExpr(E->getType(),
E->getLocStart(),
@@ -7433,7 +7965,7 @@ TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) {
if (!getDerived().AlwaysRebuild() &&
SubExpr.get() == E->getExprOperand())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildCXXTypeidExpr(E->getType(),
E->getLocStart(),
@@ -7452,7 +7984,7 @@ TreeTransform<Derived>::TransformCXXUuidofExpr(CXXUuidofExpr *E) {
if (!getDerived().AlwaysRebuild() &&
TInfo == E->getTypeOperandSourceInfo())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildCXXUuidofExpr(E->getType(),
E->getLocStart(),
@@ -7468,7 +8000,7 @@ TreeTransform<Derived>::TransformCXXUuidofExpr(CXXUuidofExpr *E) {
if (!getDerived().AlwaysRebuild() &&
SubExpr.get() == E->getExprOperand())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildCXXUuidofExpr(E->getType(),
E->getLocStart(),
@@ -7479,14 +8011,14 @@ TreeTransform<Derived>::TransformCXXUuidofExpr(CXXUuidofExpr *E) {
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
- return SemaRef.Owned(E);
+ return E;
}
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformCXXNullPtrLiteralExpr(
CXXNullPtrLiteralExpr *E) {
- return SemaRef.Owned(E);
+ return E;
}
template<typename Derived>
@@ -7497,7 +8029,7 @@ TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) {
if (!getDerived().AlwaysRebuild() && T == E->getType()) {
// Make sure that we capture 'this'.
getSema().CheckCXXThisCapture(E->getLocStart());
- return SemaRef.Owned(E);
+ return E;
}
return getDerived().RebuildCXXThisExpr(E->getLocStart(), T, E->isImplicit());
@@ -7512,7 +8044,7 @@ TreeTransform<Derived>::TransformCXXThrowExpr(CXXThrowExpr *E) {
if (!getDerived().AlwaysRebuild() &&
SubExpr.get() == E->getSubExpr())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildCXXThrowExpr(E->getThrowLoc(), SubExpr.get(),
E->isThrownVariableInScope());
@@ -7529,7 +8061,7 @@ TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
if (!getDerived().AlwaysRebuild() &&
Param == E->getParam())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildCXXDefaultArgExpr(E->getUsedLocation(), Param);
}
@@ -7544,7 +8076,7 @@ TreeTransform<Derived>::TransformCXXDefaultInitExpr(CXXDefaultInitExpr *E) {
return ExprError();
if (!getDerived().AlwaysRebuild() && Field == E->getField())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildCXXDefaultInitExpr(E->getExprLoc(), Field);
}
@@ -7559,7 +8091,7 @@ TreeTransform<Derived>::TransformCXXScalarValueInitExpr(
if (!getDerived().AlwaysRebuild() &&
T == E->getTypeSourceInfo())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildCXXScalarValueInitExpr(T,
/*FIXME:*/T->getTypeLoc().getEndLoc(),
@@ -7592,12 +8124,12 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
Expr *OldInit = E->getInitializer();
ExprResult NewInit;
if (OldInit)
- NewInit = getDerived().TransformExpr(OldInit);
+ NewInit = getDerived().TransformInitializer(OldInit, true);
if (NewInit.isInvalid())
return ExprError();
// Transform new operator and delete operator.
- FunctionDecl *OperatorNew = 0;
+ FunctionDecl *OperatorNew = nullptr;
if (E->getOperatorNew()) {
OperatorNew = cast_or_null<FunctionDecl>(
getDerived().TransformDecl(E->getLocStart(),
@@ -7606,7 +8138,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
return ExprError();
}
- FunctionDecl *OperatorDelete = 0;
+ FunctionDecl *OperatorDelete = nullptr;
if (E->getOperatorDelete()) {
OperatorDelete = cast_or_null<FunctionDecl>(
getDerived().TransformDecl(E->getLocStart(),
@@ -7640,7 +8172,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
}
}
- return SemaRef.Owned(E);
+ return E;
}
QualType AllocType = AllocTypeInfo->getType();
@@ -7655,16 +8187,14 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
// Do nothing
} else if (const ConstantArrayType *ConsArrayT
= dyn_cast<ConstantArrayType>(ArrayT)) {
- ArraySize
- = SemaRef.Owned(IntegerLiteral::Create(SemaRef.Context,
- ConsArrayT->getSize(),
- SemaRef.Context.getSizeType(),
- /*FIXME:*/E->getLocStart()));
+ ArraySize = IntegerLiteral::Create(SemaRef.Context, ConsArrayT->getSize(),
+ SemaRef.Context.getSizeType(),
+ /*FIXME:*/ E->getLocStart());
AllocType = ConsArrayT->getElementType();
} else if (const DependentSizedArrayType *DepArrayT
= dyn_cast<DependentSizedArrayType>(ArrayT)) {
if (DepArrayT->getSizeExpr()) {
- ArraySize = SemaRef.Owned(DepArrayT->getSizeExpr());
+ ArraySize = DepArrayT->getSizeExpr();
AllocType = DepArrayT->getElementType();
}
}
@@ -7680,7 +8210,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
AllocTypeInfo,
ArraySize.get(),
E->getDirectInitRange(),
- NewInit.take());
+ NewInit.get());
}
template<typename Derived>
@@ -7691,7 +8221,7 @@ TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) {
return ExprError();
// Transform the delete operator, if known.
- FunctionDecl *OperatorDelete = 0;
+ FunctionDecl *OperatorDelete = nullptr;
if (E->getOperatorDelete()) {
OperatorDelete = cast_or_null<FunctionDecl>(
getDerived().TransformDecl(E->getLocStart(),
@@ -7718,7 +8248,7 @@ TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) {
}
}
- return SemaRef.Owned(E);
+ return E;
}
return getDerived().RebuildCXXDeleteExpr(E->getLocStart(),
@@ -7737,7 +8267,7 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
ParsedType ObjectTypePtr;
bool MayBePseudoDestructor = false;
- Base = SemaRef.ActOnStartCXXMemberReference(0, Base.get(),
+ Base = SemaRef.ActOnStartCXXMemberReference(nullptr, Base.get(),
E->getOperatorLoc(),
E->isArrow()? tok::arrow : tok::period,
ObjectTypePtr,
@@ -7760,7 +8290,7 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
if (E->getDestroyedTypeInfo()) {
TypeSourceInfo *DestroyedTypeInfo
= getDerived().TransformTypeInObjectScope(E->getDestroyedTypeInfo(),
- ObjectType, 0, SS);
+ ObjectType, nullptr, SS);
if (!DestroyedTypeInfo)
return ExprError();
Destroyed = DestroyedTypeInfo;
@@ -7774,7 +8304,7 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
ParsedType T = SemaRef.getDestructorName(E->getTildeLoc(),
*E->getDestroyedTypeIdentifier(),
E->getDestroyedTypeLoc(),
- /*Scope=*/0,
+ /*Scope=*/nullptr,
SS, ObjectTypePtr,
false);
if (!T)
@@ -7785,11 +8315,11 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
E->getDestroyedTypeLoc());
}
- TypeSourceInfo *ScopeTypeInfo = 0;
+ TypeSourceInfo *ScopeTypeInfo = nullptr;
if (E->getScopeTypeInfo()) {
CXXScopeSpec EmptySS;
ScopeTypeInfo = getDerived().TransformTypeInObjectScope(
- E->getScopeTypeInfo(), ObjectType, 0, EmptySS);
+ E->getScopeTypeInfo(), ObjectType, nullptr, EmptySS);
if (!ScopeTypeInfo)
return ExprError();
}
@@ -7831,9 +8361,8 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(
// Expand using declarations.
if (isa<UsingDecl>(InstD)) {
UsingDecl *UD = cast<UsingDecl>(InstD);
- for (UsingDecl::shadow_iterator I = UD->shadow_begin(),
- E = UD->shadow_end(); I != E; ++I)
- R.addDecl(*I);
+ for (auto *I : UD->shadows())
+ R.addDecl(I);
continue;
}
@@ -7892,44 +8421,6 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(
template<typename Derived>
ExprResult
-TreeTransform<Derived>::TransformUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
- TypeSourceInfo *T = getDerived().TransformType(E->getQueriedTypeSourceInfo());
- if (!T)
- return ExprError();
-
- if (!getDerived().AlwaysRebuild() &&
- T == E->getQueriedTypeSourceInfo())
- return SemaRef.Owned(E);
-
- return getDerived().RebuildUnaryTypeTrait(E->getTrait(),
- E->getLocStart(),
- T,
- E->getLocEnd());
-}
-
-template<typename Derived>
-ExprResult
-TreeTransform<Derived>::TransformBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
- TypeSourceInfo *LhsT = getDerived().TransformType(E->getLhsTypeSourceInfo());
- if (!LhsT)
- return ExprError();
-
- TypeSourceInfo *RhsT = getDerived().TransformType(E->getRhsTypeSourceInfo());
- if (!RhsT)
- return ExprError();
-
- if (!getDerived().AlwaysRebuild() &&
- LhsT == E->getLhsTypeSourceInfo() && RhsT == E->getRhsTypeSourceInfo())
- return SemaRef.Owned(E);
-
- return getDerived().RebuildBinaryTypeTrait(E->getTrait(),
- E->getLocStart(),
- LhsT, RhsT,
- E->getLocEnd());
-}
-
-template<typename Derived>
-ExprResult
TreeTransform<Derived>::TransformTypeTraitExpr(TypeTraitExpr *E) {
bool ArgChanged = false;
SmallVector<TypeSourceInfo *, 4> Args;
@@ -8055,7 +8546,7 @@ TreeTransform<Derived>::TransformTypeTraitExpr(TypeTraitExpr *E) {
}
if (!getDerived().AlwaysRebuild() && !ArgChanged)
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildTypeTrait(E->getTrait(),
E->getLocStart(),
@@ -8072,7 +8563,7 @@ TreeTransform<Derived>::TransformArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
if (!getDerived().AlwaysRebuild() &&
T == E->getQueriedTypeSourceInfo())
- return SemaRef.Owned(E);
+ return E;
ExprResult SubExpr;
{
@@ -8082,7 +8573,7 @@ TreeTransform<Derived>::TransformArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
return ExprError();
if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getDimensionExpression())
- return SemaRef.Owned(E);
+ return E;
}
return getDerived().RebuildArrayTypeTrait(E->getTrait(),
@@ -8103,25 +8594,44 @@ TreeTransform<Derived>::TransformExpressionTraitExpr(ExpressionTraitExpr *E) {
return ExprError();
if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getQueriedExpression())
- return SemaRef.Owned(E);
+ return E;
}
return getDerived().RebuildExpressionTrait(
E->getTrait(), E->getLocStart(), SubExpr.get(), E->getLocEnd());
}
-template<typename Derived>
-ExprResult
-TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
- DependentScopeDeclRefExpr *E) {
- return TransformDependentScopeDeclRefExpr(E, /*IsAddressOfOperand*/false);
+template <typename Derived>
+ExprResult TreeTransform<Derived>::TransformParenDependentScopeDeclRefExpr(
+ ParenExpr *PE, DependentScopeDeclRefExpr *DRE, bool AddrTaken,
+ TypeSourceInfo **RecoveryTSI) {
+ ExprResult NewDRE = getDerived().TransformDependentScopeDeclRefExpr(
+ DRE, AddrTaken, RecoveryTSI);
+
+ // Propagate both errors and recovered types, which return ExprEmpty.
+ if (!NewDRE.isUsable())
+ return NewDRE;
+
+ // We got an expr, wrap it up in parens.
+ if (!getDerived().AlwaysRebuild() && NewDRE.get() == DRE)
+ return PE;
+ return getDerived().RebuildParenExpr(NewDRE.get(), PE->getLParen(),
+ PE->getRParen());
+}
+
+template <typename Derived>
+ExprResult TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
+ DependentScopeDeclRefExpr *E) {
+ return TransformDependentScopeDeclRefExpr(E, /*IsAddressOfOperand=*/false,
+ nullptr);
}
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
DependentScopeDeclRefExpr *E,
- bool IsAddressOfOperand) {
+ bool IsAddressOfOperand,
+ TypeSourceInfo **RecoveryTSI) {
assert(E->getQualifierLoc());
NestedNameSpecifierLoc QualifierLoc
= getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc());
@@ -8144,13 +8654,11 @@ TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
// Note: it is sufficient to compare the Name component of NameInfo:
// if name has not changed, DNLoc has not changed either.
NameInfo.getName() == E->getDeclName())
- return SemaRef.Owned(E);
+ return E;
- return getDerived().RebuildDependentScopeDeclRefExpr(QualifierLoc,
- TemplateKWLoc,
- NameInfo,
- /*TemplateArgs*/ 0,
- IsAddressOfOperand);
+ return getDerived().RebuildDependentScopeDeclRefExpr(
+ QualifierLoc, TemplateKWLoc, NameInfo, /*TemplateArgs=*/nullptr,
+ IsAddressOfOperand, RecoveryTSI);
}
TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc());
@@ -8159,11 +8667,9 @@ TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
TransArgs))
return ExprError();
- return getDerived().RebuildDependentScopeDeclRefExpr(QualifierLoc,
- TemplateKWLoc,
- NameInfo,
- &TransArgs,
- IsAddressOfOperand);
+ return getDerived().RebuildDependentScopeDeclRefExpr(
+ QualifierLoc, TemplateKWLoc, NameInfo, &TransArgs, IsAddressOfOperand,
+ RecoveryTSI);
}
template<typename Derived>
@@ -8204,7 +8710,7 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) {
// Mark the constructor as referenced.
// FIXME: Instantiation-specific
SemaRef.MarkFunctionReferenced(E->getLocStart(), Constructor);
- return SemaRef.Owned(E);
+ return E;
}
return getDerived().RebuildCXXConstructExpr(T, /*FIXME:*/E->getLocStart(),
@@ -8212,6 +8718,7 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) {
Args,
E->hadMultipleCandidates(),
E->isListInitialization(),
+ E->isStdInitListInitialization(),
E->requiresZeroInitialization(),
E->getConstructionKind(),
E->getParenOrBraceRange());
@@ -8325,8 +8832,8 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
TypeSourceInfo *OldCallOpTSI = E->getCallOperator()->getTypeSourceInfo();
FunctionProtoTypeLoc OldCallOpFPTL =
OldCallOpTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>();
- TypeSourceInfo *NewCallOpTSI = 0;
-
+ TypeSourceInfo *NewCallOpTSI = nullptr;
+
const bool CallOpWasAlreadyTransformed =
getDerived().AlreadyTransformed(OldCallOpTSI->getType());
@@ -8342,7 +8849,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
TypeLocBuilder NewCallOpTLBuilder;
QualType NewCallOpType = TransformFunctionProtoType(NewCallOpTLBuilder,
OldCallOpFPTL,
- 0, 0);
+ nullptr, 0);
NewCallOpTSI = NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context,
NewCallOpType);
}
@@ -8355,7 +8862,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
FunctionProtoTypeLoc NewCallOpFPTL =
NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>();
ParmVarDecl **NewParamDeclArray = NewCallOpFPTL.getParmArray();
- const unsigned NewNumArgs = NewCallOpFPTL.getNumArgs();
+ const unsigned NewNumArgs = NewCallOpFPTL.getNumParams();
for (unsigned I = 0; I < NewNumArgs; ++I) {
// If this call operator's type does not require transformation,
@@ -8418,7 +8925,8 @@ TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E,
bool Invalid = false;
// Introduce the context of the call operator.
- Sema::ContextRAII SavedContext(getSema(), CallOperator);
+ Sema::ContextRAII SavedContext(getSema(), CallOperator,
+ /*NewThisContext*/false);
LambdaScopeInfo *const LSI = getSema().getCurLambda();
// Enter the scope of the lambda.
@@ -8512,6 +9020,9 @@ TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E,
// Capture the transformed variable.
getSema().tryCaptureVariable(CapturedVar, C->getLocation(), Kind);
}
+
+ // FIXME: Retain a pack expansion if RetainExpansion is true.
+
continue;
}
@@ -8539,7 +9050,7 @@ TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E,
getSema().PushExpressionEvaluationContext(Sema::PotentiallyEvaluated);
if (Invalid) {
- getSema().ActOnLambdaError(E->getLocStart(), /*CurScope=*/0,
+ getSema().ActOnLambdaError(E->getLocStart(), /*CurScope=*/nullptr,
/*IsInstantiation=*/true);
return ExprError();
}
@@ -8547,13 +9058,14 @@ TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E,
// Instantiate the body of the lambda expression.
StmtResult Body = getDerived().TransformStmt(E->getBody());
if (Body.isInvalid()) {
- getSema().ActOnLambdaError(E->getLocStart(), /*CurScope=*/0,
+ getSema().ActOnLambdaError(E->getLocStart(), /*CurScope=*/nullptr,
/*IsInstantiation=*/true);
return ExprError();
}
- return getSema().ActOnLambdaExpr(E->getLocStart(), Body.take(),
- /*CurScope=*/0, /*IsInstantiation=*/true);
+ return getSema().ActOnLambdaExpr(E->getLocStart(), Body.get(),
+ /*CurScope=*/nullptr,
+ /*IsInstantiation=*/true);
}
template<typename Derived>
@@ -8574,7 +9086,7 @@ TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr(
if (!getDerived().AlwaysRebuild() &&
T == E->getTypeSourceInfo() &&
!ArgumentChanged)
- return SemaRef.Owned(E);
+ return E;
// FIXME: we're faking the locations of the commas
return getDerived().RebuildCXXUnresolvedConstructExpr(T,
@@ -8588,7 +9100,7 @@ ExprResult
TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
CXXDependentScopeMemberExpr *E) {
// Transform the base of the expression.
- ExprResult Base((Expr*) 0);
+ ExprResult Base((Expr*) nullptr);
Expr *OldBase;
QualType BaseType;
QualType ObjectType;
@@ -8601,7 +9113,7 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
// Start the member reference and compute the object's type.
ParsedType ObjectTy;
bool MayBePseudoDestructor = false;
- Base = SemaRef.ActOnStartCXXMemberReference(0, Base.get(),
+ Base = SemaRef.ActOnStartCXXMemberReference(nullptr, Base.get(),
E->getOperatorLoc(),
E->isArrow()? tok::arrow : tok::period,
ObjectTy,
@@ -8612,7 +9124,7 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
ObjectType = ObjectTy.get();
BaseType = ((Expr*) Base.get())->getType();
} else {
- OldBase = 0;
+ OldBase = nullptr;
BaseType = getDerived().TransformType(E->getBaseType());
ObjectType = BaseType->getAs<PointerType>()->getPointeeType();
}
@@ -8654,7 +9166,7 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
QualifierLoc == E->getQualifierLoc() &&
NameInfo.getName() == E->getMember() &&
FirstQualifierInScope == E->getFirstQualifierFoundInScope())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildCXXDependentScopeMemberExpr(Base.get(),
BaseType,
@@ -8664,7 +9176,7 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
TemplateKWLoc,
FirstQualifierInScope,
NameInfo,
- /*TemplateArgs*/ 0);
+ /*TemplateArgs*/nullptr);
}
TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc());
@@ -8688,13 +9200,13 @@ template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old) {
// Transform the base of the expression.
- ExprResult Base((Expr*) 0);
+ ExprResult Base((Expr*) nullptr);
QualType BaseType;
if (!Old->isImplicitAccess()) {
Base = getDerived().TransformExpr(Old->getBase());
if (Base.isInvalid())
return ExprError();
- Base = getSema().PerformMemberExprBaseConversion(Base.take(),
+ Base = getSema().PerformMemberExprBaseConversion(Base.get(),
Old->isArrow());
if (Base.isInvalid())
return ExprError();
@@ -8736,9 +9248,8 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old)
// Expand using declarations.
if (isa<UsingDecl>(InstD)) {
UsingDecl *UD = cast<UsingDecl>(InstD);
- for (UsingDecl::shadow_iterator I = UD->shadow_begin(),
- E = UD->shadow_end(); I != E; ++I)
- R.addDecl(*I);
+ for (auto *I : UD->shadows())
+ R.addDecl(I);
continue;
}
@@ -8773,7 +9284,7 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old)
// first-qualifier-in-scope here, just in case we had a dependent
// base (and therefore couldn't do the check) and a
// nested-name-qualifier (and therefore could do the lookup).
- NamedDecl *FirstQualifierInScope = 0;
+ NamedDecl *FirstQualifierInScope = nullptr;
return getDerived().RebuildUnresolvedMemberExpr(Base.get(),
BaseType,
@@ -8784,7 +9295,7 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old)
FirstQualifierInScope,
R,
(Old->hasExplicitTemplateArgs()
- ? &TransArgs : 0));
+ ? &TransArgs : nullptr));
}
template<typename Derived>
@@ -8796,7 +9307,7 @@ TreeTransform<Derived>::TransformCXXNoexceptExpr(CXXNoexceptExpr *E) {
return ExprError();
if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getOperand())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildCXXNoexceptExpr(E->getSourceRange(),SubExpr.get());
}
@@ -8809,7 +9320,7 @@ TreeTransform<Derived>::TransformPackExpansionExpr(PackExpansionExpr *E) {
return ExprError();
if (!getDerived().AlwaysRebuild() && Pattern.get() == E->getPattern())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildPackExpansion(Pattern.get(), E->getEllipsisLoc(),
E->getNumExpansions());
@@ -8821,7 +9332,7 @@ TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) {
// If E is not value-dependent, then nothing will change when we transform it.
// Note: This is an instantiation-centric view.
if (!E->isValueDependent())
- return SemaRef.Owned(E);
+ return E;
// Note: None of the implementations of TryExpandParameterPacks can ever
// produce a diagnostic when given only a single unexpanded parameter pack,
@@ -8837,7 +9348,7 @@ TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) {
return ExprError();
if (RetainExpansion)
- return SemaRef.Owned(E);
+ return E;
NamedDecl *Pack = E->getPack();
if (!ShouldExpand) {
@@ -8860,7 +9371,7 @@ ExprResult
TreeTransform<Derived>::TransformSubstNonTypeTemplateParmPackExpr(
SubstNonTypeTemplateParmPackExpr *E) {
// Default behavior is to do nothing with this transformation.
- return SemaRef.Owned(E);
+ return E;
}
template<typename Derived>
@@ -8868,14 +9379,14 @@ ExprResult
TreeTransform<Derived>::TransformSubstNonTypeTemplateParmExpr(
SubstNonTypeTemplateParmExpr *E) {
// Default behavior is to do nothing with this transformation.
- return SemaRef.Owned(E);
+ return E;
}
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformFunctionParmPackExpr(FunctionParmPackExpr *E) {
// Default behavior is to do nothing with this transformation.
- return SemaRef.Owned(E);
+ return E;
}
template<typename Derived>
@@ -8901,7 +9412,7 @@ TreeTransform<Derived>::TransformObjCStringLiteral(ObjCStringLiteral *E) {
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformObjCBoolLiteralExpr(ObjCBoolLiteralExpr *E) {
- return SemaRef.Owned(E);
+ return E;
}
template<typename Derived>
@@ -8913,7 +9424,7 @@ TreeTransform<Derived>::TransformObjCBoxedExpr(ObjCBoxedExpr *E) {
if (!getDerived().AlwaysRebuild() &&
SubExpr.get() == E->getSubExpr())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildObjCBoxedExpr(E->getSourceRange(), SubExpr.get());
}
@@ -9016,6 +9527,7 @@ TreeTransform<Derived>::TransformObjCDictionaryLiteral(
// If any unexpanded parameter packs remain, we still have a
// pack expansion.
+ // FIXME: Can this really happen?
if (Key.get()->containsUnexpandedParameterPack() ||
Value.get()->containsUnexpandedParameterPack())
Element.EllipsisLoc = OrigElement.EllipsisLoc;
@@ -9023,6 +9535,8 @@ TreeTransform<Derived>::TransformObjCDictionaryLiteral(
Elements.push_back(Element);
}
+ // FIXME: Retain a pack expansion if RetainExpansion is true.
+
// We've finished with this pack expansion.
continue;
}
@@ -9068,7 +9582,7 @@ TreeTransform<Derived>::TransformObjCEncodeExpr(ObjCEncodeExpr *E) {
if (!getDerived().AlwaysRebuild() &&
EncodedTypeInfo == E->getEncodedTypeSourceInfo())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildObjCEncodeExpr(E->getAtLoc(),
EncodedTypeInfo,
@@ -9100,7 +9614,7 @@ TransformObjCBridgedCastExpr(ObjCBridgedCastExpr *E) {
if (!getDerived().AlwaysRebuild() &&
TSInfo == E->getTypeInfoAsWritten() &&
Result.get() == E->getSubExpr())
- return SemaRef.Owned(E);
+ return E;
return SemaRef.BuildObjCBridgedCast(E->getLParenLoc(), E->getBridgeKind(),
E->getBridgeKeywordLoc(), TSInfo,
@@ -9170,13 +9684,13 @@ TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) {
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformObjCSelectorExpr(ObjCSelectorExpr *E) {
- return SemaRef.Owned(E);
+ return E;
}
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformObjCProtocolExpr(ObjCProtocolExpr *E) {
- return SemaRef.Owned(E);
+ return E;
}
template<typename Derived>
@@ -9192,7 +9706,7 @@ TreeTransform<Derived>::TransformObjCIvarRefExpr(ObjCIvarRefExpr *E) {
// If nothing changed, just retain the existing expression.
if (!getDerived().AlwaysRebuild() &&
Base.get() == E->getBase())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildObjCIvarRefExpr(Base.get(), E->getDecl(),
E->getLocation(),
@@ -9205,7 +9719,7 @@ TreeTransform<Derived>::TransformObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
// 'super' and types never change. Property never changes. Just
// retain the existing expression.
if (!E->isObjectReceiver())
- return SemaRef.Owned(E);
+ return E;
// Transform the base expression.
ExprResult Base = getDerived().TransformExpr(E->getBase());
@@ -9217,7 +9731,7 @@ TreeTransform<Derived>::TransformObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
// If nothing changed, just retain the existing expression.
if (!getDerived().AlwaysRebuild() &&
Base.get() == E->getBase())
- return SemaRef.Owned(E);
+ return E;
if (E->isExplicitProperty())
return getDerived().RebuildObjCPropertyRefExpr(Base.get(),
@@ -9247,7 +9761,7 @@ TreeTransform<Derived>::TransformObjCSubscriptRefExpr(ObjCSubscriptRefExpr *E) {
// If nothing changed, just retain the existing expression.
if (!getDerived().AlwaysRebuild() &&
Key.get() == E->getKeyExpr() && Base.get() == E->getBaseExpr())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildObjCSubscriptRefExpr(E->getRBracket(),
Base.get(), Key.get(),
@@ -9266,7 +9780,7 @@ TreeTransform<Derived>::TransformObjCIsaExpr(ObjCIsaExpr *E) {
// If nothing changed, just retain the existing expression.
if (!getDerived().AlwaysRebuild() &&
Base.get() == E->getBase())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildObjCIsaExpr(Base.get(), E->getIsaMemberLoc(),
E->getOpLoc(),
@@ -9285,7 +9799,7 @@ TreeTransform<Derived>::TransformShuffleVectorExpr(ShuffleVectorExpr *E) {
if (!getDerived().AlwaysRebuild() &&
!ArgumentChanged)
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildShuffleVectorExpr(E->getBuiltinLoc(),
SubExprs,
@@ -9306,7 +9820,7 @@ TreeTransform<Derived>::TransformConvertVectorExpr(ConvertVectorExpr *E) {
if (!getDerived().AlwaysRebuild() &&
Type == E->getTypeSourceInfo() &&
SrcExpr.get() == E->getSrcExpr())
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildConvertVectorExpr(E->getBuiltinLoc(),
SrcExpr.get(), Type,
@@ -9318,7 +9832,7 @@ ExprResult
TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
BlockDecl *oldBlock = E->getBlockDecl();
- SemaRef.ActOnBlockStart(E->getCaretLocation(), /*Scope=*/0);
+ SemaRef.ActOnBlockStart(E->getCaretLocation(), /*Scope=*/nullptr);
BlockScopeInfo *blockScope = SemaRef.getCurBlock();
blockScope->TheDecl->setIsVariadic(oldBlock->isVariadic());
@@ -9332,14 +9846,14 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
if (getDerived().TransformFunctionTypeParams(E->getCaretLocation(),
oldBlock->param_begin(),
oldBlock->param_size(),
- 0, paramTypes, &params)) {
- getSema().ActOnBlockError(E->getCaretLocation(), /*Scope=*/0);
+ nullptr, paramTypes, &params)) {
+ getSema().ActOnBlockError(E->getCaretLocation(), /*Scope=*/nullptr);
return ExprError();
}
const FunctionProtoType *exprFunctionType = E->getFunctionType();
QualType exprResultType =
- getDerived().TransformType(exprFunctionType->getResultType());
+ getDerived().TransformType(exprFunctionType->getReturnType());
QualType functionType =
getDerived().RebuildFunctionProtoType(exprResultType, paramTypes,
@@ -9358,7 +9872,7 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
// Transform the body
StmtResult body = getDerived().TransformStmt(E->getBody());
if (body.isInvalid()) {
- getSema().ActOnBlockError(E->getCaretLocation(), /*Scope=*/0);
+ getSema().ActOnBlockError(E->getCaretLocation(), /*Scope=*/nullptr);
return ExprError();
}
@@ -9366,9 +9880,8 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
// In builds with assertions, make sure that we captured everything we
// captured before.
if (!SemaRef.getDiagnostics().hasErrorOccurred()) {
- for (BlockDecl::capture_iterator i = oldBlock->capture_begin(),
- e = oldBlock->capture_end(); i != e; ++i) {
- VarDecl *oldCapture = i->getVariable();
+ for (const auto &I : oldBlock->captures()) {
+ VarDecl *oldCapture = I.getVariable();
// Ignore parameter packs.
if (isa<ParmVarDecl>(oldCapture) &&
@@ -9385,7 +9898,7 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
#endif
return SemaRef.ActOnBlockStmtExpr(E->getCaretLocation(), body.get(),
- /*Scope=*/0);
+ /*Scope=*/nullptr);
}
template<typename Derived>
@@ -9407,7 +9920,7 @@ TreeTransform<Derived>::TransformAtomicExpr(AtomicExpr *E) {
if (!getDerived().AlwaysRebuild() &&
!ArgumentChanged)
- return SemaRef.Owned(E);
+ return E;
return getDerived().RebuildAtomicExpr(E->getBuiltinLoc(), SubExprs,
RetTy, E->getOp(), E->getRParenLoc());
@@ -9445,8 +9958,8 @@ QualType
TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType,
QualType ClassType,
SourceLocation Sigil) {
- return SemaRef.BuildMemberPointerType(PointeeType, ClassType,
- Sigil, getDerived().getBaseEntity());
+ return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Sigil,
+ getDerived().getBaseEntity());
}
template<typename Derived>
@@ -9492,7 +10005,7 @@ TreeTransform<Derived>::RebuildConstantArrayType(QualType ElementType,
const llvm::APInt &Size,
unsigned IndexTypeQuals,
SourceRange BracketsRange) {
- return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, 0,
+ return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, nullptr,
IndexTypeQuals, BracketsRange);
}
@@ -9502,7 +10015,7 @@ TreeTransform<Derived>::RebuildIncompleteArrayType(QualType ElementType,
ArrayType::ArraySizeModifier SizeMod,
unsigned IndexTypeQuals,
SourceRange BracketsRange) {
- return getDerived().RebuildArrayType(ElementType, SizeMod, 0, 0,
+ return getDerived().RebuildArrayType(ElementType, SizeMod, nullptr, nullptr,
IndexTypeQuals, BracketsRange);
}
@@ -9513,7 +10026,7 @@ TreeTransform<Derived>::RebuildVariableArrayType(QualType ElementType,
Expr *SizeExpr,
unsigned IndexTypeQuals,
SourceRange BracketsRange) {
- return getDerived().RebuildArrayType(ElementType, SizeMod, 0,
+ return getDerived().RebuildArrayType(ElementType, SizeMod, nullptr,
SizeExpr,
IndexTypeQuals, BracketsRange);
}
@@ -9525,7 +10038,7 @@ TreeTransform<Derived>::RebuildDependentSizedArrayType(QualType ElementType,
Expr *SizeExpr,
unsigned IndexTypeQuals,
SourceRange BracketsRange) {
- return getDerived().RebuildArrayType(ElementType, SizeMod, 0,
+ return getDerived().RebuildArrayType(ElementType, SizeMod, nullptr,
SizeExpr,
IndexTypeQuals, BracketsRange);
}
@@ -9561,7 +10074,7 @@ TreeTransform<Derived>::RebuildDependentSizedExtVectorType(QualType ElementType,
template<typename Derived>
QualType TreeTransform<Derived>::RebuildFunctionProtoType(
QualType T,
- llvm::MutableArrayRef<QualType> ParamTypes,
+ MutableArrayRef<QualType> ParamTypes,
const FunctionProtoType::ExtProtoInfo &EPI) {
return SemaRef.BuildFunctionType(T, ParamTypes,
getDerived().getBaseLocation(),
@@ -9657,7 +10170,7 @@ TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
TemplateName.setIdentifier(&Name, NameLoc);
Sema::TemplateTy Template;
SourceLocation TemplateKWLoc; // FIXME: retrieve it from caller.
- getSema().ActOnDependentTemplateName(/*Scope=*/0,
+ getSema().ActOnDependentTemplateName(/*Scope=*/nullptr,
SS, TemplateKWLoc, TemplateName,
ParsedType::make(ObjectType),
/*EnteringContext=*/false,
@@ -9677,7 +10190,7 @@ TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
Name.setOperatorFunctionId(NameLoc, Operator, SymbolLocations);
SourceLocation TemplateKWLoc; // FIXME: retrieve it from caller.
Sema::TemplateTy Template;
- getSema().ActOnDependentTemplateName(/*Scope=*/0,
+ getSema().ActOnDependentTemplateName(/*Scope=*/nullptr,
SS, TemplateKWLoc, Name,
ParsedType::make(ObjectType),
/*EnteringContext=*/false,
@@ -9695,6 +10208,24 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
Expr *Callee = OrigCallee->IgnoreParenCasts();
bool isPostIncDec = Second && (Op == OO_PlusPlus || Op == OO_MinusMinus);
+ if (First->getObjectKind() == OK_ObjCProperty) {
+ BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op);
+ if (BinaryOperator::isAssignmentOp(Opc))
+ return SemaRef.checkPseudoObjectAssignment(/*Scope=*/nullptr, OpLoc, Opc,
+ First, Second);
+ ExprResult Result = SemaRef.CheckPlaceholderExpr(First);
+ if (Result.isInvalid())
+ return ExprError();
+ First = Result.get();
+ }
+
+ if (Second && Second->getObjectKind() == OK_ObjCProperty) {
+ ExprResult Result = SemaRef.CheckPlaceholderExpr(Second);
+ if (Result.isInvalid())
+ return ExprError();
+ Second = Result.get();
+ }
+
// Determine whether this should be a builtin operation.
if (Op == OO_Subscript) {
if (!First->getType()->isOverloadableType() &&
@@ -9704,8 +10235,8 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
Second, OpLoc);
} else if (Op == OO_Arrow) {
// -> is never a builtin operation.
- return SemaRef.BuildOverloadedArrowExpr(0, First, OpLoc);
- } else if (Second == 0 || isPostIncDec) {
+ 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.
@@ -9735,9 +10266,6 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Callee)) {
assert(ULE->requiresADL());
-
- // FIXME: Do we have to check
- // IsAcceptableNonMemberOperatorCandidate for each of these?
Functions.append(ULE->decls_begin(), ULE->decls_end());
} else {
// If we've resolved this to a particular non-member function, just call
@@ -9750,7 +10278,7 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
// Add any functions found via argument-dependent lookup.
Expr *Args[2] = { First, Second };
- unsigned NumArgs = 1 + (Second != 0);
+ unsigned NumArgs = 1 + (Second != nullptr);
// Create the overloaded operator invocation for unary operators.
if (NumArgs == 1 || isPostIncDec) {
@@ -9828,26 +10356,43 @@ TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(Expr *Base,
return getSema().BuildMemberReferenceExpr(Base, BaseType,
OperatorLoc, isArrow,
SS, TemplateKWLoc,
- /*FIXME: FirstQualifier*/ 0,
+ /*FIXME: FirstQualifier*/ nullptr,
NameInfo,
- /*TemplateArgs*/ 0);
+ /*TemplateArgs*/ nullptr);
}
template<typename Derived>
StmtResult
TreeTransform<Derived>::TransformCapturedStmt(CapturedStmt *S) {
SourceLocation Loc = S->getLocStart();
- unsigned NumParams = S->getCapturedDecl()->getNumParams();
- getSema().ActOnCapturedRegionStart(Loc, /*CurScope*/0,
- S->getCapturedRegionKind(), NumParams);
- StmtResult Body = getDerived().TransformStmt(S->getCapturedStmt());
+ CapturedDecl *CD = S->getCapturedDecl();
+ unsigned NumParams = CD->getNumParams();
+ unsigned ContextParamPos = CD->getContextParamPosition();
+ SmallVector<Sema::CapturedParamNameType, 4> Params;
+ for (unsigned I = 0; I < NumParams; ++I) {
+ if (I != ContextParamPos) {
+ Params.push_back(
+ std::make_pair(
+ CD->getParam(I)->getName(),
+ getDerived().TransformType(CD->getParam(I)->getType())));
+ } else {
+ Params.push_back(std::make_pair(StringRef(), QualType()));
+ }
+ }
+ getSema().ActOnCapturedRegionStart(Loc, /*CurScope*/nullptr,
+ S->getCapturedRegionKind(), Params);
+ StmtResult Body;
+ {
+ Sema::CompoundScopeRAII CompoundScope(getSema());
+ Body = getDerived().TransformStmt(S->getCapturedStmt());
+ }
if (Body.isInvalid()) {
getSema().ActOnCapturedRegionError();
return StmtError();
}
- return getSema().ActOnCapturedRegionEnd(Body.take());
+ return getSema().ActOnCapturedRegionEnd(Body.get());
}
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.cpp b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.cpp
index c7d43b7..be99540 100644
--- a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.cpp
@@ -62,7 +62,7 @@ void TypeLocBuilder::grow(size_t NewCapacity) {
TypeLoc TypeLocBuilder::pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment) {
#ifndef NDEBUG
- QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType();
+ QualType TLast = TypeLoc(T, nullptr).getNextTypeLoc().getType();
assert(TLast == LastTy &&
"mismatch between last type and new type's inner type");
LastTy = T;
diff --git a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h
index b1e9098..c3f874e 100644
--- a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h
+++ b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h
@@ -94,7 +94,7 @@ class TypeLocBuilder {
/// Pushes space for a new TypeLoc of the given type. Invalidates
/// any TypeLocs previously retrieved from this builder.
template <class TyLocType> TyLocType push(QualType T) {
- TyLocType Loc = TypeLoc(T, 0).castAs<TyLocType>();
+ TyLocType Loc = TypeLoc(T, nullptr).castAs<TyLocType>();
size_t LocalSize = Loc.getLocalDataSize();
unsigned LocalAlign = Loc.getLocalDataAlignment();
return pushImpl(T, LocalSize, LocalAlign).castAs<TyLocType>();
OpenPOWER on IntegriCloud