diff options
author | dim <dim@FreeBSD.org> | 2014-11-24 18:11:16 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2014-11-24 18:11:16 +0000 |
commit | 6148c19c738a92f344008aa3f88f4e008bada0ee (patch) | |
tree | d4426858455f04d0d8c25a2f9eb9ea5582ffe1b6 /contrib/llvm/tools/clang/lib/Sema | |
parent | 2c8643c6396b0a3db33430cf9380e70bbb9efce0 (diff) | |
parent | 173a4f43a911175643bda81ee675e8d9269056ea (diff) | |
download | FreeBSD-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')
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, ¶ms)) { - getSema().ActOnBlockError(E->getCaretLocation(), /*Scope=*/0); + nullptr, paramTypes, ¶ms)) { + 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>(); |